From afc48c7cfe5e859832e753a987b9405544ce82e8 Mon Sep 17 00:00:00 2001
From: Frank Binns <frank.binns@imgtec.com>
Date: Tue, 29 Jan 2019 14:36:25 +0000
Subject: [PATCH] egl: add support for EXT_image_gl_colorspace

---
 src/egl/drivers/dri2/egl_dri2.c | 57 +++++++++++++++++++++++++++++++--
 src/egl/main/eglapi.c           |  1 +
 src/egl/main/egldisplay.h       |  1 +
 src/egl/main/eglimage.c         | 14 ++++++++
 src/egl/main/eglimage.h         |  3 ++
 5 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index 2f8414e..6b26ff9 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -1084,6 +1084,9 @@ dri2_setup_screen(_EGLDisplay *disp)
           dri2_dpy->image->createImageFromBuffer) {
          disp->Extensions.IMG_cl_image = EGL_TRUE;
       }
+
+      if (disp->Extensions.KHR_gl_colorspace)
+         disp->Extensions.EXT_image_gl_colorspace = EGL_TRUE;
    }
 
    if (dri2_dpy->flush_control)
@@ -2724,6 +2727,11 @@ dri2_create_image_wayland_wl_buffer_tizen(_EGLDisplay *disp, _EGLContext *ctx,
       return NULL;
    }
 
+   if (attrs.GLColorspace != EGL_GL_COLORSPACE_DEFAULT_EXT) {
+      _eglError(EGL_BAD_MATCH, "unsupported colorspace");
+      return NULL;
+   }
+
    if (tbm_surface_get_info(tbm_surf, &info)) {
       _eglError(EGL_BAD_PARAMETER, "tbm_surface_get_info");
       return NULL;
@@ -2799,6 +2807,11 @@ dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx,
    if (!_eglParseImageAttribList(&attrs, disp, attr_list))
       return NULL;
 
+   if (attrs.GLColorspace != EGL_GL_COLORSPACE_DEFAULT_EXT) {
+      _eglError(EGL_BAD_MATCH, "unsupported colorspace");
+      return NULL;
+   }
+
    plane = attrs.PlaneWL;
    f = buffer->driver_format;
    if (plane < 0 || plane >= f->nplanes) {
@@ -2862,6 +2875,11 @@ dri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
    if (!_eglParseImageAttribList(&attrs, disp, attr_list))
       return EGL_NO_IMAGE_KHR;
 
+   if (attrs.GLColorspace != EGL_GL_COLORSPACE_DEFAULT_EXT) {
+      _eglError(EGL_BAD_MATCH, "unsupported colorspace");
+      return EGL_NO_IMAGE_KHR;
+   }
+
    switch (target) {
    case EGL_GL_TEXTURE_2D_KHR:
       if (!disp->Extensions.KHR_gl_texture_2D_image) {
@@ -3007,6 +3025,11 @@ dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
       return NULL;
    }
 
+   if (attrs.GLColorspace != EGL_GL_COLORSPACE_DEFAULT_EXT) {
+      _eglError(EGL_BAD_MATCH, "unsupported colorspace");
+      return NULL;
+   }
+
    switch (attrs.DRMBufferFormatMESA) {
    case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
       format = __DRI_IMAGE_FORMAT_ARGB8888;
@@ -3189,6 +3212,23 @@ dri2_num_fourcc_format_planes(EGLint format)
    }
 }
 
+static int
+dri2_get_srgb_fourcc(int drm_fourcc)
+{
+   switch (drm_fourcc) {
+   case DRM_FORMAT_ARGB8888:
+      return __DRI_IMAGE_FOURCC_SARGB8888;
+   case DRM_FORMAT_ABGR8888:
+      return __DRI_IMAGE_FOURCC_SABGR8888;
+   case DRM_FORMAT_BGR888:
+      return __DRI_IMAGE_FOURCC_SBGR888;
+   default:
+      _eglLog(_EGL_DEBUG, "%s: no matching sRGB FourCC for %#x",
+              __func__, drm_fourcc);
+      return 0;
+   }
+}
+
 /* Returns the total number of file descriptors. Zero indicates an error. */
 static unsigned
 dri2_check_dma_buf_format(const _EGLImageAttribs *attrs)
@@ -3334,6 +3374,7 @@ dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx,
    int fds[DMA_BUF_MAX_PLANES];
    int pitches[DMA_BUF_MAX_PLANES];
    int offsets[DMA_BUF_MAX_PLANES];
+   int fourcc;
    uint64_t modifier;
    bool has_modifier = false;
    unsigned error;
@@ -3359,6 +3400,18 @@ dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx,
    if (!num_fds)
       return NULL;
 
+   if (attrs.GLColorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
+      fourcc = dri2_get_srgb_fourcc(attrs.DMABufFourCC.Value);
+      if (fourcc == 0) {
+         _eglError(EGL_BAD_MATCH, "unsupported colorspace");
+         return NULL;
+      }
+   } else {
+      assert(attrs.GLColorspace == EGL_GL_COLORSPACE_LINEAR_KHR ||
+             attrs.GLColorspace == EGL_GL_COLORSPACE_DEFAULT_EXT);
+      fourcc = attrs.DMABufFourCC.Value;
+   }
+
    for (unsigned i = 0; i < num_fds; ++i) {
       fds[i] = attrs.DMABufPlaneFds[i].Value;
       pitches[i] = attrs.DMABufPlanePitches[i].Value;
@@ -3403,7 +3456,7 @@ dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx,
       }
       dri_image =
          dri2_dpy->image->createImageFromDmaBufs2(dri2_dpy->dri_screen,
-            attrs.Width, attrs.Height, attrs.DMABufFourCC.Value,
+            attrs.Width, attrs.Height, fourcc,
             modifier, fds, num_fds, pitches, offsets,
             attrs.DMABufYuvColorSpaceHint.Value,
             attrs.DMABufSampleRangeHint.Value,
@@ -3415,7 +3468,7 @@ dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx,
    else {
       dri_image =
          dri2_dpy->image->createImageFromDmaBufs(dri2_dpy->dri_screen,
-            attrs.Width, attrs.Height, attrs.DMABufFourCC.Value,
+            attrs.Width, attrs.Height, fourcc,
             fds, num_fds, pitches, offsets,
             attrs.DMABufYuvColorSpaceHint.Value,
             attrs.DMABufSampleRangeHint.Value,
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index e4f2c43..2d3931d 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -508,6 +508,7 @@ _eglCreateExtensionsString(_EGLDisplay *disp)
    _EGL_CHECK_EXTENSION(EXT_create_context_robustness);
    _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import);
    _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import_modifiers);
+   _EGL_CHECK_EXTENSION(EXT_image_gl_colorspace);
    _EGL_CHECK_EXTENSION(EXT_protected_surface);
    _EGL_CHECK_EXTENSION(EXT_surface_CTA861_3_metadata);
    _EGL_CHECK_EXTENSION(EXT_surface_SMPTE2086_metadata);
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index 8489af9..6e5b29f 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -108,6 +108,7 @@ struct _egl_extensions
    EGLBoolean EXT_create_context_robustness;
    EGLBoolean EXT_image_dma_buf_import;
    EGLBoolean EXT_image_dma_buf_import_modifiers;
+   EGLBoolean EXT_image_gl_colorspace;
    EGLBoolean EXT_pixel_format_float;
    EGLBoolean EXT_protected_surface;
    EGLBoolean EXT_surface_CTA861_3_metadata;
diff --git a/src/egl/main/eglimage.c b/src/egl/main/eglimage.c
index 64bf7f2..73d4e85 100644
--- a/src/egl/main/eglimage.c
+++ b/src/egl/main/eglimage.c
@@ -46,6 +46,18 @@ _eglParseKHRImageAttribs(_EGLImageAttribs *attrs, _EGLDisplay *disp,
       attrs->ImagePreserved = val;
       break;
 
+   case EGL_GL_COLORSPACE_KHR:
+      if (!disp->Extensions.EXT_image_gl_colorspace)
+         return EGL_BAD_PARAMETER;
+
+      if (val != EGL_GL_COLORSPACE_SRGB_KHR &&
+          val != EGL_GL_COLORSPACE_LINEAR_KHR &&
+          val != EGL_GL_COLORSPACE_DEFAULT_EXT)
+         return EGL_BAD_PARAMETER;
+
+      attrs->GLColorspace = val;
+      break;
+
    case EGL_GL_TEXTURE_LEVEL_KHR:
       if (!disp->Extensions.KHR_gl_texture_2D_image)
          return EGL_BAD_PARAMETER;
@@ -285,6 +297,8 @@ _eglParseImageAttribList(_EGLImageAttribs *attrs, _EGLDisplay *disp,
 
    memset(attrs, 0, sizeof(*attrs));
 
+   attrs->GLColorspace = EGL_GL_COLORSPACE_DEFAULT_EXT;
+
    if (!attrib_list)
       return EGL_TRUE;
 
diff --git a/src/egl/main/eglimage.h b/src/egl/main/eglimage.h
index 9837f05..fc02d7a 100644
--- a/src/egl/main/eglimage.h
+++ b/src/egl/main/eglimage.h
@@ -80,6 +80,9 @@ struct _egl_image_attribs
    struct _egl_image_attrib_int DMABufChromaHorizontalSiting;
    struct _egl_image_attrib_int DMABufChromaVerticalSiting;
 
+   /* EGL_EXT_image_gl_colorspace */
+   EGLint GLColorspace;
+
    /* EGL_EXT_protected_surface */
    EGLBoolean ProtectedContent;
 };
