Move EGLConfig selection to RenderEngine

Bug: 12230666
Change-Id: I8d1111a7e0fd9d9e2525e6a80da8ce46d7dd085d
Signed-off-by: Jesse Hall <jessehall@google.com>
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index ba82cad..759839b 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -29,7 +29,9 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
-RenderEngine* RenderEngine::create(EGLDisplay display, EGLConfig config) {
+RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat) {
+    EGLConfig config = chooseEglConfig(display, hwcFormat);
+
     EGLint renderableType = 0;
     EGLint contextClientVersion = 0;
 
@@ -96,7 +98,7 @@
         engine = new GLES20RenderEngine();
         break;
     }
-    engine->setEGLContext(ctxt);
+    engine->setEGLHandles(config, ctxt);
 
     ALOGI("OpenGL ES informations:");
     ALOGI("vendor    : %s", extensions.getVendor());
@@ -118,10 +120,15 @@
 RenderEngine::~RenderEngine() {
 }
 
-void RenderEngine::setEGLContext(EGLContext ctxt) {
+void RenderEngine::setEGLHandles(EGLConfig config, EGLContext ctxt) {
+    mEGLConfig = config;
     mEGLContext = ctxt;
 }
 
+EGLContext RenderEngine::getEGLConfig() const {
+    return mEGLConfig;
+}
+
 EGLContext RenderEngine::getEGLContext() const {
     return mEGLContext;
 }
@@ -235,5 +242,163 @@
 }
 
 // ---------------------------------------------------------------------------
+
+static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs,
+        EGLint attribute, EGLint wanted, EGLConfig* outConfig) {
+    EGLConfig config = NULL;
+    EGLint numConfigs = -1, n = 0;
+    eglGetConfigs(dpy, NULL, 0, &numConfigs);
+    EGLConfig* const configs = new EGLConfig[numConfigs];
+    eglChooseConfig(dpy, attrs, configs, numConfigs, &n);
+
+    if (n) {
+        if (attribute != EGL_NONE) {
+            for (int i=0 ; i<n ; i++) {
+                EGLint value = 0;
+                eglGetConfigAttrib(dpy, configs[i], attribute, &value);
+                if (wanted == value) {
+                    *outConfig = configs[i];
+                    delete [] configs;
+                    return NO_ERROR;
+                }
+            }
+        } else {
+            // just pick the first one
+            *outConfig = configs[0];
+            delete [] configs;
+            return NO_ERROR;
+        }
+    }
+    delete [] configs;
+    return NAME_NOT_FOUND;
+}
+
+class EGLAttributeVector {
+    struct Attribute;
+    class Adder;
+    friend class Adder;
+    KeyedVector<Attribute, EGLint> 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; }
+};
+
+
+static status_t selectEGLConfig(EGLDisplay display, EGLint format,
+    EGLint renderableType, EGLConfig* config) {
+    // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if
+    // it is to be used with WIFI displays
+    status_t err;
+    EGLint wantedAttribute;
+    EGLint wantedAttributeValue;
+
+    EGLAttributeVector attribs;
+    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;
+    } else {
+        // if no renderable type specified, fallback to a simplified query
+        wantedAttribute                         = EGL_NATIVE_VISUAL_ID;
+        wantedAttributeValue                    = format;
+    }
+
+    err = selectConfigForAttribute(display, attribs,
+            wantedAttribute, wantedAttributeValue, config);
+    if (err == NO_ERROR) {
+        EGLint caveat;
+        if (eglGetConfigAttrib(display, *config, EGL_CONFIG_CAVEAT, &caveat))
+            ALOGW_IF(caveat == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!");
+    }
+
+    return err;
+}
+
+EGLConfig RenderEngine::chooseEglConfig(EGLDisplay display, int format) {
+    status_t err;
+    EGLConfig config;
+
+    // First try to get an ES2 config
+    err = selectEGLConfig(display, format, EGL_OPENGL_ES2_BIT, &config);
+    if (err != NO_ERROR) {
+        // If ES2 fails, try ES1
+        err = selectEGLConfig(display, format, EGL_OPENGL_ES_BIT, &config);
+        if (err != NO_ERROR) {
+            // still didn't work, probably because we're on the emulator...
+            // try a simplified query
+            ALOGW("no suitable EGLConfig found, trying a simpler query");
+            err = selectEGLConfig(display, format, 0, &config);
+            if (err != NO_ERROR) {
+                // 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;
+    eglGetConfigAttrib(display, config, EGL_RED_SIZE,   &r);
+    eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
+    eglGetConfigAttrib(display, config, EGL_BLUE_SIZE,  &b);
+    eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
+    ALOGI("EGL information:");
+    ALOGI("vendor    : %s", eglQueryString(display, EGL_VENDOR));
+    ALOGI("version   : %s", eglQueryString(display, EGL_VERSION));
+    ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS));
+    ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
+    ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
+
+    return config;
+}
+
+// ---------------------------------------------------------------------------
 }; // namespace android
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 3c7f9ab..4dc9457 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -44,8 +44,9 @@
     };
     static GlesVersion parseGlesVersion(const char* str);
 
+    EGLConfig mEGLConfig;
     EGLContext mEGLContext;
-    void setEGLContext(EGLContext ctxt);
+    void setEGLHandles(EGLConfig config, EGLContext ctxt);
 
     virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName, uint32_t* status) = 0;
     virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName) = 0;
@@ -55,7 +56,9 @@
     virtual ~RenderEngine() = 0;
 
 public:
-    static RenderEngine* create(EGLDisplay display, EGLConfig config);
+    static RenderEngine* create(EGLDisplay display, int hwcFormat);
+
+    static EGLConfig chooseEglConfig(EGLDisplay display, int format);
 
     // dump the extension strings. always call the base class.
     virtual void dump(String8& result);
@@ -107,6 +110,7 @@
     virtual size_t getMaxTextureSize() const = 0;
     virtual size_t getMaxViewportDims() const = 0;
 
+    EGLConfig getEGLConfig() const;
     EGLContext getEGLContext() const;
 };
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 9d94c87..ec64390 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -318,128 +318,6 @@
     postMessageAsync(new MessageDestroyGLTexture(getRenderEngine(), texture));
 }
 
-status_t SurfaceFlinger::selectConfigForAttribute(
-        EGLDisplay dpy,
-        EGLint const* attrs,
-        EGLint attribute, EGLint wanted,
-        EGLConfig* outConfig)
-{
-    EGLConfig config = NULL;
-    EGLint numConfigs = -1, n=0;
-    eglGetConfigs(dpy, NULL, 0, &numConfigs);
-    EGLConfig* const configs = new EGLConfig[numConfigs];
-    eglChooseConfig(dpy, attrs, configs, numConfigs, &n);
-
-    if (n) {
-        if (attribute != EGL_NONE) {
-            for (int i=0 ; i<n ; i++) {
-                EGLint value = 0;
-                eglGetConfigAttrib(dpy, configs[i], attribute, &value);
-                if (wanted == value) {
-                    *outConfig = configs[i];
-                    delete [] configs;
-                    return NO_ERROR;
-                }
-            }
-        } else {
-            // just pick the first one
-            *outConfig = configs[0];
-            delete [] configs;
-            return NO_ERROR;
-        }
-    }
-    delete [] configs;
-    return NAME_NOT_FOUND;
-}
-
-class EGLAttributeVector {
-    struct Attribute;
-    class Adder;
-    friend class Adder;
-    KeyedVector<Attribute, EGLint> 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; }
-};
-
-status_t SurfaceFlinger::selectEGLConfig(EGLDisplay display, EGLint nativeVisualId,
-    EGLint renderableType, EGLConfig* config) {
-    // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if
-    // it is to be used with WIFI displays
-    status_t err;
-    EGLint wantedAttribute;
-    EGLint wantedAttributeValue;
-
-    EGLAttributeVector attribs;
-    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;
-
-    } else {
-        // if no renderable type specified, fallback to a simplified query
-        wantedAttribute                         = EGL_NATIVE_VISUAL_ID;
-        wantedAttributeValue                    = nativeVisualId;
-    }
-
-    err = selectConfigForAttribute(display, attribs, wantedAttribute,
-        wantedAttributeValue, config);
-    if (err == NO_ERROR) {
-        EGLint caveat;
-        if (eglGetConfigAttrib(display, *config, EGL_CONFIG_CAVEAT, &caveat))
-            ALOGW_IF(caveat == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!");
-    }
-    return err;
-}
-
 class DispSyncSource : public VSyncSource, private DispSync::Callback {
 public:
     DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync) :
@@ -521,51 +399,12 @@
     mHwc = new HWComposer(this,
             *static_cast<HWComposer::EventHandler *>(this));
 
-    // First try to get an ES2 config
-    err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), EGL_OPENGL_ES2_BIT,
-            &mEGLConfig);
-
-    if (err != NO_ERROR) {
-        // If ES2 fails, try ES1
-        err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(),
-                EGL_OPENGL_ES_BIT, &mEGLConfig);
-    }
-
-    if (err != NO_ERROR) {
-        // still didn't work, probably because we're on the emulator...
-        // try a simplified query
-        ALOGW("no suitable EGLConfig found, trying a simpler query");
-        err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), 0, &mEGLConfig);
-    }
-
-    if (err != NO_ERROR) {
-        // 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;
-    eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_RED_SIZE,   &r);
-    eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_GREEN_SIZE, &g);
-    eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_BLUE_SIZE,  &b);
-    eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_ALPHA_SIZE, &a);
-    ALOGI("EGL informations:");
-    ALOGI("vendor    : %s", eglQueryString(mEGLDisplay, EGL_VENDOR));
-    ALOGI("version   : %s", eglQueryString(mEGLDisplay, EGL_VERSION));
-    ALOGI("extensions: %s", eglQueryString(mEGLDisplay, EGL_EXTENSIONS));
-    ALOGI("Client API: %s", eglQueryString(mEGLDisplay, EGL_CLIENT_APIS)?:"Not Supported");
-    ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, mEGLConfig);
-
     // get a RenderEngine for the given display / config (can't fail)
-    mRenderEngine = RenderEngine::create(mEGLDisplay, mEGLConfig);
+    mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc->getVisualID());
 
     // retrieve the EGL context that was selected/created
     mEGLContext = mRenderEngine->getEGLContext();
 
-    // figure out which format we got
-    eglGetConfigAttrib(mEGLDisplay, mEGLConfig,
-            EGL_NATIVE_VISUAL_ID, &mEGLNativeVisualId);
-
     LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
             "couldn't create EGLContext");
 
@@ -584,7 +423,7 @@
             sp<DisplayDevice> hw = new DisplayDevice(this,
                     type, allocateHwcDisplayId(type), isSecure, token,
                     fbs, bq,
-                    mEGLConfig);
+                    mRenderEngine->getEGLConfig());
             if (i > DisplayDevice::DISPLAY_PRIMARY) {
                 // FIXME: currently we don't get blank/unblank requests
                 // for displays other than the main display, so we always
@@ -1347,7 +1186,8 @@
                     if (dispSurface != NULL) {
                         sp<DisplayDevice> hw = new DisplayDevice(this,
                                 state.type, hwcDisplayId, state.isSecure,
-                                display, dispSurface, producer, mEGLConfig);
+                                display, dispSurface, producer,
+                                mRenderEngine->getEGLConfig());
                         hw->setLayerStack(state.layerStack);
                         hw->setProjection(state.orientation,
                                 state.viewport, state.frame);
@@ -2544,7 +2384,6 @@
             "  refresh-rate              : %f fps\n"
             "  x-dpi                     : %f\n"
             "  y-dpi                     : %f\n"
-            "  EGL_NATIVE_VISUAL_ID      : %d\n"
             "  gpu_to_cpu_unsupported    : %d\n"
             ,
             mLastSwapBufferTime/1000.0,
@@ -2553,7 +2392,6 @@
             1e9 / hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY),
             hwc.getDpiX(HWC_DISPLAY_PRIMARY),
             hwc.getDpiY(HWC_DISPLAY_PRIMARY),
-            mEGLNativeVisualId,
             !mGpuToCpuSupported);
 
     result.appendFormat("  eglSwapBuffers time: %f us\n",
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index f08e66a..80bb619 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -317,10 +317,6 @@
     /* ------------------------------------------------------------------------
      * EGL
      */
-    static status_t selectConfigForAttribute(EGLDisplay dpy,
-        EGLint const* attrs, EGLint attribute, EGLint value, EGLConfig* outConfig);
-    static status_t selectEGLConfig(EGLDisplay disp, EGLint visualId,
-        EGLint renderableType, EGLConfig* config);
     size_t getMaxTextureSize() const;
     size_t getMaxViewportDims() const;
 
@@ -431,9 +427,7 @@
     sp<EventThread> mSFEventThread;
     sp<EventControlThread> mEventControlThread;
     EGLContext mEGLContext;
-    EGLConfig mEGLConfig;
     EGLDisplay mEGLDisplay;
-    EGLint mEGLNativeVisualId;
     sp<IBinder> mBuiltinDisplays[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES];
 
     // Can only accessed from the main thread, these members