summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/specs/WL_create_wayland_buffer_from_image.spec101
-rw-r--r--include/EGL/eglmesaext.h10
-rw-r--r--src/egl/drivers/dri2/platform_wayland.c78
-rw-r--r--src/egl/main/eglapi.c25
-rw-r--r--src/egl/main/eglapi.h8
-rw-r--r--src/egl/main/egldisplay.h1
-rw-r--r--src/egl/main/eglmisc.c1
7 files changed, 224 insertions, 0 deletions
diff --git a/docs/specs/WL_create_wayland_buffer_from_image.spec b/docs/specs/WL_create_wayland_buffer_from_image.spec
new file mode 100644
index 00000000000..aa5eb4d24d9
--- /dev/null
+++ b/docs/specs/WL_create_wayland_buffer_from_image.spec
@@ -0,0 +1,101 @@
+Name
+
+ WL_create_wayland_buffer_from_image
+
+Name Strings
+
+ EGL_WL_create_wayland_buffer_from_image
+
+Contributors
+
+ Neil Roberts
+ Axel Davy
+ Daniel Stone
+
+Contact
+
+ Neil Roberts <[email protected]>
+
+Status
+
+ Proposal
+
+Version
+
+ Version 2, October 25, 2013
+
+Number
+
+ EGL Extension #not assigned
+
+Dependencies
+
+ Requires EGL 1.4 or later. This extension is written against the
+ wording of the EGL 1.4 specification.
+
+ EGL_KHR_base_image is required.
+
+Overview
+
+ This extension provides an entry point to create a wl_buffer which shares
+ its contents with a given EGLImage. The expected use case for this is in a
+ nested Wayland compositor which is using subsurfaces to present buffers
+ from its clients. Using this extension it can attach the client buffers
+ directly to the subsurface without having to blit the contents into an
+ intermediate buffer. The compositing can then be done in the parent
+ compositor.
+
+ The nested compositor can create an EGLImage from a client buffer resource
+ using the existing WL_bind_wayland_display extension. It should also be
+ possible to create buffers using other types of images although there is
+ no expected use case for that.
+
+IP Status
+
+ Open-source; freely implementable.
+
+New Procedures and Functions
+
+ struct wl_buffer *eglCreateWaylandBufferFromImageWL(EGLDisplay dpy,
+ EGLImageKHR image);
+
+New Tokens
+
+ None.
+
+Additions to the EGL 1.4 Specification:
+
+ To create a client-side wl_buffer from an EGLImage call
+
+ struct wl_buffer *eglCreateWaylandBufferFromImageWL(EGLDisplay dpy,
+ EGLImageKHR image);
+
+ The returned buffer will share the contents with the given EGLImage. Any
+ updates to the image will also be updated in the wl_buffer. Typically the
+ EGLImage will be generated in a nested Wayland compositor using a buffer
+ resource from a client via the EGL_WL_bind_wayland_display extension.
+
+ If there was an error then the function will return NULL. In particular it
+ will generate EGL_BAD_MATCH if the implementation is not able to represent
+ the image as a wl_buffer. The possible reasons for this error are
+ implementation-dependant but may include problems such as an unsupported
+ format or tiling mode or that the buffer is in memory that is inaccessible
+ to the GPU that the given EGLDisplay is using.
+
+Issues
+
+ 1) Under what circumstances can the EGL_BAD_MATCH error be generated? Does
+ this include for example unsupported tiling modes?
+
+ RESOLVED: Yes, the EGL_BAD_MATCH error can be generated for any reason
+ which prevents the implementation from representing the image as a
+ wl_buffer. For example, these problems can be but are not limited to
+ unsupported tiling modes, inaccessible memory or an unsupported pixel
+ format.
+
+Revision History
+
+ Version 1, September 6, 2013
+ Initial draft (Neil Roberts)
+ Version 2, October 25, 2013
+ Added a note about more possible reasons for returning EGL_BAD_FORMAT.
diff --git a/include/EGL/eglmesaext.h b/include/EGL/eglmesaext.h
index 1f07d4cde5f..14fb07a7196 100644
--- a/include/EGL/eglmesaext.h
+++ b/include/EGL/eglmesaext.h
@@ -134,6 +134,16 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYWAYLANDBUFFERWL) (EGLDisplay dpy, st
#endif
+#ifndef EGL_WL_create_wayland_buffer_from_image
+#define EGL_WL_create_wayland_buffer_from_image 1
+
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI struct wl_buffer * EGLAPIENTRY eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImageKHR image);
+#endif
+typedef struct wl_buffer * (EGLAPIENTRYP PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWL) (EGLDisplay dpy, EGLImageKHR image);
+
+#endif
+
#ifndef EGL_NOK_swap_region
#define EGL_NOK_swap_region 1
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index 43e8f4b0c5a..443bdcaeda3 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -651,6 +651,81 @@ dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
return dri2_swap_buffers_with_damage (drv, disp, draw, NULL, 0);
}
+static struct wl_buffer *
+dri2_create_wayland_buffer_from_image_wl(_EGLDriver *drv,
+ _EGLDisplay *disp,
+ _EGLImage *img)
+{
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+ struct dri2_egl_image *dri2_img = dri2_egl_image(img);
+ __DRIimage *image = dri2_img->dri_image;
+ struct wl_buffer *buffer;
+ int width, height, format, pitch;
+ enum wl_drm_format wl_format;
+
+ dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FORMAT, &format);
+
+ switch (format) {
+ case __DRI_IMAGE_FORMAT_ARGB8888:
+ if (!(dri2_dpy->formats & HAS_ARGB8888))
+ goto bad_format;
+ wl_format = WL_DRM_FORMAT_ARGB8888;
+ break;
+ case __DRI_IMAGE_FORMAT_XRGB8888:
+ if (!(dri2_dpy->formats & HAS_XRGB8888))
+ goto bad_format;
+ wl_format = WL_DRM_FORMAT_XRGB8888;
+ break;
+ default:
+ goto bad_format;
+ }
+
+ dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_WIDTH, &width);
+ dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_HEIGHT, &height);
+ dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &pitch);
+
+ if (dri2_dpy->capabilities & WL_DRM_CAPABILITY_PRIME) {
+ int fd;
+
+ dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FD, &fd);
+
+ buffer =
+ wl_drm_create_prime_buffer(dri2_dpy->wl_drm,
+ fd,
+ width, height,
+ wl_format,
+ 0, pitch,
+ 0, 0,
+ 0, 0);
+
+ close(fd);
+ } else {
+ int name;
+
+ dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_NAME, &name);
+
+ buffer =
+ wl_drm_create_buffer(dri2_dpy->wl_drm,
+ name,
+ width, height,
+ pitch,
+ wl_format);
+ }
+
+ /* The buffer object will have been created with our internal event queue
+ * because it is using the wl_drm object as a proxy factory. We want the
+ * buffer to be used by the application so we'll reset it to the display's
+ * default event queue */
+ if (buffer)
+ wl_proxy_set_queue((struct wl_proxy *) buffer, NULL);
+
+ return buffer;
+
+bad_format:
+ _eglError(EGL_BAD_MATCH, "unsupported image format");
+ return NULL;
+}
+
static int
dri2_wayland_authenticate(_EGLDisplay *disp, uint32_t id)
{
@@ -812,6 +887,8 @@ dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp)
drv->API.SwapBuffersWithDamageEXT = dri2_swap_buffers_with_damage;
drv->API.Terminate = dri2_terminate;
drv->API.QueryBufferAge = dri2_query_buffer_age;
+ drv->API.CreateWaylandBufferFromImageWL =
+ dri2_create_wayland_buffer_from_image_wl;
dri2_dpy = calloc(1, sizeof *dri2_dpy);
if (!dri2_dpy)
@@ -892,6 +969,7 @@ dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp)
}
disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
+ disp->Extensions.WL_create_wayland_buffer_from_image = EGL_TRUE;
disp->Extensions.EXT_buffer_age = EGL_TRUE;
dri2_dpy->authenticate = dri2_wayland_authenticate;
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 66f96de4140..9ac2ef44698 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -973,6 +973,9 @@ eglGetProcAddress(const char *procname)
{ "eglUnbindWaylandDisplayWL", (_EGLProc) eglUnbindWaylandDisplayWL },
{ "eglQueryWaylandBufferWL", (_EGLProc) eglQueryWaylandBufferWL },
#endif
+#ifdef EGL_WL_create_wayland_buffer_from_image
+ { "eglCreateWaylandBufferFromImageWL", (_EGLProc) eglCreateWaylandBufferFromImageWL },
+#endif
{ "eglPostSubBufferNV", (_EGLProc) eglPostSubBufferNV },
#ifdef EGL_EXT_swap_buffers_with_damage
{ "eglSwapBuffersWithDamageEXT", (_EGLProc) eglSwapBuffersWithDamageEXT },
@@ -1601,6 +1604,28 @@ eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer,
}
#endif
+#ifdef EGL_WL_create_wayland_buffer_from_image
+struct wl_buffer * EGLAPIENTRY
+eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImageKHR image)
+{
+ _EGLDisplay *disp = _eglLockDisplay(dpy);
+ _EGLImage *img;
+ _EGLDriver *drv;
+ struct wl_buffer *ret;
+
+ _EGL_CHECK_DISPLAY(disp, NULL, drv);
+ assert(disp->Extensions.WL_create_wayland_buffer_from_image);
+
+ img = _eglLookupImage(image, disp);
+
+ if (!img)
+ RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL);
+
+ ret = drv->API.CreateWaylandBufferFromImageWL(drv, disp, img);
+
+ RETURN_EGL_EVAL(disp, ret);
+}
+#endif
EGLBoolean EGLAPIENTRY
eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface,
diff --git a/src/egl/main/eglapi.h b/src/egl/main/eglapi.h
index 4a4f9765219..05803449a2e 100644
--- a/src/egl/main/eglapi.h
+++ b/src/egl/main/eglapi.h
@@ -126,6 +126,10 @@ typedef EGLBoolean (*UnbindWaylandDisplayWL_t)(_EGLDriver *drv, _EGLDisplay *dis
typedef EGLBoolean (*QueryWaylandBufferWL_t)(_EGLDriver *drv, _EGLDisplay *displ, struct wl_resource *buffer, EGLint attribute, EGLint *value);
#endif
+#ifdef EGL_WL_create_wayland_buffer_from_image
+typedef struct wl_buffer * (*CreateWaylandBufferFromImageWL_t)(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img);
+#endif
+
typedef EGLBoolean (*PostSubBufferNV_t)(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surface, EGLint x, EGLint y, EGLint width, EGLint height);
typedef EGLint (*QueryBufferAge_t)(_EGLDriver *drv,
@@ -210,6 +214,10 @@ struct _egl_api
QueryWaylandBufferWL_t QueryWaylandBufferWL;
#endif
+#ifdef EGL_WL_create_wayland_buffer_from_image
+ CreateWaylandBufferFromImageWL_t CreateWaylandBufferFromImageWL;
+#endif
+
#ifdef EGL_EXT_swap_buffers_with_damage
SwapBuffersWithDamageEXT_t SwapBuffersWithDamageEXT;
#endif /* EGL_EXT_swap_buffers_with_damage */
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index fefd19c47b2..b95b2f79852 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -91,6 +91,7 @@ struct _egl_extensions
EGLBoolean MESA_drm_image;
EGLBoolean WL_bind_wayland_display;
+ EGLBoolean WL_create_wayland_buffer_from_image;
EGLBoolean KHR_image_base;
EGLBoolean KHR_image_pixmap;
diff --git a/src/egl/main/eglmisc.c b/src/egl/main/eglmisc.c
index 2decc1b778d..cff61669dc8 100644
--- a/src/egl/main/eglmisc.c
+++ b/src/egl/main/eglmisc.c
@@ -92,6 +92,7 @@ _eglUpdateExtensionsString(_EGLDisplay *dpy)
_EGL_CHECK_EXTENSION(MESA_drm_image);
_EGL_CHECK_EXTENSION(WL_bind_wayland_display);
+ _EGL_CHECK_EXTENSION(WL_create_wayland_buffer_from_image);
_EGL_CHECK_EXTENSION(KHR_image_base);
_EGL_CHECK_EXTENSION(KHR_image_pixmap);