Android N之SurfaceFlinger流程解析(6)
来源:互联网 发布:剑三代练淘宝下单好吗 编辑:程序博客网 时间:2024/06/05 10:43
今天晚上来看了一下在SurfaceFlinger类中的成员函数init中的关于创建RenderEngine的部分,首先看一下源码:
RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat) { // EGL_ANDROIDX_no_config_context is an experimental extension with no // written specification. It will be replaced by something more formal. // SurfaceFlinger is using it to allow a single EGLContext to render to // both a 16-bit primary display framebuffer and a 32-bit virtual display // framebuffer. // // The code assumes that ES2 or later is available if this extension is // supported. EGLConfig config = EGL_NO_CONFIG; if (!findExtension( eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS), "EGL_ANDROIDX_no_config_context")) { config = chooseEglConfig(display, hwcFormat); } EGLint renderableType = 0; if (config == EGL_NO_CONFIG) { renderableType = EGL_OPENGL_ES2_BIT; } else if (!eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType)) { LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE"); } EGLint contextClientVersion = 0; if (renderableType & EGL_OPENGL_ES2_BIT) { contextClientVersion = 2; } else if (renderableType & EGL_OPENGL_ES_BIT) { contextClientVersion = 1; } else { LOG_ALWAYS_FATAL("no supported EGL_RENDERABLE_TYPEs"); } // Also create our EGLContext EGLint contextAttributes[] = { EGL_CONTEXT_CLIENT_VERSION, contextClientVersion, // MUST be first#ifdef EGL_IMG_context_priority#ifdef HAS_CONTEXT_PRIORITY#warning "using EGL_IMG_context_priority" EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_HIGH_IMG,#endif#endif EGL_NONE, EGL_NONE }; EGLContext ctxt = eglCreateContext(display, config, NULL, contextAttributes); // if can't create a GL context, we can only abort. LOG_ALWAYS_FATAL_IF(ctxt==EGL_NO_CONTEXT, "EGLContext creation failed"); // now figure out what version of GL did we actually get // NOTE: a dummy surface is not needed if KHR_create_context is supported EGLConfig dummyConfig = config; if (dummyConfig == EGL_NO_CONFIG) { dummyConfig = chooseEglConfig(display, hwcFormat); } EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE }; EGLSurface dummy = eglCreatePbufferSurface(display, dummyConfig, attribs); LOG_ALWAYS_FATAL_IF(dummy==EGL_NO_SURFACE, "can't create dummy pbuffer"); EGLBoolean success = eglMakeCurrent(display, dummy, dummy, ctxt); LOG_ALWAYS_FATAL_IF(!success, "can't make dummy pbuffer current"); GLExtensions& extensions(GLExtensions::getInstance()); extensions.initWithGLStrings( glGetString(GL_VENDOR), glGetString(GL_RENDERER), glGetString(GL_VERSION), glGetString(GL_EXTENSIONS)); GlesVersion version = parseGlesVersion( extensions.getVersion() ); // initialize the renderer while GL is current RenderEngine* engine = NULL; switch (version) { case GLES_VERSION_1_0: engine = new GLES10RenderEngine(); break; case GLES_VERSION_1_1: engine = new GLES11RenderEngine(); break; case GLES_VERSION_2_0: case GLES_VERSION_3_0: engine = new GLES20RenderEngine(); break; } engine->setEGLHandles(config, ctxt); ALOGI("OpenGL ES informations:"); ALOGI("vendor : %s", extensions.getVendor()); ALOGI("renderer : %s", extensions.getRenderer()); ALOGI("version : %s", extensions.getVersion()); ALOGI("extensions: %s", extensions.getExtension()); ALOGI("GL_MAX_TEXTURE_SIZE = %zu", engine->getMaxTextureSize()); ALOGI("GL_MAX_VIEWPORT_DIMS = %zu", engine->getMaxViewportDims()); eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroySurface(display, dummy); return engine;}
如果觉得一开始看代码不舒服的话,我们先来看一下示意图。
下面来继续分析在创建RenderEngine中的几个主要的函数:
1.chooseEglConfig
首先大概看一下chooseEglConfig的结构:
分别介绍一下其中涉及到的EGL的接口:
eglGetConfigs:
此函数用来获取显示设备支持的配置,其参数含义如下:
EGLBoolean eglGetConfigs(EGLDisplay display, // 已初始化好 EGLConfig* configs, // 如果为NULL,则返回EGL_TRUE和numConfigs,即图形系统所有可用的配置 EGLint maxConfigs, // 上面那个configs数组的容量 EGLint* numConfigs); // 图形系统返回的实际的可用的配置个数,存储在configs数组里
该函数源代码如下:
EGLBoolean eglGetConfigs( EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config){ clearError(); const egl_display_ptr dp = validate_display(dpy); if (!dp) return EGL_FALSE; if (num_config==0) { return setError(EGL_BAD_PARAMETER, EGL_FALSE); } EGLBoolean res = EGL_FALSE; *num_config = 0; egl_connection_t* const cnx = &gEGLImpl; if (cnx->dso) { res = cnx->egl.eglGetConfigs( dp->disp.dpy, configs, config_size, num_config); } return res;}
eglChooseConfig:
此函数的工作主要是查询底层窗口系统支持的所有EGL表面配置,通过configAttributes []指定的需求,EGL返回最佳的配置列表。首先返回最佳配置的个数,然后分配空间存储返回分配置列表数组。然后选择RGB,深度最匹配的配置。
其参数的设置如下:
EGLBoolean eglChooseConfig(EGLDisplay display, const EGLint* attribs, // 你想要的属性事先定义到这个数组里 EGLConfig* configs, // 图形系统将返回若干满足条件的配置到该数组 EGLint maxConfigs, // 上面数组的容量 EGLint* numConfigs); // 图形系统返回的可用的配置个数
其源码如下:
EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config){ clearError(); const egl_display_ptr dp = validate_display(dpy); if (!dp) return EGL_FALSE; if (num_config==0) { return setError(EGL_BAD_PARAMETER, EGL_FALSE); } EGLBoolean res = EGL_FALSE; *num_config = 0; egl_connection_t* const cnx = &gEGLImpl; if (cnx->dso) { if (attrib_list) { char value[PROPERTY_VALUE_MAX]; property_get("debug.egl.force_msaa", value, "false"); if (!strcmp(value, "true")) { size_t attribCount = 0; EGLint attrib = attrib_list[0]; // Only enable MSAA if the context is OpenGL ES 2.0 and // if no caveat is requested const EGLint *attribRendererable = NULL; const EGLint *attribCaveat = NULL; // Count the number of attributes and look for // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT while (attrib != EGL_NONE) { attrib = attrib_list[attribCount]; switch (attrib) { case EGL_RENDERABLE_TYPE: attribRendererable = &attrib_list[attribCount]; break; case EGL_CONFIG_CAVEAT: attribCaveat = &attrib_list[attribCount]; break; } attribCount++; } if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT && (!attribCaveat || attribCaveat[1] != EGL_NONE)) { // Insert 2 extra attributes to force-enable MSAA 4x EGLint aaAttribs[attribCount + 4]; aaAttribs[0] = EGL_SAMPLE_BUFFERS; aaAttribs[1] = 1; aaAttribs[2] = EGL_SAMPLES; aaAttribs[3] = 4; memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint)); EGLint numConfigAA; EGLBoolean resAA = cnx->egl.eglChooseConfig( dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA); if (resAA == EGL_TRUE && numConfigAA > 0) { ALOGD("Enabling MSAA 4x"); *num_config = numConfigAA; return resAA; } } } } res = cnx->egl.eglChooseConfig( dp->disp.dpy, attrib_list, configs, config_size, num_config); } return res;}
eglGetConfigAttrib:
此函数的作用主要是查询指定配置的指定属性,其函数的参数定义如下:
EGLBoolean eglGetConfigAttrib(EGLDisplay display, // 已初始化 EGLConfig config, // 某个配置 EGLint attribute, // 某个属性 EGLint * value);
其源码如下:
EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value){ clearError(); egl_connection_t* cnx = NULL; const egl_display_ptr dp = validate_display_connection(dpy, cnx); if (!dp) return EGL_FALSE; return cnx->egl.eglGetConfigAttrib( dp->disp.dpy, config, attribute, value);}
以上为chooseEglConfig中的分析结果。
2.eglCreateContext
其主要的作用是创建渲染上下文,
EGLContext eglCreateContext(EGLDisplay display, EGLConfig config, EGLContext context, // EGL_NO_CONTEXT表示不向其它的context共享资源 const EGLint * attribs)
3.eglCreatePbufferSurface:主要是创建在显存中的帧
4.eglMakeCurrent:指定EGLcontext为当前上下文
5.eglDestroySurface:释放Surface相关资源
感觉这篇文章主要在解释egl的接口了,下次抽时间好好看一下egl的接口的实现。
0 0
- Android N之SurfaceFlinger流程解析(6)
- Android N之SurfaceFlinger流程解析(1)
- Android N之SurfaceFlinger流程解析(2)
- Android N之SurfaceFlinger流程解析(3)
- Android N之SurfaceFlinger流程解析(4)
- Android N之SurfaceFlinger流程解析(5)
- Android SurfaceFlinger process 流程分析
- Android SurfaceFlinger VSync流程分析
- 【Android】Android SurfaceFlinger之SurfaceFlinger启动过程
- Android GDI之SurfaceFlinger
- Android GDI之SurfaceFlinger
- Android SurfaceFlinger之SurfaceFlinger启动过程
- 【Android】Android SurfaceFlinger之Gralloc
- 【Android】Android SurfaceFlinger之NativeWindow
- 【Android】Android SurfaceFlinger之BufferQueue
- 【Android】Android SurfaceFlinger之VSync
- Android SurfaceFlinger 学习之路(三)----Android开机动画流程简述
- Android surfaceflinger (4) -Vsync产生上报流程
- CSS3新vw, vh单位
- 马尔可夫平稳过程到MCMC采样
- android中px与sp,dp之间的转换
- 1983 等式问题
- linux学习第一天
- Android N之SurfaceFlinger流程解析(6)
- SqueezeNet运用到Faster RCNN进行目标检测+OHEM
- angularJs 取<input type='file'>中文件名 (ng-model获取不了)
- 归并排序
- 排序学习
- 单例模式
- Bridge 模式
- Simplify Path
- codeforces 743D Chloe and pleasant prizes (DFS/树形DP)