diff options
-rw-r--r-- | docs/specs/WL_create_wayland_buffer_from_image.spec | 101 | ||||
-rw-r--r-- | include/EGL/eglmesaext.h | 10 | ||||
-rw-r--r-- | src/egl/drivers/dri2/platform_wayland.c | 78 | ||||
-rw-r--r-- | src/egl/main/eglapi.c | 25 | ||||
-rw-r--r-- | src/egl/main/eglapi.h | 8 | ||||
-rw-r--r-- | src/egl/main/egldisplay.h | 1 | ||||
-rw-r--r-- | src/egl/main/eglmisc.c | 1 |
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); |