From 2185f8b420ee1b150f761893a9c47cffff645cde Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 18 Sep 2013 16:20:26 -0700 Subject: [PATCH] Fix GLES context version selection Explicitly selects an ES 2.0 config first, then an ES 1.x config, before attempting the fallback path for the emulator. Bug: 10820214 Change-Id: Ia8cc084c02a0e3de910def024da8a08d02bbd89d --- .../RenderEngine/RenderEngine.cpp | 24 +++++-- services/surfaceflinger/SurfaceFlinger.cpp | 70 +++++++++++-------- services/surfaceflinger/SurfaceFlinger.h | 3 +- 3 files changed, 61 insertions(+), 36 deletions(-) diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp index 46f628dd8..c36fcde3f 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp @@ -30,9 +30,25 @@ namespace android { // --------------------------------------------------------------------------- RenderEngine* RenderEngine::create(EGLDisplay display, EGLConfig config) { + EGLint renderableType = 0; + EGLint contextClientVersion = 0; + + // query the renderable type, setting the EGL_CONTEXT_CLIENT_VERSION accordingly + if (!eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType)) { + LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE"); + } + + 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, 2, // MUST be first + EGL_CONTEXT_CLIENT_VERSION, contextClientVersion, // MUST be first #ifdef EGL_IMG_context_priority #ifdef HAS_CONTEXT_PRIORITY #warning "using EGL_IMG_context_priority" @@ -41,13 +57,7 @@ RenderEngine* RenderEngine::create(EGLDisplay display, EGLConfig config) { #endif EGL_NONE, EGL_NONE }; - EGLContext ctxt = eglCreateContext(display, config, NULL, contextAttributes); - if (ctxt == EGL_NO_CONTEXT) { - // maybe ES 2.x is not supported - ALOGW("can't create an ES 2.x context, trying 1.x"); - ctxt = eglCreateContext(display, config, NULL, contextAttributes + 2); - } // if can't create a GL context, we can only abort. LOG_ALWAYS_FATAL_IF(ctxt==EGL_NO_CONTEXT, "EGLContext creation failed"); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index def461811..02aef2b27 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -366,43 +366,40 @@ public: operator EGLint const* () const { return &mList.keyAt(0).v; } }; -EGLConfig SurfaceFlinger::selectEGLConfig(EGLDisplay display, EGLint nativeVisualId) { +EGLConfig SurfaceFlinger::selectEGLConfig(EGLDisplay display, EGLint nativeVisualId, + EGLint renderableType) { // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if // it is to be used with WIFI displays EGLConfig config; EGLint dummy; status_t err; + EGLint wantedAttribute; + EGLint wantedAttributeValue; EGLAttributeVector attribs; - // TODO: enable ES2 - //attribs[EGL_RENDERABLE_TYPE] = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT; - attribs[EGL_SURFACE_TYPE] = EGL_WINDOW_BIT | EGL_PBUFFER_BIT; - attribs[EGL_RECORDABLE_ANDROID] = EGL_TRUE; - attribs[EGL_FRAMEBUFFER_TARGET_ANDROID] = EGL_TRUE; - attribs[EGL_RED_SIZE] = 8; - attribs[EGL_GREEN_SIZE] = 8; - attribs[EGL_BLUE_SIZE] = 8; + if (renderableType) { + attribs[EGL_RENDERABLE_TYPE] = renderableType; + attribs[EGL_RECORDABLE_ANDROID] = EGL_TRUE; + attribs[EGL_SURFACE_TYPE] = EGL_WINDOW_BIT|EGL_PBUFFER_BIT; + attribs[EGL_FRAMEBUFFER_TARGET_ANDROID] = EGL_TRUE; + attribs[EGL_RED_SIZE] = 8; + attribs[EGL_GREEN_SIZE] = 8; + attribs[EGL_BLUE_SIZE] = 8; + wantedAttribute = EGL_NONE; + wantedAttributeValue = EGL_NONE; - err = selectConfigForAttribute(display, attribs, EGL_NONE, EGL_NONE, &config); + } else { + // if no renderable type specified, fallback to a simplified query + attribs[EGL_RECORDABLE_ANDROID] = EGL_TRUE; + wantedAttribute = EGL_NATIVE_VISUAL_ID; + wantedAttributeValue = nativeVisualId; + } + + err = selectConfigForAttribute(display, attribs, wantedAttribute, + wantedAttributeValue, &config); if (!err) goto success; - // this didn't work, probably because we're on the emulator... - // try a simplified query - ALOGW("no suitable EGLConfig found, trying a simpler query"); - attribs.remove(EGL_RENDERABLE_TYPE); - attribs.remove(EGL_FRAMEBUFFER_TARGET_ANDROID); - attribs.remove(EGL_RECORDABLE_ANDROID); - attribs.remove(EGL_RED_SIZE); - attribs.remove(EGL_GREEN_SIZE); - attribs.remove(EGL_BLUE_SIZE); - err = selectConfigForAttribute(display, attribs, - EGL_NATIVE_VISUAL_ID, nativeVisualId, &config); - if (!err) - goto success; - - // this EGL is too lame for Android - LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up"); return 0; success: @@ -427,8 +424,25 @@ void SurfaceFlinger::init() { mHwc = new HWComposer(this, *static_cast(this)); - // initialize the config and context (can't fail) - mEGLConfig = selectEGLConfig(mEGLDisplay, mHwc->getVisualID()); + // First try to get an ES2 config + mEGLConfig = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), EGL_OPENGL_ES2_BIT); + + if (!mEGLConfig) { + // If ES2 fails, try ES1 + mEGLConfig = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), EGL_OPENGL_ES_BIT); + } + + if (!mEGLConfig) { + // still didn't work, probably because we're on the emulator... + // try a simplified query + ALOGW("no suitable EGLConfig found, trying a simpler query"); + mEGLConfig = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), 0); + } + + if (!mEGLConfig) { + // this EGL is too lame for android + LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up"); + } // print some debugging info EGLint r,g,b,a; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 347e3e360..0cfc6004e 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -317,7 +317,8 @@ private: */ static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs, EGLint attribute, EGLint value, EGLConfig* outConfig); - static EGLConfig selectEGLConfig(EGLDisplay disp, EGLint visualId); + static EGLConfig selectEGLConfig(EGLDisplay disp, EGLint visualId, + EGLint renderableType); size_t getMaxTextureSize() const; size_t getMaxViewportDims() const;