From 5f0aea2e24c8f17b9852949a4554bb9f9424c9d7 Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Tue, 17 May 2016 13:43:31 -0500 Subject: [PATCH] gl_drm: Add wayland dmabuf native surface support --- src/modules/evas/engines/gl_drm/evas_engine.c | 170 +++++++++++++++++++++++++- 1 file changed, 164 insertions(+), 6 deletions(-) diff --git a/src/modules/evas/engines/gl_drm/evas_engine.c b/src/modules/evas/engines/gl_drm/evas_engine.c index 91b134d..34c0d9e 100644 --- a/src/modules/evas/engines/gl_drm/evas_engine.c +++ b/src/modules/evas/engines/gl_drm/evas_engine.c @@ -608,6 +608,66 @@ _re_winfree(Render_Engine *re) evas_outbuf_unsurf(eng_get_ob(re)); } +/* Code from weston's gl-renderer... */ +static EGLImageKHR +import_simple_dmabuf(EGLDisplay display, struct dmabuf_attributes *attributes) +{ + EGLint attribs[30]; + int atti = 0; + + /* This requires the Mesa commit in + * Mesa 10.3 (08264e5dad4df448e7718e782ad9077902089a07) or + * Mesa 10.2.7 (55d28925e6109a4afd61f109e845a8a51bd17652). + * Otherwise Mesa closes the fd behind our back and re-importing + * will fail. + * https://bugs.freedesktop.org/show_bug.cgi?id=76188 + */ + + attribs[atti++] = EGL_WIDTH; + attribs[atti++] = attributes->width; + attribs[atti++] = EGL_HEIGHT; + attribs[atti++] = attributes->height; + attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT; + attribs[atti++] = attributes->format; + /* XXX: Add modifier here when supported */ + + if (attributes->n_planes > 0) + { + attribs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT; + attribs[atti++] = attributes->fd[0]; + attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT; + attribs[atti++] = attributes->offset[0]; + attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT; + attribs[atti++] = attributes->stride[0]; + } + + if (attributes->n_planes > 1) + { + attribs[atti++] = EGL_DMA_BUF_PLANE1_FD_EXT; + attribs[atti++] = attributes->fd[1]; + attribs[atti++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT; + attribs[atti++] = attributes->offset[1]; + attribs[atti++] = EGL_DMA_BUF_PLANE1_PITCH_EXT; + attribs[atti++] = attributes->stride[1]; + } + + if (attributes->n_planes > 2) + { + attribs[atti++] = EGL_DMA_BUF_PLANE2_FD_EXT; + attribs[atti++] = attributes->fd[2]; + attribs[atti++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT; + attribs[atti++] = attributes->offset[2]; + attribs[atti++] = EGL_DMA_BUF_PLANE2_PITCH_EXT; + attribs[atti++] = attributes->stride[2]; + } + + attribs[atti++] = EGL_NONE; + + return glsym_eglCreateImage(display, EGL_NO_CONTEXT, + EGL_LINUX_DMA_BUF_EXT, + NULL, attribs); +} + static void _native_cb_bind(void *image) { @@ -617,7 +677,18 @@ _native_cb_bind(void *image) if (!(img = image)) return; if (!(n = img->native.data)) return; - if (n->ns.type == EVAS_NATIVE_SURFACE_WL) + if (n->ns.type == EVAS_NATIVE_SURFACE_WL_DMABUF) + { + void *v; + + /* Must re-import every time for coherency. */ + if (n->ns_data.wl_surface_dmabuf.image) + glsym_eglDestroyImage(img->native.disp, n->ns_data.wl_surface_dmabuf.image); + v = import_simple_dmabuf(img->native.disp, &n->ns_data.wl_surface_dmabuf.attr); + glsym_glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, v); + n->ns_data.wl_surface_dmabuf.image = v; + } + else if (n->ns.type == EVAS_NATIVE_SURFACE_WL) { if (n->ns_data.wl_surface.surface) { @@ -645,7 +716,13 @@ _native_cb_unbind(void *image) if (!(img = image)) return; if (!(n = img->native.data)) return; - if (n->ns.type == EVAS_NATIVE_SURFACE_WL) + if (n->ns.type == EVAS_NATIVE_SURFACE_WL_DMABUF) + { + if (n->ns_data.wl_surface_dmabuf.image) + glsym_eglDestroyImage(img->native.disp, n->ns_data.wl_surface_dmabuf.image); + n->ns_data.wl_surface_dmabuf.image = NULL; + } + else if (n->ns.type == EVAS_NATIVE_SURFACE_WL) { //glBindTexture(GL_TEXTURE_2D, 0); //really need? } @@ -667,7 +744,23 @@ _native_cb_free(void *image) if (!(n = img->native.data)) return; if (!(img->native.shared)) return; - if (n->ns.type == EVAS_NATIVE_SURFACE_WL) + if (n->ns.type == EVAS_NATIVE_SURFACE_WL_DMABUF) + { + wlid = n->ns_data.wl_surface_dmabuf.resource; + eina_hash_del(img->native.shared->native_wl_hash, &wlid, img); + if (n->ns_data.wl_surface.surface) + { + if (glsym_eglDestroyImage) + { + glsym_eglDestroyImage(img->native.disp, n->ns_data.wl_surface_dmabuf.image); + if (eglGetError() != EGL_SUCCESS) + ERR("eglDestroyImage() failed."); + } + else + ERR("Try eglDestroyImage on EGL with no support"); + } + } + else if (n->ns.type == EVAS_NATIVE_SURFACE_WL) { wlid = (void*)n->ns_data.wl_surface.wl_buf; eina_hash_del(img->native.shared->native_wl_hash, &wlid, img); @@ -1073,7 +1166,19 @@ eng_image_native_set(void *data, void *image, void *native) if (ns) { - if (ns->type == EVAS_NATIVE_SURFACE_WL) + if (ns->type == EVAS_NATIVE_SURFACE_WL_DMABUF) + { + wl_buf = ns->data.wl_dmabuf.resource; + if (img->native.data) + { + Evas_Native_Surface *ens; + + ens = img->native.data; + if (ens->data.wl_dmabuf.resource == wl_buf) + return img; + } + } + else if (ns->type == EVAS_NATIVE_SURFACE_WL) { wl_buf = ns->data.wl.legacy_buffer; if (img->native.data) @@ -1114,7 +1219,22 @@ eng_image_native_set(void *data, void *image, void *native) if (!ns) return img; - if (ns->type == EVAS_NATIVE_SURFACE_WL) + if (ns->type == EVAS_NATIVE_SURFACE_WL_DMABUF) + { + wlid = wl_buf; + img2 = eina_hash_find(ob->gl_context->shared->native_wl_hash, &wlid); + if (img2 == img) return img; + if (img2) + { + if((n = img2->native.data)) + { + glsym_evas_gl_common_image_ref(img2); + glsym_evas_gl_common_image_free(img); + return img2; + } + } + } + else if (ns->type == EVAS_NATIVE_SURFACE_WL) { wlid = wl_buf; img2 = eina_hash_find(ob->gl_context->shared->native_wl_hash, &wlid); @@ -1152,7 +1272,45 @@ eng_image_native_set(void *data, void *image, void *native) if (!(img = img2)) return NULL; - if (ns->type == EVAS_NATIVE_SURFACE_WL) + if (ns->type == EVAS_NATIVE_SURFACE_WL_DMABUF) + { + if (native) + { + struct dmabuf_attributes *a; + + a = ns->data.wl_dmabuf.attr; + if (a->version != 1) + { + glsym_evas_gl_common_image_free(img); + return NULL; + } + if ((n = calloc(1, sizeof(Native)))) + { + struct dmabuf_attributes *a; + + a = ns->data.wl_dmabuf.attr; + memcpy(&(n->ns), ns, sizeof(Evas_Native_Surface)); + memcpy(&n->ns_data.wl_surface_dmabuf.attr, a, sizeof(*a)); + eina_hash_add(ob->gl_context->shared->native_wl_hash, + &wlid, img); + + n->ns_data.wl_surface_dmabuf.resource = wl_buf; + img->native.yinvert = 1; + img->native.loose = 0; + img->native.disp = ob->egl.disp; + img->native.shared = ob->gl_context->shared; + img->native.data = n; + img->native.func.bind = _native_cb_bind; + img->native.func.unbind = _native_cb_unbind; + img->native.func.free = _native_cb_free; + img->native.target = GL_TEXTURE_2D; + img->native.mipmap = 0; + + glsym_evas_gl_common_image_native_enable(img); + } + } + } + else if (ns->type == EVAS_NATIVE_SURFACE_WL) { if (native) { -- 2.7.4