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
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index 46f628d..c36fcde 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -30,9 +30,25 @@
// ---------------------------------------------------------------------------
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 @@
#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 def4618..02aef2b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -366,43 +366,40 @@
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 @@
mHwc = new HWComposer(this,
*static_cast<HWComposer::EventHandler *>(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 347e3e3..0cfc600 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -317,7 +317,8 @@
*/
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;