am e5f7bf74: am b6c21004: Merge "Implement per-display EGLConfig and configless EGLContext"

* commit 'e5f7bf7471b21226c9a6b875e9e8f2fb2cba72e2':
  Implement per-display EGLConfig and configless EGLContext
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 800137b..0d0f98d 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -53,6 +53,7 @@
         const sp<SurfaceFlinger>& flinger,
         DisplayType type,
         int32_t hwcId,
+        int format,
         bool isSecure,
         const wp<IBinder>& displayToken,
         const sp<DisplaySurface>& displaySurface,
@@ -76,9 +77,6 @@
     mNativeWindow = new Surface(producer, false);
     ANativeWindow* const window = mNativeWindow.get();
 
-    int format;
-    window->query(window, NATIVE_WINDOW_FORMAT, &format);
-
     // Make sure that composition can never be stalled by a virtual display
     // consumer that isn't processing buffers fast enough. We have to do this
     // in two places:
@@ -96,6 +94,9 @@
     EGLSurface surface;
     EGLint w, h;
     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    if (config == EGL_NO_CONFIG) {
+        config = RenderEngine::chooseEglConfig(display, format);
+    }
     surface = eglCreateWindowSurface(display, config, window, NULL);
     eglQuerySurface(display, surface, EGL_WIDTH,  &mDisplayWidth);
     eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index c3abe89..01a9d2e 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -75,6 +75,7 @@
             const sp<SurfaceFlinger>& flinger,
             DisplayType type,
             int32_t hwcId,  // negative for non-HWC-composited displays
+            int format,
             bool isSecure,
             const wp<IBinder>& displayToken,
             const sp<DisplaySurface>& displaySurface,
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index c7d1a90..1b652c3 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -455,7 +455,11 @@
 }
 
 uint32_t HWComposer::getFormat(int disp) const {
-    return mDisplayData[disp].format;
+    if (uint32_t(disp)>31 || !mAllocatedDisplayIDs.hasBit(disp)) {
+        return HAL_PIXEL_FORMAT_RGBA_8888;
+    } else {
+        return mDisplayData[disp].format;
+    }
 }
 
 float HWComposer::getDpiX(int disp) const {
@@ -1147,7 +1151,7 @@
 }
 
 HWComposer::DisplayData::DisplayData()
-:   width(0), height(0), format(0),
+:   width(0), height(0), format(HAL_PIXEL_FORMAT_RGBA_8888),
     xdpi(0.0f), ydpi(0.0f),
     refresh(0),
     connected(false),
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index 759839b..2871ce9 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -25,21 +25,51 @@
 #include "GLExtensions.h"
 #include "Mesh.h"
 
+EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
+
 // ---------------------------------------------------------------------------
 namespace android {
 // ---------------------------------------------------------------------------
 
-RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat) {
-    EGLConfig config = chooseEglConfig(display, hwcFormat);
+static bool findExtension(const char* exts, const char* name) {
+    if (!exts)
+        return false;
+    size_t len = strlen(name);
 
-    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");
+    const char* pos = exts;
+    while ((pos = strstr(pos, name)) != NULL) {
+        if (pos[len] == '\0' || pos[len] == ' ')
+            return true;
+        pos += len;
     }
 
+    return false;
+}
+
+RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat) {
+    // EGL_ANDROIDX_no_config_context is an experimental extension with no
+    // written specification. It will be replaced by something more formal.
+    // SurfaceFlinger is using it to allow a single EGLContext to render to
+    // both a 16-bit primary display framebuffer and a 32-bit virtual display
+    // framebuffer.
+    //
+    // The code assumes that ES2 or later is available if this extension is
+    // supported.
+    EGLConfig config = EGL_NO_CONFIG;
+    if (!findExtension(
+            eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS),
+            "EGL_ANDROIDX_no_config_context")) {
+        config = chooseEglConfig(display, hwcFormat);
+    }
+
+    EGLint renderableType = 0;
+    if (config == EGL_NO_CONFIG) {
+        renderableType = EGL_OPENGL_ES2_BIT;
+    } else if (!eglGetConfigAttrib(display, config,
+            EGL_RENDERABLE_TYPE, &renderableType)) {
+        LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE");
+    }
+    EGLint contextClientVersion = 0;
     if (renderableType & EGL_OPENGL_ES2_BIT) {
         contextClientVersion = 2;
     } else if (renderableType & EGL_OPENGL_ES_BIT) {
@@ -68,8 +98,12 @@
     // now figure out what version of GL did we actually get
     // NOTE: a dummy surface is not needed if KHR_create_context is supported
 
+    EGLConfig dummyConfig = config;
+    if (dummyConfig == EGL_NO_CONFIG) {
+        dummyConfig = chooseEglConfig(display, hwcFormat);
+    }
     EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE };
-    EGLSurface dummy = eglCreatePbufferSurface(display, config, attribs);
+    EGLSurface dummy = eglCreatePbufferSurface(display, dummyConfig, attribs);
     LOG_ALWAYS_FATAL_IF(dummy==EGL_NO_SURFACE, "can't create dummy pbuffer");
     EGLBoolean success = eglMakeCurrent(display, dummy, dummy, ctxt);
     LOG_ALWAYS_FATAL_IF(!success, "can't make dummy pbuffer current");
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 4dc9457..577dc0a 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -25,6 +25,8 @@
 #include <EGL/eglext.h>
 #include <ui/mat4.h>
 
+#define EGL_NO_CONFIG ((EGLConfig)0)
+
 // ---------------------------------------------------------------------------
 namespace android {
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ec64390..c00b034 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -420,8 +420,9 @@
 
             sp<BufferQueue> bq = new BufferQueue(new GraphicBufferAlloc());
             sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i, bq);
+            int32_t hwcId = allocateHwcDisplayId(type);
             sp<DisplayDevice> hw = new DisplayDevice(this,
-                    type, allocateHwcDisplayId(type), isSecure, token,
+                    type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
                     fbs, bq,
                     mRenderEngine->getEGLConfig());
             if (i > DisplayDevice::DISPLAY_PRIMARY) {
@@ -1185,7 +1186,8 @@
                     const wp<IBinder>& display(curr.keyAt(i));
                     if (dispSurface != NULL) {
                         sp<DisplayDevice> hw = new DisplayDevice(this,
-                                state.type, hwcDisplayId, state.isSecure,
+                                state.type, hwcDisplayId,
+                                mHwc->getFormat(hwcDisplayId), state.isSecure,
                                 display, dispSurface, producer,
                                 mRenderEngine->getEGLConfig());
                         hw->setLayerStack(state.layerStack);