qmlglsrc: use glBlitFramebuffer to copy texture for GLES3.0
authorHaihua Hu <jared.hu@nxp.com>
Tue, 10 Jan 2017 08:54:48 +0000 (16:54 +0800)
committerMatthew Waters <matthew@centricular.com>
Tue, 10 Jan 2017 10:34:30 +0000 (21:34 +1100)
If support glBlitFrameBuffer, use it for texture copy instead
of glCopyTexImage2D

https://bugzilla.gnome.org/show_bug.cgi?id=777078

ext/qt/qtwindow.cc
ext/qt/qtwindow.h

index 362a173..92c5834 100644 (file)
@@ -67,6 +67,8 @@ struct _QtGLWindowPrivate
   GstGLDisplay *display;
   GstGLContext *other_context;
 
+  GLuint fbo;
+
   /* frames that qmlview rendered in its gl thread */
   quint64 frames_rendered;
   quint64 start;
@@ -121,6 +123,8 @@ QtGLWindow::QtGLWindow ( QWindow * parent, QQuickWindow *src ) :
   else
     connect (source, SIGNAL(sceneGraphInitialized()), this, SLOT(onSceneGraphInitialized()), Qt::DirectConnection);
 
+  connect (source, SIGNAL(sceneGraphInvalidated()), this, SLOT(onSceneGraphInvalidated()), Qt::DirectConnection);
+
   GST_DEBUG ("%p init Qt Window", this->priv->display);
 }
 
@@ -224,7 +228,23 @@ QtGLWindow::afterRendering()
       this->source->renderTargetId(), dst_tex, width,height);
 
   gl->BindTexture (GL_TEXTURE_2D, dst_tex);
-  gl->CopyTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, width, height, 0);
+  if (gl->BlitFramebuffer) {
+    gl->BindFramebuffer (GL_DRAW_FRAMEBUFFER, this->priv->fbo);
+    gl->FramebufferTexture2D (GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+              GL_TEXTURE_2D, dst_tex, 0);
+
+    ret = gst_gl_context_check_framebuffer_status (context);
+    if (!ret) {
+      GST_ERROR ("FBO errors");
+      goto errors;
+    }
+    gl->ReadBuffer (GL_COLOR_ATTACHMENT0);
+    gl->BlitFramebuffer (0, 0, width, height,
+        0, 0, width, height,
+        GL_COLOR_BUFFER_BIT, GL_LINEAR);
+  } else {
+    gl->CopyTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, width, height, 0);
+  }
   
   GST_DEBUG ("rendering finished");
 
@@ -268,10 +288,38 @@ QtGLWindow::onSceneGraphInitialized()
   this->priv->initted = gst_qt_get_gl_wrapcontext (this->priv->display,
       &this->priv->other_context, NULL);
 
+  if (this->priv->initted && this->priv->other_context) {
+    const GstGLFuncs *gl;
+
+    gst_gl_context_activate (this->priv->other_context, TRUE);
+    gl = this->priv->other_context->gl_vtable;
+
+    gl->GenFramebuffers (1, &this->priv->fbo);
+
+    gst_gl_context_activate (this->priv->other_context, FALSE);
+  }
+
   GST_DEBUG ("%p created wrapped GL context %" GST_PTR_FORMAT, this,
       this->priv->other_context);
 }
 
+void
+QtGLWindow::onSceneGraphInvalidated()
+{
+  GST_DEBUG ("scene graph invalidated");
+
+  if (this->priv->fbo && this->priv->other_context) {
+    const GstGLFuncs *gl;
+
+    gst_gl_context_activate (this->priv->other_context, TRUE);
+    gl = this->priv->other_context->gl_vtable;
+
+    gl->DeleteFramebuffers (1, &this->priv->fbo);
+
+    gst_gl_context_activate (this->priv->other_context, FALSE);
+  }
+}
+
 bool
 QtGLWindow::getGeometry(int * width, int * height)
 {
index a617c07..697f389 100644 (file)
@@ -48,6 +48,7 @@ private Q_SLOTS:
     void beforeRendering ();
     void afterRendering ();
     void onSceneGraphInitialized ();
+    void onSceneGraphInvalidated ();
     void aboutToQuit();
 
 private: