[PATCH 2/6] gl-renderer: introduce a new struct dmabuf_image
Emmanuel Gil Peyrot
emmanuel.peyrot at collabora.com
Tue Nov 24 11:28:25 PST 2015
This struct serves as renderer data for linux-dmabuf buffers, and can
contain multiple struct egl_image, simplifying this latter in the
common non-dmabuf case.
Signed-off-by: Emmanuel Gil Peyrot <emmanuel.peyrot at collabora.com>
Reviewed-by: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
Reviewed-by: Daniel Stone <daniels at collabora.com>
Differential Revision: https://phabricator.freedesktop.org/D333
---
src/gl-renderer.c | 167 +++++++++++++++++++++++++++++++++++-------------------
1 file changed, 109 insertions(+), 58 deletions(-)
diff --git a/src/gl-renderer.c b/src/gl-renderer.c
index d5356b6..90e4842 100644
--- a/src/gl-renderer.c
+++ b/src/gl-renderer.c
@@ -99,9 +99,12 @@ struct egl_image {
struct gl_renderer *renderer;
EGLImageKHR image;
int refcount;
+};
- /* Only used for dmabuf imported buffer */
+struct dmabuf_image {
struct linux_dmabuf_buffer *dmabuf;
+ int num_images;
+ struct egl_image *images[3];
struct wl_list link;
};
@@ -191,6 +194,13 @@ struct gl_renderer {
static PFNEGLGETPLATFORMDISPLAYEXTPROC get_platform_display = NULL;
+static inline const char *
+dump_format(uint32_t *format)
+{
+ // FIXME: this won’t work properly on big-endian.
+ return (const char *)format;
+}
+
static inline struct gl_output_state *
get_output_state(struct weston_output *output)
{
@@ -222,7 +232,6 @@ egl_image_create(struct gl_renderer *gr, EGLenum target,
struct egl_image *img;
img = zalloc(sizeof *img);
- wl_list_init(&img->link);
img->renderer = gr;
img->refcount = 1;
img->image = gr->create_image(gr->egl_display, EGL_NO_CONTEXT,
@@ -255,16 +264,37 @@ egl_image_unref(struct egl_image *image)
if (image->refcount > 0)
return image->refcount;
- if (image->dmabuf)
- linux_dmabuf_buffer_set_user_data(image->dmabuf, NULL, NULL);
-
gr->destroy_image(gr->egl_display, image->image);
- wl_list_remove(&image->link);
free(image);
return 0;
}
+static struct dmabuf_image*
+dmabuf_image_create(void)
+{
+ struct dmabuf_image *img;
+
+ img = zalloc(sizeof *img);
+ wl_list_init(&img->link);
+
+ return img;
+}
+
+static void
+dmabuf_image_destroy(struct dmabuf_image *image)
+{
+ int i;
+
+ for (i = 0; i < image->num_images; ++i)
+ egl_image_unref(image->images[i]);
+
+ if (image->dmabuf)
+ linux_dmabuf_buffer_set_user_data(image->dmabuf, NULL, NULL);
+
+ wl_list_remove(&image->link);
+}
+
static const char *
egl_error_string(EGLint code)
{
@@ -1420,23 +1450,19 @@ gl_renderer_attach_egl(struct weston_surface *es, struct weston_buffer *buffer,
static void
gl_renderer_destroy_dmabuf(struct linux_dmabuf_buffer *dmabuf)
{
- struct egl_image *image = dmabuf->user_data;
+ struct dmabuf_image *image = dmabuf->user_data;
- egl_image_unref(image);
+ dmabuf_image_destroy(image);
}
static struct egl_image *
-import_dmabuf(struct gl_renderer *gr,
- struct linux_dmabuf_buffer *dmabuf)
+import_simple_dmabuf(struct gl_renderer *gr,
+ struct dmabuf_attributes *attributes)
{
struct egl_image *image;
EGLint attribs[30];
int atti = 0;
- image = linux_dmabuf_buffer_get_user_data(dmabuf);
- if (image)
- return egl_image_ref(image);
-
/* This requires the Mesa commit in
* Mesa 10.3 (08264e5dad4df448e7718e782ad9077902089a07) or
* Mesa 10.2.7 (55d28925e6109a4afd61f109e845a8a51bd17652).
@@ -1446,38 +1472,38 @@ import_dmabuf(struct gl_renderer *gr,
*/
attribs[atti++] = EGL_WIDTH;
- attribs[atti++] = dmabuf->attributes.width;
+ attribs[atti++] = attributes->width;
attribs[atti++] = EGL_HEIGHT;
- attribs[atti++] = dmabuf->attributes.height;
+ attribs[atti++] = attributes->height;
attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
- attribs[atti++] = dmabuf->attributes.format;
+ attribs[atti++] = attributes->format;
/* XXX: Add modifier here when supported */
- if (dmabuf->attributes.n_planes > 0) {
+ if (attributes->n_planes > 0) {
attribs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT;
- attribs[atti++] = dmabuf->attributes.fd[0];
+ attribs[atti++] = attributes->fd[0];
attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
- attribs[atti++] = dmabuf->attributes.offset[0];
+ attribs[atti++] = attributes->offset[0];
attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
- attribs[atti++] = dmabuf->attributes.stride[0];
+ attribs[atti++] = attributes->stride[0];
}
- if (dmabuf->attributes.n_planes > 1) {
+ if (attributes->n_planes > 1) {
attribs[atti++] = EGL_DMA_BUF_PLANE1_FD_EXT;
- attribs[atti++] = dmabuf->attributes.fd[1];
+ attribs[atti++] = attributes->fd[1];
attribs[atti++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT;
- attribs[atti++] = dmabuf->attributes.offset[1];
+ attribs[atti++] = attributes->offset[1];
attribs[atti++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
- attribs[atti++] = dmabuf->attributes.stride[1];
+ attribs[atti++] = attributes->stride[1];
}
- if (dmabuf->attributes.n_planes > 2) {
+ if (attributes->n_planes > 2) {
attribs[atti++] = EGL_DMA_BUF_PLANE2_FD_EXT;
- attribs[atti++] = dmabuf->attributes.fd[2];
+ attribs[atti++] = attributes->fd[2];
attribs[atti++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT;
- attribs[atti++] = dmabuf->attributes.offset[2];
+ attribs[atti++] = attributes->offset[2];
attribs[atti++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
- attribs[atti++] = dmabuf->attributes.stride[2];
+ attribs[atti++] = attributes->stride[2];
}
attribs[atti++] = EGL_NONE;
@@ -1485,14 +1511,27 @@ import_dmabuf(struct gl_renderer *gr,
image = egl_image_create(gr, EGL_LINUX_DMA_BUF_EXT, NULL,
attribs);
- if (!image)
+ return image;
+}
+
+static struct dmabuf_image *
+import_dmabuf(struct gl_renderer *gr,
+ struct linux_dmabuf_buffer *dmabuf)
+{
+ struct egl_image *egl_image;
+ struct dmabuf_image *image;
+
+ egl_image = import_simple_dmabuf(gr, &dmabuf->attributes);
+ if (!egl_image) {
+ weston_log("Format %.4s unsupported by EGL, aborting\n",
+ dump_format(&dmabuf->attributes.format));
return NULL;
+ }
- /* The cache owns one ref. The caller gets another. */
+ image = dmabuf_image_create();
image->dmabuf = dmabuf;
- wl_list_insert(&gr->dmabuf_images, &image->link);
- linux_dmabuf_buffer_set_user_data(dmabuf, egl_image_ref(image),
- gl_renderer_destroy_dmabuf);
+ image->num_images = 1;
+ image->images[0] = egl_image;
return image;
}
@@ -1502,7 +1541,7 @@ gl_renderer_import_dmabuf(struct weston_compositor *ec,
struct linux_dmabuf_buffer *dmabuf)
{
struct gl_renderer *gr = get_renderer(ec);
- struct egl_image *image;
+ struct dmabuf_image *image;
int i;
assert(gr->has_dmabuf_import);
@@ -1521,8 +1560,9 @@ gl_renderer_import_dmabuf(struct weston_compositor *ec,
if (!image)
return false;
- /* Cache retains a ref. */
- egl_image_unref(image);
+ wl_list_insert(&gr->dmabuf_images, &image->link);
+ linux_dmabuf_buffer_set_user_data(dmabuf, image,
+ gl_renderer_destroy_dmabuf);
return true;
}
@@ -1552,7 +1592,9 @@ gl_renderer_attach_dmabuf(struct weston_surface *surface,
{
struct gl_renderer *gr = get_renderer(surface->compositor);
struct gl_surface_state *gs = get_surface_state(surface);
+ struct dmabuf_image *image;
int i;
+ int ret;
if (!gr->has_dmabuf_import) {
linux_dmabuf_buffer_send_server_error(dmabuf,
@@ -1586,27 +1628,40 @@ gl_renderer_attach_dmabuf(struct weston_surface *surface,
*
* Here we release the cache reference which has to be final.
*/
- gs->images[0] = linux_dmabuf_buffer_get_user_data(dmabuf);
- if (gs->images[0]) {
- int ret;
+ image = linux_dmabuf_buffer_get_user_data(dmabuf);
- ret = egl_image_unref(gs->images[0]);
+ /* The dmabuf_image should have been created during the import */
+ assert(image != NULL);
+
+ for (i = 0; i < image->num_images; ++i) {
+ ret = egl_image_unref(image->images[i]);
assert(ret == 0);
}
- gs->images[0] = import_dmabuf(gr, dmabuf);
- if (!gs->images[0]) {
- linux_dmabuf_buffer_send_server_error(dmabuf,
- "EGL dmabuf import failed");
- return;
+ for (i = 0; i < image->num_images; ++i) {
+ image->images[i] = import_simple_dmabuf(gr, &image->dmabuf->attributes);
+ if (!image->images[i]) {
+ image->num_images = 0;
+ while (i) {
+ ret = egl_image_unref(image->images[--i])
+ assert(ret == 0);
+ }
+ linux_dmabuf_buffer_send_server_error(dmabuf,
+ "EGL dmabuf import failed");
+ return;
+ }
}
- gs->num_images = 1;
- ensure_textures(gs, 1);
+ gs->num_images = image->num_images;
+ for (i = 0; i < gs->num_images; ++i)
+ gs->images[i] = egl_image_ref(image->images[i]);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(gs->target, gs->textures[0]);
- gr->image_target_texture_2d(gs->target, gs->images[0]->image);
+ ensure_textures(gs, gs->num_images);
+ for (i = 0; i < gs->num_images; ++i) {
+ glActiveTexture(GL_TEXTURE0 + i);
+ glBindTexture(gs->target, gs->textures[i]);
+ gr->image_target_texture_2d(gs->target, gs->images[i]->image);
+ }
gs->pitch = buffer->width;
gs->height = buffer->height;
@@ -2370,7 +2425,7 @@ static void
gl_renderer_destroy(struct weston_compositor *ec)
{
struct gl_renderer *gr = get_renderer(ec);
- struct egl_image *image, *next;
+ struct dmabuf_image *image, *next;
wl_signal_emit(&gr->destroy_signal, gr);
@@ -2383,12 +2438,8 @@ gl_renderer_destroy(struct weston_compositor *ec)
EGL_NO_CONTEXT);
- wl_list_for_each_safe(image, next, &gr->dmabuf_images, link) {
- int ret;
-
- ret = egl_image_unref(image);
- assert(ret == 0);
- }
+ wl_list_for_each_safe(image, next, &gr->dmabuf_images, link)
+ dmabuf_image_destroy(image);
eglTerminate(gr->egl_display);
eglReleaseThread();
--
2.6.2
More information about the wayland-devel
mailing list