glmemory: Use glBlitFramebuffer() instead of glCopyTexImage2D() if available
authorSebastian Dröge <sebastian@centricular.com>
Wed, 22 Feb 2017 12:09:45 +0000 (14:09 +0200)
committerSebastian Dröge <sebastian@centricular.com>
Thu, 23 Feb 2017 19:57:33 +0000 (21:57 +0200)
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

gst-libs/gst/gl/glprototypes/fbo.h
gst-libs/gst/gl/gstglmemory.c

index d142483..f210f99 100644 (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,
index f19523c..b357b28 100644 (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;
 }