[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