[PATCH 3/7] gl-renderer: add dmabuf import
Louis-Francis Ratté-Boulianne
lfrb at collabora.com
Fri Dec 12 13:51:04 PST 2014
From: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
Squashed with:
gl-renderer: error if dmabuf exposed unsupported
gl_renderer: always use GL_TEXTURE_EXTERNAL_OES with dmabuf
---
src/gl-renderer.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 103 insertions(+)
diff --git a/src/gl-renderer.c b/src/gl-renderer.c
index bb46acd..bb4e409 100644
--- a/src/gl-renderer.c
+++ b/src/gl-renderer.c
@@ -35,6 +35,8 @@
#include "gl-renderer.h"
#include "vertex-clipping.h"
+#include "linux-dmabuf.h"
+#include "linux-dmabuf-server-protocol.h"
#include <EGL/eglext.h>
#include "weston-egl-ext.h"
@@ -149,6 +151,8 @@ struct gl_renderer {
int has_configless_context;
+ int has_dmabuf_import;
+
struct gl_shader texture_shader_rgba;
struct gl_shader texture_shader_rgbx;
struct gl_shader texture_shader_egl_external;
@@ -1305,12 +1309,104 @@ gl_renderer_attach_egl(struct weston_surface *es, struct weston_buffer *buffer,
}
static void
+gl_renderer_attach_dmabuf(struct weston_surface *surface,
+ struct weston_buffer *buffer,
+ struct linux_dmabuf_buffer *dmabuf)
+{
+#ifdef EGL_EXT_image_dma_buf_import
+ struct gl_renderer *gr = get_renderer(surface->compositor);
+ struct gl_surface_state *gs = get_surface_state(surface);
+ EGLint attribs[30];
+ int atti = 0;
+ int i;
+
+ assert(gr->has_dmabuf_import);
+
+ buffer->width = dmabuf->width;
+ buffer->height = dmabuf->height;
+ buffer->y_inverted = 1; /* XXX: readlly? */
+
+ attribs[atti++] = EGL_WIDTH;
+ attribs[atti++] = dmabuf->width;
+ attribs[atti++] = EGL_HEIGHT;
+ attribs[atti++] = dmabuf->height;
+ attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
+ attribs[atti++] = dmabuf->format;
+
+ if (dmabuf->n_planes > 0) {
+ attribs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT;
+ attribs[atti++] = dmabuf->dmabuf_fd[0];
+ attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
+ attribs[atti++] = dmabuf->offset[0];
+ attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
+ attribs[atti++] = dmabuf->stride[0];
+ }
+
+ if (dmabuf->n_planes > 1) {
+ attribs[atti++] = EGL_DMA_BUF_PLANE1_FD_EXT;
+ attribs[atti++] = dmabuf->dmabuf_fd[1];
+ attribs[atti++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT;
+ attribs[atti++] = dmabuf->offset[1];
+ attribs[atti++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
+ attribs[atti++] = dmabuf->stride[1];
+ }
+
+ if (dmabuf->n_planes > 2) {
+ attribs[atti++] = EGL_DMA_BUF_PLANE2_FD_EXT;
+ attribs[atti++] = dmabuf->dmabuf_fd[2];
+ attribs[atti++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT;
+ attribs[atti++] = dmabuf->offset[2];
+ attribs[atti++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
+ attribs[atti++] = dmabuf->stride[2];
+ }
+
+ attribs[atti++] = EGL_NONE;
+
+ for (i = 0; i < gs->num_images; i++)
+ gr->destroy_image(gr->egl_display, gs->images[i]);
+ gs->num_images = 0;
+ gs->target = GL_TEXTURE_EXTERNAL_OES;
+ gs->shader = &gr->texture_shader_egl_external;
+
+ ensure_textures(gs, 1);
+
+ gs->images[0] = gr->create_image(gr->egl_display, EGL_NO_CONTEXT,
+ EGL_LINUX_DMA_BUF_EXT, NULL,
+ attribs);
+ if (!gs->images[0]) {
+ /* XXX: wrong resource for error code */
+ wl_resource_post_error(dmabuf->resource,
+ ZLINUX_DMABUF_ERROR_INVALID_DMABUF,
+ "dmabuf import to EGL failed");
+ return;
+ }
+ gs->num_images = 1;
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(gs->target, gs->textures[0]);
+ gr->image_target_texture_2d(gs->target, gs->images[0]);
+
+ gs->pitch = buffer->width;
+ gs->height = buffer->height;
+ gs->buffer_type = BUFFER_TYPE_EGL;
+ gs->y_inverted = buffer->y_inverted;
+
+#else
+ /* XXX: wrong resource for error code */
+ wl_resource_post_error(dmabuf->resource,
+ ZLINUX_DMABUF_ERROR_INVALID_DMABUF,
+ "implementation error: EGL dmabuf import");
+#endif /* EGL_EXT_image_dma_buf_import */
+}
+
+static void
gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
{
struct weston_compositor *ec = es->compositor;
struct gl_renderer *gr = get_renderer(ec);
struct gl_surface_state *gs = get_surface_state(es);
struct wl_shm_buffer *shm_buffer;
+ struct linux_dmabuf_buffer *dmabuf;
EGLint format;
int i;
@@ -1336,6 +1432,8 @@ gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
else if (gr->query_buffer(gr->egl_display, (void *) buffer->resource,
EGL_TEXTURE_FORMAT, &format))
gl_renderer_attach_egl(es, buffer, format);
+ else if ((dmabuf = linux_dmabuf_buffer_get(buffer->resource)))
+ gl_renderer_attach_dmabuf(es, buffer, dmabuf);
else {
weston_log("unhandled buffer type!\n");
weston_buffer_reference(&gs->buffer_ref, NULL);
@@ -1948,6 +2046,11 @@ gl_renderer_setup_egl_extensions(struct weston_compositor *ec)
gr->has_configless_context = 1;
#endif
+#ifdef EGL_EXT_image_dma_buf_import
+ if (strstr(extensions, "EGL_EXT_image_dma_buf_import"))
+ gr->has_dmabuf_import = 1;
+#endif
+
return 0;
}
--
2.1.0
More information about the wayland-devel
mailing list