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 <jared.hu@nxp.com> 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
This commit is contained in:
Sebastian Dröge 2017-02-22 14:09:45 +02:00 committed by Tim-Philipp Müller
parent 48f79e9f60
commit a6cbe2a2cb
2 changed files with 80 additions and 20 deletions

View file

@ -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,

View file

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