Mesa (master): egl_dri2: Add support for MESA_image_drm

Kristian Høgsberg krh at kemper.freedesktop.org
Wed Aug 25 13:20:49 UTC 2010


Module: Mesa
Branch: master
Commit: 5aaa53e66cc49bf0d28ec53bdab4e3b7f714e5ba
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=5aaa53e66cc49bf0d28ec53bdab4e3b7f714e5ba

Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Thu Jun  3 21:36:40 2010 -0400

egl_dri2: Add support for MESA_image_drm

---

 include/GL/internal/dri_interface.h |   19 +++
 src/egl/drivers/dri2/egl_dri2.c     |  223 +++++++++++++++++++++++++++++++++++
 2 files changed, 242 insertions(+), 0 deletions(-)

diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 2c85464..ff83ff1 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -789,6 +789,17 @@ struct __DRIdri2ExtensionRec {
 #define __DRI_IMAGE_FORMAT_XRGB8888     0x1002
 #define __DRI_IMAGE_FORMAT_ARGB8888     0x1003
 
+#define __DRI_IMAGE_USE_SHARE		0x0001
+#define __DRI_IMAGE_USE_SCANOUT		0x0002
+
+/**
+ * queryImage attributes
+ */
+
+#define __DRI_IMAGE_ATTRIB_STRIDE	0x2000
+#define __DRI_IMAGE_ATTRIB_HANDLE	0x2001
+#define __DRI_IMAGE_ATTRIB_NAME		0x2002
+
 typedef struct __DRIimageRec          __DRIimage;
 typedef struct __DRIimageExtensionRec __DRIimageExtension;
 struct __DRIimageExtensionRec {
@@ -804,8 +815,16 @@ struct __DRIimageExtensionRec {
 					       void *loaderPrivate);
 
     void (*destroyImage)(__DRIimage *image);
+
+    __DRIimage *(*createImage)(__DRIscreen *screen,
+			       int width, int height, int format,
+			       unsigned int use,
+			       void *loaderPrivate);
+
+   GLboolean (*queryImage)(__DRIimage *image, int attrib, int *value);
 };
 
+
 /**
  * This extension must be implemented by the loader and passed to the
  * driver at screen creation time.  The EGLImage entry points in the
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index efb93bc..2b78bcc 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -836,6 +836,7 @@ dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp,
 	 goto cleanup_configs;
    }
 
+   disp->Extensions.MESA_drm_image = EGL_TRUE;
    disp->Extensions.KHR_image_base = EGL_TRUE;
    disp->Extensions.KHR_image_pixmap = EGL_TRUE;
    disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
@@ -994,6 +995,7 @@ dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp,
    for (i = 0; dri2_dpy->driver_configs[i]; i++)
       dri2_add_config(disp, dri2_dpy->driver_configs[i], i + 1, 0, 0);
 
+   disp->Extensions.MESA_drm_image = EGL_TRUE;
    disp->Extensions.KHR_image_base = EGL_TRUE;
    disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
    disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
@@ -1621,6 +1623,96 @@ dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
 }
 
 static _EGLImage *
+dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
+				  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;
+   EGLint width, height, format, name, stride, pitch, i, err;
+
+   name = (EGLint) buffer;
+
+   err = EGL_SUCCESS;
+   width = 0;
+   height = 0;
+   format = 0;
+   stride = 0;
+
+   for (i = 0; attr_list[i] != EGL_NONE; i++) {
+      EGLint attr = attr_list[i++];
+      EGLint val = attr_list[i];
+
+      switch (attr) {
+      case EGL_WIDTH:
+	 width = val;
+         break;
+      case EGL_HEIGHT:
+	 height = val;
+         break;
+      case EGL_DRM_BUFFER_FORMAT_MESA:
+	 format = val;
+         break;
+      case EGL_DRM_BUFFER_STRIDE_MESA:
+	 stride = val;
+         break;
+      default:
+         err = EGL_BAD_ATTRIBUTE;
+         break;
+      }
+
+      if (err != EGL_SUCCESS) {
+         _eglLog(_EGL_WARNING, "bad image attribute 0x%04x", attr);
+	 return NULL;
+      }
+   }
+
+   if (width <= 0 || height <= 0 || stride <= 0) {
+      _eglError(EGL_BAD_PARAMETER,
+		"bad width, height or stride");
+      return NULL;
+   }
+
+   switch (format) {
+   case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
+      format = __DRI_IMAGE_FORMAT_ARGB8888;
+      pitch = stride;
+      break;
+   default:
+      _eglError(EGL_BAD_PARAMETER,
+		"dri2_create_image_khr: unsupported pixmap depth");
+      return NULL;
+   }
+
+   dri2_img = malloc(sizeof *dri2_img);
+   if (!dri2_img) {
+      _eglError(EGL_BAD_ALLOC, "dri2_create_image_mesa_drm");
+      return NULL;
+   }
+
+   if (!_eglInitImage(&dri2_img->base, disp, attr_list)) {
+      free(dri2_img);
+      return NULL;
+   }
+
+   dri2_img->dri_image =
+      dri2_dpy->image->createImageFromName(dri2_ctx->dri_context,
+					   width,
+					   height,
+					   format,
+					   name,
+					   pitch,
+					   dri2_img);
+   if (dri2_img->dri_image == NULL) {
+      free(dri2_img);
+      _eglError(EGL_BAD_ALLOC, "dri2_create_image_mesa_drm");
+      return NULL;
+   }
+
+   return &dri2_img->base;
+}
+
+static _EGLImage *
 dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
 		      _EGLContext *ctx, EGLenum target,
 		      EGLClientBuffer buffer, const EGLint *attr_list)
@@ -1630,6 +1722,8 @@ dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
       return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
    case EGL_GL_RENDERBUFFER_KHR:
       return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
+   case EGL_DRM_BUFFER_MESA:
+      return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list);
    default:
       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
       return EGL_NO_IMAGE_KHR;
@@ -1648,6 +1742,133 @@ dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image)
    return EGL_TRUE;
 }
 
+static _EGLImage *
+dri2_create_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp,
+			   const EGLint *attr_list)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   struct dri2_egl_image *dri2_img;
+   int width, height, format, i;
+   unsigned int use, dri_use, valid_mask;
+   EGLint err = EGL_SUCCESS;
+
+   dri2_img = malloc(sizeof *dri2_img);
+   if (!dri2_img) {
+      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
+      return EGL_NO_IMAGE_KHR;
+   }
+
+   if (!attr_list) {
+      err = EGL_BAD_PARAMETER;
+      goto cleanup_img;
+   }
+
+   if (!_eglInitImage(&dri2_img->base, disp, attr_list)) {
+      err = EGL_BAD_PARAMETER;
+      goto cleanup_img;
+   }
+
+   width = 0;
+   height = 0;
+   format = 0;
+   use = 0;
+   for (i = 0; attr_list[i] != EGL_NONE; i++) {
+      EGLint attr = attr_list[i++];
+      EGLint val = attr_list[i];
+
+      switch (attr) {
+      case EGL_WIDTH:
+	 width = val;
+         break;
+      case EGL_HEIGHT:
+	 height = val;
+         break;
+      case EGL_DRM_BUFFER_FORMAT_MESA:
+	 format = val;
+         break;
+      case EGL_DRM_BUFFER_USE_MESA:
+	 use = val;
+         break;
+      default:
+         err = EGL_BAD_ATTRIBUTE;
+         break;
+      }
+
+      if (err != EGL_SUCCESS) {
+         _eglLog(_EGL_WARNING, "bad image attribute 0x%04x", attr);
+	 goto cleanup_img;
+      }
+   }
+
+   if (width <= 0 || height <= 0) {
+      _eglLog(_EGL_WARNING, "bad width or height (%dx%d)", width, height);
+      goto cleanup_img;
+   }
+
+   switch (format) {
+   case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
+      format = __DRI_IMAGE_FORMAT_ARGB8888;
+      break;
+   default:
+      _eglLog(_EGL_WARNING, "bad image format value 0x%04x", format);
+      goto cleanup_img;
+   }
+
+   valid_mask =
+      EGL_DRM_BUFFER_USE_SCANOUT_MESA |
+      EGL_DRM_BUFFER_USE_SHARE_MESA; 
+   if (use & ~valid_mask) {
+      _eglLog(_EGL_WARNING, "bad image use bit 0x%04x", use & ~valid_mask);
+      goto cleanup_img;
+   }
+
+   dri_use = 0;
+   if (use & EGL_DRM_BUFFER_USE_SHARE_MESA)
+      dri_use |= __DRI_IMAGE_USE_SHARE;
+   if (use & EGL_DRM_BUFFER_USE_SCANOUT_MESA)
+      dri_use |= __DRI_IMAGE_USE_SCANOUT;
+
+   dri2_img->dri_image = 
+      dri2_dpy->image->createImage(dri2_dpy->dri_screen,
+				   width, height, format, dri_use, dri2_img);
+   if (dri2_img->dri_image == NULL) {
+      err = EGL_BAD_ALLOC;
+      goto cleanup_img;
+   }
+
+   return &dri2_img->base;
+
+ cleanup_img:
+   free(dri2_img);
+   _eglError(err, "dri2_create_drm_image_mesa");
+
+   return EGL_NO_IMAGE_KHR;
+}
+
+static EGLBoolean
+dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
+			  EGLint *name, EGLint *handle, EGLint *stride)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   struct dri2_egl_image *dri2_img = dri2_egl_image(img);
+
+   if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image,
+					    __DRI_IMAGE_ATTRIB_NAME, name)) {
+      _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa");
+      return EGL_FALSE;
+   }
+
+   if (handle)
+      dri2_dpy->image->queryImage(dri2_img->dri_image,
+				  __DRI_IMAGE_ATTRIB_HANDLE, handle);
+
+   if (stride)
+      dri2_dpy->image->queryImage(dri2_img->dri_image,
+				  __DRI_IMAGE_ATTRIB_STRIDE, stride);
+
+   return EGL_TRUE;
+}
+
 /**
  * This is the main entrypoint into the driver, called by libEGL.
  * Create a new _EGLDriver object and init its dispatch table.
@@ -1681,6 +1902,8 @@ _eglMain(const char *args)
    dri2_drv->base.API.CreateImageKHR = dri2_create_image_khr;
    dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr;
    dri2_drv->base.API.SwapBuffersRegionNOK = dri2_swap_buffers_region;
+   dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa;
+   dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa;
 
    dri2_drv->base.Name = "DRI2";
    dri2_drv->base.Unload = dri2_unload;




More information about the mesa-commit mailing list