From 6d9dc4ffa940f9bde48fc68c85b54ab1b839ea49 Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Tue, 11 Mar 2014 11:50:53 +0000
Subject: [PATCH] Add EGL_IMG_cl_image extension

Add support for the experimental EGL_IMG_cl_image extension to EGL, and
the DRI2 EGL driver.

---
 include/EGL/eglmesaext.h            |  5 +++
 include/GL/internal/dri_interface.h | 13 +++++++
 src/egl/drivers/dri2/egl_dri2.c     | 60 +++++++++++++++++++++++++----
 src/egl/main/eglapi.c               |  1 +
 src/egl/main/egldisplay.h           |  2 +
 5 files changed, 73 insertions(+), 8 deletions(-)

diff --git a/include/EGL/eglmesaext.h b/include/EGL/eglmesaext.h
index f0395a8..5d11f3e 100644
--- a/include/EGL/eglmesaext.h
+++ b/include/EGL/eglmesaext.h
@@ -49,6 +49,11 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGIONNOK) (EGLDisplay dpy, EG
 #define EGL_DRM_BUFFER_FORMAT_RGB565_MESA       0x3292
 #endif /* EGL_MESA_drm_image_formats */
 
+#ifndef EGL_IMG_cl_image
+#define EGL_IMG_cl_image 1
+#define EGL_CL_IMAGE_IMG			0x6010
+#endif /* Experimental eglCreateImageKHR target */
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 5102894..b197092 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -1831,6 +1831,19 @@ struct __DRIimageExtensionRec {
                                             const unsigned int modifier_count,
                                             unsigned int use,
                                             void *loaderPrivate);
+
+   /**
+    * Support for experimental EGL_CL_IMAGE_IMG.
+    * Like createImageFromTexture, but from a buffer, the contents
+    * of which depend on the target.
+    *
+    * \since 8
+    */
+   __DRIimage *(*createImageFromBuffer)(__DRIcontext *context,
+                                        int target,
+                                        void *buffer,
+                                        unsigned *error,
+                                        void *loaderPrivate);
 };
 
 
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index eee28eb..dea5899 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -995,6 +995,10 @@ dri2_setup_screen(_EGLDisplay *disp)
          disp->Extensions.EXT_image_dma_buf_import_modifiers = EGL_TRUE;
       }
 #endif
+      if (dri2_dpy->image->base.version >= 8 &&
+          dri2_dpy->image->createImageFromBuffer) {
+         disp->Extensions.IMG_cl_image = EGL_TRUE;
+      }
    }
 
    if (dri2_dpy->flush_control)
@@ -2360,17 +2364,13 @@ dri2_get_sync_values_chromium(_EGLDisplay *disp, _EGLSurface *surf,
    return dri2_dpy->vtbl->get_sync_values(disp, surf, ust, msc, sbc);
 }
 
-/**
- * Set the error code after a call to
- * dri2_egl_image::dri_image::createImageFromTexture.
- */
 static void
-dri2_create_image_khr_texture_error(int dri_error)
+dri2_create_image_khr_error(int dri_error)
 {
    EGLint egl_error = egl_error_from_dri_image_error(dri_error);
 
    if (egl_error != EGL_SUCCESS)
-      _eglError(egl_error, "dri2_create_image_khr_texture");
+      _eglError(egl_error, "dri2_create_image_khr");
 }
 
 static _EGLImage *
@@ -2449,7 +2449,49 @@ dri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
                                               attrs.GLTextureLevel,
                                               &error,
                                               NULL);
-   dri2_create_image_khr_texture_error(error);
+   dri2_create_image_khr_error(error);
+
+   if (!dri2_img->dri_image) {
+      free(dri2_img);
+      return EGL_NO_IMAGE_KHR;
+   }
+   return &dri2_img->base;
+}
+
+static _EGLImage *
+dri2_create_image_img_buffer(_EGLDisplay *disp, _EGLContext *ctx,
+				   EGLenum target,
+				   EGLClientBuffer buffer,
+				   const EGLint *attr_list)
+{
+   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;
+   unsigned error;
+
+   switch (target) {
+   case EGL_CL_IMAGE_IMG:
+      break;
+   default:
+      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
+      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;
+   }
+
+   _eglInitImage(&dri2_img->base, disp);
+
+   dri2_img->dri_image =
+      dri2_dpy->image->createImageFromBuffer(dri2_ctx->dri_context,
+                                              target,
+                                              buffer,
+                                              &error,
+                                              NULL);
+   dri2_create_image_khr_error(error);
 
    if (!dri2_img->dri_image) {
       free(dri2_img);
@@ -2916,7 +2958,7 @@ dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx,
             &error,
             NULL);
    }
-   dri2_create_image_khr_texture_error(error);
+   dri2_create_image_khr_error(error);
 
    if (!dri_image)
       return EGL_NO_IMAGE_KHR;
@@ -3152,6 +3194,8 @@ dri2_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,
    case EGL_WAYLAND_BUFFER_WL:
       return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list);
 #endif
+   case EGL_CL_IMAGE_IMG:
+      return dri2_create_image_img_buffer(disp, ctx, target, buffer, attr_list);
    default:
       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
       return EGL_NO_IMAGE_KHR;
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 17e36af..6ffcff8 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -549,6 +549,7 @@ _eglCreateExtensionsString(_EGLDisplay *disp)
    _EGL_CHECK_EXTENSION(WL_bind_wayland_display);
    _EGL_CHECK_EXTENSION(WL_create_wayland_buffer_from_image);
 
+   _EGL_CHECK_EXTENSION(IMG_cl_image);
 #undef _EGL_CHECK_EXTENSION
 }
 
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index 4d2afbc..5b05dcc 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -150,6 +150,8 @@ struct _egl_extensions
 
    EGLBoolean WL_bind_wayland_display;
    EGLBoolean WL_create_wayland_buffer_from_image;
+
+   EGLBoolean IMG_cl_image;
 };
 
 struct _egl_display
