OSDN Git Service

Pre-test native window pointer for validity
[android-x86/frameworks-native.git] / opengl / libs / EGL / eglApi.cpp
index c01725d..c2ac564 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <hardware/gralloc.h>
 #include <system/window.h>
+#include <sys/mman.h>
 
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 
 using namespace android;
 
+// This extension has not been ratified yet, so can't be shipped.
+// Implementation is incomplete and untested.
+#define ENABLE_EGL_KHR_GL_COLORSPACE 0
+
 // ----------------------------------------------------------------------------
 
 namespace android {
@@ -82,7 +87,9 @@ extern char const * const gExtensionString  =
         "EGL_KHR_image_base "                   // mandatory
         "EGL_KHR_image_pixmap "
         "EGL_KHR_lock_surface "
+#if (ENABLE_EGL_KHR_GL_COLORSPACE != 0)
         "EGL_KHR_gl_colorspace "
+#endif
         "EGL_KHR_gl_texture_2D_image "
         "EGL_KHR_gl_texture_cubemap_image "
         "EGL_KHR_gl_renderbuffer_image "
@@ -93,6 +100,7 @@ extern char const * const gExtensionString  =
         "EGL_NV_system_time "
         "EGL_ANDROID_image_native_buffer "      // mandatory
         "EGL_KHR_wait_sync "                    // strongly recommended
+        "EGL_ANDROID_recordable "               // mandatory
         ;
 
 // extensions not exposed to applications but used by the ANDROID system
@@ -100,8 +108,7 @@ extern char const * const gExtensionString  =
 //      "EGL_IMG_hibernate_process "            // optional
 //      "EGL_ANDROID_native_fence_sync "        // strongly recommended
 //      "EGL_ANDROID_framebuffer_target "       // mandatory for HWC 1.1
-//      "EGL_ANDROID_recordable "               // mandatory
-
+//      "EGL_ANDROID_image_crop "               // optional
 
 /*
  * EGL Extensions entry-points exposed to 3rd party applications
@@ -363,10 +370,39 @@ EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
 }
 
 // ----------------------------------------------------------------------------
+// Utility procedure to test a NativeWindowType for validity before referencing
+// through the pointer.  It's not feasible to test for deliberate forgeries,
+// but this heuristic is good enough to test for basic accidental cases, using
+// the special "magic" value placed in a native-window structure.
+// ----------------------------------------------------------------------------
+EGLBoolean isValidNativeWindow(NativeWindowType window)
+{
+    ANativeWindow *nwindow = static_cast<ANativeWindow*>(window);
+    // the msync system call returns with ENOMEM error for unmapped memory
+    // pages.  This is used here as a way to test whether we can read through a
+    // pointer without getting a segfault.
+    uintptr_t pagesize = (uintptr_t) sysconf(_SC_PAGESIZE);
+    uintptr_t addr = ((uintptr_t)(&nwindow->common.magic)) & (~(pagesize - 1));
+    int rc = msync((void *)addr, pagesize, MS_ASYNC);
+    if (0 == rc) {
+        if (nwindow->common.magic == ANDROID_NATIVE_WINDOW_MAGIC)
+            return EGL_TRUE;
+        else
+            return EGL_FALSE;
+    }
+    if (ENOMEM == errno)
+        return EGL_FALSE;
+    ALOGE("error unexpected msync error: %s (%d)",
+                            strerror(-errno), errno);
+    return EGL_FALSE;
+}
+
+
+// ----------------------------------------------------------------------------
 // surfaces
 // ----------------------------------------------------------------------------
 
-// The EGL_KHR_gl_colorspace spec hasn't been published yet, so these haven't
+// The EGL_KHR_gl_colorspace spec hasn't been ratified 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
@@ -380,14 +416,12 @@ 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;
+            case HAL_PIXEL_FORMAT_sRGB_X_8888: return HAL_PIXEL_FORMAT_RGBX_8888;
         }
     } 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;
+            case HAL_PIXEL_FORMAT_RGBX_8888: return HAL_PIXEL_FORMAT_sRGB_X_8888;
         }
     }
     return fmt;
@@ -404,17 +438,23 @@ EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
     if (dp) {
         EGLDisplay iDpy = dp->disp.dpy;
 
+        if (!isValidNativeWindow(window)) {
+            ALOGE("EGLNativeWindow %p invalid", window);
+            return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
+        }
         if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != OK) {
             ALOGE("EGLNativeWindowType %p already connected to another API",
                     window);
             return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
         }
 
-        // Set the native window's buffers format to match this config.
+        // Set the native window's buffers format to match what this config requests.
         // 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.
+#if WORKAROUND_BUG_10194508
+#warning "WORKAROUND_10194508 enabled"
         EGLint format;
         if (!cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_NATIVE_VISUAL_ID,
                 &format)) {
@@ -427,10 +467,62 @@ EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
                     attr += 2) {
                 if (*attr == EGL_GL_COLORSPACE_KHR &&
                         dp->haveExtension("EGL_KHR_gl_colorspace")) {
-                    format = modifyFormatColorspace(format, *(attr+1));
+                    if (ENABLE_EGL_KHR_GL_COLORSPACE) {
+                        format = modifyFormatColorspace(format, *(attr+1));
+                    } else {
+                        // Normally we'd pass through unhandled attributes to
+                        // the driver. But in case the driver implements this
+                        // extension but we're disabling it, we want to prevent
+                        // it getting through -- support will be broken without
+                        // our help.
+                        ALOGE("sRGB window surfaces not supported");
+                        return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+                    }
+                }
+            }
+        }
+#else
+        // by default, just pick RGBA_8888
+        EGLint format = HAL_PIXEL_FORMAT_RGBA_8888;
+
+        EGLint a = 0;
+        cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a);
+        if (a > 0) {
+            // alpha-channel requested, there's really only one suitable format
+            format = HAL_PIXEL_FORMAT_RGBA_8888;
+        } else {
+            EGLint r, g, b;
+            r = g = b = 0;
+            cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE,   &r);
+            cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g);
+            cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE,  &b);
+            EGLint colorDepth = r + g + b;
+            if (colorDepth <= 16) {
+                format = HAL_PIXEL_FORMAT_RGB_565;
+            } else {
+                format = HAL_PIXEL_FORMAT_RGBX_8888;
+            }
+        }
+
+        // now select a corresponding sRGB format if needed
+        if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
+            for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
+                if (*attr == EGL_GL_COLORSPACE_KHR) {
+                    if (ENABLE_EGL_KHR_GL_COLORSPACE) {
+                        format = modifyFormatColorspace(format, *(attr+1));
+                    } else {
+                        // Normally we'd pass through unhandled attributes to
+                        // the driver. But in case the driver implements this
+                        // extension but we're disabling it, we want to prevent
+                        // it getting through -- support will be broken without
+                        // our help.
+                        ALOGE("sRGB window surfaces not supported");
+                        return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+                    }
                 }
             }
         }
+#endif
         if (format != 0) {
             int err = native_window_set_buffers_format(window, format);
             if (err != 0) {
@@ -713,7 +805,8 @@ EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
         }
     } else {
         // this will ALOGE the error
-        result = setError(c->cnx->egl.eglGetError(), EGL_FALSE);
+        egl_connection_t* const cnx = &gEGLImpl;
+        result = setError(cnx->egl.eglGetError(), EGL_FALSE);
     }
     return result;
 }