OSDN Git Service

Add support for EGL_KHR_gl_colorspace
authorJesse Hall <jessehall@google.com>
Thu, 8 Aug 2013 20:40:22 +0000 (13:40 -0700)
committerJesse Hall <jessehall@google.com>
Tue, 13 Aug 2013 19:10:51 +0000 (12:10 -0700)
Change-Id: I684d0b8556cd6c84ee4b4d67e1bb95c3b96fccfb

opengl/libs/EGL/eglApi.cpp
opengl/libs/EGL/egl_display.cpp
opengl/libs/EGL/egl_display.h
services/surfaceflinger/Layer.cpp

index e5e2dc0..c01725d 100644 (file)
@@ -82,6 +82,7 @@ extern char const * const gExtensionString  =
         "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 @@ EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
 // 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 @@ EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
     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 @@ EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
             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.
index 8d7890b..0380521 100644 (file)
@@ -44,6 +44,16 @@ extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
 
 // ----------------------------------------------------------------------------
 
+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 @@ EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) {
             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 @@ EGLBoolean egl_display_t::makeCurrent(egl_context_t* c, egl_context_t* cur_c,
     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) {
index 754085c..87f27f8 100644 (file)
@@ -99,6 +99,8 @@ public:
     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 {
index 2defe34..ddbe6f2 100644 (file)
@@ -582,6 +582,7 @@ bool Layer::getOpacityForFormat(uint32_t format) {
     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)