[3/7] gl-renderer: add dmabuf import

Submitted by Louis-Francis Ratté-Boulianne on Dec. 12, 2014, 9:51 p.m.

Details

Message ID 1418421068-3854-4-git-send-email-lfrb@collabora.com
State RFC
Headers show

Not browsing as part of any series.

Commit Message

Louis-Francis Ratté-Boulianne Dec. 12, 2014, 9:51 p.m.
From: Pekka Paalanen <pekka.paalanen@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(+)

Patch hide | download patch | download mbox

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;
 }