diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index ceae8d789..b3650bdcf 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -237,10 +237,10 @@ void SurfaceFlinger::deleteTextureAsync(GLuint texture) { postMessageAsync(new MessageDestroyGLTexture(texture)); } -status_t SurfaceFlinger::selectConfigForPixelFormat( +status_t SurfaceFlinger::selectConfigForAttribute( EGLDisplay dpy, EGLint const* attrs, - PixelFormat format, + EGLint attribute, EGLint wanted, EGLConfig* outConfig) { EGLConfig config = NULL; @@ -249,11 +249,20 @@ status_t SurfaceFlinger::selectConfigForPixelFormat( EGLConfig* const configs = new EGLConfig[numConfigs]; eglChooseConfig(dpy, attrs, configs, numConfigs, &n); - for (int i=0 ; i0 && format == nativeVisualId) { - *outConfig = configs[i]; + if (n) { + if (attribute != EGL_NONE) { + for (int i=0 ; i mList; + struct Attribute { + Attribute() {}; + Attribute(EGLint v) : v(v) { } + EGLint v; + bool operator < (const Attribute& other) const { + // this places EGL_NONE at the end + EGLint lhs(v); + EGLint rhs(other.v); + if (lhs == EGL_NONE) lhs = 0x7FFFFFFF; + if (rhs == EGL_NONE) rhs = 0x7FFFFFFF; + return lhs < rhs; + } + }; + class Adder { + friend class EGLAttributeVector; + EGLAttributeVector& v; + EGLint attribute; + Adder(EGLAttributeVector& v, EGLint attribute) + : v(v), attribute(attribute) { + } + public: + void operator = (EGLint value) { + if (attribute != EGL_NONE) { + v.mList.add(attribute, value); + } + } + operator EGLint () const { return v.mList[attribute]; } + }; +public: + EGLAttributeVector() { + mList.add(EGL_NONE, EGL_NONE); + } + void remove(EGLint attribute) { + if (attribute != EGL_NONE) { + mList.removeItem(attribute); + } + } + Adder operator [] (EGLint attribute) { + return Adder(*this, attribute); + } + EGLint operator [] (EGLint attribute) const { + return mList[attribute]; + } + // cast-operator to (EGLint const*) + operator EGLint const* () const { return &mList.keyAt(0).v; } +}; + EGLConfig SurfaceFlinger::selectEGLConfig(EGLDisplay display, EGLint nativeVisualId) { // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if // it is to be used with WIFI displays @@ -269,32 +330,42 @@ EGLConfig SurfaceFlinger::selectEGLConfig(EGLDisplay display, EGLint nativeVisua EGLint dummy; status_t err; - EGLint attribs[] = { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - // The rest of the attributes must be in this order and at the end - // of the list; we rely on that for fallback searches below. - EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_RECORDABLE_ANDROID, EGL_TRUE, - EGL_NONE - }; - err = selectConfigForPixelFormat(display, attribs, nativeVisualId, &config); + EGLAttributeVector attribs; + attribs[EGL_SURFACE_TYPE] = EGL_WINDOW_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; + + err = selectConfigForAttribute(display, attribs, EGL_NONE, EGL_NONE, &config); + if (!err) + goto success; + + // maybe we failed because of EGL_FRAMEBUFFER_TARGET_ANDROID + ALOGW("no suitable EGLConfig found, trying without EGL_FRAMEBUFFER_TARGET_ANDROID"); + attribs.remove(EGL_FRAMEBUFFER_TARGET_ANDROID); + err = selectConfigForAttribute(display, attribs, + EGL_NATIVE_VISUAL_ID, nativeVisualId, &config); if (!err) goto success; // maybe we failed because of EGL_RECORDABLE_ANDROID ALOGW("no suitable EGLConfig found, trying without EGL_RECORDABLE_ANDROID"); - attribs[NELEM(attribs) - 3] = EGL_NONE; - err = selectConfigForPixelFormat(display, attribs, nativeVisualId, &config); + attribs.remove(EGL_RECORDABLE_ANDROID); + err = selectConfigForAttribute(display, attribs, + EGL_NATIVE_VISUAL_ID, nativeVisualId, &config); if (!err) goto success; // allow less than 24-bit color; the non-gpu-accelerated emulator only // supports 16-bit color ALOGW("no suitable EGLConfig found, trying with 16-bit color allowed"); - attribs[NELEM(attribs) - 9] = EGL_NONE; - err = selectConfigForPixelFormat(display, attribs, nativeVisualId, &config); + 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; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 0a019ceec..e5b939d5e 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -309,8 +309,8 @@ private: /* ------------------------------------------------------------------------ * EGL */ - static status_t selectConfigForPixelFormat(EGLDisplay dpy, - EGLint const* attrs, PixelFormat format, EGLConfig* outConfig); + static status_t selectConfigForAttribute(EGLDisplay dpy, + EGLint const* attrs, EGLint attribute, EGLint value, EGLConfig* outConfig); static EGLConfig selectEGLConfig(EGLDisplay disp, EGLint visualId); static EGLContext createGLContext(EGLDisplay disp, EGLConfig config); void initializeGL(EGLDisplay display);