From 670f182a1f0401f34b1fb7ead50644589737f0d2 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Tue, 10 Jan 2012 22:16:26 +0000 Subject: [PATCH] egl_dri2/wayland: handle creating xrgb8888 images MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit When creating an EGLImage from a struct wl_buffer * this ensures that we create an XRGB8888 image if the wayland buffer doesn't have an alpha channel. To determine if a wl_buffer has a valid alpha channel this patch adds an internal wayland_drm_buffer_has_alpha() function. It's important to get the internal format for an EGLImage right so that if a GL texture is later created from the image then the GL driver will know if it should sample the alpha from the texture or flatten it to a constant of 1.0. This avoids needing fragment program workarounds in wayland compositors to manually ignore the alpha component of textures created from wayland buffers. krh: Edited to use wl_buffer_get_format() instead of wl_buffer_has_alpha(). Reviewed-by: Kristian Høgsberg --- src/egl/drivers/dri2/egl_dri2.c | 125 ++++++++++++---------- src/egl/wayland/wayland-drm/wayland-drm.c | 8 ++ src/egl/wayland/wayland-drm/wayland-drm.h | 3 + 3 files changed, 80 insertions(+), 56 deletions(-) diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index 47de978404d..a7ebf599974 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -993,40 +993,17 @@ dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx, } static _EGLImage * -dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx, - EGLClientBuffer buffer, const EGLint *attr_list) +dri2_create_image_drm_name(_EGLDisplay *disp, _EGLContext *ctx, + EGLint name, + const _EGLImageAttribs *attrs, + EGLint format, + EGLint pitch) { struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_image *dri2_img; - EGLint format, name, pitch, err; - _EGLImageAttribs attrs; (void) ctx; - name = (EGLint) (uintptr_t) buffer; - - err = _eglParseImageAttribList(&attrs, disp, attr_list); - if (err != EGL_SUCCESS) - return NULL; - - if (attrs.Width <= 0 || attrs.Height <= 0 || - attrs.DRMBufferStrideMESA <= 0) { - _eglError(EGL_BAD_PARAMETER, - "bad width, height or stride"); - return NULL; - } - - switch (attrs.DRMBufferFormatMESA) { - case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA: - format = __DRI_IMAGE_FORMAT_ARGB8888; - pitch = attrs.DRMBufferStrideMESA; - break; - default: - _eglError(EGL_BAD_PARAMETER, - "dri2_create_image_khr: unsupported pixmap depth"); - return NULL; - } - dri2_img = malloc(sizeof *dri2_img); if (!dri2_img) { _eglError(EGL_BAD_ALLOC, "dri2_create_image_mesa_drm"); @@ -1040,8 +1017,8 @@ dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx, dri2_img->dri_image = dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen, - attrs.Width, - attrs.Height, + attrs->Width, + attrs->Height, format, name, pitch, @@ -1055,48 +1032,84 @@ dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx, return &dri2_img->base; } -#ifdef HAVE_WAYLAND_PLATFORM static _EGLImage * -dri2_reference_drm_image(_EGLDisplay *disp, _EGLContext *ctx, - __DRIimage *dri_image, EGLint width, EGLint height) +dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx, + EGLClientBuffer buffer, const EGLint *attr_list) { - struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); - EGLint attr_list[] = { - EGL_WIDTH, 0, - EGL_HEIGHT, 0, - EGL_DRM_BUFFER_STRIDE_MESA, 0, - EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, - EGL_NONE - }; - EGLint name, stride; - - dri2_dpy->image->queryImage(dri_image, __DRI_IMAGE_ATTRIB_NAME, &name); - dri2_dpy->image->queryImage(dri_image, __DRI_IMAGE_ATTRIB_STRIDE, &stride); + EGLint format, name, pitch, err; + _EGLImageAttribs attrs; + + name = (EGLint) (uintptr_t) buffer; + + err = _eglParseImageAttribList(&attrs, disp, attr_list); + if (err != EGL_SUCCESS) + return NULL; - attr_list[1] = width; - attr_list[3] = height; - attr_list[5] = stride / 4; + if (attrs.Width <= 0 || attrs.Height <= 0 || + attrs.DRMBufferStrideMESA <= 0) { + _eglError(EGL_BAD_PARAMETER, + "bad width, height or stride"); + return NULL; + } - return dri2_create_image_mesa_drm_buffer(disp, ctx, - (EGLClientBuffer)(intptr_t) name, - attr_list); + switch (attrs.DRMBufferFormatMESA) { + case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA: + format = __DRI_IMAGE_FORMAT_ARGB8888; + pitch = attrs.DRMBufferStrideMESA; + break; + default: + _eglError(EGL_BAD_PARAMETER, + "dri2_create_image_khr: unsupported pixmap depth"); + return NULL; + } + + return dri2_create_image_drm_name (disp, ctx, name, &attrs, format, pitch); } +#ifdef HAVE_WAYLAND_PLATFORM static _EGLImage * dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx, EGLClientBuffer _buffer, const EGLint *attr_list) { struct wl_buffer *buffer = (struct wl_buffer *) _buffer; - (void) attr_list; + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + __DRIimage *dri_image; + _EGLImageAttribs attrs; + EGLint format, name, stride, pitch, err; if (!wayland_buffer_is_drm(buffer)) return NULL; - return dri2_reference_drm_image(disp, ctx, - wayland_drm_buffer_get_buffer(buffer), - buffer->width, - buffer->height); + dri_image = wayland_drm_buffer_get_buffer(buffer); + + dri2_dpy->image->queryImage(dri_image, __DRI_IMAGE_ATTRIB_NAME, &name); + dri2_dpy->image->queryImage(dri_image, __DRI_IMAGE_ATTRIB_STRIDE, &stride); + + err = _eglParseImageAttribList(&attrs, disp, attr_list); + if (err != EGL_SUCCESS) + return NULL; + + attrs.Width = buffer->width; + attrs.Height = buffer->height; + + switch (wayland_drm_buffer_get_format(buffer)) { + case WL_DRM_FORMAT_ARGB32: + case WL_DRM_FORMAT_PREMULTIPLIED_ARGB32: + format = __DRI_IMAGE_FORMAT_ARGB8888; + break; + case WL_DRM_FORMAT_XRGB32: + _eglError(EGL_BAD_PARAMETER, + "dri2_create_image_khr: unsupported wl_buffer format"); + format = __DRI_IMAGE_FORMAT_XRGB8888; + break; + default: + return NULL; + } + + pitch = stride / 4; + + return dri2_create_image_drm_name(disp, ctx, name, &attrs, format, pitch); } #endif diff --git a/src/egl/wayland/wayland-drm/wayland-drm.c b/src/egl/wayland/wayland-drm/wayland-drm.c index 82ca6aa9017..43f91691046 100644 --- a/src/egl/wayland/wayland-drm/wayland-drm.c +++ b/src/egl/wayland/wayland-drm/wayland-drm.c @@ -205,6 +205,14 @@ wayland_buffer_is_drm(struct wl_buffer *buffer) (void (**)(void)) &drm_buffer_interface; } +uint32_t +wayland_drm_buffer_get_format(struct wl_buffer *buffer_base) +{ + struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) buffer_base; + + return buffer->format; +} + void * wayland_drm_buffer_get_buffer(struct wl_buffer *buffer_base) { diff --git a/src/egl/wayland/wayland-drm/wayland-drm.h b/src/egl/wayland/wayland-drm/wayland-drm.h index c9a90cad1ba..bec50a5539f 100644 --- a/src/egl/wayland/wayland-drm/wayland-drm.h +++ b/src/egl/wayland/wayland-drm/wayland-drm.h @@ -29,6 +29,9 @@ wayland_drm_uninit(struct wl_drm *drm); int wayland_buffer_is_drm(struct wl_buffer *buffer); +uint32_t +wayland_drm_buffer_get_format(struct wl_buffer *buffer_base); + void * wayland_drm_buffer_get_buffer(struct wl_buffer *buffer); -- 2.30.2