Talk:Canvas Threading

From FlightGear wiki
Jump to navigation Jump to search

This whole Nasal/Canvas performance debate seems to be a recurring topic on the forum, so could just as well add to the article until things are improving:

--Hooray (talk) 08:52, 26 November 2020 (EST)

for folks wanting to tinker with pbuffer based Canvas ctx

diff --git a/src/Canvas/FGCanvasSystemAdapter.cxx b/src/Canvas/FGCanvasSystemAdapter.cxx
index a0b9b6651..7a69500e1 100644
--- a/src/Canvas/FGCanvasSystemAdapter.cxx
+++ b/src/Canvas/FGCanvasSystemAdapter.cxx
@@ -69,14 +69,14 @@ namespace canvas
   //----------------------------------------------------------------------------
   void FGCanvasSystemAdapter::addCamera(osg::Camera* camera) const
   {
-    globals->get_renderer()->addCamera(camera, false);
+    globals->get_renderer()->addCamera(camera, false, true);
   }
 
   //----------------------------------------------------------------------------
   void FGCanvasSystemAdapter::removeCamera(osg::Camera* camera) const
   {
     if( globals->get_renderer() )
-      globals->get_renderer()->removeCamera(camera);
+      globals->get_renderer()->removeCamera(camera, true);
   }
 
   //----------------------------------------------------------------------------
diff --git a/src/Main/options.cxx b/src/Main/options.cxx
index f0f9c43e3..d82fbb766 100644
--- a/src/Main/options.cxx
+++ b/src/Main/options.cxx
@@ -2001,6 +2001,10 @@ struct OptionDesc {
     {"developer",                    true,  OPTION_IGNORE | OPTION_BOOL, "", false, "", nullptr },
     {"jsbsim-output-directive-file", true,  OPTION_STRING, "/sim/jsbsim/output-directive-file", false, "", nullptr },
     {"disable-gui",                  false, OPTION_FUNC, "", false, "", fgOptDisableGUI },
+
+    // this enables pbuffer creation for the main osgviewer window, so that the we have an actual headless option for unit testing/standalone benchmarks
+    {"enable-headless",              false, OPTION_BOOL, "/sim/startup/enable-headless-mode", true, "", nullptr },
+
     {"graphics-preset",              true,  OPTION_STRING, "/sim/rendering/preset", false, "", nullptr},
     {"composite-viewer",             true,  OPTION_INT,    "/sim/rendering/composite-viewer-enabled", false, "", nullptr},
     {"restart-launcher",             false, OPTION_BOOL, "/sim/restart-launcher-on-exit", true, "", nullptr},
diff --git a/src/Viewer/WindowBuilder.cxx b/src/Viewer/WindowBuilder.cxx
index 4bedcd77e..6cc8eeb91 100644
--- a/src/Viewer/WindowBuilder.cxx
+++ b/src/Viewer/WindowBuilder.cxx
@@ -126,6 +126,10 @@ void WindowBuilder::makeDefaultTraits(bool stencil)
         }
         SG_LOG(SG_VIEW,SG_DEBUG,"Using initial window size: " << w << " x " << h);
     }
+
+    if (fgGetBool("/sim/startup/enable-headless-mode",false)) {
+	    traits->pbuffer = true;
+    } // enable headless mode
 }
     
 } // of namespace flightgear
@@ -251,8 +255,9 @@ GraphicsWindow* WindowBuilder::buildWindow(const SGPropertyNode* winNode, bool i
     auto traits = new GraphicsContext::Traits(*defaultTraits);
 
     // Attempt to share context with the window that was created first
-    if (!wsa->windows.empty())
+    if (!wsa->windows.empty() && fgGetBool("/sim/viewer/enable-shared-gl-context",true))
         traits->sharedContext = wsa->windows.front()->gc;
+   
 
     int traitsSet = setFromProperty(traits->hostName, winNode, "host-name");
     traitsSet |= setFromProperty(traits->displayNum, winNode, "display");
diff --git a/src/Viewer/renderer.cxx b/src/Viewer/renderer.cxx
index 419c01697..31507f8b0 100644
--- a/src/Viewer/renderer.cxx
+++ b/src/Viewer/renderer.cxx
@@ -56,6 +56,11 @@
 #include <osg/Version>
 #include <osg/TexEnv>
 
+#include <osg/CameraView>
+#include <osg/GraphicsContext>
+#include <osgViewer/CompositeViewer>
+
+
 #include <osgUtil/LineSegmentIntersector>
 
 #include <osg/io_utils>
@@ -117,6 +122,10 @@
 #include <Viewer/PUICamera.hxx>
 #endif
 
+#include <Viewer/renderer.hxx>
+#include <Viewer/WindowBuilder.hxx>
+#include <Viewer/WindowSystemAdapter.hxx>
+
 using namespace osg;
 using namespace flightgear;
 
@@ -1104,20 +1113,64 @@ FGRenderer::setEventHandler(FGEventHandler* eventHandler_)
 }
 
 void
-FGRenderer::addCamera(osg::Camera* camera, bool useSceneData)
+FGRenderer::addCamera(osg::Camera* camera, bool useSceneData, bool isCanvasCam)
 {
-    osg::Camera *guiCamera = getGUICamera(CameraGroup::getDefault());
-    osg::GraphicsContext *gc = guiCamera->getGraphicsContext();
-    camera->setGraphicsContext(gc);
-    if (composite_viewer) {
-        composite_viewer->getView(0)->addSlave(camera, false);
+    osg::Camera *guiCamera = nullptr;
+    osg::ref_ptr<osg::GraphicsContext> gc = nullptr;
+    guiCamera = getGUICamera(CameraGroup::getDefault());
+    gc = guiCamera->getGraphicsContext(); 
+     if(isCanvasCam) { // we're about to set up a new canvas cam
+        SG_LOG(SG_VIEW, SG_ALERT, "Adding new Canvas Camera");
+
+	if (_CanvasGraphicsContext) { // the ctx is already set up
+        SG_LOG(SG_VIEW, SG_ALERT, " [Using exising Canvas pbuffer ctx]");
+	camera->setGraphicsContext( _CanvasGraphicsContext.get() );
+        SG_LOG(SG_GENERAL, SG_ALERT, "Canvas Camera GC set up!");
+ 
+	}else { // we don't have a ctx yet, so need to set up a new pbuffer ctx first
+        SG_LOG(SG_VIEW, SG_ALERT, "==> Initial Canvas GraphicsContext Setup (Canvas renders on a separate GL ctx)");
+
+	osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
+	traits->x=0; traits->y=0;
+        traits->width  = fgGetInt("/sim/rendering/canvas/ctx-width",1);
+        traits->height = fgGetInt("/sim/rendering/canvas/ctx-height",1);
+        traits->windowDecoration = false;
+	bool useDoubleBuffering = fgGetBool("/sim/rendering/canvas/enable-double-buffering",true);
+        traits->doubleBuffer = useDoubleBuffering;
+	bool useSharedCtx = fgGetBool("/sim/rendering/canvas/enable-shared-ctx",false);
+        traits->sharedContext = (useSharedCtx)?gc:0; //NOTE: By default, we're not using a shared context here, despite being on a separate GL context
+	traits->pbuffer=fgGetBool("/sim/rendering/canvas/enable-pbuffer-ctx",true);
+
+        traits->readDISPLAY();
+	traits->setUndefinedScreenDetailsToDefaultScreen();
+
+        _CanvasGraphicsContext = osg::GraphicsContext::createGraphicsContext(traits);
+	if(!_CanvasGraphicsContext || !_CanvasGraphicsContext->valid() ) {
+	SG_LOG(SG_GENERAL, SG_ALERT, "Canvas pbuffer GC not valid");
+	}
+	else {
+	 _CanvasGraphicsContext->realize();
+	 _CanvasGraphicsContext->makeCurrent();
+	camera->setGraphicsContext( _CanvasGraphicsContext.get() );
+        SG_LOG(SG_GENERAL, SG_ALERT, "Canvas Camera GC set up!");
+	} // we have a valid ctx
+	} // custom Canvas specific GC
+    } else {
+    SG_LOG(SG_GENERAL, SG_ALERT, "Setting up a non Canvas camera");
+    camera->setGraphicsContext( gc );
+    SG_LOG(SG_GENERAL, SG_ALERT, "Camera GC set up!");
+    }
+
+   if (composite_viewer) {
+        composite_viewer->getView(0)->addSlave(camera, useSceneData);
+        SG_LOG(SG_GENERAL, SG_ALERT, "Slave cam added to CV viewer");
     } else {
-        viewer->addSlave(camera, false);
+        viewer->addSlave(camera, useSceneData);
     }
 }
 
 void
-FGRenderer::removeCamera(osg::Camera* camera)
+FGRenderer::removeCamera(osg::Camera* camera, bool isCanvasCam)
 {
     if (composite_viewer) {
         unsigned int index = composite_viewer->getView(0)
diff --git a/src/Viewer/renderer.hxx b/src/Viewer/renderer.hxx
index e87afedae..01ad2c935 100644
--- a/src/Viewer/renderer.hxx
+++ b/src/Viewer/renderer.hxx
@@ -91,9 +91,9 @@ public:
 
     /** Add a top level camera.
      */
-    void addCamera(osg::Camera* camera, bool useSceneData);
+    void addCamera(osg::Camera* camera, bool useSceneData, bool isCanvasCam=false);
 
-    void removeCamera(osg::Camera* camera);
+    void removeCamera(osg::Camera* camera, bool isCanvasCam = false);
 
     SGSky* getSky() const { return _sky; }
 
@@ -101,6 +101,7 @@ public:
 
 protected:
     int composite_viewer_enabled = -1;
+    osg::ref_ptr<osg::GraphicsContext> _CanvasGraphicsContext;
     osg::ref_ptr<osgViewer::Viewer> viewer;
     osg::ref_ptr<osgViewer::CompositeViewer> composite_viewer;
     osg::ref_ptr<flightgear::FGEventHandler> eventHandler;
diff --git a/src/Viewer/sview.cxx b/src/Viewer/sview.cxx
index 230099311..0c0c8e5a5 100644
--- a/src/Viewer/sview.cxx
+++ b/src/Viewer/sview.cxx
@@ -1730,7 +1730,7 @@ std::shared_ptr<SviewView> SviewCreate(SGPropertyNode* config)
     /* https://www.mail-archive.com/osg-users@lists.openscenegraph.org/msg29820.html
     Passing (false, false) here seems to cause a hang on startup. */
     view->getDatabasePager()->setUnrefImageDataAfterApplyPolicy(true, false);
-    osg::GraphicsContext::createNewContextID();
+    //osg::GraphicsContext::createNewContextID();
     
     osg::Camera* main_camera = main_view->getCamera();
     osg::Camera* camera = view->getCamera();

This unsigned comment was added by Hooray (Talk | contribs) 20:37, 4 September 2021‎ (UTC)