From 8c2118823b3d42840cc6f48cbdc0e1b342f90b80 Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Thu, 17 Nov 2016 02:41:14 +1100 Subject: gl/egl: remove EGLImage functions from egl context By adding the necessary GstEGLImage entry points to create a GstEGLImage from a GstGLMemory. https://bugzilla.gnome.org/show_bug.cgi?id=774518 --- gst-libs/gst/gl/egl/gsteglimage.c | 250 ++++++++++++++++++++++++--------- gst-libs/gst/gl/egl/gsteglimage.h | 7 +- gst-libs/gst/gl/egl/gstglcontext_egl.c | 31 ---- gst-libs/gst/gl/egl/gstglcontext_egl.h | 6 - gst-libs/gst/gl/egl/gstglmemoryegl.c | 20 +-- 5 files changed, 194 insertions(+), 120 deletions(-) (limited to 'gst-libs') diff --git a/gst-libs/gst/gl/egl/gsteglimage.c b/gst-libs/gst/gl/egl/gsteglimage.c index cc6c4bdae..24dacdc33 100644 --- a/gst-libs/gst/gl/egl/gsteglimage.c +++ b/gst-libs/gst/gl/egl/gsteglimage.c @@ -39,6 +39,7 @@ #endif #include "gsteglimage.h" +#include #include #if GST_GL_HAVE_DMABUF @@ -176,7 +177,8 @@ gst_egl_image_new_wrapped (GstGLContext * context, EGLImageKHR image, GstEGLImage *img = NULL; g_return_val_if_fail (context != NULL, NULL); - g_return_val_if_fail (GST_IS_GL_CONTEXT_EGL (context), NULL); + g_return_val_if_fail ((gst_gl_context_get_gl_platform (context) & + GST_GL_PLATFORM_EGL) != 0, NULL); g_return_val_if_fail (image != EGL_NO_IMAGE_KHR, NULL); img = g_new0 (GstEGLImage, 1); @@ -195,6 +197,165 @@ gst_egl_image_new_wrapped (GstGLContext * context, EGLImageKHR image, return img; } +static EGLImageKHR +_gst_egl_image_create (GstGLContext * context, guint target, + EGLClientBuffer buffer, guintptr * attribs) +{ + EGLDisplay egl_display = EGL_DEFAULT_DISPLAY; + EGLContext egl_context = EGL_NO_CONTEXT; + EGLImageKHR img = EGL_NO_IMAGE_KHR; + GstGLDisplayEGL *display_egl; + gint plat_major, plat_minor; + guint attrib_len = 0; + + gst_gl_context_get_gl_platform_version (context, &plat_major, &plat_minor); + + display_egl = gst_gl_display_egl_from_gl_display (context->display); + if (!display_egl) { + GST_WARNING_OBJECT (context, "Failed to retrieve GstGLDisplayEGL from %" + GST_PTR_FORMAT, context->display); + return EGL_NO_IMAGE_KHR; + } + egl_display = + (EGLDisplay) gst_gl_display_get_handle (GST_GL_DISPLAY (display_egl)); + gst_object_unref (display_egl); + +#if GST_GL_HAVE_DMABUF + if (target != EGL_LINUX_DMA_BUF_EXT) + egl_context = (EGLContext) gst_gl_context_get_gl_context (context); +#endif + + if (attribs) + while (attribs[attrib_len++] != EGL_NONE) { + } +#ifdef EGL_VERSION_1_5 + if (GST_GL_CHECK_GL_VERSION (plat_major, plat_minor, 1, 5)) { + EGLImageKHR (*gst_eglCreateImage) (EGLDisplay dpy, EGLContext ctx, + EGLenum target, EGLClientBuffer buffer, const EGLAttrib * attrib_list); + EGLAttrib *egl_attribs = NULL; + guint i; + + gst_eglCreateImage = gst_gl_context_get_proc_address (context, + "eglCreateImage"); + if (!gst_eglCreateImage) { + GST_ERROR_OBJECT (context, "\"eglCreateImage\" not exposed by the " + "implementation as required by EGL >= 1.5"); + return EGL_NO_IMAGE_KHR; + } + + if (attribs) { + egl_attribs = g_new0 (EGLAttrib, attrib_len); + for (i = 0; i < attrib_len; i++) + egl_attribs[i] = (EGLAttrib) attribs[i]; + } + + img = gst_eglCreateImage (egl_display, egl_context, target, buffer, + egl_attribs); + + g_free (egl_attribs); + } else +#endif + { + EGLImageKHR (*gst_eglCreateImageKHR) (EGLDisplay dpy, EGLContext ctx, + EGLenum target, EGLClientBuffer buffer, const EGLint * attrib_list); + EGLint *egl_attribs = NULL; + gint i; + + gst_eglCreateImageKHR = gst_gl_context_get_proc_address (context, + "eglCreateImageKHR"); + if (!gst_eglCreateImageKHR) { + GST_WARNING_OBJECT (context, "\"eglCreateImageKHR\" not exposed by the " + "implementation"); + return EGL_NO_IMAGE_KHR; + } + + if (attribs) { + egl_attribs = g_new0 (EGLint, attrib_len); + for (i = 0; i < attrib_len; i++) + egl_attribs[i] = (EGLint) attribs[i]; + } + + img = gst_eglCreateImageKHR (egl_display, egl_context, target, buffer, + egl_attribs); + + g_free (egl_attribs); + } + + return img; +} + +static void +_gst_egl_image_destroy (GstGLContext * context, EGLImageKHR image) +{ + EGLBoolean (*gst_eglDestroyImage) (EGLDisplay dpy, EGLImageKHR image); + EGLDisplay egl_display = EGL_DEFAULT_DISPLAY; + GstGLDisplayEGL *display_egl; + + gst_eglDestroyImage = gst_gl_context_get_proc_address (context, + "eglDestroyImage"); + if (!gst_eglDestroyImage) { + gst_eglDestroyImage = gst_gl_context_get_proc_address (context, + "eglDestroyImageKHR"); + if (!gst_eglDestroyImage) { + GST_ERROR_OBJECT (context, "\"eglDestroyImage\" not exposed by the " + "implementation"); + return; + } + } + + display_egl = gst_gl_display_egl_from_gl_display (context->display); + if (!display_egl) { + GST_WARNING_OBJECT (context, "Failed to retrieve GstGLDisplayEGL from %" + GST_PTR_FORMAT, context->display); + return; + } + egl_display = + (EGLDisplay) gst_gl_display_get_handle (GST_GL_DISPLAY (display_egl)); + gst_object_unref (display_egl); + + if (!gst_eglDestroyImage (egl_display, image)) + GST_WARNING_OBJECT (context, "eglDestroyImage failed"); +} + +static void +_destroy_egl_image (GstEGLImage * image, gpointer user_data) +{ + _gst_egl_image_destroy (image->context, image->image); +} + +/** + * gst_egl_image_from_texture: + * @context: a #GstGLContext (must be an EGL context) + * @gl_mem: a #GstGLMemory + * @attribs: additional attributes to add to the eglCreateImage() call. + * + * Returns: (transfer full): a #GstEGLImage wrapping @gl_mem or %NULL on failure + */ +GstEGLImage * +gst_egl_image_from_texture (GstGLContext * context, GstGLMemory * gl_mem, + guintptr * attribs) +{ + EGLenum egl_target; + EGLImageKHR img; + + if (gl_mem->tex_target != GST_GL_TEXTURE_TARGET_2D) { + GST_FIXME_OBJECT (context, "Only know how to create EGLImage's from 2D " + "textures"); + return NULL; + } + + egl_target = EGL_GL_TEXTURE_2D_KHR; + + img = _gst_egl_image_create (context, egl_target, + (EGLClientBuffer) (guintptr) gl_mem->tex_id, attribs); + if (!img) + return NULL; + + return gst_egl_image_new_wrapped (context, img, gl_mem->tex_type, + GST_VIDEO_GL_TEXTURE_ORIENTATION_X_NORMAL_Y_NORMAL, + NULL, (GstEGLImageDestroyNotify) _destroy_egl_image); +} + #if GST_GL_HAVE_DMABUF /* * GStreamer format descriptions differ from DRM formats as the representation @@ -266,12 +427,6 @@ _drm_fourcc_from_info (GstVideoInfo * info, int plane) } } -static void -_destroy_egl_image (GstEGLImage * image, gpointer user_data) -{ - image->context->eglDestroyImage (image->context->egl_display, image->image); -} - /** * gst_egl_image_from_dmabuf: * @context: a #GstGLContext (must be an EGL context) @@ -286,15 +441,11 @@ GstEGLImage * gst_egl_image_from_dmabuf (GstGLContext * context, gint dmabuf, GstVideoInfo * in_info, gint plane, gsize offset) { - GstGLContextEGL *ctx_egl = GST_GL_CONTEXT_EGL (context); - gint fourcc; - gint atti = 0; - EGLint attribs[13]; -#ifdef EGL_VERSION_1_5 - EGLAttrib attribs_1_5[13]; -#endif - EGLImageKHR img = EGL_NO_IMAGE_KHR; GstVideoGLTextureType type; + guintptr attribs[13]; + EGLImageKHR img; + gint atti = 0; + gint fourcc; fourcc = _drm_fourcc_from_info (in_info, plane); type = @@ -306,55 +457,26 @@ gst_egl_image_from_dmabuf (GstGLContext * context, GST_VIDEO_INFO_COMP_WIDTH (in_info, plane), GST_VIDEO_INFO_COMP_HEIGHT (in_info, plane)); -#ifdef EGL_VERSION_1_5 - if (GST_GL_CHECK_GL_VERSION (ctx_egl->egl_major, ctx_egl->egl_minor, 1, 5)) { - attribs_1_5[atti++] = EGL_WIDTH; - attribs_1_5[atti++] = GST_VIDEO_INFO_COMP_WIDTH (in_info, plane); - attribs_1_5[atti++] = EGL_HEIGHT; - attribs_1_5[atti++] = GST_VIDEO_INFO_COMP_HEIGHT (in_info, plane); - attribs_1_5[atti++] = EGL_LINUX_DRM_FOURCC_EXT; - attribs_1_5[atti++] = fourcc; - attribs_1_5[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT; - attribs_1_5[atti++] = dmabuf; - attribs_1_5[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT; - attribs_1_5[atti++] = offset; - attribs_1_5[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT; - attribs_1_5[atti++] = GST_VIDEO_INFO_PLANE_STRIDE (in_info, plane); - attribs_1_5[atti] = EGL_NONE; - - for (int i = 0; i < atti; i++) - GST_LOG ("attr %i: %" G_GINTPTR_FORMAT, i, attribs_1_5[i]); - - g_assert (atti == 12); - - img = ctx_egl->eglCreateImage (ctx_egl->egl_display, EGL_NO_CONTEXT, - EGL_LINUX_DMA_BUF_EXT, NULL, attribs_1_5); - - } else -#endif - { - attribs[atti++] = EGL_WIDTH; - attribs[atti++] = GST_VIDEO_INFO_COMP_WIDTH (in_info, plane); - attribs[atti++] = EGL_HEIGHT; - attribs[atti++] = GST_VIDEO_INFO_COMP_HEIGHT (in_info, plane); - attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT; - attribs[atti++] = fourcc; - attribs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT; - attribs[atti++] = dmabuf; - attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT; - attribs[atti++] = offset; - attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT; - attribs[atti++] = GST_VIDEO_INFO_PLANE_STRIDE (in_info, plane); - attribs[atti] = EGL_NONE; - - for (int i = 0; i < atti; i++) - GST_LOG ("attr %i: %08X", i, attribs[i]); - - g_assert (atti == 12); - - img = ctx_egl->eglCreateImageKHR (ctx_egl->egl_display, EGL_NO_CONTEXT, - EGL_LINUX_DMA_BUF_EXT, NULL, attribs); - } + attribs[atti++] = EGL_WIDTH; + attribs[atti++] = GST_VIDEO_INFO_COMP_WIDTH (in_info, plane); + attribs[atti++] = EGL_HEIGHT; + attribs[atti++] = GST_VIDEO_INFO_COMP_HEIGHT (in_info, plane); + attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT; + attribs[atti++] = fourcc; + attribs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT; + attribs[atti++] = dmabuf; + attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT; + attribs[atti++] = offset; + attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT; + attribs[atti++] = GST_VIDEO_INFO_PLANE_STRIDE (in_info, plane); + attribs[atti] = EGL_NONE; + + for (int i = 0; i < atti; i++) + GST_LOG ("attr %i: %" G_GINTPTR_FORMAT, i, attribs[i]); + + g_assert (atti == 12); + + img = _gst_egl_image_create (context, EGL_LINUX_DMA_BUF_EXT, NULL, attribs); if (!img) { GST_WARNING ("eglCreateImage failed: %s", gst_egl_get_error_string (eglGetError ())); diff --git a/gst-libs/gst/gl/egl/gsteglimage.h b/gst-libs/gst/gl/egl/gsteglimage.h index 46ee4ffdc..0b93e1007 100644 --- a/gst-libs/gst/gl/egl/gsteglimage.h +++ b/gst-libs/gst/gl/egl/gsteglimage.h @@ -27,7 +27,7 @@ #include #include -#include +#include G_BEGIN_DECLS @@ -51,7 +51,7 @@ struct _GstEGLImage { GstMiniObject parent; - GstGLContextEGL *context; + GstGLContext *context; EGLImageKHR image; GstVideoGLTextureType type; /* FIXME: remove this and use the affine transformation meta instead */ @@ -73,6 +73,9 @@ GstEGLImage * gst_egl_image_new_wrapped (GstGLContext * EGLImageKHR gst_egl_image_get_image (GstEGLImage * image); GstVideoGLTextureOrientation gst_egl_image_get_orientation (GstEGLImage * image); +GstEGLImage * gst_egl_image_from_texture (GstGLContext * context, + GstGLMemory * gl_mem, + guintptr * attribs); #if GST_GL_HAVE_DMABUF GstEGLImage * gst_egl_image_from_dmabuf (GstGLContext * context, gint dmabuf, diff --git a/gst-libs/gst/gl/egl/gstglcontext_egl.c b/gst-libs/gst/gl/egl/gstglcontext_egl.c index 78c14a367..25cd8a8d7 100644 --- a/gst-libs/gst/gl/egl/gstglcontext_egl.c +++ b/gst-libs/gst/gl/egl/gstglcontext_egl.c @@ -557,27 +557,6 @@ gst_gl_context_egl_create_context (GstGLContext * context, goto failure; } } - - /* EGLImage functions */ - if (GST_GL_CHECK_GL_VERSION (egl_major, egl_minor, 1, 5)) { - egl->eglCreateImage = gst_gl_context_get_proc_address (context, - "eglCreateImage"); - egl->eglDestroyImage = gst_gl_context_get_proc_address (context, - "eglDestroyImage"); - if (egl->eglCreateImage == NULL || egl->eglDestroyImage == NULL) { - egl->eglCreateImage = NULL; - egl->eglDestroyImage = NULL; - } - } else if (gst_gl_check_extension ("EGL_KHR_image_base", egl->egl_exts)) { - egl->eglCreateImageKHR = gst_gl_context_get_proc_address (context, - "eglCreateImageKHR"); - egl->eglDestroyImage = gst_gl_context_get_proc_address (context, - "eglDestroyImageKHR"); - if (egl->eglCreateImageKHR == NULL || egl->eglDestroyImage == NULL) { - egl->eglCreateImageKHR = NULL; - egl->eglDestroyImage = NULL; - } - } egl->egl_major = egl_major; egl->egl_minor = egl_minor; @@ -787,16 +766,6 @@ gst_gl_context_egl_check_feature (GstGLContext * context, const gchar * feature) { GstGLContextEGL *context_egl = GST_GL_CONTEXT_EGL (context); - if (g_strcmp0 (feature, "EGL_KHR_image_base") == 0) { - if (GST_GL_CHECK_GL_VERSION (context_egl->egl_major, context_egl->egl_minor, - 1, 5)) - return context_egl->eglCreateImage != NULL - && context_egl->eglDestroyImage != NULL; - else - return context_egl->eglCreateImageKHR != NULL && - context_egl->eglDestroyImage != NULL; - } - return gst_gl_check_extension (feature, context_egl->egl_exts); } diff --git a/gst-libs/gst/gl/egl/gstglcontext_egl.h b/gst-libs/gst/gl/egl/gstglcontext_egl.h index e85126180..32293a5e4 100644 --- a/gst-libs/gst/gl/egl/gstglcontext_egl.h +++ b/gst-libs/gst/gl/egl/gstglcontext_egl.h @@ -68,12 +68,6 @@ struct _GstGLContextEGL const gchar *egl_exts; - EGLImageKHR (*eglCreateImageKHR) (EGLDisplay dpy, EGLContext ctx, EGLenum target, - EGLClientBuffer buffer, const EGLint *attrib_list); - EGLImageKHR (*eglCreateImage) (EGLDisplay dpy, EGLContext ctx, EGLenum target, - EGLClientBuffer buffer, const EGLAttrib *attrib_list); - EGLBoolean (*eglDestroyImage) (EGLDisplay dpy, EGLImageKHR image); - /* Cached handle */ EGLNativeWindowType window_handle; }; diff --git a/gst-libs/gst/gl/egl/gstglmemoryegl.c b/gst-libs/gst/gl/egl/gstglmemoryegl.c index 3cd194140..fd7d25c60 100644 --- a/gst-libs/gst/gl/egl/gstglmemoryegl.c +++ b/gst-libs/gst/gl/egl/gstglmemoryegl.c @@ -174,17 +174,10 @@ _gl_mem_egl_alloc (GstGLBaseMemoryAllocator * allocator, return mem; } -static void -_destroy_egl_image (GstEGLImage * image, gpointer user_data) -{ - image->context->eglDestroyImage (image->context->egl_display, image->image); -} - static gboolean _gl_mem_create (GstGLMemoryEGL * gl_mem, GError ** error) { GstGLContext *context = gl_mem->mem.mem.context; - GstGLContextEGL *ctx_egl = GST_GL_CONTEXT_EGL (context); const GstGLFuncs *gl = context->gl_vtable; GstGLBaseMemoryAllocatorClass *alloc_class; @@ -200,21 +193,14 @@ _gl_mem_create (GstGLMemoryEGL * gl_mem, GError ** error) return FALSE; if (gl_mem->image == NULL) { - EGLImageKHR image = ctx_egl->eglCreateImageKHR (ctx_egl->egl_display, - ctx_egl->egl_context, EGL_GL_TEXTURE_2D_KHR, - (EGLClientBuffer) (guintptr) gl_mem->mem.tex_id, NULL); - - GST_TRACE ("Generating EGLImage handle:%p from a texture:%u", - gl_mem->image, gl_mem->mem.tex_id); + gl_mem->image = gst_egl_image_from_texture (context, + (GstGLMemory *) gl_mem, NULL); - if (eglGetError () != EGL_SUCCESS) { + if (!gl_mem->image) { g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED, "Failed to create EGLImage"); return FALSE; } - - gl_mem->image = gst_egl_image_new_wrapped (context, image, 0, 0, - NULL, (GstEGLImageDestroyNotify) _destroy_egl_image); } else { gl->ActiveTexture (GL_TEXTURE0 + gl_mem->mem.plane); gl->BindTexture (GL_TEXTURE_2D, gl_mem->mem.tex_id); -- cgit v1.2.3