Android N之SurfaceFlinger流程解析(3)
来源:互联网 发布:软件系统推广方案 编辑:程序博客网 时间:2024/06/09 16:05
SurfaceFlinger中关于EGL部分的解释:
什么是EGL?
EGL 是 OpenGL ES 和底层 Native 平台视窗系统之间的接口。
EGL的数据类型:
EGLBoolean ——EGL_TRUE =1, EGL_FALSE=0EGLint ——int 数据类型EGLDisplay ——系统显示 ID 或句柄,可以理解为一个前端的显示窗口EGLConfig ——Surface的EGL配置,可以理解为绘制目标framebuffer的配置属性EGLSurface ——系统窗口或 frame buffer 句柄 ,可以理解为一个后端的渲染目标窗口。EGLContext ——OpenGL ES 图形上下文,它代表了OpenGL状态机;如果没有它,OpenGL指令就没有执行的环境。NativeDisplayType——Native 系统显示类型,标识你所开发设备的物理屏幕NativeWindowType ——Native 系统窗口缓存类型,标识系统窗口NativePixmapType ——Native 系统 frame buffer,可以作为 Framebuffer 的系统图像(内存)数据类型,该类型只用于离屏渲染.
EGL的接口介绍:
1.获取Display
EGLDisplay eglGetDisplay(EGLNativeDisplayType display){ clearError(); uintptr_t index = reinterpret_cast<uintptr_t>(display); if (index >= NUM_DISPLAYS) { return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); } if (egl_init_drivers() == EGL_FALSE) { return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); } EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display); return dpy;}
获得Display要调用EGLboolean eglGetDisplay(NativeDisplay dpy),参数一般为 EGL_DEFAULT_DISPLAY 。
2.初始化egl
EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor){ clearError(); egl_display_ptr dp = get_display(dpy); if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); EGLBoolean res = dp->initialize(major, minor); return res;}
调用 EGLboolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor),主要是做EGL初始化的工作。
3.选择Config
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;}
用EGLboolean eglGetConfigs(EGLDisplay dpy, EGLConfig * config, EGLint config_size, EGLint *num_config) 来获得所有config。然后会将获取到的Config结果保存在config[]中,而获取到的Config个数保存 在num_config中,调用eglGetConfig()来查询系统支持的Config总个数。
4.构造Surface
EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list){ clearError(); egl_connection_t* cnx = NULL; egl_display_ptr dp = validate_display_connection(dpy, cnx); if (dp) { EGLDisplay iDpy = dp->disp.dpy; int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL); if (result != OK) { ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) " "failed (%#x) (already connected to another API?)", window, result); return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); } // Set the native window's buffers format to match what this config requests. // Whether to use sRGB gamma is not part of the EGLconfig, but is part // of our native format. So if sRGB gamma is requested, we have to // modify the EGLconfig's format before setting the native window's // format. // by default, just pick RGBA_8888 EGLint format = HAL_PIXEL_FORMAT_RGBA_8888; android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN; EGLint a = 0; cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a); if (a > 0) { // alpha-channel requested, there's really only one suitable format format = HAL_PIXEL_FORMAT_RGBA_8888; } else { EGLint r, g, b; r = g = b = 0; cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE, &r); cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g); cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE, &b); EGLint colorDepth = r + g + b; if (colorDepth <= 16) { format = HAL_PIXEL_FORMAT_RGB_565; } else { format = HAL_PIXEL_FORMAT_RGBX_8888; } } // now select a corresponding sRGB format if needed if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) { for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) { if (*attr == EGL_GL_COLORSPACE_KHR) { if (ENABLE_EGL_KHR_GL_COLORSPACE) { dataSpace = modifyBufferDataspace(dataSpace, *(attr+1)); } else { // Normally we'd pass through unhandled attributes to // the driver. But in case the driver implements this // extension but we're disabling it, we want to prevent // it getting through -- support will be broken without // our help. ALOGE("sRGB window surfaces not supported"); return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); } } } } if (format != 0) { int err = native_window_set_buffers_format(window, format); if (err != 0) { ALOGE("error setting native window pixel format: %s (%d)", strerror(-err), err); native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); } } if (dataSpace != 0) { int err = native_window_set_buffers_data_space(window, dataSpace); if (err != 0) { ALOGE("error setting native window pixel dataSpace: %s (%d)", strerror(-err), err); native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); } } // the EGL spec requires that a new EGLSurface default to swap interval // 1, so explicitly set that on the window here. ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window); anw->setSwapInterval(anw, 1); EGLSurface surface = cnx->egl.eglCreateWindowSurface( iDpy, config, window, attrib_list); if (surface != EGL_NO_SURFACE) { egl_surface_t* s = new egl_surface_t(dp.get(), config, window, surface, cnx); return s; } // EGLSurface creation failed native_window_set_buffers_format(window, 0); native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); } return EGL_NO_SURFACE;}
调用EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig confg, NativeWindow win, EGLint *cfg_attr)来创建一个Surface,其实这个Surface实际上就是一个FrameBuffer,也是后面渲染的目标。
5.创建Context
EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list){ clearError(); egl_connection_t* cnx = NULL; const egl_display_ptr dp = validate_display_connection(dpy, cnx); if (dp) { if (share_list != EGL_NO_CONTEXT) { if (!ContextRef(dp.get(), share_list).get()) { return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT); } egl_context_t* const c = get_context(share_list); share_list = c->context; } EGLContext context = cnx->egl.eglCreateContext( dp->disp.dpy, config, share_list, attrib_list); if (context != EGL_NO_CONTEXT) { // figure out if it's a GLESv1 or GLESv2 int version = 0; if (attrib_list) { while (*attrib_list != EGL_NONE) { GLint attr = *attrib_list++; GLint value = *attrib_list++; if (attr == EGL_CONTEXT_CLIENT_VERSION) { if (value == 1) { version = egl_connection_t::GLESv1_INDEX; } else if (value == 2 || value == 3) { version = egl_connection_t::GLESv2_INDEX; } } }; } egl_context_t* c = new egl_context_t(dpy, context, config, cnx, version); return c; } } return EGL_NO_CONTEXT;}
6.送显
EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface){ return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0);}
7.EGL变量之间的绑定
EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx){ if (egl_display_t::is_valid(dpy) == EGL_FALSE) return setError(EGL_BAD_DISPLAY, EGL_FALSE); if (draw) { egl_surface_t* s = (egl_surface_t*)draw; if (!s->isValid()) return setError(EGL_BAD_SURFACE, EGL_FALSE); if (s->dpy != dpy) return setError(EGL_BAD_DISPLAY, EGL_FALSE); // TODO: check that draw is compatible with the context } if (read && read!=draw) { egl_surface_t* s = (egl_surface_t*)read; if (!s->isValid()) return setError(EGL_BAD_SURFACE, EGL_FALSE); if (s->dpy != dpy) return setError(EGL_BAD_DISPLAY, EGL_FALSE); // TODO: check that read is compatible with the context } EGLContext current_ctx = EGL_NO_CONTEXT; if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT)) return setError(EGL_BAD_MATCH, EGL_FALSE); if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT)) return setError(EGL_BAD_MATCH, EGL_FALSE); if (ctx == EGL_NO_CONTEXT) { // if we're detaching, we need the current context current_ctx = (EGLContext)getGlThreadSpecific(); } else { egl_context_t* c = egl_context_t::context(ctx); egl_surface_t* d = (egl_surface_t*)draw; egl_surface_t* r = (egl_surface_t*)read; if ((d && d->ctx && d->ctx != ctx) || (r && r->ctx && r->ctx != ctx)) { // one of the surface is bound to a context in another thread return setError(EGL_BAD_ACCESS, EGL_FALSE); } } ogles_context_t* gl = (ogles_context_t*)ctx; if (makeCurrent(gl) == 0) { if (ctx) { egl_context_t* c = egl_context_t::context(ctx); egl_surface_t* d = (egl_surface_t*)draw; egl_surface_t* r = (egl_surface_t*)read; if (c->draw) { egl_surface_t* s = reinterpret_cast<egl_surface_t*>(c->draw); s->disconnect(); s->ctx = EGL_NO_CONTEXT; if (s->zombie) delete s; } if (c->read) { // FIXME: unlock/disconnect the read surface too } c->draw = draw; c->read = read; if (c->flags & egl_context_t::NEVER_CURRENT) { c->flags &= ~egl_context_t::NEVER_CURRENT; GLint w = 0; GLint h = 0; if (draw) { w = d->getWidth(); h = d->getHeight(); } ogles_surfaceport(gl, 0, 0); ogles_viewport(gl, 0, 0, w, h); ogles_scissor(gl, 0, 0, w, h); } if (d) { if (d->connect() == EGL_FALSE) { return EGL_FALSE; } d->ctx = ctx; d->bindDrawSurface(gl); } if (r) { // FIXME: lock/connect the read surface too r->ctx = ctx; r->bindReadSurface(gl); } } else { // if surfaces were bound to the context bound to this thread // mark then as unbound. if (current_ctx) { egl_context_t* c = egl_context_t::context(current_ctx); egl_surface_t* d = (egl_surface_t*)c->draw; egl_surface_t* r = (egl_surface_t*)c->read; if (d) { c->draw = 0; d->disconnect(); d->ctx = EGL_NO_CONTEXT; if (d->zombie) delete d; } if (r) { c->read = 0; r->ctx = EGL_NO_CONTEXT; // FIXME: unlock/disconnect the read surface too } } } return EGL_TRUE; } return setError(EGL_BAD_ACCESS, EGL_FALSE);}
该接口将申请到的display,draw(surface)和 context进行了绑定。也就是说,在context下的OpenGL API指令将draw(surface)作为其渲染最终目的地。而display作为draw(surface)的前端显示。调用后,当前线程使用的EGLContex为context。
- Android N之SurfaceFlinger流程解析(3)
- Android N之SurfaceFlinger流程解析(1)
- Android N之SurfaceFlinger流程解析(2)
- Android N之SurfaceFlinger流程解析(4)
- Android N之SurfaceFlinger流程解析(5)
- Android N之SurfaceFlinger流程解析(6)
- Android SurfaceFlinger process 流程分析
- Android SurfaceFlinger VSync流程分析
- 【Android】Android SurfaceFlinger之SurfaceFlinger启动过程
- Android GDI之SurfaceFlinger
- Android GDI之SurfaceFlinger
- Android SurfaceFlinger之SurfaceFlinger启动过程
- android graphic(3)—surfaceflinger的启动流程
- android graphic(3)—surfaceflinger的启动流程
- 【Android】Android SurfaceFlinger之Gralloc
- 【Android】Android SurfaceFlinger之NativeWindow
- 【Android】Android SurfaceFlinger之BufferQueue
- 【Android】Android SurfaceFlinger之VSync
- 进程调度算法之FCFS
- android 购物车
- Darwin Streaming Server for Windows 安裝
- 使用Apache POI导出Excel数据有BUG
- 分类算法之决策树(Decision tree)
- Android N之SurfaceFlinger流程解析(3)
- 微商公社新兵连第四天
- 集合框架_Collection集合的高级功能测试
- Linux卸载home独立分区
- 第十五周 oj训练 C语言习题 字符串长度
- ThoughtBot 的Git 使用规范流程
- [jFinal]动态网络工程开发环境配置
- 单例模式的几种实现方式总结
- Leetcode 287. Find the Duplicate Number O(n)解法和O(nlogn)解法