Hi On Mon, Mar 30, 2015 at 8:12 AM, Dave Airlie <airl...@gmail.com> wrote:
> From: Dave Airlie <airl...@redhat.com> > > 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 > > v2.3: > add modifiers to query interface and 64-bit type for that (Daniel Stone) > specifiy what happens to num fds vs num planes differences. (Chad Versace) > > v2.4: > fix grammar (Daniel Stone) > > Signed-off-by: Dave Airlie <airl...@redhat.com> > --- > docs/specs/MESA_image_dma_buf_export.txt | 142 > +++++++++++++++++++++++++++++++ > include/EGL/eglmesaext.h | 8 ++ > include/GL/internal/dri_interface.h | 4 +- > src/egl/drivers/dri2/egl_dri2.c | 59 ++++++++++++- > src/egl/main/eglapi.c | 48 +++++++++++ > 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, 332 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..3bc5890 > --- /dev/null > +++ b/docs/specs/MESA_image_dma_buf_export.txt > @@ -0,0 +1,142 @@ > +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 supporting > 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 complementary functionality to > EGL_EXT_image_dma_buf_import. > + > +IP Status > + > + Open-source; freely implementable. > + > +New Types > + > + This is a 64 bit unsigned integer. > + > + typedef khronos_uint64_t EGLuint64MESA; > + > + > +New Procedures and Functions > + > + EGLBoolean eglExportDMABUFImageQueryMESA(EGLDisplay dpy, > + EGLImageKHR image, > + int *fourcc, > + int *num_planes, > + EGLuint64MESA *modifiers); > + > + 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, > + EGLuint64MESA *modifiers); > + > + is used to retrieve the pixel format of the buffer, as specified by > + drm_fourcc.h, the number of planes in the image and the Linux > + drm modifiers. <fourcc>, <num_planes> and <modifiers> 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. > + If the number of fds is less than the number of planes, then > + subsequent fd slots should contain -1. > + > + 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. > + > +4. If number of planes and number of fds differ what should we do? > + > +ANSWER: Return -1 for the secondary slots, as this avoids having > +to dup the fd extra times to make the interface sane. > + > +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..595babd 100644 > --- a/include/EGL/eglmesaext.h > +++ b/include/EGL/eglmesaext.h > @@ -170,6 +170,14 @@ typedef EGLBoolean (EGLAPIENTRYP > PFNEGLSWAPBUFFERSREGIONNOK) (EGLDisplay dpy, EG > #define EGL_NO_CONFIG_MESA ((EGLConfig)0) > #endif > > +#if KHRONOS_SUPPORT_INT64 > +#ifndef EGL_MESA_image_dma_buf_export > +#define EGL_MESA_image_dma_buf_export 1 > +typedef khronos_uint64_t EGLuint64MESA; > +EGLAPI EGLBoolean EGLAPIENTRY eglExportDMABUFImageQueryMESA (EGLDisplay > dpy, EGLImageKHR image, EGLint *fourcc, EGLint *nplanes, EGLuint64MESA > *modifiers); > +EGLAPI EGLBoolean EGLAPIENTRY eglExportDMABUFImageMESA (EGLDisplay dpy, > EGLImageKHR image, int *fds, EGLint *strides, EGLint *offsets); > +#endif > +#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..3d0a8fe 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,55 @@ 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, > + EGLuint64MESA *modifiers) > +{ > + 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); > + > + if (modifiers) > + *modifiers = 0; > + > + 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 +2273,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..2d2ed39 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 > EGL_MESA_image_dma_buf_export instead? > + { "eglExportDMABUFImageQueryMESA", (_EGLProc) > eglExportDMABUFImageQueryMESA }, > + { "eglExportDMABUFImageMESA", (_EGLProc) eglExportDMABUFImageMESA }, > +#endif > { NULL, NULL } > }; > EGLint i; > @@ -1801,3 +1805,47 @@ 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, > + EGLuint64MESA *modifiers) > +{ > + _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, > + modifiers); > + > + 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..092abb9 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, > EGLuint64MESA *modifiers); > +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) > s/boolean/bool +{ > + 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.3.3 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/mesa-dev > -- Marc-André Lureau
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev