From a6cbe2a2cbfe7aeb7a2ea1a412d085812fda35a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 22 Feb 2017 14:09:45 +0200 Subject: [PATCH] glmemory: Use glBlitFramebuffer() instead of glCopyTexImage2D() if available glBlitFramebuffer() is new GLES3/GL3 API. They are probably often implemented in terms of each other, and glBlitFramebuffer() can potentially be implemented more flexible. Let's use it if available. Also it actually works on imx6 with DirectVIV textures. Based on a patch by Haihua Hu from https://github.com/Freescale/meta-freescale/blob/master/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad/ https://bugzilla.gnome.org/show_bug.cgi?id=779070 --- gst-libs/gst/gl/glprototypes/fbo.h | 7 ++- gst-libs/gst/gl/gstglmemory.c | 93 ++++++++++++++++++++++++------ 2 files changed, 80 insertions(+), 20 deletions(-) diff --git a/gst-libs/gst/gl/glprototypes/fbo.h b/gst-libs/gst/gl/glprototypes/fbo.h index d142483b7c..f210f997d8 100644 --- a/gst-libs/gst/gl/glprototypes/fbo.h +++ b/gst-libs/gst/gl/glprototypes/fbo.h @@ -102,9 +102,10 @@ GST_GL_EXT_FUNCTION (GLboolean, IsFramebuffer, GST_GL_EXT_END () GST_GL_EXT_BEGIN (offscreen_blit, - GST_GL_API_NONE, - 255, 255, - 255, 255, /* not in either GLES */ + GST_GL_API_OPENGL | GST_GL_API_OPENGL3 | + GST_GL_API_GLES2, + 3, 0, + 3, 0, "EXT\0ANGLE\0", "framebuffer_blit\0") GST_GL_EXT_FUNCTION (void, BlitFramebuffer, diff --git a/gst-libs/gst/gl/gstglmemory.c b/gst-libs/gst/gl/gstglmemory.c index f19523c91d..b357b28ef6 100644 --- a/gst-libs/gst/gl/gstglmemory.c +++ b/gst-libs/gst/gl/gstglmemory.c @@ -70,6 +70,13 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_GL_MEMORY); #define GL_TEXTURE_EXTERNAL_OES 0x8D65 #endif +#ifndef GL_READ_FRAMEBUFFER +#define GL_READ_FRAMEBUFFER 0x8CA8 +#endif +#ifndef GL_DRAW_FRAMEBUFFER +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#endif + G_DEFINE_TYPE (GstGLMemoryAllocator, gst_gl_memory_allocator, GST_TYPE_GL_BASE_MEMORY_ALLOCATOR); @@ -627,7 +634,8 @@ gst_gl_memory_copy_teximage (GstGLMemory * src, guint tex_id, guint out_gl_format, out_tex_target; GstMapInfo sinfo; guint src_tex_id; - guint fbo; + guint fbo[2]; + guint n_fbos; gl = src->mem.context->gl_vtable; out_tex_target = gst_gl_texture_target_to_gl (out_target); @@ -659,32 +667,83 @@ gst_gl_memory_copy_teximage (GstGLMemory * src, guint tex_id, "texture %i", src, src_tex_id, tex_id); /* FIXME: try and avoid creating and destroying fbo's every copy... */ - /* create a framebuffer object */ - gl->GenFramebuffers (1, &fbo); - gl->BindFramebuffer (GL_FRAMEBUFFER, fbo); + if (!gl->BlitFramebuffer) { + /* create a framebuffer object */ + n_fbos = 1; + gl->GenFramebuffers (n_fbos, &fbo[0]); + gl->BindFramebuffer (GL_FRAMEBUFFER, fbo[0]); - gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - gst_gl_texture_target_to_gl (src->tex_target), src_tex_id, 0); + gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + gst_gl_texture_target_to_gl (src->tex_target), src_tex_id, 0); -// if (!gst_gl_context_check_framebuffer_status (src->context)) -// goto fbo_error; + if (!gst_gl_context_check_framebuffer_status (src->mem.context)) + goto fbo_error; - gl->BindTexture (out_tex_target, tex_id); - gst_gl_query_start_log (GST_GL_BASE_MEMORY_CAST (src)->query, - GST_CAT_GL_MEMORY, GST_LEVEL_LOG, NULL, "%s", "CopyTexImage2D took"); - gl->CopyTexImage2D (out_tex_target, 0, out_gl_format, 0, 0, out_width, - out_height, 0); - gst_gl_query_end (GST_GL_BASE_MEMORY_CAST (src)->query); + gl->BindTexture (out_tex_target, tex_id); + gst_gl_query_start_log (GST_GL_BASE_MEMORY_CAST (src)->query, + GST_CAT_GL_MEMORY, GST_LEVEL_LOG, NULL, "%s", "CopyTexImage2D took"); + gl->CopyTexImage2D (out_tex_target, 0, out_gl_format, 0, 0, out_width, + out_height, 0); + gst_gl_query_end (GST_GL_BASE_MEMORY_CAST (src)->query); - gl->BindTexture (out_tex_target, 0); - gl->BindFramebuffer (GL_FRAMEBUFFER, 0); + gl->BindTexture (out_tex_target, 0); + gl->BindFramebuffer (GL_FRAMEBUFFER, 0); - gl->DeleteFramebuffers (1, &fbo); + gl->DeleteFramebuffers (n_fbos, &fbo[0]); + } else { + /* create a framebuffer object */ + n_fbos = 2; + gl->GenFramebuffers (n_fbos, &fbo[0]); + + gl->BindFramebuffer (GL_READ_FRAMEBUFFER, fbo[0]); + gl->FramebufferTexture2D (GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + gst_gl_texture_target_to_gl (src->tex_target), src_tex_id, 0); + + if (!gst_gl_context_check_framebuffer_status (src->mem.context)) + goto fbo_error; + + gl->BindFramebuffer (GL_DRAW_FRAMEBUFFER, fbo[1]); + + gl->FramebufferTexture2D (GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + gst_gl_texture_target_to_gl (src->tex_target), tex_id, 0); + + if (!gst_gl_context_check_framebuffer_status (src->mem.context)) + goto fbo_error; + + gl->BindTexture (out_tex_target, tex_id); + gst_gl_query_start_log (GST_GL_BASE_MEMORY_CAST (src)->query, + GST_CAT_GL_MEMORY, GST_LEVEL_LOG, NULL, "%s", "BlitFramebuffer took"); + gl->ReadBuffer (GL_COLOR_ATTACHMENT0); + gl->DrawBuffer (GL_COLOR_ATTACHMENT0); + gl->BlitFramebuffer (0, 0, out_width, out_height, + 0, 0, out_width, out_height, GL_COLOR_BUFFER_BIT, GL_NEAREST); + gst_gl_query_end (GST_GL_BASE_MEMORY_CAST (src)->query); + + gl->BindTexture (out_tex_target, 0); + gl->BindFramebuffer (GL_DRAW_FRAMEBUFFER, 0); + gl->BindFramebuffer (GL_READ_FRAMEBUFFER, 0); + + gl->DeleteFramebuffers (n_fbos, &fbo[0]); + } gst_memory_unmap (GST_MEMORY_CAST (src), &sinfo); return TRUE; +fbo_error: + { + gl->BindTexture (out_tex_target, 0); + if (!gl->BlitFramebuffer) { + gl->BindFramebuffer (GL_FRAMEBUFFER, 0); + } else { + gl->BindFramebuffer (GL_DRAW_FRAMEBUFFER, 0); + gl->BindFramebuffer (GL_READ_FRAMEBUFFER, 0); + } + + gl->DeleteFramebuffers (n_fbos, &fbo[0]); + + gst_memory_unmap (GST_MEMORY_CAST (src), &sinfo); + } error: return FALSE; }