Merge "gui: CpuConsumer::lockNextBuffer change return code when too many bufs acquired" into klp-dev
diff --git a/cmds/flatland/Composers.cpp b/cmds/flatland/Composers.cpp
index 8365a31..15cdb29 100644
--- a/cmds/flatland/Composers.cpp
+++ b/cmds/flatland/Composers.cpp
@@ -14,6 +14,9 @@
  * limitations under the License.
  */
 
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
 #include "Flatland.h"
 #include "GLHelper.h"
 
diff --git a/cmds/flatland/GLHelper.cpp b/cmds/flatland/GLHelper.cpp
index 3928039..42694b3 100644
--- a/cmds/flatland/GLHelper.cpp
+++ b/cmds/flatland/GLHelper.cpp
@@ -14,6 +14,9 @@
  * limitations under the License.
  */
 
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
 #include <ui/DisplayInfo.h>
 #include <gui/SurfaceComposerClient.h>
 
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index e5e2dc0..c01725d 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -82,6 +82,7 @@
         "EGL_KHR_image_base "                   // mandatory
         "EGL_KHR_image_pixmap "
         "EGL_KHR_lock_surface "
+        "EGL_KHR_gl_colorspace "
         "EGL_KHR_gl_texture_2D_image "
         "EGL_KHR_gl_texture_cubemap_image "
         "EGL_KHR_gl_renderbuffer_image "
@@ -365,6 +366,33 @@
 // surfaces
 // ----------------------------------------------------------------------------
 
+// The EGL_KHR_gl_colorspace spec hasn't been published yet, so these haven't
+// been added to the Khronos egl.h.
+#define EGL_GL_COLORSPACE_KHR           EGL_VG_COLORSPACE
+#define EGL_GL_COLORSPACE_SRGB_KHR      EGL_VG_COLORSPACE_sRGB
+#define EGL_GL_COLORSPACE_LINEAR_KHR    EGL_VG_COLORSPACE_LINEAR
+
+// Turn linear formats into corresponding sRGB formats when colorspace is
+// EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear
+// formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where
+// the modification isn't possible, the original format is returned.
+static int modifyFormatColorspace(int fmt, EGLint colorspace) {
+    if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
+        switch (fmt) {
+            case HAL_PIXEL_FORMAT_sRGB_A_8888: return HAL_PIXEL_FORMAT_RGBA_8888;
+            case HAL_PIXEL_FORMAT_sRGB_888:    return HAL_PIXEL_FORMAT_RGB_888;
+        }
+    } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
+        switch (fmt) {
+            case HAL_PIXEL_FORMAT_RGBA_8888: return HAL_PIXEL_FORMAT_sRGB_A_8888;
+            case HAL_PIXEL_FORMAT_RGBX_8888: return HAL_PIXEL_FORMAT_sRGB_A_8888;
+            case HAL_PIXEL_FORMAT_BGRA_8888: return HAL_PIXEL_FORMAT_sRGB_A_8888;
+            case HAL_PIXEL_FORMAT_RGB_888:   return HAL_PIXEL_FORMAT_sRGB_888;
+        }
+    }
+    return fmt;
+}
+
 EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
                                     NativeWindowType window,
                                     const EGLint *attrib_list)
@@ -375,7 +403,6 @@
     egl_display_ptr dp = validate_display_connection(dpy, cnx);
     if (dp) {
         EGLDisplay iDpy = dp->disp.dpy;
-        EGLint format;
 
         if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != OK) {
             ALOGE("EGLNativeWindowType %p already connected to another API",
@@ -383,19 +410,36 @@
             return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
         }
 
-        // set the native window's buffers format to match this config
-        if (cnx->egl.eglGetConfigAttrib(iDpy,
-                config, EGL_NATIVE_VISUAL_ID, &format)) {
-            if (format != 0) {
-                int err = native_window_set_buffers_format(window, format);
-                if (err != 0) {
-                    ALOGE("error setting native window pixel format: %s (%d)",
-                            strerror(-err), err);
-                    native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
-                    return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
+        // Set the native window's buffers format to match this config.
+        // Whether to use sRGB gamma is not part of the EGLconfig, but is part
+        // of our native format. So if sRGB gamma is requested, we have to
+        // modify the EGLconfig's format before setting the native window's
+        // format.
+        EGLint format;
+        if (!cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_NATIVE_VISUAL_ID,
+                &format)) {
+            ALOGE("eglGetConfigAttrib(EGL_NATIVE_VISUAL_ID) failed: %#x",
+                    eglGetError());
+            format = 0;
+        }
+        if (attrib_list) {
+            for (const EGLint* attr = attrib_list; *attr != EGL_NONE;
+                    attr += 2) {
+                if (*attr == EGL_GL_COLORSPACE_KHR &&
+                        dp->haveExtension("EGL_KHR_gl_colorspace")) {
+                    format = modifyFormatColorspace(format, *(attr+1));
                 }
             }
         }
+        if (format != 0) {
+            int err = native_window_set_buffers_format(window, format);
+            if (err != 0) {
+                ALOGE("error setting native window pixel format: %s (%d)",
+                        strerror(-err), err);
+                native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
+                return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
+            }
+        }
 
         // the EGL spec requires that a new EGLSurface default to swap interval
         // 1, so explicitly set that on the window here.
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 8d7890b..0380521 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -44,6 +44,16 @@
 
 // ----------------------------------------------------------------------------
 
+static bool findExtension(const char* exts, const char* name, size_t nameLen) {
+    if (exts) {
+        const char* match = strstr(exts, name);
+        if (match && (match[nameLen] == '\0' || match[nameLen] == ' ')) {
+            return true;
+        }
+    }
+    return false;
+}
+
 egl_display_t egl_display_t::sDisplay[NUM_DISPLAYS];
 
 egl_display_t::egl_display_t() :
@@ -196,14 +206,9 @@
             if (len) {
                 // NOTE: we could avoid the copy if we had strnstr.
                 const String8 ext(start, len);
-                // now look for this extension
-                if (disp.queryString.extensions) {
-                    // if we find it, add this extension string to our list
-                    // (and don't forget the space)
-                    const char* match = strstr(disp.queryString.extensions, ext.string());
-                    if (match && (match[len] == ' ' || match[len] == 0)) {
-                        mExtensionString.append(start, len+1);
-                    }
+                if (findExtension(disp.queryString.extensions, ext.string(),
+                        len)) {
+                    mExtensionString.append(start, len+1);
                 }
             }
             // process the next extension string, and skip the space.
@@ -367,6 +372,13 @@
     return result;
 }
 
+bool egl_display_t::haveExtension(const char* name, size_t nameLen) const {
+    if (!nameLen) {
+        nameLen = strlen(name);
+    }
+    return findExtension(mExtensionString.string(), name, nameLen);
+}
+
 // ----------------------------------------------------------------------------
 
 bool egl_display_t::HibernationMachine::incWakeCount(WakeRefStrength strength) {
diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h
index 754085c..87f27f8 100644
--- a/opengl/libs/EGL/egl_display.h
+++ b/opengl/libs/EGL/egl_display.h
@@ -99,6 +99,8 @@
     char const * getClientApiString() const { return mClientApiString.string(); }
     char const * getExtensionString() const { return mExtensionString.string(); }
 
+    bool haveExtension(const char* name, size_t nameLen = 0) const;
+
     inline uint32_t getRefsCount() const { return refs; }
 
     struct strings_t {
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index a63a80a..531db20 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -572,6 +572,7 @@
     switch (format) {
         case HAL_PIXEL_FORMAT_RGBA_8888:
         case HAL_PIXEL_FORMAT_BGRA_8888:
+        case HAL_PIXEL_FORMAT_sRGB_A_8888:
             return false;
     }
     // in all other case, we have no blending (also for unknown formats)
diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp
index 428cdb8..19f17df 100644
--- a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp
@@ -15,12 +15,12 @@
  */
 
 #include <GLES/gl.h>
+#include <GLES/glext.h>
 
 #include <utils/String8.h>
 #include <cutils/compiler.h>
 
 #include "GLES11RenderEngine.h"
-#include "GLExtensions.h"
 #include "Mesh.h"
 
 // ---------------------------------------------------------------------------
@@ -183,6 +183,31 @@
     glDisable(GL_BLEND);
 }
 
+void GLES11RenderEngine::bindImageAsFramebuffer(EGLImageKHR image,
+        uint32_t* texName, uint32_t* fbName, uint32_t* status) {
+    GLuint tname, name;
+    // turn our EGLImage into a texture
+    glGenTextures(1, &tname);
+    glBindTexture(GL_TEXTURE_2D, tname);
+    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);
+
+    // create a Framebuffer Object to render into
+    glGenFramebuffersOES(1, &name);
+    glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
+    glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES,
+            GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0);
+
+    *status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
+    *texName = tname;
+    *fbName = name;
+}
+
+void GLES11RenderEngine::unbindFramebuffer(uint32_t texName, uint32_t fbName) {
+    glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
+    glDeleteFramebuffersOES(1, &fbName);
+    glDeleteTextures(1, &texName);
+}
+
 void GLES11RenderEngine::fillWithColor(const Mesh& mesh, float r, float g, float b, float a) {
     glColor4f(r, g, b, a);
     glDisable(GL_TEXTURE_EXTERNAL_OES);
@@ -219,14 +244,13 @@
 }
 
 void GLES11RenderEngine::dump(String8& result) {
-    const GLExtensions& extensions(GLExtensions::getInstance());
-    result.appendFormat("GLES: %s, %s, %s\n",
-            extensions.getVendor(),
-            extensions.getRenderer(),
-            extensions.getVersion());
-    result.appendFormat("%s\n", extensions.getExtension());
+    RenderEngine::dump(result);
 }
 
 // ---------------------------------------------------------------------------
 }; // namespace android
 // ---------------------------------------------------------------------------
+
+#if defined(__gl2_h_)
+#error "don't include gl2/gl2.h in this file"
+#endif
diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
index 8bb7ed1..d20ff1c 100644
--- a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
@@ -37,6 +37,10 @@
     GLint mMaxViewportDims[2];
     GLint mMaxTextureSize;
 
+    virtual void bindImageAsFramebuffer(EGLImageKHR image,
+            uint32_t* texName, uint32_t* fbName, uint32_t* status);
+    virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName);
+
 public:
     GLES11RenderEngine();
 
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 9be12bf..4add66b 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -17,6 +17,7 @@
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
 #include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
 
 #include <utils/String8.h>
 #include <utils/Trace.h>
@@ -24,7 +25,6 @@
 #include <cutils/compiler.h>
 
 #include "GLES20RenderEngine.h"
-#include "GLExtensions.h"
 #include "Program.h"
 #include "ProgramCache.h"
 #include "Description.h"
@@ -157,6 +157,32 @@
     glDisable(GL_BLEND);
 }
 
+
+void GLES20RenderEngine::bindImageAsFramebuffer(EGLImageKHR image,
+        uint32_t* texName, uint32_t* fbName, uint32_t* status) {
+    GLuint tname, name;
+    // turn our EGLImage into a texture
+    glGenTextures(1, &tname);
+    glBindTexture(GL_TEXTURE_2D, tname);
+    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);
+
+    // create a Framebuffer Object to render into
+    glGenFramebuffers(1, &name);
+    glBindFramebuffer(GL_FRAMEBUFFER, name);
+    glFramebufferTexture2D(GL_FRAMEBUFFER,
+            GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tname, 0);
+
+    *status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+    *texName = tname;
+    *fbName = name;
+}
+
+void GLES20RenderEngine::unbindFramebuffer(uint32_t texName, uint32_t fbName) {
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    glDeleteFramebuffers(1, &fbName);
+    glDeleteTextures(1, &texName);
+}
+
 void GLES20RenderEngine::fillWithColor(const Mesh& mesh, float r, float g, float b, float a) {
     mState.setColor(r, g, b, a);
     disableTexturing();
@@ -200,14 +226,13 @@
 }
 
 void GLES20RenderEngine::dump(String8& result) {
-    const GLExtensions& extensions(GLExtensions::getInstance());
-    result.appendFormat("GLES: %s, %s, %s\n",
-            extensions.getVendor(),
-            extensions.getRenderer(),
-            extensions.getVersion());
-    result.appendFormat("%s\n", extensions.getExtension());
+    RenderEngine::dump(result);
 }
 
 // ---------------------------------------------------------------------------
 }; // namespace android
 // ---------------------------------------------------------------------------
+
+#if defined(__gl_h_)
+#error "don't include gl/gl.h in this file"
+#endif
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
index 873a6435..2998874 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -41,6 +41,10 @@
 
     Description mState;
 
+    virtual void bindImageAsFramebuffer(EGLImageKHR image,
+            uint32_t* texName, uint32_t* fbName, uint32_t* status);
+    virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName);
+
 public:
     GLES20RenderEngine();
 
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
index 835ed8a..4911609 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
@@ -43,6 +43,8 @@
     friend Formatter& indent(Formatter& f);
     friend Formatter& dedent(Formatter& f);
 public:
+    Formatter() : mIndent(0) {}
+
     String8 getString() const {
         return mString;
     }
@@ -120,6 +122,10 @@
     if (needs.getTextureTarget() == Key::TEXTURE_EXT) {
         fs << "#extension GL_OES_EGL_image_external : require";
     }
+
+    // default precision is required-ish in fragment shaders
+    fs << "precision mediump float;";
+
     if (needs.getTextureTarget() == Key::TEXTURE_EXT) {
         fs << "uniform samplerExternalOES sampler;"
            << "varying vec2 outTexCoords;";
@@ -138,28 +144,16 @@
     } else {
         fs << "gl_FragColor = color;";
     }
+    if (needs.isOpaque()) {
+        fs << "gl_FragColor.a = 1.0;";
+    }
     if (needs.hasPlaneAlpha()) {
         // modulate the alpha value with planeAlpha
         if (needs.isPremultiplied()) {
             // ... and the color too if we're premultiplied
-            if (needs.isOpaque()) {
-                // ... we're opaque, only premultiply the color component
-                fs << "gl_FragColor.rgb *= alphaPlane;"
-                   << "gl_FragColor.a = alphaPlane;";
-            } else {
-                fs << "gl_FragColor *= alphaPlane;";
-            }
+            fs << "gl_FragColor *= alphaPlane;";
         } else {
-            // not premultiplied
-            if (needs.isOpaque()) {
-                fs << "gl_FragColor.a = alphaPlane;";
-            } else {
-                fs << "gl_FragColor.a *= alphaPlane;";
-            }
-        }
-    } else {
-        if (needs.isOpaque()) {
-            fs << "gl_FragColor.a = 1.0;";
+            fs << "gl_FragColor.a *= alphaPlane;";
         }
     }
     fs << dedent << "}";
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index ee51bd9..063be2e 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -190,34 +190,29 @@
     glDeleteTextures(count, names);
 }
 
+void RenderEngine::dump(String8& result) {
+    const GLExtensions& extensions(GLExtensions::getInstance());
+    result.appendFormat("GLES: %s, %s, %s\n",
+            extensions.getVendor(),
+            extensions.getRenderer(),
+            extensions.getVersion());
+    result.appendFormat("%s\n", extensions.getExtension());
+}
+
 // ---------------------------------------------------------------------------
 
 RenderEngine::BindImageAsFramebuffer::BindImageAsFramebuffer(
         RenderEngine& engine, EGLImageKHR image) : mEngine(engine)
 {
-    GLuint tname, name;
-    // turn our EGLImage into a texture
-    glGenTextures(1, &tname);
-    glBindTexture(GL_TEXTURE_2D, tname);
-    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);
-    // create a Framebuffer Object to render into
-    glGenFramebuffersOES(1, &name);
-    glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
-    glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES,
-            GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0);
-    mStatus = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
+    mEngine.bindImageAsFramebuffer(image, &mTexName, &mFbName, &mStatus);
+
     ALOGE_IF(mStatus != GL_FRAMEBUFFER_COMPLETE_OES,
             "glCheckFramebufferStatusOES error %d", mStatus);
-    mTexName = tname;
-    mFbName = name;
 }
 
 RenderEngine::BindImageAsFramebuffer::~BindImageAsFramebuffer() {
     // back to main framebuffer
-    glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
-    glDeleteFramebuffersOES(1, &mFbName);
-    glDeleteTextures(1, &mTexName);
-
+    mEngine.unbindFramebuffer(mTexName, mFbName);
 }
 
 status_t RenderEngine::BindImageAsFramebuffer::getStatus() const {
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index f4fa30b..3c2b2ea 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -45,6 +45,9 @@
     EGLContext mEGLContext;
     void setEGLContext(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;
+
 protected:
     RenderEngine();
     virtual ~RenderEngine() = 0;
@@ -52,6 +55,9 @@
 public:
     static RenderEngine* create(EGLDisplay display, EGLConfig config);
 
+    // dump the extension strings. always call the base class.
+    virtual void dump(String8& result);
+
     // helpers
     void clearWithColor(float red, float green, float blue, float alpha);
     void fillRegionWithColor(const Region& region, uint32_t height,
@@ -65,8 +71,8 @@
 
     class BindImageAsFramebuffer {
         RenderEngine& mEngine;
-        unsigned int mTexName, mFbName;
-        unsigned int mStatus;
+        uint32_t mTexName, mFbName;
+        uint32_t mStatus;
     public:
         BindImageAsFramebuffer(RenderEngine& engine, EGLImageKHR image);
         ~BindImageAsFramebuffer();
@@ -75,7 +81,6 @@
 
     // set-up
     virtual void checkErrors() const;
-    virtual void dump(String8& result) = 0;
     virtual void setViewportAndProjection(size_t vpw, size_t vph, size_t w, size_t h, bool yswap) = 0;
     virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha) = 0;
     virtual void setupDimLayerBlending(int alpha) = 0;