[Mesa-dev,v3,5/5] egl: Add MESA_image_sRGB extension.

Submitted by John Kåre Alsaker on April 26, 2014, 2:25 p.m.

Details

Message ID 1398522355-29770-5-git-send-email-john.kare.alsaker@gmail.com
State New
Headers show

Not browsing as part of any series.

Commit Message

John Kåre Alsaker April 26, 2014, 2:25 p.m.
This gives applications access to use DRIimage.duplicateImage to create
sRGB and linear views from EGL images.
---
 include/EGL/eglmesaext.h                |   7 ++
 src/egl/drivers/dri2/egl_dri2.c         | 201 +++++++++++++++++++-------------
 src/egl/drivers/dri2/egl_dri2.h         |  11 +-
 src/egl/drivers/dri2/platform_android.c |  36 +++---
 src/egl/drivers/dri2/platform_drm.c     |  36 +++---
 src/egl/drivers/dri2/platform_wayland.c |   2 +-
 src/egl/drivers/dri2/platform_x11.c     |  37 +++---
 src/egl/main/eglcurrent.c               |   3 +
 src/egl/main/egldisplay.h               |   1 +
 src/egl/main/eglimage.c                 |   6 +
 src/egl/main/eglimage.h                 |   3 +
 src/egl/main/eglmisc.c                  |   1 +
 12 files changed, 192 insertions(+), 152 deletions(-)

Patch hide | download patch | download mbox

diff --git a/include/EGL/eglmesaext.h b/include/EGL/eglmesaext.h
index 5fcc527..740f676 100644
--- a/include/EGL/eglmesaext.h
+++ b/include/EGL/eglmesaext.h
@@ -109,6 +109,13 @@  typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETDRMDISPLAYMESA) (int fd);
 #endif
 #endif
 
+#ifndef EGL_MESA_image_sRGB
+#define EGL_MESA_image_sRGB 1
+#define EGL_GAMMA_MESA 0x3290 /* eglCreateImageKHR attribute */
+#define EGL_DEFAULT_MESA 0x3291
+#define EGL_BAD_VIEW_MESA 0x3292
+#endif
+
 #ifndef EGL_WL_bind_wayland_display
 #define EGL_WL_bind_wayland_display 1
 
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index a132964..5b421ac 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -529,6 +529,10 @@  dri2_setup_screen(_EGLDisplay *disp)
          disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
          disp->Extensions.KHR_gl_texture_cubemap_image = EGL_TRUE;
       }
+      if (dri2_dpy->image->base.version >= 9 &&
+          dri2_dpy->image->duplicateImage) {
+         disp->Extensions.MESA_image_sRGB = EGL_TRUE;
+      }
 #ifdef HAVE_DRM_PLATFORM
       if (dri2_dpy->image->base.version >= 8 &&
           dri2_dpy->image->createImageFromDmaBufs) {
@@ -1218,6 +1222,47 @@  dri2_release_tex_image(_EGLDriver *drv,
    return EGL_TRUE;
 }
 
+static EGLBoolean
+dri2_process_dri_image(_EGLDisplay *disp, __DRIimage **dri_image,
+                  const _EGLImageAttribs *attrs)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   __DRIimage *result;
+
+   if (attrs->GammaMESA == EGL_DEFAULT_MESA) {
+      return EGL_TRUE;
+   }
+
+   if (!disp->Extensions.MESA_image_sRGB) {
+      goto bad_view;
+   }
+
+   if (attrs->GammaMESA != EGL_COLORSPACE_sRGB &&
+       attrs->GammaMESA != EGL_COLORSPACE_LINEAR) {
+      goto bad_view;
+   }
+
+   result = dri2_dpy->image->duplicateImage(dri2_dpy->dri_screen,
+                  *dri_image,
+                  attrs->GammaMESA == EGL_COLORSPACE_sRGB ?
+                     __DRI_IMAGE_FLAG_SRGB_VIEW :
+                     __DRI_IMAGE_FLAG_LINEAR_VIEW, NULL);
+
+   if (result == NULL) {
+      goto bad_view;
+   }
+
+   dri2_dpy->image->destroyImage(*dri_image);
+
+   *dri_image = result;
+
+   return EGL_TRUE;
+
+bad_view:
+   _eglError(EGL_BAD_VIEW_MESA, "dri2_create_image");
+   return EGL_FALSE;
+}
+
 static _EGLImage*
 dri2_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
                   EGLenum target, EGLClientBuffer buffer,
@@ -1228,9 +1273,11 @@  dri2_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
                                        attr_list);
 }
 
-static _EGLImage *
-dri2_create_image_from_dri(_EGLDisplay *disp, __DRIimage *dri_image)
+_EGLImage *
+dri2_create_image_from_dri(_EGLDisplay *disp, __DRIimage *dri_image,
+                  const _EGLImageAttribs *attrs)
 {
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    struct dri2_egl_image *dri2_img;
 
    if (dri_image == NULL) {
@@ -1238,26 +1285,35 @@  dri2_create_image_from_dri(_EGLDisplay *disp, __DRIimage *dri_image)
       return NULL;
    }
 
+   if (!dri2_process_dri_image(disp, &dri_image, attrs)) {
+      goto error;
+   }
+
    dri2_img = malloc(sizeof *dri2_img);
    if (!dri2_img) {
       _eglError(EGL_BAD_ALLOC, "dri2_create_image");
-      return NULL;
+      goto error;
    }
 
    if (!_eglInitImage(&dri2_img->base, disp)) {
+      _eglError(EGL_BAD_ALLOC, "dri2_create_image");
       free(dri2_img);
-      return NULL;
+      goto error;
    }
 
    dri2_img->dri_image = dri_image;
 
    return &dri2_img->base;
+
+error:
+   dri2_dpy->image->destroyImage(dri_image);
+   return NULL;
 }
 
 static _EGLImage *
 dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
 				   EGLClientBuffer buffer,
-				   const EGLint *attr_list)
+				   const _EGLImageAttribs *attrs)
 {
    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
@@ -1273,36 +1329,32 @@  dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
       dri2_dpy->image->createImageFromRenderbuffer(dri2_ctx->dri_context,
                                                    renderbuffer, NULL);
 
-   return dri2_create_image_from_dri(disp, dri_image);
+   return dri2_create_image_from_dri(disp, dri_image, attrs);
 }
 
 #ifdef HAVE_DRM_PLATFORM
 static _EGLImage *
 dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
-				  EGLClientBuffer buffer, const EGLint *attr_list)
+				  EGLClientBuffer buffer,
+				  const _EGLImageAttribs *attrs)
 {
    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
-   EGLint format, name, pitch, err;
-   _EGLImageAttribs attrs;
+   EGLint format, name, pitch;
    __DRIimage *dri_image;
 
    name = (EGLint) (uintptr_t) buffer;
 
-   err = _eglParseImageAttribList(&attrs, disp, attr_list);
-   if (err != EGL_SUCCESS)
-      return NULL;
-
-   if (attrs.Width <= 0 || attrs.Height <= 0 ||
-       attrs.DRMBufferStrideMESA <= 0) {
+   if (attrs->Width <= 0 || attrs->Height <= 0 ||
+       attrs->DRMBufferStrideMESA <= 0) {
       _eglError(EGL_BAD_PARAMETER,
 		"bad width, height or stride");
       return NULL;
    }
 
-   switch (attrs.DRMBufferFormatMESA) {
+   switch (attrs->DRMBufferFormatMESA) {
    case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
       format = __DRI_IMAGE_FORMAT_ARGB8888;
-      pitch = attrs.DRMBufferStrideMESA;
+      pitch = attrs->DRMBufferStrideMESA;
       break;
    default:
       _eglError(EGL_BAD_PARAMETER,
@@ -1312,14 +1364,14 @@  dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
 
    dri_image =
       dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
-					   attrs.Width,
-					   attrs.Height,
+					   attrs->Width,
+					   attrs->Height,
 					   format,
 					   name,
 					   pitch,
 					   NULL);
 
-   return dri2_create_image_from_dri(disp, dri_image);
+   return dri2_create_image_from_dri(disp, dri_image, attrs);
 }
 #endif
 
@@ -1346,14 +1398,12 @@  static const struct wl_drm_components_descriptor {
 static _EGLImage *
 dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx,
 				    EGLClientBuffer _buffer,
-				    const EGLint *attr_list)
+				    const _EGLImageAttribs *attrs)
 {
    struct wl_drm_buffer *buffer;
    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    const struct wl_drm_components_descriptor *f;
    __DRIimage *dri_image;
-   _EGLImageAttribs attrs;
-   EGLint err;
    int32_t plane;
 
    buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm,
@@ -1361,13 +1411,7 @@  dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx,
    if (!buffer)
        return NULL;
 
-   err = _eglParseImageAttribList(&attrs, disp, attr_list);
-   plane = attrs.PlaneWL;
-   if (err != EGL_SUCCESS) {
-      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer");
-      return NULL;
-   }
-
+   plane = attrs->PlaneWL;
    f = buffer->driver_format;
    if (plane < 0 || plane >= f->nplanes) {
       _eglError(EGL_BAD_PARAMETER,
@@ -1382,7 +1426,7 @@  dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx,
       return NULL;
    }
 
-   return dri2_create_image_from_dri(disp, dri_image);
+   return dri2_create_image_from_dri(disp, dri_image, attrs);
 }
 #endif
 
@@ -1424,13 +1468,12 @@  static _EGLImage *
 dri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
 				   EGLenum target,
 				   EGLClientBuffer buffer,
-				   const EGLint *attr_list)
+				   const _EGLImageAttribs *attrs)
 {
    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
-   struct dri2_egl_image *dri2_img;
+   __DRIimage *dri_image;
    GLuint texture = (GLuint) (uintptr_t) buffer;
-   _EGLImageAttribs attrs;
    GLuint depth;
    GLenum gl_target;
    unsigned error;
@@ -1440,16 +1483,13 @@  dri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
       return EGL_NO_IMAGE_KHR;
    }
 
-   if (_eglParseImageAttribList(&attrs, disp, attr_list) != EGL_SUCCESS)
-      return EGL_NO_IMAGE_KHR;
-
    switch (target) {
    case EGL_GL_TEXTURE_2D_KHR:
       depth = 0;
       gl_target = GL_TEXTURE_2D;
       break;
    case EGL_GL_TEXTURE_3D_KHR:
-      depth = attrs.GLTextureZOffset;
+      depth = attrs->GLTextureZOffset;
       gl_target = GL_TEXTURE_3D;
       break;
    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
@@ -1466,33 +1506,17 @@  dri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
       return EGL_NO_IMAGE_KHR;
    }
 
-   dri2_img = malloc(sizeof *dri2_img);
-   if (!dri2_img) {
-      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
-      return EGL_NO_IMAGE_KHR;
-   }
-
-   if (!_eglInitImage(&dri2_img->base, disp)) {
-      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
-      free(dri2_img);
-      return EGL_NO_IMAGE_KHR;
-   }
-
-   dri2_img->dri_image =
+   dri_image =
       dri2_dpy->image->createImageFromTexture(dri2_ctx->dri_context,
                                               gl_target,
                                               texture,
                                               depth,
-                                              attrs.GLTextureLevel,
+                                              attrs->GLTextureLevel,
                                               &error,
-                                              dri2_img);
+                                              NULL);
    dri2_create_image_khr_texture_error(error);
 
-   if (!dri2_img->dri_image) {
-      free(dri2_img);
-      return EGL_NO_IMAGE_KHR;
-   }
-   return &dri2_img->base;
+   return dri2_create_image_from_dri(disp, dri_image, attrs);
 }
 
 static struct wl_buffer*
@@ -1693,12 +1717,11 @@  dri2_take_dma_buf_ownership(const int *fds, unsigned num_fds)
 
 static _EGLImage *
 dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx,
-			  EGLClientBuffer buffer, const EGLint *attr_list)
+			  EGLClientBuffer buffer,
+			  const _EGLImageAttribs *attrs)
 {
    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    _EGLImage *res;
-   EGLint err;
-   _EGLImageAttribs attrs;
    __DRIimage *dri_image;
    unsigned num_fds;
    unsigned i;
@@ -1718,33 +1741,27 @@  dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx,
       return NULL;
    }
 
-   err = _eglParseImageAttribList(&attrs, disp, attr_list);
-   if (err != EGL_SUCCESS) {
-      _eglError(err, "bad attribute");
+   if (!dri2_check_dma_buf_attribs(attrs))
       return NULL;
-   }
 
-   if (!dri2_check_dma_buf_attribs(&attrs))
-      return NULL;
-
-   num_fds = dri2_check_dma_buf_format(&attrs);
+   num_fds = dri2_check_dma_buf_format(attrs);
    if (!num_fds)
       return NULL;
 
    for (i = 0; i < num_fds; ++i) {
-      fds[i] = attrs.DMABufPlaneFds[i].Value;
-      pitches[i] = attrs.DMABufPlanePitches[i].Value;
-      offsets[i] = attrs.DMABufPlaneOffsets[i].Value;
+      fds[i] = attrs->DMABufPlaneFds[i].Value;
+      pitches[i] = attrs->DMABufPlanePitches[i].Value;
+      offsets[i] = attrs->DMABufPlaneOffsets[i].Value;
    }
 
    dri_image =
       dri2_dpy->image->createImageFromDmaBufs(dri2_dpy->dri_screen,
-         attrs.Width, attrs.Height, attrs.DMABufFourCC.Value,
+         attrs->Width, attrs->Height, attrs->DMABufFourCC.Value,
          fds, num_fds, pitches, offsets,
-         attrs.DMABufYuvColorSpaceHint.Value,
-         attrs.DMABufSampleRangeHint.Value,
-         attrs.DMABufChromaHorizontalSiting.Value,
-         attrs.DMABufChromaVerticalSiting.Value,
+         attrs->DMABufYuvColorSpaceHint.Value,
+         attrs->DMABufSampleRangeHint.Value,
+         attrs->DMABufChromaHorizontalSiting.Value,
+         attrs->DMABufChromaVerticalSiting.Value,
          &error,
          NULL);
    dri2_create_image_khr_texture_error(error);
@@ -1752,7 +1769,7 @@  dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx,
    if (!dri_image)
       return EGL_NO_IMAGE_KHR;
 
-   res = dri2_create_image_from_dri(disp, dri_image);
+   res = dri2_create_image_from_dri(disp, dri_image, attrs);
    if (res)
       dri2_take_dma_buf_ownership(fds, num_fds);
 
@@ -1763,7 +1780,7 @@  dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx,
 _EGLImage *
 dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
 		      _EGLContext *ctx, EGLenum target,
-		      EGLClientBuffer buffer, const EGLint *attr_list)
+		      EGLClientBuffer buffer, const _EGLImageAttribs *attrs)
 {
    (void) drv;
 
@@ -1775,20 +1792,20 @@  dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
    case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
    case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
-      return dri2_create_image_khr_texture(disp, ctx, target, buffer, attr_list);
+      return dri2_create_image_khr_texture(disp, ctx, target, buffer, attrs);
    case EGL_GL_RENDERBUFFER_KHR:
-      return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
+      return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attrs);
 #ifdef HAVE_DRM_PLATFORM
    case EGL_DRM_BUFFER_MESA:
-      return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list);
+      return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attrs);
 #endif
 #ifdef HAVE_WAYLAND_PLATFORM
    case EGL_WAYLAND_BUFFER_WL:
-      return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list);
+      return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attrs);
 #endif
 #ifdef HAVE_DRM_PLATFORM
    case EGL_LINUX_DMA_BUF_EXT:
-      return dri2_create_image_dma_buf(disp, ctx, buffer, attr_list);
+      return dri2_create_image_dma_buf(disp, ctx, buffer, attrs);
 #endif
    default:
       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
@@ -1796,6 +1813,22 @@  dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
    }
 }
 
+_EGLImage *
+dri2_create_image_khr_default(_EGLDriver *drv, _EGLDisplay *disp,
+                          _EGLContext *ctx, EGLenum target,
+                          EGLClientBuffer buffer, const EGLint *attr_list)
+{
+   EGLint err;
+   _EGLImageAttribs attrs;
+
+   err = _eglParseImageAttribList(&attrs, disp, attr_list);
+   if (err != EGL_SUCCESS) {
+      return NULL;
+   }
+
+   return dri2_create_image_khr(drv, disp, ctx, target, buffer, &attrs);
+}
+
 static EGLBoolean
 dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image)
 {
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index e62e265..84c400f 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -311,9 +311,18 @@  dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
 		const unsigned int *rgba_masks);
 
 _EGLImage *
+dri2_create_image_from_dri(_EGLDisplay *disp, __DRIimage *dri_image,
+                  const _EGLImageAttribs *attrs);
+
+_EGLImage *
 dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
 		      _EGLContext *ctx, EGLenum target,
-		      EGLClientBuffer buffer, const EGLint *attr_list);
+		      EGLClientBuffer buffer, const _EGLImageAttribs *attrs);
+
+_EGLImage *
+dri2_create_image_khr_default(_EGLDriver *drv, _EGLDisplay *disp,
+                          _EGLContext *ctx, EGLenum target,
+                          EGLClientBuffer buffer, const EGLint *attr_list);
 
 EGLBoolean
 dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp);
diff --git a/src/egl/drivers/dri2/platform_android.c b/src/egl/drivers/dri2/platform_android.c
index 7b1db76..3f40eab 100644
--- a/src/egl/drivers/dri2/platform_android.c
+++ b/src/egl/drivers/dri2/platform_android.c
@@ -325,10 +325,11 @@  droid_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
 
 static _EGLImage *
 dri2_create_image_android_native_buffer(_EGLDisplay *disp, _EGLContext *ctx,
-                                        struct ANativeWindowBuffer *buf)
+                                        struct ANativeWindowBuffer *buf,
+                                        const _EGLImageAttribs *attrs)
 {
    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
-   struct dri2_egl_image *dri2_img;
+   __DRIimage *dri_image;
    int name;
    EGLint format;
 
@@ -380,18 +381,7 @@  dri2_create_image_android_native_buffer(_EGLDisplay *disp, _EGLContext *ctx,
       break;
    }
 
-   dri2_img = calloc(1, sizeof(*dri2_img));
-   if (!dri2_img) {
-      _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm");
-      return NULL;
-   }
-
-   if (!_eglInitImage(&dri2_img->base, disp)) {
-      free(dri2_img);
-      return NULL;
-   }
-
-   dri2_img->dri_image =
+   dri_image =
       dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
 					   buf->width,
 					   buf->height,
@@ -399,13 +389,8 @@  dri2_create_image_android_native_buffer(_EGLDisplay *disp, _EGLContext *ctx,
 					   name,
 					   buf->stride,
 					   dri2_img);
-   if (!dri2_img->dri_image) {
-      free(dri2_img);
-      _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm");
-      return NULL;
-   }
 
-   return &dri2_img->base;
+   return dri2_create_image_from_dri(disp, dri_image, attrs);
 }
 
 static _EGLImage *
@@ -413,12 +398,19 @@  droid_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
 		       _EGLContext *ctx, EGLenum target,
 		       EGLClientBuffer buffer, const EGLint *attr_list)
 {
+   EGLint err;
+   _EGLImageAttribs attrs;
+
+   err = _eglParseImageAttribList(&attrs, disp, attr_list);
+   if (err != EGL_SUCCESS)
+      return NULL;
+
    switch (target) {
    case EGL_NATIVE_BUFFER_ANDROID:
       return dri2_create_image_android_native_buffer(disp, ctx,
-            (struct ANativeWindowBuffer *) buffer);
+            (struct ANativeWindowBuffer *) buffer, &attrs);
    default:
-      return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
+      return dri2_create_image_khr(drv, disp, ctx, target, buffer, &attrs);
    }
 }
 
diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c
index 9a7633a..80eafea 100644
--- a/src/egl/drivers/dri2/platform_drm.c
+++ b/src/egl/drivers/dri2/platform_drm.c
@@ -407,31 +407,16 @@  dri2_drm_query_buffer_age(_EGLDriver *drv,
 
 static _EGLImage *
 dri2_drm_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
-                                 EGLClientBuffer buffer, const EGLint *attr_list)
+                                 EGLClientBuffer buffer,
+                                 const _EGLImageAttribs *attrs)
 {
    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    struct gbm_dri_bo *dri_bo = gbm_dri_bo((struct gbm_bo *) buffer);
-   struct dri2_egl_image *dri2_img;
+   __DRIimage *dri_image;
 
-   dri2_img = malloc(sizeof *dri2_img);
-   if (!dri2_img) {
-      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr_pixmap");
-      return NULL;
-   }
-
-   if (!_eglInitImage(&dri2_img->base, disp)) {
-      free(dri2_img);
-      return NULL;
-   }
+   dri_image = dri2_dpy->image->dupImage(dri_bo->image, NULL);
 
-   dri2_img->dri_image = dri2_dpy->image->dupImage(dri_bo->image, dri2_img);
-   if (dri2_img->dri_image == NULL) {
-      free(dri2_img);
-      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr_pixmap");
-      return NULL;
-   }
-
-   return &dri2_img->base;
+   return dri2_create_image_from_dri(disp, dri_image, attrs);
 }
 
 static _EGLImage *
@@ -439,13 +424,20 @@  dri2_drm_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
                           _EGLContext *ctx, EGLenum target,
                           EGLClientBuffer buffer, const EGLint *attr_list)
 {
+   EGLint err;
+   _EGLImageAttribs attrs;
+
    (void) drv;
 
+   err = _eglParseImageAttribList(&attrs, disp, attr_list);
+   if (err != EGL_SUCCESS)
+      return NULL;
+
    switch (target) {
    case EGL_NATIVE_PIXMAP_KHR:
-      return dri2_drm_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
+      return dri2_drm_create_image_khr_pixmap(disp, ctx, buffer, &attrs);
    default:
-      return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
+      return dri2_create_image_khr(drv, disp, ctx, target, buffer, &attrs);
    }
 }
 
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index 37dcf19..113c62a 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -955,7 +955,7 @@  static struct dri2_egl_display_vtbl dri2_wl_display_vtbl = {
    .create_pixmap_surface = dri2_wl_create_pixmap_surface,
    .create_pbuffer_surface = dri2_fallback_create_pbuffer_surface,
    .destroy_surface = dri2_wl_destroy_surface,
-   .create_image = dri2_create_image_khr,
+   .create_image = dri2_create_image_khr_default,
    .swap_interval = dri2_wl_swap_interval,
    .swap_buffers = dri2_wl_swap_buffers,
    .swap_buffers_with_damage = dri2_wl_swap_buffers_with_damage,
diff --git a/src/egl/drivers/dri2/platform_x11.c b/src/egl/drivers/dri2/platform_x11.c
index 7b585a2..995869c 100644
--- a/src/egl/drivers/dri2/platform_x11.c
+++ b/src/egl/drivers/dri2/platform_x11.c
@@ -896,10 +896,11 @@  dri2_x11_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
 
 static _EGLImage *
 dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
-			     EGLClientBuffer buffer, const EGLint *attr_list)
+			     EGLClientBuffer buffer,
+			     const _EGLImageAttribs *attrs)
 {
    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
-   struct dri2_egl_image *dri2_img;
+   __DRIimage *dri_image;
    unsigned int attachments[1];
    xcb_drawable_t drawable;
    xcb_dri2_get_buffers_cookie_t buffers_cookie;
@@ -953,35 +954,20 @@  dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
       return NULL;
    }
 
-   dri2_img = malloc(sizeof *dri2_img);
-   if (!dri2_img) {
-      free(buffers_reply);
-      free(geometry_reply);
-      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
-      return EGL_NO_IMAGE_KHR;
-   }
-
-   if (!_eglInitImage(&dri2_img->base, disp)) {
-      free(buffers_reply);
-      free(geometry_reply);
-      free(dri2_img);
-      return EGL_NO_IMAGE_KHR;
-   }
-
    stride = buffers[0].pitch / buffers[0].cpp;
-   dri2_img->dri_image =
+   dri_image =
       dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
 					   buffers_reply->width,
 					   buffers_reply->height,
 					   format,
 					   buffers[0].name,
 					   stride,
-					   dri2_img);
+					   NULL);
 
    free(buffers_reply);
    free(geometry_reply);
 
-   return &dri2_img->base;
+   return dri2_create_image_from_dri(disp, dri_image, attrs);
 }
 
 static _EGLImage *
@@ -989,13 +975,20 @@  dri2_x11_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
 			  _EGLContext *ctx, EGLenum target,
 			  EGLClientBuffer buffer, const EGLint *attr_list)
 {
+   EGLint err;
+   _EGLImageAttribs attrs;
+
    (void) drv;
 
+   err = _eglParseImageAttribList(&attrs, disp, attr_list);
+   if (err != EGL_SUCCESS)
+      return NULL;
+
    switch (target) {
    case EGL_NATIVE_PIXMAP_KHR:
-      return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
+      return dri2_create_image_khr_pixmap(disp, ctx, buffer, &attrs);
    default:
-      return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
+      return dri2_create_image_khr(drv, disp, ctx, target, buffer, &attrs);
    }
 }
 
diff --git a/src/egl/main/eglcurrent.c b/src/egl/main/eglcurrent.c
index fcb732d..03ca063 100644
--- a/src/egl/main/eglcurrent.c
+++ b/src/egl/main/eglcurrent.c
@@ -325,6 +325,9 @@  _eglError(EGLint errCode, const char *msg)
          s = "EGL_BAD_MODE_MESA";
          break;
 #endif
+      case EGL_BAD_VIEW_MESA:
+         s = "EGL_BAD_VIEW_MESA";
+         break;
       default:
          s = "other EGL error";
       }
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index 970c21a..5b9cee3 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -89,6 +89,7 @@  struct _egl_extensions
    EGLBoolean MESA_copy_context;
    EGLBoolean MESA_drm_display;
    EGLBoolean MESA_drm_image;
+   EGLBoolean MESA_image_sRGB;
    EGLBoolean MESA_configless_context;
 
    EGLBoolean WL_bind_wayland_display;
diff --git a/src/egl/main/eglimage.c b/src/egl/main/eglimage.c
index 818b597..80a8e4d 100644
--- a/src/egl/main/eglimage.c
+++ b/src/egl/main/eglimage.c
@@ -49,6 +49,7 @@  _eglParseImageAttribList(_EGLImageAttribs *attrs, _EGLDisplay *dpy,
    attrs->ImagePreserved = EGL_FALSE;
    attrs->GLTextureLevel = 0;
    attrs->GLTextureZOffset = 0;
+   attrs->GammaMESA = EGL_DEFAULT_MESA;
 
    if (!attrib_list)
       return err;
@@ -88,6 +89,11 @@  _eglParseImageAttribList(_EGLImageAttribs *attrs, _EGLDisplay *dpy,
          attrs->DRMBufferStrideMESA = val;
          break;
 
+      /* EGL_MESA_image_sRGB */
+      case EGL_GAMMA_MESA:
+         attrs->GammaMESA = val;
+         break;
+
       /* EGL_WL_bind_wayland_display */
       case EGL_WAYLAND_PLANE_WL:
          attrs->PlaneWL = val;
diff --git a/src/egl/main/eglimage.h b/src/egl/main/eglimage.h
index 1b4d6cd..996de7b 100644
--- a/src/egl/main/eglimage.h
+++ b/src/egl/main/eglimage.h
@@ -56,6 +56,9 @@  struct _egl_image_attribs
    EGLint DRMBufferUseMESA;
    EGLint DRMBufferStrideMESA;
 
+   /* EGL_MESA_image_sRGB */
+   EGLint GammaMESA;
+
    /* EGL_WL_bind_wayland_display */
    EGLint PlaneWL;
 
diff --git a/src/egl/main/eglmisc.c b/src/egl/main/eglmisc.c
index 65669d8..e5ccd81 100644
--- a/src/egl/main/eglmisc.c
+++ b/src/egl/main/eglmisc.c
@@ -90,6 +90,7 @@  _eglUpdateExtensionsString(_EGLDisplay *dpy)
    _EGL_CHECK_EXTENSION(MESA_copy_context);
    _EGL_CHECK_EXTENSION(MESA_drm_display);
    _EGL_CHECK_EXTENSION(MESA_drm_image);
+   _EGL_CHECK_EXTENSION(MESA_image_sRGB);
    _EGL_CHECK_EXTENSION(MESA_configless_context);
 
    _EGL_CHECK_EXTENSION(WL_bind_wayland_display);