intptr_tm-gtframebuffer-gtbase 18. pHandle hnd 1.3.2 屏幕设备不支持page flip模式 在mapFrameBufferLockedhardware/msm7k/libgralloc-qsd8k/framebuffer.cpp中可以得知如果屏幕设备不支持page flip模式那么numBuffer值将为1而不是2那么映射过来的屏幕缓存区将只有一个屏幕大小不够支持page flip模式那么此时将不使用这一个屏幕大小的屏幕缓存区而改为去dev/pmem设备去申请。
gralloc_alloc_framebuffer_lockedhardware/msm7k/libgralloc-qsd8k/gpu.cpp cpp view plaincopy 1. const uint32_t bufferMask m-gtbufferMask 2. const uint32_t numBuffers m-gtnumBuffers 3. const size_t bufferSize m-gtfinfo.line_length m-gtinfo.yres 4. if numBuffers 1 5. // If we have only one buffer we never use page-flipping. Instead 6. // we return a regular buffer which will be memcpyed to the main 7. // screen when post is called. 8. int newUsage usage amp GRALLOC_USAGE_HW_FB GRALLOC_USAGE_HW_2D 9. return gralloc_alloc_bufferbufferSize newUsage pHandle 10. 2. 打开Overlay 同选择gralloc library相似根据属性值来选择何时的overlay库如果vendor厂商没有提供overlay库的话那么系统将使用默认的overlay库overlay.default.so。
同样的我们获得overlay库的HAL_MODULE_INFO_SYM结构体作为系统调用overlay的接口。
cpp view plaincopy 1. if hw_get_moduleOVERLAY_HARDWARE_MODULE_ID ampmodule 0 2. overlay_control_openmodule ampmOverlayEngine 3. 3. 选择OpenGL ES library也即软/硬件加速 OpenGL Open Graphics Library3 is a standard specification defining a cross-language cross-platform API for writing applications that produce 2D and 3D computer graphics. The interface consists of over 250 different function calls which can be used to draw complex three-dimensional scenes from simple primitives. OpenGL was developed by Silicon Graphics Inc. SGI in 19924 and is widely used in CAD virtual reality scientific visualization information visualization flight simulation and video games. OpenGL is managed by the non-profit technology consortium Khronos Group.。
android是默认支持OpenGL ES软件加速的library为libGLES_
android源码路径为frameworksbaseopengllibagl如果手机设备支持硬件加速的话那么复杂的图像处理工作将交由GPU去处理那么效率将大大提高。
但是如果系统真的存在硬件加速它是如何选择何时用软件加速何时用硬件加速的呢 如何查看是否有GPU来实现硬件加速很容易查看/system/lib/egl/egl.cfg文件内容 java view plaincopy 1. 0 0 android 2. 0 1 adreno200 因此只要我们的移动设备芯片集成了GPU并提供了对应的GL图形库那么我们就可以在我们的工程中device目录下的egl.cfg文件中加入类似上面的配置那么我们的系统就会支持硬件加速。
如adreno200 GPU提供的GL图形库 cpp view plaincopy 1. libGLESv1_CM_adreno200.so 2. libGLESv2_adreno200.so 3. libEGL_adreno200.so 那么假如我们的系统中软硬件加速都支持了那么我们从代码来看能不能让用户自由的选择加速类型我们带着问题来研究一下代码。
3.1 OpenGL初始化 在调用不管是软件加速的还是硬件加速的OpenGL api之前我们都需要把软硬两种模式的各自的OpenGL api提取出来抽象出一个interface来供系统使用这个过程我称之为OpenGL初始化过程。
软硬两种模式的OpenGL api被分别指定到了一个全局数组的对应位置。
frameworks/base/opengl/libs/EGL/egl.cpp cpp view plaincopy 1. static egl_connection_t gEGLImplIMPL_NUM_IMPLEMENTATIONS cpp view plaincopy 1. enum 2. IMPL_HARDWARE 0 3. IMPL_SOFTWARE 4. IMPL_NUM_IMPLEMENTATIONS 5. gEGLImplIMPL_HARDWARE中保存着硬件图形设备的OpenGL api地址从 cpp view plaincopy 1. libGLESv1_CM_adreno200.so 2. libGLESv2_adreno200.so 3. libEGL_adreno200.so 这3个库中获得gEGLImplIMPL_SOFTWARE中保存着软件的OpenGL api地址从libGLES_android.so中获取。
这部分代码在egl_init_drivers_lockedframeworks/base/opengl/libs/EGL/egl.cpp 3.2 EGL和GLES api 在OpenGL的初始化过程中OpenGL提供了两套api分别称为EGL和GLES。
android在OPENGL初始化过程中会将两种不同的接口分开管理从下面代码中我们可以看到EGL和GLES api地址被存储到了不同的位置。
frameworksbaseopengllibsEGLLoader.h cpp view plaincopy 1. enum 2. EGL 0x01 3. GLESv1_CM 0x02 4. GLESv2 0x04 5. load_driverframeworksbaseopengllibsEGLLoader.cpp 上面枚举的EGL表示ELG apiGLESvq1_CM表示OpenGL ES 1.0的apiGLESv2表示OpenGL ES 2.0的api。
EGL api地址最终被存储在gEGLImpl.egl中 GLESvq1_CM api地址最终被存储在gEGLImpl.hooksGLESv1_INDEX-gtgl中 GLESv2 api地址最终被存储在gEGLImpl.hooksGLESv2_INDEX-gtgl中 3.2.1 EGL api EGL is an interface between Khronos rendering APIs such as OpenGL ES or OpenVG and the underlying native platform window system. It handles graphics context management surface/buffer binding and rendering synchronization and enables high-performance accelerated mixed-mode 2D and 3D rendering using other Khronos APIs. 上面引用了官方的定义可以看出EGL是系统和OPENGL ES之间的接口它的声明在文件frameworksbaseopengllibsEGLegl_entries.in。
3.2.2 GLES GLES才是真正的OpenGL ES的api它的声明我们可以在frameworksbaseopengllibsentries.in找到。
目前的android系统不但将EGL提供给系统使用同时将GLES也提供给了系统使用这个我们可以在最开始的显示系统的结构图中可以看到surfacefliger和framework的opengl模块均可以访问EGL和GLES接口。
3.3 OpenGL config 每个OpenGL库都根据不同的像素格式pixel format提供了一系统的configandroid根据framebuffer中设置的像素格式来选择合适的configandroid根据中各config中的属性信息来创建main surface和openGL上下文。
3.3.1 系统默认pixel format 当前的代码分析是基于gingerbread的在mapFrameBufferLockedhardware/msm7k/libgralloc-qsd8k/framebuffer.cpp中我们可以找到framebuffer的pixel format的类型 1. ifinfo.bits_per_pixel 32 2. / 3. Explicitly request RGBA_8888 4. / 5. 6. / Note: the GL driver does not have a r8 g8 b8 a0 config so if we do 7. not use the MDP for composition i.e. hw composition 0 ask for 8. RGBA instead of RGBX. / 9. if property_getquotdebug.sf.hwquot property NULL gt 0 ampamp atoiproperty 0 10. module-gtfbFormat HAL_PIXEL_FORMAT_RGBX_8888 11. else ifproperty_getquotdebug.composition.typequot property NULL gt 0 ampamp strncmppropertyquotmdpquot 3 0 12. module-gtfbFormat HAL_PIXEL_FORMAT_RGBX_8888 13. else 14. module-gtfbFormat HAL_PIXEL_FORMAT_RGBA_8888 15. else 16. / 17. Explicitly request 5/6/5 18. / 19. module-gtfbFormat HAL_PIXEL_FORMAT_RGB_565 20. 21. 目前的移动设备都是真彩色所以这里我们认为我们的屏幕设备支持的是HAL_PIXEL_FORMAT_RGBA_8888。
3.3.2 config初始化 所有的OpenGL库提供的config同样需要将软硬两种模式的各自的OpenGL config提取出来供系统使用如同OpenGL api地址一样。
OpenGL config提取出来后保存在另外一个全局变量 static egl_display_t gDisplayNUM_DISPLAYS // EGLDisplay are global not attached to a given thread const unsignedint NUM_DISPLAYS 1 中不同于gEGLImpl分开保存软硬件api所有的config不论软硬件的均保存在gDisplay0因为所有的config是以屏幕区分的同一块屏幕应该保存同一份config信息。
在提取出的openGL的config时会保存到gDisplay0.config中在这儿有一个很tricky的实现它保证了硬件加速器的优先使用 1. // sort our configurations so we can do binary-searches 2. qsort dp-gtconfigs 3. dp-gtnumTotalConfigs 4. sizeofegl_config_t cmp_configs 最终上述代码会将gDisplay0.config中的配置按照先硬件的后软件的规则做一个总体的排序。
代码在eglInitializeframeworks/base/opengl/libs/EGL/egl.cpp 3.3.3 config选择 上文说到android会根据framebuffer的pixel format信息来获取对应的config这个过程只选择一个合适的config选到为止。
3.3.3.1 满足属性要求 并不是所有的config都可以被选择首先这个config的属性需要满足 initDisplayHardware.cpp 1. // initialize EGL 2. EGLint attribs 3. EGL_SURFACE_TYPE EGL_WINDOW_BIT 4. EGL_NONE 0 5. EGL_NONE 6. 3.3.3.2 满足RGBA要求 在pixelflinger中为系统提供了各个pixel format的基本信息RGBA值字节数/pixel位数/pixel。
system/core/libpixelflinger/format.cpp 1. static GGLFormat const gPixelFormatInfos 2. // Alpha Red Green Blue 3. 0 0 0 0 0 0 0 0 0 0 0 // PIXEL_FORMAT_NONE 4. 4 32 3224 8 0 16 8 2416 GGL_RGBA // PIXEL_FORMAT_RGBA_8888 android会根据pixelflinger的pixel format信息去和openGL的config比较得到想要的config。
selectConfigForPixelFormatframeworks/base/libs/ui/EGLUtils.cpp 1. EGLConfig const configs EGLConfigmallocsizeofEGLConfignumConfigs 2. if eglChooseConfigdpy attrs configs numConfigs ampn EGL_FALSE 3. freeconfigs 4. return BAD_VALUE 5. 6. 7. const int fbSzA fbFormatInfo.getSizePixelFormatInfo::INDEX_ALPHA 8. const int fbSzR fbFormatInfo.getSizePixelFormatInfo::INDEX_RED 9. const int fbSzG fbFormatInfo.getSizePixelFormatInfo::INDEX_GREEN 10. const int fbSzB fbFormatInfo.getSizePixelFormatInfo::INDEX_BLUE 11. 12. int i 13. EGLConfig config NULL 14. for i0 iltn i 15. EGLint rgba 16. EGLConfig curr configsi 17. eglGetConfigAttribdpy curr EGL_RED_SIZE ampr 18. eglGetConfigAttribdpy curr EGL_GREEN_SIZE ampg 19. eglGetConfigAttribdpy curr EGL_BLUE_SIZE ampb 20. eglGetConfigAttribdpy curr EGL_ALPHA_SIZE ampa 21. if fbSzA lt a ampamp fbSzR lt r ampamp fbSzG lt g ampamp fbSzB lt b 22. config curr 23. break 24. 25. 4. 创建main surface 要让OpenGL进行图形处理那么需要在OpenGL中创建一个openGL surface。
代码在eglCreateWindowSurfaceframeworks/base/opengl/libs/EGL/egl.cpp 调用当前的config所处的openGL库的api来创建surface。
通过validate_display_config方法来获取当前config的openGL api。
创建的surface会和FramebufferNativeWindow关联到一起。
5. 创建 OpenGL ES 上下文 AnOpenGL context represents many things. A context stores all of the state associated with this instance of OpenGL. It represents t.
上一篇:
Android高级开发实战培训
下一篇:
7*30m公路预应力混凝土连续梁桥上部结构设计