[Mesa-dev] [PATCH] [RFC] egl: propose simple EGL_MESA_image_dma_buf_export v2.2

Dave Airlie airlied at gmail.com
Mon Mar 2 23:02:27 PST 2015


From: Dave Airlie <airlied at redhat.com>

(just resending with some cleanups/updates).

At the moment to get an EGL image to a dma-buf file descriptor,
you have to use EGL_MESA_drm_image, and then use libdrm to
convert this to a file descriptor.

This extension just provides an API modelled on EGL_MESA_drm_image,
to return a dma-buf file descriptor.

v2: update spec for new API proposal
add internal queries to get the fourcc back from intel driver.

v2.1: add gallium pieces.

v2.2: add offsets to spec and API, rename fd->fds, stride->strides
in API. rewrite spec a bit more, add some q/a

Signed-off-by: Dave Airlie <airlied at redhat.com>
---
 docs/specs/MESA_image_dma_buf_export.txt | 129 +++++++++++++++++++++++++++++++
 include/EGL/eglmesaext.h                 |   5 ++
 include/GL/internal/dri_interface.h      |   4 +-
 src/egl/drivers/dri2/egl_dri2.c          |  54 ++++++++++++-
 src/egl/main/eglapi.c                    |  46 +++++++++++
 src/egl/main/eglapi.h                    |  10 +++
 src/egl/main/egldisplay.h                |   2 +
 src/egl/main/eglfallbacks.c              |   5 ++
 src/egl/main/eglmisc.c                   |   2 +
 src/gallium/state_trackers/dri/dri2.c    |  32 +++++++-
 src/mesa/drivers/dri/i965/intel_screen.c |  25 +++++-
 11 files changed, 309 insertions(+), 5 deletions(-)
 create mode 100644 docs/specs/MESA_image_dma_buf_export.txt

diff --git a/docs/specs/MESA_image_dma_buf_export.txt b/docs/specs/MESA_image_dma_buf_export.txt
new file mode 100644
index 0000000..c8cebc7
--- /dev/null
+++ b/docs/specs/MESA_image_dma_buf_export.txt
@@ -0,0 +1,129 @@
+Name
+
+    MESA_image_dma_buf_export
+
+Name Strings
+
+    EGL_MESA_image_dma_buf_export
+
+Contributors
+
+    Dave Airlie
+
+Contact
+
+    Dave Airlie (airlied 'at' redhat 'dot' com)
+
+Status
+
+    Proposal
+
+Version
+
+    Version 2
+
+Number
+
+ <unnumbered>
+
+Dependencies
+
+    Reguires EGL 1.4 or later.  This extension is written against the
+    wording of the EGL 1.4 specification.
+
+    EGL_KHR_base_image is required.
+
+    The EGL implementation must be running on a Linux kernel supported the
+    dma_buf buffer sharing mechanism.
+
+Overview
+
+    This extension provides entry points for integrating EGLImage with the
+    dma-buf infrastructure.  The extension allows creating a Linux dma_buf
+    file descriptor or multiple file descriptors, in the case of multi-plane
+    YUV image, from an EGLImage.
+
+    It is designed to provide the opposing functionality to EGL_EXT_image_dma_buf_import.
+
+IP Status
+
+    Open-source; freely implementable.
+
+New Types
+
+    None
+
+New Procedures and Functions
+
+    EGLBoolean eglExportDMABUFImageQueryMESA(EGLDisplay dpy,
+                                  EGLImageKHR image,
+				  int *fourcc,
+				  int *num_planes);
+
+    EGLBoolean eglExportDMABUFImageMESA(EGLDisplay dpy,
+                                        EGLImageKHR image,
+                                        int *fds,
+				        EGLint *strides,
+					EGLint *offsets);
+
+New Tokens
+
+    None
+
+
+Additions to the EGL 1.4 Specification:
+
+    To mirror the import extension, this extension attempts to return
+    enough information to enable an exported dma-buf to be imported
+    via eglCreateImageKHR and EGL_LINUX_DMA_BUF_EXT token.
+
+    Retrieving the information is a two step process, so two APIs
+    are required.
+
+    The first entrypoint
+       EGLBoolean eglExportDMABUFImageQueryMESA(EGLDisplay dpy,
+                                  EGLImageKHR image,
+				  int *fourcc,
+				  int *num_planes);
+
+    is used to retrieve the pixel format of the buffer, as specified by
+    drm_fourcc.h and the number of planes in the image. <fourcc> and
+    <num_planes> may be NULL, in which case no value is retrieved.
+
+    The second entrypoint retrieves the dma_buf file descriptors,
+    strides and offsets for the image. The caller should pass
+    arrays sized according to the num_planes values retrieved previously.
+    Passing arrays of the wrong size will have undefined results.
+
+        EGLBoolean eglExportDMABUFImageMESA(EGLDisplay dpy,
+                                         EGLImageKHR image,
+					 int *fds,
+                                         EGLint *strides,
+                                         EGLint *offsets);
+
+    <fds>, <strides>, <offsets> can be NULL if the infomatation isn't
+    required by the caller.
+
+Issues
+
+1. Should the API look more like an attribute getting API?
+
+ANSWER: No, from a user interface pov, having to iterate across calling
+the API up to 12 times using attribs seems like the wrong solution.
+
+2. Should the API take a plane and just get the fd/stride/offset for that
+   plane?
+
+ANSWER: UNKNOWN,this might be just as valid an API.
+
+3. Does ownership of the file descriptor remain with the app?
+
+ANSWER: Yes, the app is responsible for closing any fds retrieved.
+
+Revision History
+
+    Version 2, March, 2015
+        Add a query interface (Dave Airlie)
+    Version 1, June 3, 2014
+        Initial draft (Dave Airlie)
+
diff --git a/include/EGL/eglmesaext.h b/include/EGL/eglmesaext.h
index 5fcc527..d75ccde 100644
--- a/include/EGL/eglmesaext.h
+++ b/include/EGL/eglmesaext.h
@@ -170,6 +170,11 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGIONNOK) (EGLDisplay dpy, EG
 #define EGL_NO_CONFIG_MESA			((EGLConfig)0)
 #endif
 
+#ifndef EGL_MESA_image_dma_buf_export
+#define EGL_MESA_image_dma_buf_export 1
+EGLAPI EGLBoolean EGLAPIENTRY eglExportDMABUFImageQueryMESA (EGLDisplay dpy, EGLImageKHR image, EGLint *fourcc, EGLint *nplanes);
+EGLAPI EGLBoolean EGLAPIENTRY eglExportDMABUFImageMESA (EGLDisplay dpy, EGLImageKHR image, int *fds, EGLint *strides, EGLint *offsets);
+#endif
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 1d670b1..eb7da23 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -1006,7 +1006,7 @@ struct __DRIdri2ExtensionRec {
  * extensions.
  */
 #define __DRI_IMAGE "DRI_IMAGE"
-#define __DRI_IMAGE_VERSION 10
+#define __DRI_IMAGE_VERSION 11
 
 /**
  * These formats correspond to the similarly named MESA_FORMAT_*
@@ -1097,6 +1097,8 @@ struct __DRIdri2ExtensionRec {
 #define __DRI_IMAGE_ATTRIB_FD           0x2007 /* available in versions
                                                 * 7+. Each query will return a
                                                 * new fd. */
+#define __DRI_IMAGE_ATTRIB_FOURCC       0x2008 /* available in versions 11 */
+#define __DRI_IMAGE_ATTRIB_NUM_PLANES   0x2009 /* available in versions 11 */
 
 enum __DRIYUVColorSpace {
    __DRI_YUV_COLOR_SPACE_UNDEFINED = 0,
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index 6306483..ca94cf0 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -524,8 +524,14 @@ dri2_setup_screen(_EGLDisplay *disp)
 
          capabilities = dri2_dpy->image->getCapabilities(dri2_dpy->dri_screen);
          disp->Extensions.MESA_drm_image = (capabilities & __DRI_IMAGE_CAP_GLOBAL_NAMES) != 0;
-      } else
+
+         if (dri2_dpy->image->base.version >= 11)
+            disp->Extensions.MESA_image_dma_buf_export = EGL_TRUE;
+      } else {
          disp->Extensions.MESA_drm_image = EGL_TRUE;
+         if (dri2_dpy->image->base.version >= 11)
+            disp->Extensions.MESA_image_dma_buf_export = EGL_TRUE;
+      }
 
       disp->Extensions.KHR_image_base = EGL_TRUE;
       disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
@@ -1964,6 +1970,50 @@ dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
 
    return EGL_TRUE;
 }
+
+static EGLBoolean
+dri2_export_dma_buf_image_query_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
+                                     EGLint *fourcc, EGLint *nplanes)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   struct dri2_egl_image *dri2_img = dri2_egl_image(img);
+
+   (void) drv;
+
+
+   if (nplanes)
+      dri2_dpy->image->queryImage(dri2_img->dri_image,
+				  __DRI_IMAGE_ATTRIB_NUM_PLANES, nplanes);
+   if (fourcc)
+      dri2_dpy->image->queryImage(dri2_img->dri_image,
+				  __DRI_IMAGE_ATTRIB_FOURCC, fourcc);
+
+   return EGL_TRUE;
+}
+
+static EGLBoolean
+dri2_export_dma_buf_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
+                               int *fds, EGLint *strides, EGLint *offsets)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   struct dri2_egl_image *dri2_img = dri2_egl_image(img);
+
+   (void) drv;
+
+   /* rework later to provide multiple fds/strides/offsets */
+   if (fds)
+      dri2_dpy->image->queryImage(dri2_img->dri_image,
+				  __DRI_IMAGE_ATTRIB_FD, fds);
+
+   if (strides)
+      dri2_dpy->image->queryImage(dri2_img->dri_image,
+				  __DRI_IMAGE_ATTRIB_STRIDE, strides);
+
+   if (offsets)
+      offsets[0] = 0;
+
+   return EGL_TRUE;
+}
 #endif
 
 #ifdef HAVE_WAYLAND_PLATFORM
@@ -2218,6 +2268,8 @@ _eglBuiltInDriverDRI2(const char *args)
 #ifdef HAVE_LIBDRM
    dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa;
    dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa;
+   dri2_drv->base.API.ExportDMABUFImageQueryMESA = dri2_export_dma_buf_image_query_mesa;
+   dri2_drv->base.API.ExportDMABUFImageMESA = dri2_export_dma_buf_image_mesa;
 #endif
 #ifdef HAVE_WAYLAND_PLATFORM
    dri2_drv->base.API.BindWaylandDisplayWL = dri2_bind_wayland_display_wl;
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index db44a26..1def5bf 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -1114,6 +1114,10 @@ eglGetProcAddress(const char *procname)
       { "eglCreatePlatformWindowSurfaceEXT", (_EGLProc) eglCreatePlatformWindowSurfaceEXT },
       { "eglCreatePlatformPixmapSurfaceEXT", (_EGLProc) eglCreatePlatformPixmapSurfaceEXT },
       { "eglGetSyncValuesCHROMIUM", (_EGLProc) eglGetSyncValuesCHROMIUM },
+#ifdef EGL_MESA_drm_buf_image_export
+      { "eglExportDMABUFImageQueryMESA", (_EGLProc) eglExportDMABUFImageQueryMESA },
+      { "eglExportDMABUFImageMESA", (_EGLProc) eglExportDMABUFImageMESA },
+#endif
       { NULL, NULL }
    };
    EGLint i;
@@ -1801,3 +1805,45 @@ eglGetSyncValuesCHROMIUM(EGLDisplay display, EGLSurface surface,
 
    RETURN_EGL_EVAL(disp, ret);
 }
+
+#ifdef EGL_MESA_image_dma_buf_export
+EGLBoolean EGLAPIENTRY
+eglExportDMABUFImageQueryMESA(EGLDisplay dpy, EGLImageKHR image,
+                              EGLint *fourcc, EGLint *nplanes)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLImage *img = _eglLookupImage(image, disp);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
+   assert(disp->Extensions.MESA_image_dma_buf_export);
+
+   if (!img)
+      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
+
+   ret = drv->API.ExportDMABUFImageQueryMESA(drv, disp, img, fourcc, nplanes);
+
+   RETURN_EGL_EVAL(disp, ret);
+}
+
+EGLBoolean EGLAPIENTRY
+eglExportDMABUFImageMESA(EGLDisplay dpy, EGLImageKHR image,
+                         int *fds, EGLint *strides, EGLint *offsets)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLImage *img = _eglLookupImage(image, disp);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
+   assert(disp->Extensions.MESA_image_dma_buf_export);
+
+   if (!img)
+      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
+
+   ret = drv->API.ExportDMABUFImageMESA(drv, disp, img, fds, strides, offsets);
+
+   RETURN_EGL_EVAL(disp, ret);
+}
+#endif
diff --git a/src/egl/main/eglapi.h b/src/egl/main/eglapi.h
index cb01cab..27594c7 100644
--- a/src/egl/main/eglapi.h
+++ b/src/egl/main/eglapi.h
@@ -141,6 +141,11 @@ typedef EGLBoolean (*SwapBuffersWithDamageEXT_t) (_EGLDriver *drv, _EGLDisplay *
 
 typedef EGLBoolean (*GetSyncValuesCHROMIUM_t) (_EGLDisplay *dpy, _EGLSurface *surface, EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc);
 
+#ifdef EGL_MESA_image_dma_buf_export
+typedef EGLBoolean (*ExportDMABUFImageQueryMESA_t)(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img, EGLint *fourcc, EGLint *stride);
+typedef EGLBoolean (*ExportDMABUFImageMESA_t)(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img, EGLint *fds, EGLint *strides, EGLint *offsets);
+#endif
+
 /**
  * The API dispatcher jumps through these functions
  */
@@ -228,6 +233,11 @@ struct _egl_api
 
    QueryBufferAge_t QueryBufferAge;
    GetSyncValuesCHROMIUM_t GetSyncValuesCHROMIUM;
+
+#ifdef EGL_MESA_image_dma_buf_export
+   ExportDMABUFImageQueryMESA_t ExportDMABUFImageQueryMESA;
+   ExportDMABUFImageMESA_t ExportDMABUFImageMESA;
+#endif
 };
 
 #endif /* EGLAPI_INCLUDED */
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index bcdc2b2..8581cb2 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -123,6 +123,8 @@ struct _egl_extensions
    EGLBoolean EXT_buffer_age;
    EGLBoolean EXT_swap_buffers_with_damage;
    EGLBoolean EXT_image_dma_buf_import;
+
+   EGLBoolean MESA_image_dma_buf_export;
 };
 
 
diff --git a/src/egl/main/eglfallbacks.c b/src/egl/main/eglfallbacks.c
index 0b70e92..6127426 100644
--- a/src/egl/main/eglfallbacks.c
+++ b/src/egl/main/eglfallbacks.c
@@ -120,4 +120,9 @@ _eglInitDriverFallbacks(_EGLDriver *drv)
 #ifdef EGL_NOK_swap_region
    drv->API.SwapBuffersRegionNOK = NULL;
 #endif
+
+#ifdef EGL_MESA_dma_buf_image_export
+   drv->API.ExportDMABUFImageQueryMESA = NULL;
+   drv->API.ExportDMABUFImageMESA = NULL;
+#endif
 }
diff --git a/src/egl/main/eglmisc.c b/src/egl/main/eglmisc.c
index 2f49809..7837684 100644
--- a/src/egl/main/eglmisc.c
+++ b/src/egl/main/eglmisc.c
@@ -126,6 +126,8 @@ _eglUpdateExtensionsString(_EGLDisplay *dpy)
    _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import);
 
    _EGL_CHECK_EXTENSION(NV_post_sub_buffer);
+
+   _EGL_CHECK_EXTENSION(MESA_image_dma_buf_export);
 #undef _EGL_CHECK_EXTENSION
 }
 
diff --git a/src/gallium/state_trackers/dri/dri2.c b/src/gallium/state_trackers/dri/dri2.c
index 7d65ba3..f8f4ecf 100644
--- a/src/gallium/state_trackers/dri/dri2.c
+++ b/src/gallium/state_trackers/dri/dri2.c
@@ -76,6 +76,30 @@ static int convert_fourcc(int format, int *dri_components_p)
    return format;
 }
 
+static int convert_to_fourcc(int format)
+{
+   switch(format) {
+   case __DRI_IMAGE_FORMAT_RGB565:
+      format = __DRI_IMAGE_FOURCC_RGB565;
+      break;
+   case __DRI_IMAGE_FORMAT_ARGB8888:
+      format = __DRI_IMAGE_FOURCC_ARGB8888;
+      break;
+   case __DRI_IMAGE_FORMAT_XRGB8888:
+      format = __DRI_IMAGE_FOURCC_XRGB8888;
+      break;
+   case __DRI_IMAGE_FORMAT_ABGR8888:
+      format = __DRI_IMAGE_FOURCC_ABGR8888;
+      break;
+   case __DRI_IMAGE_FORMAT_XBGR8888:
+      format = __DRI_IMAGE_FOURCC_XBGR8888;
+      break;
+   default:
+      return -1;
+   }
+   return format;
+}
+
 /**
  * DRI2 flush extension.
  */
@@ -909,6 +933,12 @@ dri2_query_image(__DRIimage *image, int attrib, int *value)
          return GL_FALSE;
       *value = image->dri_components;
       return GL_TRUE;
+   case __DRI_IMAGE_ATTRIB_FOURCC:
+      *value = convert_to_fourcc(image->dri_format);
+      return GL_TRUE;
+   case __DRI_IMAGE_ATTRIB_NUM_PLANES:
+      *value = 1;
+      return GL_TRUE;
    default:
       return GL_FALSE;
    }
@@ -1203,7 +1233,7 @@ dri2_get_capabilities(__DRIscreen *_screen)
 
 /* The extension is modified during runtime if DRI_PRIME is detected */
 static __DRIimageExtension dri2ImageExtension = {
-    .base = { __DRI_IMAGE, 10 },
+    .base = { __DRI_IMAGE, 11 },
 
     .createImageFromName          = dri2_create_image_from_name,
     .createImageFromRenderbuffer  = dri2_create_image_from_renderbuffer,
diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
index cea7ddf..39e8eaf 100644
--- a/src/mesa/drivers/dri/i965/intel_screen.c
+++ b/src/mesa/drivers/dri/i965/intel_screen.c
@@ -300,6 +300,17 @@ intel_image_format_lookup(int fourcc)
    return f;
 }
 
+static boolean intel_lookup_fourcc(int dri_format, int *fourcc)
+{
+   for (unsigned i = 0; i < ARRAY_SIZE(intel_image_formats); i++) {
+      if (intel_image_formats[i].planes[0].dri_format == dri_format) {
+         *fourcc = intel_image_formats[i].fourcc;
+         return true;
+      }
+   }
+   return false;
+}
+
 static __DRIimage *
 intel_allocate_image(int dri_format, void *loaderPrivate)
 {
@@ -559,6 +570,14 @@ intel_query_image(__DRIimage *image, int attrib, int *value)
       if (drm_intel_bo_gem_export_to_prime(image->bo, value) == 0)
          return true;
       return false;
+   case __DRI_IMAGE_ATTRIB_FOURCC:
+      if (intel_lookup_fourcc(image->dri_format, value))
+         return true;
+      return false;
+   case __DRI_IMAGE_ATTRIB_NUM_PLANES:
+      *value = 1;
+      return true;
+
   default:
       return false;
    }
@@ -784,7 +803,7 @@ intel_from_planar(__DRIimage *parent, int plane, void *loaderPrivate)
 }
 
 static const __DRIimageExtension intelImageExtension = {
-    .base = { __DRI_IMAGE, 8 },
+    .base = { __DRI_IMAGE, 11 },
 
     .createImageFromName                = intel_create_image_from_name,
     .createImageFromRenderbuffer        = intel_create_image_from_renderbuffer,
@@ -797,7 +816,9 @@ static const __DRIimageExtension intelImageExtension = {
     .fromPlanar                         = intel_from_planar,
     .createImageFromTexture             = intel_create_image_from_texture,
     .createImageFromFds                 = intel_create_image_from_fds,
-    .createImageFromDmaBufs             = intel_create_image_from_dma_bufs
+    .createImageFromDmaBufs             = intel_create_image_from_dma_bufs,
+    .blitImage                          = NULL,
+    .getCapabilities                    = NULL
 };
 
 static int
-- 
2.1.0



More information about the mesa-dev mailing list