gl_drm: Add wayland dmabuf native surface support

This commit is contained in:
Derek Foreman 2016-05-17 13:43:31 -05:00
parent 72b1997f06
commit 5f0aea2e24
1 changed files with 164 additions and 6 deletions

View File

@ -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)
{