[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