[Mesa-dev,7/9] egl: implement EGL_KHR_gl_colorspace

Submitted by Marek Olšák on June 10, 2015, 4:27 p.m.

Details

Message ID 1433953640-2815-8-git-send-email-maraeo@gmail.com
State New
Headers show

Not browsing as part of any series.

Commit Message

Marek Olšák June 10, 2015, 4:27 p.m.
From: Marek Olšák <marek.olsak@amd.com>

---
 src/egl/drivers/dri2/egl_dri2.c         | 40 ++++++++++++++++++++++++++-------
 src/egl/drivers/dri2/egl_dri2.h         |  6 +++++
 src/egl/drivers/dri2/platform_android.c |  4 ++++
 src/egl/drivers/dri2/platform_drm.c     |  9 +++++---
 src/egl/drivers/dri2/platform_wayland.c |  9 +++++---
 src/egl/drivers/dri2/platform_x11.c     | 12 +++++-----
 src/egl/main/eglconfig.c                |  3 ++-
 src/egl/main/eglsurface.c               | 24 ++++++++++++++++++++
 src/egl/main/eglsurface.h               |  1 +
 9 files changed, 87 insertions(+), 21 deletions(-)

Patch hide | download patch | download mbox

diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index eacb36c..84f0afb 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -28,6 +28,7 @@ 
 #define WL_HIDE_DEPRECATED
 
 #include <stdint.h>
+#include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
@@ -109,6 +110,18 @@  EGLint dri2_to_egl_attribute_map[] = {
    0,				/* __DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE */
 };
 
+const __DRIconfig *
+dri2_get_dri_config(struct dri2_egl_config *conf, EGLint surface_type,
+                    EGLenum colorspace)
+{
+   if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR)
+      return surface_type == EGL_WINDOW_BIT ? conf->dri_srgb_double_config :
+                                              conf->dri_srgb_single_config;
+   else
+      return surface_type == EGL_WINDOW_BIT ? conf->dri_double_config :
+                                              conf->dri_single_config;
+}
+
 static EGLBoolean
 dri2_match_config(const _EGLConfig *conf, const _EGLConfig *criteria)
 {
@@ -130,6 +143,7 @@  dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
    struct dri2_egl_display *dri2_dpy;
    _EGLConfig base;
    unsigned int attrib, value, double_buffer;
+   bool srgb = false;
    EGLint key, bind_to_texture_rgb, bind_to_texture_rgba;
    unsigned int dri_masks[4] = { 0, 0, 0, 0 };
    _EGLConfig *matching_config;
@@ -202,6 +216,9 @@  dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
          /* Don't expose visuals with the accumulation buffer. */
          if (value > 0)
             return NULL;
+
+      case __DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE:
+         srgb = value != 0;
          break;
 
       default:
@@ -249,28 +266,35 @@  dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
    if (num_configs == 1) {
       conf = (struct dri2_egl_config *) matching_config;
 
-      if (double_buffer && !conf->dri_double_config)
+      if (double_buffer && srgb && !conf->dri_srgb_double_config)
+         conf->dri_srgb_double_config = dri_config;
+      else if (double_buffer && !srgb && !conf->dri_double_config)
          conf->dri_double_config = dri_config;
-      else if (!double_buffer && !conf->dri_single_config)
+      else if (!double_buffer && srgb && !conf->dri_srgb_single_config)
+         conf->dri_srgb_single_config = dri_config;
+      else if (!double_buffer && !srgb && !conf->dri_single_config)
          conf->dri_single_config = dri_config;
       else
          /* a similar config type is already added (unlikely) => discard */
          return NULL;
    }
    else if (num_configs == 0) {
-      conf = malloc(sizeof *conf);
+      conf = calloc(1, sizeof *conf);
       if (conf == NULL)
          return NULL;
 
       memcpy(&conf->base, &base, sizeof base);
       if (double_buffer) {
-         conf->dri_double_config = dri_config;
-         conf->dri_single_config = NULL;
+         if (srgb)
+            conf->dri_srgb_double_config = dri_config;
+         else
+            conf->dri_double_config = dri_config;
       } else {
-         conf->dri_single_config = dri_config;
-         conf->dri_double_config = NULL;
+         if (srgb)
+            conf->dri_srgb_single_config = dri_config;
+         else
+            conf->dri_single_config = dri_config;
       }
-      conf->base.SurfaceType = 0;
       conf->base.ConfigID = config_id;
 
       _eglLinkConfig(&conf->base);
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index adade3d..6b9a48e 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -285,6 +285,8 @@  struct dri2_egl_config
    _EGLConfig         base;
    const __DRIconfig *dri_single_config;
    const __DRIconfig *dri_double_config;
+   const __DRIconfig *dri_srgb_single_config;
+   const __DRIconfig *dri_srgb_double_config;
 };
 
 struct dri2_egl_image
@@ -354,4 +356,8 @@  dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *disp);
 void
 dri2_flush_drawable_for_swapbuffers(_EGLDisplay *disp, _EGLSurface *draw);
 
+const __DRIconfig *
+dri2_get_dri_config(struct dri2_egl_config *conf, EGLint surface_type,
+                    EGLenum colorspace);
+
 #endif /* EGL_DRI2_INCLUDED */
diff --git a/src/egl/drivers/dri2/platform_android.c b/src/egl/drivers/dri2/platform_android.c
index fed3073..3cb2459 100644
--- a/src/egl/drivers/dri2/platform_android.c
+++ b/src/egl/drivers/dri2/platform_android.c
@@ -199,6 +199,7 @@  droid_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
    struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
    struct dri2_egl_surface *dri2_surf;
    struct ANativeWindow *window = native_window;
+   const __DRIconfig *config;
 
    dri2_surf = calloc(1, sizeof *dri2_surf);
    if (!dri2_surf) {
@@ -230,6 +231,9 @@  droid_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
       window->query(window, NATIVE_WINDOW_HEIGHT, &dri2_surf->base.Height);
    }
 
+   config = dri2_get_dri_config(dri2_conf, EGL_WINDOW_BIT,
+                                dri2_surf->base.GLColorspace);
+
    dri2_surf->dri_drawable =
       (*dri2_dpy->dri2->createNewDrawable)(dri2_dpy->dri_screen,
 					   dri2_conf->dri_double_config,
diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c
index 3391afc..4cda266 100644
--- a/src/egl/drivers/dri2/platform_drm.c
+++ b/src/egl/drivers/dri2/platform_drm.c
@@ -128,10 +128,13 @@  dri2_drm_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
    }
 
    if (dri2_dpy->dri2) {
+      const __DRIconfig *config =
+         dri2_get_dri_config(dri2_conf, EGL_WINDOW_BIT,
+                             dri2_surf->base.GLColorspace);
+
       dri2_surf->dri_drawable =
-         (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
-                                               dri2_conf->dri_double_config,
-                                               dri2_surf->gbm_surf);
+         (*dri2_dpy->dri2->createNewDrawable)(dri2_dpy->dri_screen, config,
+                                              dri2_surf->gbm_surf);
 
    } else {
       assert(dri2_dpy->swrast != NULL);
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index ea2f9f2..429d2cb 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -130,6 +130,7 @@  dri2_wl_create_surface(_EGLDriver *drv, _EGLDisplay *disp,
    struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
    struct wl_egl_window *window = native_window;
    struct dri2_egl_surface *dri2_surf;
+   const __DRIconfig *config;
 
    (void) drv;
 
@@ -157,10 +158,12 @@  dri2_wl_create_surface(_EGLDriver *drv, _EGLDisplay *disp,
    dri2_surf->base.Width =  -1;
    dri2_surf->base.Height = -1;
 
+   config = dri2_get_dri_config(dri2_conf, EGL_WINDOW_BIT,
+                                dri2_surf->base.GLColorspace);
+
    dri2_surf->dri_drawable = 
-      (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
-					    dri2_conf->dri_double_config,
-					    dri2_surf);
+      (*dri2_dpy->dri2->createNewDrawable)(dri2_dpy->dri_screen, config,
+                                           dri2_surf);
    if (dri2_surf->dri_drawable == NULL) {
       _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
       goto cleanup_dri_drawable;
diff --git a/src/egl/drivers/dri2/platform_x11.c b/src/egl/drivers/dri2/platform_x11.c
index e0d0fdc..66717cd 100644
--- a/src/egl/drivers/dri2/platform_x11.c
+++ b/src/egl/drivers/dri2/platform_x11.c
@@ -238,12 +238,12 @@  dri2_x11_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
    }
 
    if (dri2_dpy->dri2) {
-      dri2_surf->dri_drawable = 
-	 (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
-					       type == EGL_WINDOW_BIT ?
-					       dri2_conf->dri_double_config : 
-					       dri2_conf->dri_single_config,
-					       dri2_surf);
+      const __DRIconfig *config =
+         dri2_get_dri_config(dri2_conf, type, dri2_surf->base.GLColorspace);
+
+      dri2_surf->dri_drawable =
+	 (*dri2_dpy->dri2->createNewDrawable)(dri2_dpy->dri_screen, config,
+					      dri2_surf);
    } else {
       assert(dri2_dpy->swrast);
       dri2_surf->dri_drawable = 
diff --git a/src/egl/main/eglconfig.c b/src/egl/main/eglconfig.c
index cf65c69..c445d9b 100644
--- a/src/egl/main/eglconfig.c
+++ b/src/egl/main/eglconfig.c
@@ -83,7 +83,8 @@  _eglLinkConfig(_EGLConfig *conf)
    _EGLDisplay *dpy = conf->Display;
 
    /* sanity check */
-   assert(dpy && conf->ConfigID > 0);
+   assert(dpy);
+   assert(conf->ConfigID > 0);
 
    if (!dpy->Configs) {
       dpy->Configs = _eglCreateArray("Config", 16);
diff --git a/src/egl/main/eglsurface.c b/src/egl/main/eglsurface.c
index 76c60e9..541353f 100644
--- a/src/egl/main/eglsurface.c
+++ b/src/egl/main/eglsurface.c
@@ -84,6 +84,22 @@  _eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list)
 
       switch (attr) {
       /* common attributes */
+      case EGL_GL_COLORSPACE_KHR:
+         if (!dpy->Extensions.KHR_gl_colorspace) {
+            err = EGL_BAD_ATTRIBUTE;
+            break;
+         }
+         switch (val) {
+         case EGL_GL_COLORSPACE_SRGB_KHR:
+         case EGL_GL_COLORSPACE_LINEAR_KHR:
+            break;
+         default:
+            err = EGL_BAD_ATTRIBUTE;
+         }
+         if (err != EGL_SUCCESS)
+            break;
+         surf->GLColorspace = val;
+         break;
       case EGL_VG_COLORSPACE:
          switch (val) {
          case EGL_VG_COLORSPACE_sRGB:
@@ -272,6 +288,7 @@  _eglInitSurface(_EGLSurface *surf, _EGLDisplay *dpy, EGLint type,
    surf->RenderBuffer = renderBuffer;
    surf->VGAlphaFormat = EGL_VG_ALPHA_FORMAT_NONPRE;
    surf->VGColorspace = EGL_VG_COLORSPACE_sRGB;
+   surf->GLColorspace = EGL_GL_COLORSPACE_LINEAR_KHR;
 
    surf->MipmapLevel = 0;
    surf->MultisampleResolve = EGL_MULTISAMPLE_RESOLVE_DEFAULT;
@@ -352,6 +369,13 @@  _eglQuerySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
    case EGL_VG_COLORSPACE:
       *value = surface->VGColorspace;
       break;
+   case EGL_GL_COLORSPACE_KHR:
+      if (!dpy->Extensions.KHR_gl_colorspace) {
+         _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
+         return EGL_FALSE;
+      }
+      *value = surface->GLColorspace;
+      break;
    case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
       *value = surface->PostSubBufferSupportedNV;
       break;
diff --git a/src/egl/main/eglsurface.h b/src/egl/main/eglsurface.h
index 74c429a..fc799ee 100644
--- a/src/egl/main/eglsurface.h
+++ b/src/egl/main/eglsurface.h
@@ -65,6 +65,7 @@  struct _egl_surface
    EGLenum RenderBuffer;
    EGLenum VGAlphaFormat;
    EGLenum VGColorspace;
+   EGLenum GLColorspace;
 
    /* attributes set by eglSurfaceAttrib */
    EGLint MipmapLevel;

Comments

On Wed, Jun 10, 2015 at 9:27 AM, Marek Olšák <maraeo@gmail.com> wrote:
> From: Marek Olšák <marek.olsak@amd.com>
>
> ---
>  src/egl/drivers/dri2/egl_dri2.c         | 40 ++++++++++++++++++++++++++-------
>  src/egl/drivers/dri2/egl_dri2.h         |  6 +++++
>  src/egl/drivers/dri2/platform_android.c |  4 ++++
>  src/egl/drivers/dri2/platform_drm.c     |  9 +++++---
>  src/egl/drivers/dri2/platform_wayland.c |  9 +++++---
>  src/egl/drivers/dri2/platform_x11.c     | 12 +++++-----
>  src/egl/main/eglconfig.c                |  3 ++-
>  src/egl/main/eglsurface.c               | 24 ++++++++++++++++++++
>  src/egl/main/eglsurface.h               |  1 +
>  9 files changed, 87 insertions(+), 21 deletions(-)
>
> diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
> index eacb36c..84f0afb 100644
> --- a/src/egl/drivers/dri2/egl_dri2.c
> +++ b/src/egl/drivers/dri2/egl_dri2.c
> @@ -28,6 +28,7 @@
>  #define WL_HIDE_DEPRECATED
>
>  #include <stdint.h>
> +#include <stdbool.h>
>  #include <stdlib.h>
>  #include <string.h>
>  #include <stdio.h>
> @@ -109,6 +110,18 @@ EGLint dri2_to_egl_attribute_map[] = {
>     0,                          /* __DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE */
>  };
>
> +const __DRIconfig *
> +dri2_get_dri_config(struct dri2_egl_config *conf, EGLint surface_type,
> +                    EGLenum colorspace)
> +{
> +   if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR)
> +      return surface_type == EGL_WINDOW_BIT ? conf->dri_srgb_double_config :
> +                                              conf->dri_srgb_single_config;
> +   else
> +      return surface_type == EGL_WINDOW_BIT ? conf->dri_double_config :
> +                                              conf->dri_single_config;
> +}
> +
>  static EGLBoolean
>  dri2_match_config(const _EGLConfig *conf, const _EGLConfig *criteria)
>  {
> @@ -130,6 +143,7 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
>     struct dri2_egl_display *dri2_dpy;
>     _EGLConfig base;
>     unsigned int attrib, value, double_buffer;
> +   bool srgb = false;
>     EGLint key, bind_to_texture_rgb, bind_to_texture_rgba;
>     unsigned int dri_masks[4] = { 0, 0, 0, 0 };
>     _EGLConfig *matching_config;
> @@ -202,6 +216,9 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
>           /* Don't expose visuals with the accumulation buffer. */
>           if (value > 0)
>              return NULL;
> +

Please mark this with a /* fallthrough */ comment so that static
analysis tools don't think there's a missing break.

> +      case __DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE:
> +         srgb = value != 0;
>           break;
>
>        default:
On Wed, Jun 10, 2015 at 6:47 PM, Matt Turner <mattst88@gmail.com> wrote:
> On Wed, Jun 10, 2015 at 9:27 AM, Marek Olšák <maraeo@gmail.com> wrote:
>> From: Marek Olšák <marek.olsak@amd.com>
>>
>> ---
>>  src/egl/drivers/dri2/egl_dri2.c         | 40 ++++++++++++++++++++++++++-------
>>  src/egl/drivers/dri2/egl_dri2.h         |  6 +++++
>>  src/egl/drivers/dri2/platform_android.c |  4 ++++
>>  src/egl/drivers/dri2/platform_drm.c     |  9 +++++---
>>  src/egl/drivers/dri2/platform_wayland.c |  9 +++++---
>>  src/egl/drivers/dri2/platform_x11.c     | 12 +++++-----
>>  src/egl/main/eglconfig.c                |  3 ++-
>>  src/egl/main/eglsurface.c               | 24 ++++++++++++++++++++
>>  src/egl/main/eglsurface.h               |  1 +
>>  9 files changed, 87 insertions(+), 21 deletions(-)
>>
>> diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
>> index eacb36c..84f0afb 100644
>> --- a/src/egl/drivers/dri2/egl_dri2.c
>> +++ b/src/egl/drivers/dri2/egl_dri2.c
>> @@ -28,6 +28,7 @@
>>  #define WL_HIDE_DEPRECATED
>>
>>  #include <stdint.h>
>> +#include <stdbool.h>
>>  #include <stdlib.h>
>>  #include <string.h>
>>  #include <stdio.h>
>> @@ -109,6 +110,18 @@ EGLint dri2_to_egl_attribute_map[] = {
>>     0,                          /* __DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE */
>>  };
>>
>> +const __DRIconfig *
>> +dri2_get_dri_config(struct dri2_egl_config *conf, EGLint surface_type,
>> +                    EGLenum colorspace)
>> +{
>> +   if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR)
>> +      return surface_type == EGL_WINDOW_BIT ? conf->dri_srgb_double_config :
>> +                                              conf->dri_srgb_single_config;
>> +   else
>> +      return surface_type == EGL_WINDOW_BIT ? conf->dri_double_config :
>> +                                              conf->dri_single_config;
>> +}
>> +
>>  static EGLBoolean
>>  dri2_match_config(const _EGLConfig *conf, const _EGLConfig *criteria)
>>  {
>> @@ -130,6 +143,7 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
>>     struct dri2_egl_display *dri2_dpy;
>>     _EGLConfig base;
>>     unsigned int attrib, value, double_buffer;
>> +   bool srgb = false;
>>     EGLint key, bind_to_texture_rgb, bind_to_texture_rgba;
>>     unsigned int dri_masks[4] = { 0, 0, 0, 0 };
>>     _EGLConfig *matching_config;
>> @@ -202,6 +216,9 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
>>           /* Don't expose visuals with the accumulation buffer. */
>>           if (value > 0)
>>              return NULL;
>> +
>
> Please mark this with a /* fallthrough */ comment so that static
> analysis tools don't think there's a missing break.

The missing "break" is actually a bug. Thanks.

Marek