[PATCH] egl_dri2/wayland: handle creating xrgb8888 images
Robert Bragg
robert at sixbynine.org
Tue Jan 10 14:16:26 PST 2012
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.
---
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
More information about the wayland-devel
mailing list