[PATCH] egl_dri2/wayland: handle creating xrgb8888 images
Kristian Høgsberg
krh at bitplanet.net
Wed Jan 11 07:58:00 PST 2012
On Tue, Jan 10, 2012 at 5:16 PM, Robert Bragg <robert at sixbynine.org> wrote:
> From: Robert Bragg <robert at linux.intel.com>
>
> 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.
Yeah, that looks good. I prefer a wl_buffer_get_format() function
instead of the has_alpha one, and then a switch on the WL_DRM_FORMAT_*
values to map to DRI buffer formats.
We didn't just change the fragment shader, we also disabled blending
for opaque buffers, based on the buffer format. But I guess we can
require that xrgb apps mark their buffer as fully opaque (with the
upcoming "mark_this_rectangle_opaque" reqeust, and the compositor can
then disable blending and do other opaque optimizations based on that.
Kristian
> ---
> src/egl/drivers/dri2/egl_dri2.c | 113 +++++++++++++++--------------
> src/egl/wayland/wayland-drm/wayland-drm.c | 16 ++++
> src/egl/wayland/wayland-drm/wayland-drm.h | 3 +
> 3 files changed, 76 insertions(+), 56 deletions(-)
>
> diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
> index 47de978..cb192af 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,72 @@ 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;
>
> - attr_list[1] = width;
> - attr_list[3] = height;
> - attr_list[5] = stride / 4;
> + 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;
> + }
>
> - return dri2_create_image_mesa_drm_buffer(disp, ctx,
> - (EGLClientBuffer)(intptr_t) name,
> - attr_list);
> + 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;
> +
> + format = wayland_drm_buffer_has_alpha(buffer) ?
> + __DRI_IMAGE_FORMAT_ARGB8888 : __DRI_IMAGE_FORMAT_XRGB8888;
> + 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 5e520de..92a80a3 100644
> --- a/src/egl/wayland/wayland-drm/wayland-drm.c
> +++ b/src/egl/wayland/wayland-drm/wayland-drm.c
> @@ -206,6 +206,22 @@ wayland_buffer_is_drm(struct wl_buffer *buffer)
> (void (**)(void)) &drm_buffer_interface;
> }
>
> +int
> +wayland_drm_buffer_has_alpha(struct wl_buffer *buffer_base)
> +{
> + struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) buffer_base;
> + switch (buffer->format) {
> + case WL_DRM_FORMAT_ARGB32:
> + case WL_DRM_FORMAT_PREMULTIPLIED_ARGB32:
> + return 1;
> + case WL_DRM_FORMAT_XRGB32:
> + return 0;
> + default:
> + assert (0);
> + return 0;
> + }
> +}
> +
> 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 c9a90ca..e2aa6ed 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);
>
> +int
> +wayland_drm_buffer_has_alpha(struct wl_buffer *buffer_base);
> +
> void *
> wayland_drm_buffer_get_buffer(struct wl_buffer *buffer);
>
> --
> 1.7.7.5
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
More information about the wayland-devel
mailing list