This lets us specify the plane to create the image for for multiplanar wl_buffers.
Signed-off-by: Kristian Høgsberg <k...@bitplanet.net> --- docs/WL_bind_wayland_display.spec | 19 +++++- include/EGL/eglmesaext.h | 1 + src/egl/drivers/dri2/egl_dri2.c | 117 +++++++++++++++++++++++++++++++++++-- src/egl/main/eglimage.c | 5 ++ src/egl/main/eglimage.h | 3 + 5 files changed, 137 insertions(+), 8 deletions(-) diff --git a/docs/WL_bind_wayland_display.spec b/docs/WL_bind_wayland_display.spec index e2fde3c..d9bfc66 100644 --- a/docs/WL_bind_wayland_display.spec +++ b/docs/WL_bind_wayland_display.spec @@ -62,6 +62,10 @@ New Tokens EGL_WAYLAND_BUFFER_WL 0x31D5 + Accepted in the <attrib_list> parameter of eglCreateImageKHR: + + EGL_WAYLAND_PLANE_WL 0x31D6 + Additions to the EGL 1.4 Specification: To bind a server side wl_display to an EGLDisplay, call @@ -80,9 +84,15 @@ Additions to the EGL 1.4 Specification: eglUnbindWaylandDisplayWL returns EGL_FALSE when there is no wl_display bound to the EGLDisplay currently otherwise EGL_TRUE. - Import a wl_buffer by calling eglCreateImageKHR with - wl_buffer as EGLClientBuffer, EGL_WAYLAND_BUFFER_WL as the target, - NULL context and an empty attribute_list. + Import a wl_buffer by calling eglCreateImageKHR with wl_buffer as + EGLClientBuffer, EGL_WAYLAND_BUFFER_WL as the target, NULL context + and an empty attribute_list. For multi-planar buffers such as + many YUV buffers, specify the plane to create the EGLImage for by + using the EGL_WAYLAND_PLANE_WL attribute. The value of the + attribute is the index of the plane, as defined by the buffer + format. Writing to an EGLImage created from a wl_buffer in any + way (such as glTexImage2D, binding the EGLImage as a renderbuffer + etc) will result in undefined behavior. Issues @@ -90,3 +100,6 @@ Revision History Version 1, March 1, 2011 Initial draft (Benjamin Franzke) + Version 2, July 5, 2012 + Add EGL_WAYLAND_PLANE_WL attribute to allow creating an EGLImage + for different planes of planar buffer. (Kristian Høgsberg) diff --git a/include/EGL/eglmesaext.h b/include/EGL/eglmesaext.h index 52dd5b1..d291608 100644 --- a/include/EGL/eglmesaext.h +++ b/include/EGL/eglmesaext.h @@ -113,6 +113,7 @@ typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETDRMDISPLAYMESA) (int fd); #define EGL_WL_bind_wayland_display 1 #define EGL_WAYLAND_BUFFER_WL 0x31D5 /* eglCreateImageKHR target */ +#define EGL_WAYLAND_PLANE_WL 0x31D6 /* eglCreateImageKHR target */ struct wl_display; #ifdef EGL_EGLEXT_PROTOTYPES EGLAPI EGLBoolean EGLAPIENTRY eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display); diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index 7ca9d61..d003a9e 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -1057,15 +1057,122 @@ dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx, EGLClientBuffer _buffer, const EGLint *attr_list) { - struct wl_buffer *buffer = (struct wl_buffer *) _buffer; + struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) _buffer; struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); - __DRIimage *dri_image, *source; + __DRIimage *dri_image; + _EGLImageAttribs attrs; + EGLint err; + uint32_t format; + int32_t offset, stride, plane, width, height; + int cpp; - if (!wayland_buffer_is_drm(buffer)) + if (!wayland_buffer_is_drm(&buffer->buffer)) return NULL; - source = wayland_drm_buffer_get_buffer(buffer); - dri_image = dri2_dpy->image->dupImage(source, NULL); + err = _eglParseImageAttribList(&attrs, disp, attr_list); + plane = attrs.PlaneWL; + if (err != EGL_SUCCESS || plane < 0) { + _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer"); + return NULL; + } + + switch (buffer->format) { + case WL_DRM_FORMAT_ARGB8888: + case WL_DRM_FORMAT_XRGB8888: + if (plane > 0) { + _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer"); + return NULL; + } + width = buffer->buffer.width; + height = buffer->buffer.height; + format = buffer->driver_format; + offset = buffer->offset[0]; + stride = buffer->stride[0]; + cpp = 4; + break; + + case WL_DRM_FORMAT_YUV420: + if (plane > 2) { + _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer"); + return NULL; + } + + if (plane == 0) { + width = buffer->buffer.width; + height = buffer->buffer.height; + } else { + width = buffer->buffer.width / 2; + height = buffer->buffer.height / 2; + } + + format = __DRI_IMAGE_FORMAT_R8; + offset = buffer->offset[plane]; + stride = buffer->stride[plane]; + cpp = 1; + break; + + case WL_DRM_FORMAT_NV12: + if (plane > 1) { + _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); + return NULL; + } + + if (plane == 0) { + width = buffer->buffer.width; + height = buffer->buffer.height; + format = __DRI_IMAGE_FORMAT_R8; + cpp = 1; + } else { + width = buffer->buffer.width / 2; + height = buffer->buffer.height / 2; + format = __DRI_IMAGE_FORMAT_GR88; + cpp = 2; + } + + offset = buffer->offset[plane]; + stride = buffer->stride[plane]; + + break; + + case WL_DRM_FORMAT_YUYV: + if (plane > 1) { + _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer"); + return NULL; + } + + /* We set up two overlapping DRI images for YUYV buffers and + * treat them as planar buffers in the compositors. Plane 0 is + * GR88 and samples YU or YV pairs and places Y into the R + * component, while plane 1 is ARGB and samples YUYV clusters + * and places pairs and places U into the G component and V into + * A. This lets the texture sampler interpolate the Y + * components correctly when sampling from plane 0, and + * interpolate U and V correctly when sampling from plane 1. */ + + if (plane == 0) { + width = buffer->buffer.width; + height = buffer->buffer.height; + format = __DRI_IMAGE_FORMAT_GR88; + cpp = 2; + } else { + width = buffer->buffer.width / 2; + height = buffer->buffer.height; + format = __DRI_IMAGE_FORMAT_ARGB8888; + cpp = 4; + } + + offset = buffer->offset[0]; + stride = buffer->stride[0]; + break; + + default: + _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); + return NULL; + } + + dri_image = dri2_dpy->image->createSubImage(buffer->driver_buffer, + width, height, format, + offset, stride / cpp, NULL); return dri2_create_image(disp, dri_image); } diff --git a/src/egl/main/eglimage.c b/src/egl/main/eglimage.c index 1174d0a..bfae709 100644 --- a/src/egl/main/eglimage.c +++ b/src/egl/main/eglimage.c @@ -88,6 +88,11 @@ _eglParseImageAttribList(_EGLImageAttribs *attrs, _EGLDisplay *dpy, attrs->DRMBufferStrideMESA = val; break; + /* EGL_WL_bind_wayland_display */ + case EGL_WAYLAND_PLANE_WL: + attrs->PlaneWL = val; + break; + default: /* unknown attrs are ignored */ break; diff --git a/src/egl/main/eglimage.h b/src/egl/main/eglimage.h index acb36aa..9cc86d5 100644 --- a/src/egl/main/eglimage.h +++ b/src/egl/main/eglimage.h @@ -50,6 +50,9 @@ struct _egl_image_attribs EGLint DRMBufferFormatMESA; EGLint DRMBufferUseMESA; EGLint DRMBufferStrideMESA; + + /* EGL_WL_bind_wayland_display */ + EGLint PlaneWL; }; /** -- 1.7.10.2 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev