From a2260f31fbef3da69a9039b66da30a68eece2056 Mon Sep 17 00:00:00 2001
From: Gabriel Studer <gabriel.studer@unibas.ch>
Date: Wed, 21 Oct 2020 15:38:27 +0200
Subject: [PATCH] fix OpenGL artefacts at scene export

When exporting the scene for the second time, weird artefacts that looked
like shadows occured. The fix enforces to re-allocate the resources of
the offscreen QOpenGLContext. Measurements showed that reallocation is
much faster than the rate-limiting step of the Export function: dump the
file to disk. Performance impact is therefore limited. Feel free to
investigate and propose a more elegant fix...
---
 modules/gui/src/gl_canvas.cc | 31 ++++++++++++++++---------------
 1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/modules/gui/src/gl_canvas.cc b/modules/gui/src/gl_canvas.cc
index 1dfdbdb7d..da2eb2816 100644
--- a/modules/gui/src/gl_canvas.cc
+++ b/modules/gui/src/gl_canvas.cc
@@ -241,7 +241,6 @@ void GLCanvas::Export(const String& fname, unsigned int width,
 
   // setup of context, surface, fbo etc are implemented as in the QT
   // threadrenderer example
-
   gfx::Viewport old_vp = gfx::Scene::Instance().GetViewport();
 
   if(old_vp.width == static_cast<int>(width) && 
@@ -253,34 +252,36 @@ void GLCanvas::Export(const String& fname, unsigned int width,
 
   offscreen_flag_ = true;
 
-  if(offscreen_surface_ == NULL) {
-    offscreen_surface_ = new QOffscreenSurface();
-    QSurfaceFormat f = this->context()->format();
-    if(max_samples > 0) {
-      f.setSamples(max_samples);
-    } 
-    offscreen_surface_->setFormat(f);
-    offscreen_surface_->create();
-  }
-
-  if(offscreen_context_ == NULL) {
-    QOpenGLContext *current = this->context();
+  if(offscreen_context_ == NULL || offscreen_surface_ == NULL) {
     // Some GL implementations require that the currently bound context is
     // made non-current before we set up sharing, so we doneCurrent here
     // and makeCurrent down below while setting up our own context.
-    current->doneCurrent();
+    this->context()->doneCurrent();
     offscreen_context_ = new QOpenGLContext();
     QSurfaceFormat f = this->context()->format();
     if(max_samples > 0) {
       f.setSamples(max_samples);
     } 
     offscreen_context_->setFormat(f);
-    offscreen_context_->setShareContext(current);
+    offscreen_context_->setShareContext(this->context());
     offscreen_context_->create();
+
+    offscreen_surface_ = new QOffscreenSurface();
+    offscreen_surface_->setFormat(offscreen_context_->format());
+    offscreen_surface_->create();
+
     offscreen_context_->makeCurrent(offscreen_surface_);
     gfx::Scene::Instance().ContextSwitch();
     gfx::Scene::Instance().InitGL(false);
   } else {
+    this->context()->doneCurrent();
+    // The following line destroys and recreates the existing OpenGL context.
+    // This is an ugly fix to avoid weird artefacts when calling the Export 
+    // function the second time. On a low-end Laptop this requires ~5-10ms and
+    // is therefore much faster than the rate-limiting saving of the image to
+    // disk at the end of the function. Feel free to investigate and propose a
+    // more efficient solution.
+    offscreen_context_->create();
     offscreen_context_->makeCurrent(offscreen_surface_);
     gfx::Scene::Instance().ContextSwitch();
     // the following InitGL sets potentially changed glClearcolor etc
-- 
GitLab