]> git.mxchange.org Git - flightgear.git/commitdiff
Clean up OSG camera setup and interface to plib PUI
authortimoore <timoore>
Mon, 19 May 2008 21:21:03 +0000 (21:21 +0000)
committertimoore <timoore>
Mon, 19 May 2008 21:21:03 +0000 (21:21 +0000)
Switch to defining PU_USE_NONE and providing our own callback
functions to pui for "get window" and "get window size." A new
WindowSystemAdapter class assigns ID numbers to windows for the
purpose of identifying them to plib; the window size can be extracted
from the osg::GraphicsContext class in all the different
implementations (osgViewer, glut, sdl).

Implement a GraphicsContextOperation that runs code in a particular
graphics context, perhaps in another thread, and provides an
isFinished() method to test if the operation has finished. This allows
us to initialize plib PUI properly if there are multiple graphics
contexts without using fgMakeCurrent(). fgMakeCurrent() can't work in
multi-threaded OSG configurations.

Eliminate fgMakeCurrent() and all its uses, either by using
GraphicsContextOperation or by seeing that it is not necessary.

Attach the GUI camera as a slave camera.

Don't manipulate the OSG state in the drawImplementation() functions
for SGHUDAndPanelDrawable and SGPuDrawable; it's not needed.

18 files changed:
configure.ac
projects/VC7.1/FlightGear.vcproj
src/Cockpit/cockpit.cxx
src/GUI/gui.cxx
src/GUI/gui.h
src/Include/config.h-msvc8
src/Include/config.h-msvc8.in
src/Input/input.cxx
src/Main/Makefile.am
src/Main/WindowSystemAdapter.cxx [new file with mode: 0644]
src/Main/WindowSystemAdapter.hxx [new file with mode: 0644]
src/Main/fg_os.cxx
src/Main/fg_os.hxx
src/Main/fg_os_common.cxx
src/Main/fg_os_osgviewer.cxx
src/Main/fg_os_sdl.cxx
src/Main/main.cxx
src/Main/renderer.cxx

index 295578d3a0d06601a063e6f5e3f7221b1572a567..f854b750ec23d47d8a694bf12d9056d32d919177 100644 (file)
@@ -206,17 +206,14 @@ AM_CONDITIONAL(USE_GLUT, test "x$enable_glut" = "xyes")
 if test "x$enable_sdl" != "xyes" -a "x$enable_glut" != "xyes" -a "x$enable_osgviewer" != "xno"; then
    enable_osgviewer="yes"
 fi
-if test "x$enable_osgviewer" = "xyes"; then
-   AC_DEFINE([USE_OSGVIEWER], 1, [Define to use osgViewer in renderer])
-   AC_DEFINE([ENABLE_OSGVIEWER], 1, [Define to use osgViewer in renderer])
-   AC_DEFINE([PU_USE_NATIVE], 1, [Define to use native system])
-elif test "x$enable_sdl" = "xyes"; then
-   AC_DEFINE([PU_USE_SDL], 1, [Define to use SDL])
-elif test "x$enable_glut" = "xyes"; then
-   AC_DEFINE([PU_USE_GLUT], 1, [Define to use glut])
-else
-   AC_MSG_ERROR([One (and only one) of --enable-osgviewer, --enable-sdl, or --enable-glut must be supplied])
+if test \( "x$enable_osgviewer" = "xyes" \
+   -a \( "x$enable_sdl" = "xyes" -o "x$enable_glut" = "xyes" \) \) \
+   -o \( "x$enable_sdl" = "xyes" -a "x$enable_glut" = "xyes" \); then
+   echo " Only one of --enable-osgviewer, --enable-sdl, or --enable -glut may"
+   echo " be supplied."
+   exit
 fi
+AC_DEFINE([PU_USE_NONE], 1, [Define to use application's pu callbacks])
 
 AC_ARG_ENABLE(osgdebug, [  --enable-osgdebug              Use OSG debug libraries], [enable_osgdebug="$enableval"])
 
index be611d3668b4462f6d9816cbcd7d8e527b9d860f..2741f318c7b1a12f66d6a2053bb979c05cef17f7 100755 (executable)
@@ -24,7 +24,7 @@
                                Name="VCCLCompilerTool"
                                Optimization="0"
                                AdditionalIncludeDirectories="..\..\..;..\..\src;..\..\src\include;..\..\..\SimGear;&quot;..\..\..\pthreads-w32-2-7-0-release&quot;;..\..\src\FDM\JSBSim;..\..\..\OpenSceneGraph\include;..\..\..\OpenThreads\include;..\..\..\3rdParty\include"
-                               PreprocessorDefinitions="_DEBUG;WIN32;_CONSOLE;HAVE_CONFIG_H;FGFS;ENABLE_AUDIO_SUPPORT;_FG_NDEBUG;ENABLE_THREADS=1;FG_ENABLE_MULTIPASS_CLOUDS;ENABLE_SP_FMDS;_USE_MATH_DEFINES;FG_JPEG_SERVER;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;ENABLE_OSGVIEWER;PU_USE_NATIVE"
+                               PreprocessorDefinitions="_DEBUG;WIN32;_CONSOLE;HAVE_CONFIG_H;FGFS;ENABLE_AUDIO_SUPPORT;_FG_NDEBUG;ENABLE_THREADS=1;FG_ENABLE_MULTIPASS_CLOUDS;ENABLE_SP_FMDS;_USE_MATH_DEFINES;FG_JPEG_SERVER;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS"
                                StringPooling="TRUE"
                                BasicRuntimeChecks="0"
                                RuntimeLibrary="3"
@@ -88,7 +88,7 @@
                                Name="VCCLCompilerTool"
                                InlineFunctionExpansion="1"
                                AdditionalIncludeDirectories="..\..\..;..\..\src;..\..\src\include;..\..\src\FDM\JSBSim;..\..\..\SimGear;&quot;..\..\..\pthreads-w32-2-7-0-release&quot;;..\..\..\OpenSceneGraph\include;..\..\..\Producer\include;..\..\..\OpenThreads\include;..\..\..\3rdParty\include"
-                               PreprocessorDefinitions="NDEBUG;WIN32;_CONSOLE;HAVE_CONFIG_H;FGFS;ENABLE_AUDIO_SUPPORT;_FG_NDEBUG;ENABLE_THREADS=1;FG_ENABLE_MULTIPASS_CLOUDS;ENABLE_SP_FMDS;_USE_MATH_DEFINES;FG_JPEG_SERVER;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;ENABLE_OSGVIEWER;PU_USE_NATIVE"
+                               PreprocessorDefinitions="NDEBUG;WIN32;_CONSOLE;HAVE_CONFIG_H;FGFS;ENABLE_AUDIO_SUPPORT;_FG_NDEBUG;ENABLE_THREADS=1;FG_ENABLE_MULTIPASS_CLOUDS;ENABLE_SP_FMDS;_USE_MATH_DEFINES;FG_JPEG_SERVER;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS"
                                StringPooling="TRUE"
                                RuntimeLibrary="2"
                                EnableFunctionLevelLinking="TRUE"
index 26b6b94dd4aa08394d278ca075eb43899296f73b..b9e97281eec961215903ed5ba78903572657a554 100644 (file)
@@ -566,7 +566,7 @@ void fgCockpitUpdate( osg::State* state ) {
 
 
 struct FuncTable {
-    char *name;
+    const char *name;
     FLTFNPTR func;
 } fn_table[] = {
     { "agl", get_agl },
index b34e135e2a15720dbc6f513486e6c6f2f096ccc1..b730270f51d042ca7a771e1ae03778a376fcdb35 100644 (file)
@@ -34,6 +34,8 @@
 #  include <windows.h>
 #endif
 
+#include <string>
+
 #include <simgear/structure/exception.hxx>
 #include <simgear/misc/sg_path.hxx>
 #include <simgear/props/props.hxx>
 #include <Main/main.hxx>
 #include <Main/globals.hxx>
 #include <Main/fg_props.hxx>
+#include <Main/WindowSystemAdapter.hxx>
 #include <GUI/new_gui.hxx>
 
 #include "gui.h"
 #include "gui_local.hxx"
 #include "layout.hxx"
 
+using namespace osg;
+using namespace flightgear;
 
 puFont guiFnt = 0;
 
@@ -59,48 +64,76 @@ puFont guiFnt = 0;
 init the gui
 _____________________________________________________________________*/
 
-
-void guiInit()
+namespace
 {
-    char *mesa_win_state;
-
-    // Initialize PUI
-#ifndef PU_USE_NONE
-    puInit();
-#endif
-    puSetDefaultStyle         ( PUSTYLE_SMALL_SHADED ); //PUSTYLE_DEFAULT
-    puSetDefaultColourScheme  (0.8, 0.8, 0.9, 1);
-
-    FGFontCache *fc = globals->get_fontcache();
-    puFont *GuiFont = fc->get(globals->get_locale()->getStringValue("font", "typewriter.txf"), 15);
-    puSetDefaultFonts(*GuiFont, *GuiFont);
-    guiFnt = puGetDefaultLabelFont();
-
-    LayoutWidget::setDefaultFont(GuiFont, 15);
+class GUIInitOperation : public GraphicsContextOperation
+{
+public:
+    GUIInitOperation() : GraphicsContextOperation(std::string("GUI init"))
+    {
+    }
+    void run(GraphicsContext* gc)
+    {
+        WindowSystemAdapter* wsa = WindowSystemAdapter::getWSA();
+        wsa->puInitialize();
+        puSetDefaultStyle         ( PUSTYLE_SMALL_SHADED ); //PUSTYLE_DEFAULT
+        puSetDefaultColourScheme  (0.8, 0.8, 0.9, 1);
+
+        FGFontCache *fc = globals->get_fontcache();
+        puFont *GuiFont
+            = fc->get(globals->get_locale()->getStringValue("font",
+                                                            "typewriter.txf"),
+                      15);
+        puSetDefaultFonts(*GuiFont, *GuiFont);
+        guiFnt = puGetDefaultLabelFont();
+
+        LayoutWidget::setDefaultFont(GuiFont, 15);
   
-    if (!fgHasNode("/sim/startup/mouse-pointer")) {
-        // no preference specified for mouse pointer, attempt to autodetect...
-        // Determine if we need to render the cursor, or if the windowing
-        // system will do it.  First test if we are rendering with glide.
-        if ( strstr ( general.get_glRenderer(), "Glide" ) ) {
-            // Test for the MESA_GLX_FX env variable
-            if ( (mesa_win_state = getenv( "MESA_GLX_FX" )) != NULL) {
-                // test if we are fullscreen mesa/glide
-                if ( (mesa_win_state[0] == 'f') ||
-                     (mesa_win_state[0] == 'F') ) {
-                    puShowCursor ();
+        if (!fgHasNode("/sim/startup/mouse-pointer")) {
+            // no preference specified for mouse pointer, attempt to autodetect...
+            // Determine if we need to render the cursor, or if the windowing
+            // system will do it.  First test if we are rendering with
+            // glide.
+            // XXX Not bloody likely in 2008...
+            if ( strstr ( general.get_glRenderer(), "Glide" ) ) {
+                // Test for the MESA_GLX_FX env variable
+                char *mesa_win_state = getenv( "MESA_GLX_FX" );
+                if (mesa_win_state  != NULL) {
+                    // test if we are fullscreen mesa/glide
+                    if ( (mesa_win_state[0] == 'f') ||
+                         (mesa_win_state[0] == 'F') ) {
+                        puShowCursor ();
+                    }
                 }
             }
+        } else if ( !fgGetBool("/sim/startup/mouse-pointer") ) {
+            // don't show pointer
+        } else {
+            // force showing pointer
+            puShowCursor();
         }
-//        mouse_active = ~mouse_active;
-    } else if ( !fgGetBool("/sim/startup/mouse-pointer") ) {
-        // don't show pointer
-    } else {
-        // force showing pointer
-        puShowCursor();
-//        mouse_active = ~mouse_active;
     }
-       
-    // MOUSE_VIEW mode stuff
-       initMouseQuat();
+};
+
+ref_ptr<GUIInitOperation> initOp;
+}
+
+void guiStartInit()
+{
+    initOp = new GUIInitOperation;
+    WindowSystemAdapter* wsa = WindowSystemAdapter::getWSA();
+    GraphicsContext* gc = wsa->getGUIGraphicsContext();
+    gc->add(initOp.get());
 }
+
+bool guiFinishInit()
+{
+    if (!initOp.valid())
+        return false;
+    if (!initOp->isFinished())
+        return false;
+    initMouseQuat();
+    initOp = 0;
+    return true;
+}
+
index 2385d12270da0bdbfa72d170dd004b5e26680921..4897b0ed929130e021e3a145ef4526b702f3f061 100644 (file)
@@ -41,7 +41,8 @@
 
 
 // gui.cxx
-extern void guiInit();
+extern void guiStartInit();
+extern bool guiFinishInit();
 extern void mkDialog(const char *txt);
 extern void guiErrorMessage(const char *txt);
 extern void guiErrorMessage(const char *txt, const sg_throwable &throwable);
index b8d04051e7c5a038add34bad3b5065c4130d2163..6f39a170242f8a73c1aae524daa6bea534bdfda1 100755 (executable)
@@ -1,12 +1,6 @@
 
 /* Special single config.h for MSVC8 build  */
 
-#define ENABLE_OSGVIEWER
-#define PU_USE_NATIVE 
-
-#define ENABLE_OSGVIEWER        
-#define PU_USE_NATIVE
-
 /* Define to enable plib joystick support */
 #ifndef  ENABLE_PLIB_JOYSTICK
 #define ENABLE_PLIB_JOYSTICK
index 46c1b91971b38b7329584566ac21f217c6f8e5e3..cc630a070d2997b3b7891d24da8dc60905174285 100644 (file)
@@ -1,9 +1,6 @@
 
 /* Special single config.h for MSVC6 build - Geoff McLane - 23 July, 2003  */
 
-#define ENABLE_OSGVIEWER        
-#define PU_USE_NATIVE
-
 /* Define to enable plib joystick support */
 #ifndef  ENABLE_PLIB_JOYSTICK
 #define ENABLE_PLIB_JOYSTICK
index 3ecf5142f8c796faf6064a88076a1eb48cd41d60..f4168b55df72aae08b7e776088c9d617adaae67c 100644 (file)
@@ -327,8 +327,6 @@ FGInput::doMouseClick (int b, int updown, int x, int y, bool mainWindow, const o
   }
 
   if (mode.pass_through) {
-    // The pu stuff seems to need that. May be it does opengl picking ...
-    fgMakeCurrent();
     if (0 <= x && 0 <= y && puMouse(b, updown, x, y))
       return;
     else if (0 <= x && 0 <= y && (globals->get_current_panel() != 0) &&
index 3d9d94db9705a0f7ee72f5e789258707fb059453..9be3ca3746d62a5ef4a014379286bacafbb25be2 100644 (file)
@@ -62,6 +62,7 @@ libMain_a_SOURCES = \
        viewmgr.cxx viewmgr.hxx \
        FGManipulator.cxx FGManipulator.hxx \
        ViewPartitionNode.cxx ViewPartitionNode.hxx \
+       WindowSystemAdapter.hxx WindowSystemAdapter.cxx \
        $(GFX_CODE)
 
 fgfs_SOURCES = bootstrap.cxx
diff --git a/src/Main/WindowSystemAdapter.cxx b/src/Main/WindowSystemAdapter.cxx
new file mode 100644 (file)
index 0000000..14530b5
--- /dev/null
@@ -0,0 +1,118 @@
+// Copyright (C) 2008 Tim Moore
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <plib/pu.h>
+
+#include<algorithm>
+#include <functional>
+
+#include "WindowSystemAdapter.hxx"
+
+using namespace osg;
+using namespace std;
+
+using namespace flightgear;
+
+ref_ptr<WindowSystemAdapter> WindowSystemAdapter::_wsa;
+
+void GraphicsContextOperation::operator()(GraphicsContext* gc)
+{
+    run(gc);
+    ++done;
+}
+
+WindowSystemAdapter::WindowSystemAdapter() :
+    _nextWindowID(0), _nextCameraID(0), _isPuInitialized(false)
+{
+}
+
+GraphicsWindow*
+WindowSystemAdapter::registerWindow(GraphicsContext* gc,
+                                    const string& windowName)
+{
+    GraphicsWindow* window = new GraphicsWindow(gc, windowName,
+                                                _nextWindowID++);
+    windows.push_back(window);
+    return window;
+}
+
+Camera3D*
+WindowSystemAdapter::registerCamera3D(GraphicsWindow* gw, Camera* camera,
+                                      const string& cameraName)
+{
+    Camera3D* camera3D = new Camera3D(gw, camera, cameraName);
+    cameras.push_back(camera3D);
+    return camera3D;
+}
+
+GraphicsWindow*
+WindowSystemAdapter::getGUIWindow()
+{
+    WindowVector::const_iterator contextIter
+        = std::find_if(windows.begin(), windows.end(),
+                       FlagTester<GraphicsWindow>(GraphicsWindow::GUI));
+    if (contextIter == windows.end())
+        return 0;
+    else
+        return contextIter->get();
+}
+
+int
+WindowSystemAdapter::getGUIWindowID()
+{
+    const GraphicsWindow* gw = getGUIWindow();
+    if (!gw)
+        return -1;
+    else
+        return gw->id;
+}
+
+GraphicsContext*
+WindowSystemAdapter::getGUIGraphicsContext()
+{
+    GraphicsWindow* gw = getGUIWindow();
+    if (!gw)
+        return 0;
+    else
+        return gw->gc.get();
+}
+
+
+int WindowSystemAdapter::puGetWindow()
+{
+    WindowSystemAdapter* wsa = getWSA();
+    return wsa->getGUIWindowID();
+}
+
+void WindowSystemAdapter::puGetWindowSize(int* width, int* height)
+{
+    // XXX This will have to be different when multiple cameras share
+    // a single window.
+    WindowSystemAdapter* wsa = getWSA();
+    const GraphicsContext* gc = wsa->getGUIGraphicsContext();
+    const GraphicsContext::Traits *traits = gc->getTraits();
+    *width = traits->width;
+    *height = traits->height;
+}
+
+bool WindowSystemAdapter::puInitialize()
+{
+    puSetWindowFuncs(puGetWindow, 0, puGetWindowSize, 0);
+    puRealInit();
+}
diff --git a/src/Main/WindowSystemAdapter.hxx b/src/Main/WindowSystemAdapter.hxx
new file mode 100644 (file)
index 0000000..5fe8052
--- /dev/null
@@ -0,0 +1,150 @@
+// Copyright (C) 2008 Tim Moore
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+#ifndef FLIGHTGEAR_WINDOWSYSTEMADAPTER_HXX
+#define FLIGHTGEAR_WINDOWSYSTEMADAPTER_HXX 1
+
+#include <functional>
+#include <string>
+
+#include <osg/Referenced>
+#include <osg/Camera>
+#include <osg/GraphicsContext>
+#include <osg/GraphicsThread>
+
+#include <simgear/structure/SGAtomic.hxx>
+
+// Flexible Camera and window support
+namespace flightgear
+{
+/** A window opened by default or via rendering properties
+ */
+class GraphicsWindow : public osg::Referenced
+{
+public:
+    GraphicsWindow(osg::GraphicsContext* gc_, const std::string& name_,
+                   int id_, unsigned flags_ = 0) :
+        gc(gc_), name(name_), id(id_), flags(flags_)
+    {
+    }
+    /** The OSG graphics context for this window.
+     */
+    osg::ref_ptr<osg::GraphicsContext> gc;
+    /** The window's internal name.
+     */
+    std::string name;
+    enum Flags {
+        /** The GUI (and 2D cockpit) will be drawn on this window.
+         */
+        GUI = 1
+    };
+    int id;
+    unsigned flags;
+};
+
+/** Camera associated with a 3d view. The camera might occupy an
+ * entire window or share one with other cameras.
+ */
+class Camera3D : public osg::Referenced
+{
+public:
+    Camera3D(GraphicsWindow* window_, osg::Camera* camera_, const std::string& name_,
+             unsigned flags_ = 0) :
+        window(window_), camera(camera_), name(name_), flags(flags_)
+    {
+    }
+    osg::ref_ptr<GraphicsWindow> window;
+    osg::ref_ptr<osg::Camera> camera;
+    std::string name;
+    enum Flags {
+        SHARES_WINDOW = 1,      /**< Camera shares window with other cameras*/
+        MASTER = 2              /**< Camera has same view as master camera*/
+    };
+    unsigned flags;
+};
+
+typedef std::vector<osg::ref_ptr<GraphicsWindow> >  WindowVector;
+typedef std::vector<osg::ref_ptr<Camera3D> >  Camera3DVector;
+
+/**
+ * An operation that is run once with a particular GraphicsContext
+ * current.
+ */
+class GraphicsContextOperation : public osg::GraphicsOperation
+{
+public:
+    GraphicsContextOperation(const std::string& name) :
+        osg::GraphicsOperation(name, false)
+    {
+    }
+    virtual void operator()(osg::GraphicsContext* gc);
+    virtual void run(osg::GraphicsContext* gc) = 0;
+    bool isFinished() const { return done != 0; }
+private:
+    SGAtomic done;
+};
+
+/** Adapter from windows system / graphics context management API to
+ * functions used by flightgear. This papers over the difference
+ * between osgViewer Viewer, which handles multiple windows, graphics
+ * threads, etc., and the embedded viewer used with GLUT and SDL.
+ */
+class WindowSystemAdapter : public osg::Referenced
+{
+public:
+    WindowSystemAdapter();
+    virtual ~WindowSystemAdapter() {}
+    WindowVector windows;
+    Camera3DVector cameras;
+    GraphicsWindow* registerWindow(osg::GraphicsContext* gc,
+                                   const std::string& windowName);
+    Camera3D* registerCamera3D(GraphicsWindow* gw, osg::Camera* camera,
+                               const std::string& cameraName);
+    GraphicsWindow* getGUIWindow();
+    int getGUIWindowID();
+    osg::GraphicsContext* getGUIGraphicsContext();
+    /** Initialize the plib pui interface library. This might happen
+     *in another thread and may be deferred.
+     */
+    virtual bool puInitialize();
+    /** Returns true if pui initialization has finished.
+     */
+    template<typename T>
+    class FlagTester : public std::unary_function<osg::ref_ptr<T>, bool>
+    {
+    public:
+        FlagTester(unsigned flags_) : flags(flags_) {}
+        bool operator() (const osg::ref_ptr<T>& obj)
+        {
+            return (obj->flags & flags) != 0;
+        }
+        unsigned flags;
+    };
+    static WindowSystemAdapter* getWSA() { return _wsa.get(); }
+    static void setWSA(WindowSystemAdapter* wsa) { _wsa = wsa; }
+protected:
+    int _nextWindowID;
+    int _nextCameraID;
+    osg::ref_ptr<GraphicsContextOperation> _puInitOp;
+    bool _isPuInitialized;
+    static osg::ref_ptr<WindowSystemAdapter> _wsa;
+    // Default callbacks for plib
+    static int puGetWindow();
+    static void puGetWindowSize(int* width, int* height);
+
+};
+}
+#endif
index 7cf55792aadad5606327f41ecce68c0c1d5edd50..3aec6ab7fa3eac6ee0ccad31419942b0f3ea1368 100644 (file)
@@ -21,6 +21,9 @@
 #include "globals.hxx"
 #include "renderer.hxx"
 #include "fg_props.hxx"
+#include "WindowSystemAdapter.hxx"
+
+using namespace flightgear;
 
 //
 // Native glut callbacks.
@@ -153,6 +156,7 @@ static void GLUTreshape(int w, int h)
 void fgOSInit(int* argc, char** argv)
 {
     glutInit(argc, argv);
+    WindowSystemAdapter::setWSA(new WindowSystemAdapter);
 }
 
 void fgOSFullScreen()
@@ -216,10 +220,16 @@ static unsigned int getOSGModifiers(int glutModifiers)
     return result;
 }
 
-void fgOSOpenWindow(int w, int h, int bpp, bool alpha,
-                    bool stencil, bool fullscreen)
+void fgOSOpenWindow(bool stencil)
 {
+    int w = fgGetInt("/sim/startup/xsize");
+    int h = fgGetInt("/sim/startup/ysize");
+    int bpp = fgGetInt("/sim/rendering/bits-per-pixel");
+    bool alpha = fgGetBool("/sim/rendering/clouds3d-enable");
+    bool fullscreen = fgGetBool("/sim/startup/fullscreen");
+    WindowSystemAdapter* wsa = WindowSystemAdapter::getWSA();
     int mode = GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE;
+
     if(alpha) mode |= GLUT_ALPHA;
     if(stencil && bpp > 16) mode |= GLUT_STENCIL;
 
@@ -256,18 +266,21 @@ void fgOSOpenWindow(int w, int h, int bpp, bool alpha,
     int realh = h;
     viewer = new osgViewer::Viewer;
     gw = viewer->setUpViewerAsEmbeddedInWindow(0, 0, realw, realh);
+    GraphicsWindow* window = wsa->registerWindow(gw.get(), string("main"));
+    window->flags |= GraphicsWindow::GUI;
     viewer->setDatabasePager(FGScenery::getPagerSingleton());
     // now the main camera ...
-    //osg::ref_ptr<osg::Camera> camera = new osg::Camera;
-    osg::ref_ptr<osg::Camera> camera = viewer->getCamera();
+    osg::Camera* camera = new osg::Camera;
     mainCamera = camera;
-    osg::Camera::ProjectionResizePolicy rsp = osg::Camera::VERTICAL;
     // If a viewport isn't set on the camera, then it's hard to dig it
     // out of the SceneView objects in the viewer, and the coordinates
     // of mouse events are somewhat bizzare.
     camera->setViewport(new osg::Viewport(0, 0, realw, realh));
-    camera->setProjectionResizePolicy(rsp);
-    //viewer->addSlave(camera.get());
+    camera->setProjectionResizePolicy(osg::Camera::FIXED);
+    Camera3D* cam3D = wsa->registerCamera3D(window, camera, string("main"));
+    cam3D->flags |= Camera3D::MASTER; 
+    // Add as a slave for compatibility with the non-embedded osgViewer.
+    viewer->addSlave(camera);
     viewer->setCameraManipulator(globals->get_renderer()->getManipulator());
     // Let FG handle the escape key with a confirmation
     viewer->setKeyEventSetsDone(0);
@@ -280,11 +293,6 @@ void fgOSOpenWindow(int w, int h, int bpp, bool alpha,
     globals->get_renderer()->setViewer(viewer.get());
 }
 
-// Noop; the graphics context is always current
-void fgMakeCurrent()
-{
-}
-
 bool fgOSIsMainCamera(const osg::Camera*)
 {
   return true;
@@ -294,3 +302,8 @@ bool fgOSIsMainContext(const osg::GraphicsContext*)
 {
   return true;
 }
+
+osg::GraphicsContext* fgOSGetMainContext()
+{
+    return gw.get();
+}
index 48a29cdc6f3cc58be0c964c097fa37a28602eea8..c12e79b7bd0d9aa27d4a662139a5c7ff18ce65ad 100644 (file)
@@ -1,13 +1,17 @@
 #ifndef _FG_OS_HXX
 #define _FG_OS_HXX
 
-// Plib pui needs to know at compile time what toolkit is in use.
-// Change this when we move to something other than glut.
-// #define PU_USE_GLUT -- moved to configure.ac -- EMH
 #ifdef HAVE_CONFIG_H
 #  include <config.h>
 #endif
 
+#include <string>
+#include <vector>
+
+#include <osg/ref_ptr>
+#include <osg/Camera>
+#include <osg/GraphicsContext>
+
 
 enum { MOUSE_BUTTON_LEFT,
        MOUSE_BUTTON_MIDDLE,
@@ -45,8 +49,7 @@ enum { KEYMOD_NONE     = 0,
 //
 
 void fgOSInit(int* argc, char** argv);
-void fgOSOpenWindow(int w, int h, int bpp, bool alpha, bool stencil,
-                    bool fullscreen);
+void fgOSOpenWindow(bool stencil);
 void fgOSFullScreen();
 void fgOSMainLoop();
 void fgOSExit(int code);
@@ -82,9 +85,17 @@ void fgRegisterKeyHandler(fgKeyHandler func);
 void fgRegisterMouseClickHandler(fgMouseClickHandler func);
 void fgRegisterMouseMotionHandler(fgMouseMotionHandler func);
 
-void fgMakeCurrent();
-
 bool fgOSIsMainCamera(const osg::Camera* camera);
 bool fgOSIsMainContext(const osg::GraphicsContext* context);
 
+/** Get graphics context of the main camera. This is the principal
+ * window in multi-window configurations, or the only window in an
+ * embedded configuration. The GUI will be added to this context.
+ */
+osg::GraphicsContext* fgOSGetMainContext();
+
+
+
+
+
 #endif // _FG_OS_HXX
index 5cc150d9dc42604a847ab0a6b16edafdd1d88dab..5f1921df1865460bf0cc52a17ee1ef99583338c6 100644 (file)
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
+#include <config.h>
+#include <plib/pu.h>
+#include <osg/GraphicsContext>
+
 #include "fg_os.hxx"
 #include "globals.hxx"
 #include "renderer.hxx"
@@ -60,3 +64,5 @@ void fgRegisterMouseMotionHandler(fgMouseMotionHandler func)
 void fgRequestRedraw()
 {
 }
+
+
index 95bc447f2b4d2b506d27217036332a6f8e3cee09..bb09ab9e9c93b93ba4a8253bb61d4d7b64290b27 100644 (file)
 #  include <config.h>
 #endif
 
+#include <algorithm>
+#include <iostream>
+#include <sstream>
+#include <string>
+
 #include <stdlib.h>
 
 #include <simgear/compiler.h>
@@ -45,6 +50,7 @@
 #include "util.hxx"
 #include "globals.hxx"
 #include "renderer.hxx"
+#include "WindowSystemAdapter.hxx"
 
 #if (FG_OSG_VERSION >= 19008)
 #define OSG_HAS_MOUSE_CURSOR_PATCH
 // fg_os implementation
 //
 
+using namespace std;    
+using namespace flightgear;
 using namespace osg;
 
+
+
 static osg::ref_ptr<osgViewer::Viewer> viewer;
 static osg::ref_ptr<osg::Camera> mainCamera;
 
@@ -67,59 +77,24 @@ static osg::ref_ptr<osg::Camera> mainCamera;
 
 namespace
 {
-struct fgResizeCallback : public GraphicsContext::ResizedCallback
-{
-    fgResizeCallback(Camera* slaveCamera)
-        : mainSlaveCamera(slaveCamera)
-    {}
-    
-    virtual void resizedImplementation(GraphicsContext* gc, int x, int y,
-                                       int width, int height);
-    ref_ptr<Camera> mainSlaveCamera;
-};
-
-void fgResizeCallback::resizedImplementation(GraphicsContext* gc,
-                                             int x, int y,
-                                             int width, int height)
+// silly function for making the default window and camera names
+std::string makeName(const string& prefix, int num)
 {
-    View* view = mainSlaveCamera->getView();
-    View::Slave* slave = (view ?
-                          view->findSlaveForCamera(mainSlaveCamera.get()) : 0);
-    if (slave) {
-        Matrixd projOffset(slave->_projectionOffset);
-        gc->resizedImplementation(x, y, width, height);
-        // Restore projection offsets changed by
-        // GraphicsContext::resizedImplementation
-        slave->_projectionOffset = projOffset;
-    } else {
-        gc->resizedImplementation(x, y, width, height);
-    }
-    
+    std::stringstream stream;
+    stream << prefix << num;
+    return stream.str();
 }
 
-}
-void fgOSOpenWindow(int w, int h, int bpp,
-                    bool alpha, bool stencil, bool fullscreen)
+GraphicsContext::Traits*
+makeDefaultTraits(GraphicsContext::WindowingSystemInterface* wsi, bool stencil)
 {
-    osg::GraphicsContext::WindowingSystemInterface* wsi;
-    wsi = osg::GraphicsContext::getWindowingSystemInterface();
+    int w = fgGetInt("/sim/startup/xsize");
+    int h = fgGetInt("/sim/startup/ysize");
+    int bpp = fgGetInt("/sim/rendering/bits-per-pixel");
+    bool alpha = fgGetBool("/sim/rendering/clouds3d-enable");
+    bool fullscreen = fgGetBool("/sim/startup/fullscreen");
 
-    viewer = new osgViewer::Viewer;
-    viewer->setDatabasePager(FGScenery::getPagerSingleton());
-    std::string mode;
-    mode = fgGetString("/sim/rendering/multithreading-mode", "SingleThreaded");
-    if (mode == "AutomaticSelection")
-      viewer->setThreadingModel(osgViewer::Viewer::AutomaticSelection);
-    else if (mode == "CullDrawThreadPerContext")
-      viewer->setThreadingModel(osgViewer::Viewer::CullDrawThreadPerContext);
-    else if (mode == "DrawThreadPerContext")
-      viewer->setThreadingModel(osgViewer::Viewer::DrawThreadPerContext);
-    else if (mode == "CullThreadPerCameraDrawThreadPerContext")
-      viewer->setThreadingModel(osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext);
-    else
-      viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
-    osg::ref_ptr<osg::GraphicsContext::Traits> traits;
-    traits = new osg::GraphicsContext::Traits;
+    GraphicsContext::Traits* traits = new osg::GraphicsContext::Traits;
     traits->readDISPLAY();
     int cbits = (bpp <= 16) ?  5 :  8;
     int zbits = (bpp <= 16) ? 16 : 24;
@@ -132,10 +107,10 @@ void fgOSOpenWindow(int w, int h, int bpp,
     traits->doubleBuffer = true;
     traits->mipMapGeneration = true;
     traits->windowName = "FlightGear";
+    // XXX should check per window too.
     traits->sampleBuffers = fgGetBool("/sim/rendering/multi-sample-buffers", traits->sampleBuffers);
     traits->samples = fgGetBool("/sim/rendering/multi-samples", traits->samples);
     traits->vsync = fgGetBool("/sim/rendering/vsync-enable", traits->vsync);
-
     if (fullscreen) {
         unsigned width = 0;
         unsigned height = 0;
@@ -156,96 +131,166 @@ void fgOSOpenWindow(int w, int h, int bpp,
 #endif
         traits->supportsResize = true;
     }
+    return traits;
+}
+
+void setTraitsFromProperties(GraphicsContext::Traits* traits,
+                             const SGPropertyNode* winNode,
+                             GraphicsContext::WindowingSystemInterface* wsi)
+{
+    traits->hostName
+        = winNode->getStringValue("host-name", traits->hostName.c_str());
+    traits->displayNum = winNode->getIntValue("display", traits->displayNum);
+    traits->screenNum = winNode->getIntValue("screen", traits->screenNum);
+    if (winNode->getBoolValue("fullscreen",
+                              fgGetBool("/sim/startup/fullscreen"))) {
+        unsigned width = 0;
+        unsigned height = 0;
+        wsi->getScreenResolution(*traits, width, height);
+        traits->windowDecoration = false;
+        traits->width = width;
+        traits->height = height;
+        traits->supportsResize = false;
+    } else {
+        traits->windowDecoration = winNode->getBoolValue("decoration", true);
+        traits->width = winNode->getIntValue("width", traits->width);
+        traits->height = winNode->getIntValue("height", traits->height);
+        traits->supportsResize = true;
+    }
+    traits->x = winNode->getIntValue("x", traits->x);
+    traits->y = winNode->getIntValue("y", traits->y);
+    if (winNode->hasChild("window-name"))
+        traits->windowName = winNode->getStringValue("window-name");
+    else if (winNode->hasChild("name")) 
+        traits->windowName = winNode->getStringValue("name");
+}
+
+} //namespace
+
+void fgOSOpenWindow(bool stencil)
+{
+    osg::GraphicsContext::WindowingSystemInterface* wsi;
+    wsi = osg::GraphicsContext::getWindowingSystemInterface();
 
-    osg::Camera::ProjectionResizePolicy rsp = osg::Camera::VERTICAL;
+    viewer = new osgViewer::Viewer;
+    viewer->setDatabasePager(FGScenery::getPagerSingleton());
+    std::string mode;
+    mode = fgGetString("/sim/rendering/multithreading-mode", "SingleThreaded");
+    if (mode == "AutomaticSelection")
+      viewer->setThreadingModel(osgViewer::Viewer::AutomaticSelection);
+    else if (mode == "CullDrawThreadPerContext")
+      viewer->setThreadingModel(osgViewer::Viewer::CullDrawThreadPerContext);
+    else if (mode == "DrawThreadPerContext")
+      viewer->setThreadingModel(osgViewer::Viewer::DrawThreadPerContext);
+    else if (mode == "CullThreadPerCameraDrawThreadPerContext")
+      viewer->setThreadingModel(osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext);
+    else
+      viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
+    osg::ref_ptr<osg::GraphicsContext::Traits> traits
+        = makeDefaultTraits(wsi, stencil);
 
     // Ok, first the children.
     // that achieves some magic ordering og the slaves so that we end up
     // in the main window more often.
     // This can be sorted out better when we got rid of glut and sdl.
     FGManipulator* manipulator = globals->get_renderer()->getManipulator();
-    int nCameras = 0;
+    string defaultName("slave");
+    WindowSystemAdapter* wsa = WindowSystemAdapter::getWSA();
     if (fgHasNode("/sim/rendering/camera")) {
-      SGPropertyNode* renderingNode = fgGetNode("/sim/rendering");
-      for (int i = 0; i < renderingNode->nChildren(); ++i) {
-        SGPropertyNode* cameraNode = renderingNode->getChild(i);
-        if (strcmp(cameraNode->getName(), "camera") != 0)
-          continue;
-
-        // get a new copy of the traits struct
-        osg::ref_ptr<osg::GraphicsContext::Traits> cameraTraits;
-        cameraTraits = new osg::GraphicsContext::Traits(*traits);
-
-        double shearx = cameraNode->getDoubleValue("shear-x", 0);
-        double sheary = cameraNode->getDoubleValue("shear-y", 0);
-        cameraTraits->hostName
-          = cameraNode->getStringValue("host-name", traits->hostName.c_str());
-        cameraTraits->displayNum
-          = cameraNode->getIntValue("display", traits->displayNum);
-        cameraTraits->screenNum
-          = cameraNode->getIntValue("screen", traits->screenNum);
-        if (cameraNode->getBoolValue("fullscreen", fullscreen)) {
-          unsigned width = 0;
-          unsigned height = 0;
-          wsi->getScreenResolution(*cameraTraits, width, height);
-          cameraTraits->windowDecoration = false;
-          cameraTraits->width = width;
-          cameraTraits->height = height;
-          cameraTraits->supportsResize = false;
-        } else {
-          cameraTraits->windowDecoration = true;
-          cameraTraits->width = cameraNode->getIntValue("width", w);
-          cameraTraits->height = cameraNode->getIntValue("height", h);
-          cameraTraits->supportsResize = true;
-        }
-        // FIXME, currently this is too much of a problem to route the resize
-        // events. When we do no longer need sdl and such this
-        // can be simplified
-        cameraTraits->supportsResize = false;
-
-        // ok found a camera configuration, add a new slave ...
-        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
-
-        osg::GraphicsContext* gc;
-        gc = osg::GraphicsContext::createGraphicsContext(cameraTraits.get());
-        if( gc != NULL ) {
-          gc->realize();
-          camera->setGraphicsContext(gc);
-          // If a viewport isn't set on the camera, then it's hard to dig it
-          // out of the SceneView objects in the viewer, and the coordinates
-          // of mouse events are somewhat bizzare.
-          camera->setViewport(new osg::Viewport(0, 0, cameraTraits->width, cameraTraits->height));
-          camera->setProjectionResizePolicy(rsp);
-          viewer->addSlave(camera.get(), osg::Matrix::translate(-shearx, -sheary, 0), osg::Matrix());
-          nCameras++;
+        SGPropertyNode* renderingNode = fgGetNode("/sim/rendering");
+        for (int i = 0; i < renderingNode->nChildren(); ++i) {
+            SGPropertyNode* cameraNode = renderingNode->getChild(i);
+            if (strcmp(cameraNode->getName(), "camera") != 0)
+                continue;
+
+            // get a new copy of the traits struct
+            osg::ref_ptr<osg::GraphicsContext::Traits> cameraTraits;
+            cameraTraits = new osg::GraphicsContext::Traits(*traits);
+            double shearx = cameraNode->getDoubleValue("shear-x", 0);
+            double sheary = cameraNode->getDoubleValue("shear-y", 0);
+            setTraitsFromProperties(cameraTraits.get(), cameraNode, wsi);
+            // FIXME, currently this is too much of a problem to route
+            // the resize events. When we do no longer need sdl and
+            // such this can be simplified
+            cameraTraits->supportsResize = false;
+
+            // ok found a camera configuration, add a new slave if possible
+            GraphicsContext* gc
+                = GraphicsContext::createGraphicsContext(cameraTraits.get());
+            if (gc) {
+                gc->realize();
+                Camera *camera = new Camera;
+                camera->setGraphicsContext(gc);
+                // If a viewport isn't set on the camera, then it's
+                // hard to dig it out of the SceneView objects in the
+                // viewer, and the coordinates of mouse events are
+                // somewhat bizzare.
+                camera->setViewport(new Viewport(0, 0, cameraTraits->width,
+                                                 cameraTraits->height));
+                const char* cameraName = cameraNode->getStringValue("name");
+                string cameraNameString = (cameraName ? string(cameraName)
+                                           : makeName(defaultName, i));
+                GraphicsWindow* window = wsa->registerWindow(gc,
+                                                             cameraNameString);
+                Camera3D* cam3D = wsa->registerCamera3D(window, camera,
+                                                        cameraNameString);
+                if (shearx == 0 && sheary == 0)
+                    cam3D->flags |= Camera3D::MASTER;
+                viewer->addSlave(camera, Matrix::translate(-shearx, -sheary, 0),
+                                 Matrix());
+            } else {
+                SG_LOG(SG_GENERAL, SG_WARN,
+                       "Couldn't create graphics context on "
+                       << cameraTraits->hostName << ":"
+                       << cameraTraits->displayNum
+                       << "." << cameraTraits->screenNum);
+            }
         }
-      }
-      if (nCameras > 1)
-       manipulator->setResizable(false);
     }
-
     // now the main camera ...
-    osg::ref_ptr<osg::Camera> camera = new osg::Camera;
-    mainCamera = camera;
-    osg::GraphicsContext* gc;
-    gc = osg::GraphicsContext::createGraphicsContext(traits.get());
-    gc->realize();
-    gc->makeCurrent();
-    camera->setGraphicsContext(gc);
-    // If a viewport isn't set on the camera, then it's hard to dig it
-    // out of the SceneView objects in the viewer, and the coordinates
-    // of mouse events are somewhat bizzare.
-    camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
-    camera->setProjectionResizePolicy(rsp);
-    if (nCameras == 0) {
-        // Only one principal camera
-        gc->setResizedCallback(new fgResizeCallback(camera.get()));
+    // XXX mainCamera's purpose is to establish a "main graphics
+    // context" that can be made current (if necessary). But that
+    // should be a context established with a window. It's used to
+    // choose whether to render the GUI and panel camera nodes, but
+    // that's obsolete because the GUI is rendered in its own
+    // slave. And it's used to translate mouse event coordinates, but
+    // that's bogus because mouse clicks should work on any camera. In
+    // short, mainCamera must die :)
+    Camera3DVector::iterator citr
+        = find_if(wsa->cameras.begin(), wsa->cameras.end(),
+                  WindowSystemAdapter::FlagTester<Camera3D>(Camera3D::MASTER));
+    if (citr == wsa->cameras.end()) {
+        // Create a camera aligned with the master camera. Eventually
+        // this will be optional.
+        Camera* camera = new osg::Camera;
+        mainCamera = camera;
+        osg::GraphicsContext* gc
+            = osg::GraphicsContext::createGraphicsContext(traits.get());
+        gc->realize();
+        gc->makeCurrent();
+        camera->setGraphicsContext(gc);
+        // If a viewport isn't set on the camera, then it's hard to dig it
+        // out of the SceneView objects in the viewer, and the coordinates
+        // of mouse events are somewhat bizzare.
+        camera->setViewport(new osg::Viewport(0, 0,
+                                              traits->width, traits->height));
+        GraphicsWindow* window = wsa->registerWindow(gc, string("main"));
+        window->flags |= GraphicsWindow::GUI;
+        Camera3D* camera3d = wsa->registerCamera3D(window, camera,
+                                                   string("main"));
+        camera3d->flags |= Camera3D::MASTER;
+        // Why a slave? It seems to be the easiest way to assign cameras,
+        // for which we've created the graphics context ourselves, to
+        // the viewer. 
+        viewer->addSlave(camera);
+    } else {
+        mainCamera = (*citr)->camera;
     }
-    // Why a slave? It seems to be the easiest way to assign cameras,
-    // for which we've created the graphics context ourselves, to the viewer.
-    viewer->addSlave(camera.get());
-
-    viewer->setCameraManipulator(globals->get_renderer()->getManipulator());
+    if (wsa->cameras.size() != 1) {
+        manipulator->setResizable(false);
+    }
+    viewer->getCamera()->setProjectionResizePolicy(osg::Camera::FIXED);
+    viewer->setCameraManipulator(manipulator);
     // Let FG handle the escape key with a confirmation
     viewer->setKeyEventSetsDone(0);
     // The viewer won't start without some root.
@@ -288,9 +333,9 @@ void fgWarpMouse(int x, int y)
                                1.0f - 2.0f * (float)y / ysize);
 }
 
-// Noop
 void fgOSInit(int* argc, char** argv)
 {
+    WindowSystemAdapter::setWSA(new WindowSystemAdapter);
 }
 
 // Noop
@@ -345,16 +390,6 @@ int fgGetMouseCursor()
     return _cursor;
 }
 
-void fgMakeCurrent()
-{
-    if (!mainCamera.valid())
-        return;
-    osg::GraphicsContext* gc = mainCamera->getGraphicsContext();
-    if (!gc)
-        return;
-    gc->makeCurrent();
-}
-
 bool fgOSIsMainContext(const osg::GraphicsContext* context)
 {
     if (!mainCamera.valid())
@@ -374,3 +409,16 @@ bool fgOSIsMainCamera(const osg::Camera* camera)
     return true;
   return false;
 }
+
+GraphicsContext* fgOSGetMainContext()
+{
+    WindowSystemAdapter* wsa = WindowSystemAdapter::getWSA();
+    WindowVector::iterator contextIter
+        = std::find_if(wsa->windows.begin(), wsa->windows.end(),
+                       WindowSystemAdapter::FlagTester<GraphicsWindow>(GraphicsWindow::GUI));
+    if (contextIter == wsa->windows.end())
+        return 0;
+    else
+        return (*contextIter)->gc.get();
+}
+
index 018b7dd913f2811d0b92301b34f23580aa8e1527..917fff9a0d7f0a9422cf4f78924cf4d2dbab28b3 100644 (file)
@@ -8,12 +8,15 @@
 #include <simgear/debug/logstream.hxx>
 
 #include <SDL/SDL.h>
-#include <plib/pu.h>
 
 #include <Scenery/scenery.hxx>
 #include "fg_os.hxx"
 #include "globals.hxx"
 #include "renderer.hxx"
+#include "fg_props.hxx"
+#include "WindowSystemAdapter.hxx"
+
+using namespace flightgear;
 
 //
 // fg_os callback registration APIs
@@ -34,11 +37,16 @@ static osg::ref_ptr<osgViewer::Viewer> viewer;
 static osg::ref_ptr<osg::Camera> mainCamera;
 static osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> gw;
 
-void fgOSOpenWindow(int w, int h, int bpp,
-                    bool alpha, bool stencil, bool fullscreen)
+void fgOSOpenWindow(bool stencil)
 {
+    int w = fgGetInt("/sim/startup/xsize");
+    int h = fgGetInt("/sim/startup/ysize");
+    int bpp = fgGetInt("/sim/rendering/bits-per-pixel");
+    bool alpha = fgGetBool("/sim/rendering/clouds3d-enable");
+    bool fullscreen = fgGetBool("/sim/startup/fullscreen");
     int cbits = (bpp <= 16) ?  5 :  8;
     int zbits = (bpp <= 16) ? 16 : 24;
+    WindowSystemAdapter* wsa = WindowSystemAdapter::getWSA();
 
     if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE) == -1)
         throw sg_throwable(string("Failed to initialize SDL: ")
@@ -84,17 +92,20 @@ void fgOSOpenWindow(int w, int h, int bpp,
     viewer = new osgViewer::Viewer;
     viewer->setDatabasePager(FGScenery::getPagerSingleton());
     gw = viewer->setUpViewerAsEmbeddedInWindow(0, 0, realw, realh);
+    GraphicsWindow* window = wsa->registerWindow(gw.get(), string("main"));
+    window->flags |= GraphicsWindow::GUI;
     // now the main camera ...
-    //osg::ref_ptr<osg::Camera> camera = new osg::Camera;
-    osg::ref_ptr<osg::Camera> camera = viewer->getCamera();
+    osg::Camera* camera = new osg::Camera;
     mainCamera = camera;
-    osg::Camera::ProjectionResizePolicy rsp = osg::Camera::VERTICAL;
     // If a viewport isn't set on the camera, then it's hard to dig it
     // out of the SceneView objects in the viewer, and the coordinates
     // of mouse events are somewhat bizzare.
     camera->setViewport(new osg::Viewport(0, 0, realw, realh));
-    camera->setProjectionResizePolicy(rsp);
-    //viewer->addSlave(camera.get());
+    camera->setProjectionResizePolicy(osg::Camera::FIXED);
+    Camera3D* cam3D = wsa->registerCamera3D(window, camera, string("main"));
+    cam3D->flags |= Camera3D::MASTER; 
+    // Add as a slave for compatibility with the non-embedded osgViewer.
+    viewer->addSlave(camera);
     viewer->setCameraManipulator(globals->get_renderer()->getManipulator());
     // Let FG handle the escape key with a confirmation
     viewer->setKeyEventSetsDone(0);
@@ -265,7 +276,7 @@ void fgWarpMouse(int x, int y)
 
 void fgOSInit(int* argc, char** argv)
 {
-    // Nothing to do here.  SDL has no command line options.
+    WindowSystemAdapter::setWSA(new WindowSystemAdapter);
 }
 
 void fgOSFullScreen()
@@ -281,7 +292,7 @@ static struct cursor_rec {
     int h;
     int hotx;
     int hoty;
-    char *img[32]; // '.' == white, '#' == black, ' ' == transparent
+    const char *img[32]; // '.' == white, '#' == black, ' ' == transparent
 } cursors[] = {
     { MOUSE_CURSOR_POINTER, 0, // must be first!
       10, 16, 1, 1,
@@ -400,11 +411,6 @@ static void initCursors()
     }
 }
 
-// Noop; the graphics context is always current
-void fgMakeCurrent()
-{
-}
-
 bool fgOSIsMainCamera(const osg::Camera*)
 {
   return true;
@@ -414,3 +420,8 @@ bool fgOSIsMainContext(const osg::GraphicsContext*)
 {
   return true;
 }
+
+osg::GraphicsContext* fgOSGetMainContext()
+{
+    return gw.get();
+}
index 29f0d35ab20eca3011aa6fca38f2aa69b205077d..4a293ffb873d657924b268ba3aa99914b5bdcc37 100644 (file)
@@ -679,9 +679,6 @@ static void fgMainLoop( void ) {
 // then on.
 
 static void fgIdleFunction ( void ) {
-    // Some intialization requires a valid graphics context, in
-    // particular that of plib. Boo, hiss!
-    fgMakeCurrent();
     if ( idle_state == 0 ) {
         idle_state++;
 
@@ -703,10 +700,12 @@ static void fgIdleFunction ( void ) {
         SG_LOG ( SG_GENERAL, SG_INFO, "Depth buffer bits = " << tmp );
 
         // Initialize the user interface so that we can use fonts
-        guiInit();
+        guiStartInit();
 
 
     } else if ( idle_state == 1 ) {
+        if (!guiFinishInit())
+            return;
         idle_state++;
         fgSplashProgress("reading aircraft list");
 
@@ -715,23 +714,6 @@ static void fgIdleFunction ( void ) {
         idle_state++;
         // Read the list of available aircraft
         fgReadAircraft();
-
-        // get the address of our OpenGL extensions
-//         if (SGIsOpenGLExtensionSupported("GL_EXT_point_parameters") ) {
-//             glPointParameterIsSupported = true;
-//             glPointParameterfPtr = (glPointParameterfProc)
-//                 SGLookupFunction("glPointParameterfEXT");
-//             glPointParameterfvPtr = (glPointParameterfvProc)
-//                 SGLookupFunction("glPointParameterfvEXT");
-//         } else if ( SGIsOpenGLExtensionSupported("GL_ARB_point_parameters") ) {
-//             glPointParameterIsSupported = true;
-//             glPointParameterfPtr = (glPointParameterfProc)
-//                 SGLookupFunction("glPointParameterfARB");
-//             glPointParameterfvPtr = (glPointParameterfvProc)
-//                 SGLookupFunction("glPointParameterfvARB");
-//         } else {
-//             glPointParameterIsSupported = false;
-//         }
         fgSplashProgress("reading airport & navigation data");
 
 
@@ -1060,12 +1042,7 @@ bool fgMainInit( int argc, char **argv ) {
 
     // Clouds3D requires an alpha channel
     // clouds may require stencil buffer
-    fgOSOpenWindow( fgGetInt("/sim/startup/xsize"),
-                    fgGetInt("/sim/startup/ysize"),
-                    fgGetInt("/sim/rendering/bits-per-pixel"),
-                    fgGetBool("/sim/rendering/clouds3d-enable"),
-                    get_stencil_buffer,
-                    fgGetBool("/sim/startup/fullscreen") );
+    fgOSOpenWindow(get_stencil_buffer);
 
     // Initialize the splash screen right away
     fntInit();
index ed715a9d2aa4a251d7843668876082fb08f04599..8840ca5bb99418f95ef35432a87f38487a77c033 100644 (file)
@@ -18,9 +18,6 @@
 // You should have received a copy of the GNU General Public License
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// $Id$
-
 
 #ifdef HAVE_CONFIG_H
 #  include <config.h>
@@ -162,11 +159,6 @@ public:
   {
     if (!fgOSIsMainContext(state.getGraphicsContext()))
       return;
-
-    state.pushStateSet(getStateSet());
-    state.apply();
-    state.setActiveTextureUnit(0);
-    state.setClientActiveTextureUnit(0);
     state.disableAllVertexArrays();
 
     glPushAttrib(GL_ALL_ATTRIB_BITS);
@@ -176,11 +168,6 @@ public:
 
     glPopClientAttrib();
     glPopAttrib();
-
-    state.popStateSet();
-    state.dirtyAllModes();
-    state.dirtyAllAttributes();
-    state.dirtyAllVertexArrays();
   }
 
   virtual osg::Object* cloneType() const { return new SGPuDrawable; }
@@ -212,14 +199,9 @@ public:
   { drawImplementation(*renderInfo.getState()); }
   void drawImplementation(osg::State& state) const
   {
-//     std::cout << state.getGraphicsContext() << std::endl;
     if (!fgOSIsMainContext(state.getGraphicsContext()))
       return;
 
-    state.pushStateSet(getStateSet());
-    state.apply();
-    state.setActiveTextureUnit(0);
-    state.setClientActiveTextureUnit(0);
     state.disableAllVertexArrays();
 
     glPushAttrib(GL_ALL_ATTRIB_BITS);
@@ -240,11 +222,6 @@ public:
 
     glPopClientAttrib();
     glPopAttrib();
-
-    state.popStateSet();
-    state.dirtyAllModes();
-    state.dirtyAllAttributes();
-    state.dirtyAllVertexArrays();
   }
 
   virtual osg::Object* cloneType() const { return new SGHUDAndPanelDrawable; }
@@ -428,12 +405,41 @@ FGRenderer::splashinit( void ) {
 #endif
 }
 
+namespace
+{
+// Create a slave camera that will be used to render a fixed GUI-like
+// element.
+osg::Camera*
+makeSlaveCamera(osg::Camera::RenderOrder renderOrder, int orderNum)
+{
+    using namespace osg;
+    Camera* camera = new osg::Camera;
+    GraphicsContext *gc = fgOSGetMainContext();
+    
+    camera->setRenderOrder(renderOrder, orderNum);
+    camera->setClearMask(0);
+    camera->setInheritanceMask(CullSettings::ALL_VARIABLES
+                               & ~(CullSettings::COMPUTE_NEAR_FAR_MODE
+                                   | CullSettings::CULLING_MODE));
+    camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
+    camera->setCullingMode(osg::CullSettings::NO_CULLING);
+    camera->setGraphicsContext(gc);
+    // Establish an initial viewport. This may be altered,
+    // particularly when drawing a 2d panel.
+    const GraphicsContext::Traits *traits = gc->getTraits();
+    camera->setViewport(new Viewport(0, 0, traits->width, traits->height));
+    camera->setProjectionResizePolicy(Camera::FIXED);
+    camera->setReferenceFrame(Transform::ABSOLUTE_RF);
+    camera->setAllowEventFocus(false);
+    globals->get_renderer()->getViewer()->addSlave(camera, false);
+    return camera;
+}
+
+}
+
 void
-FGRenderer::init( void ) {
-    // The viewer can call this before the graphics context is current
-    // in the main thread; indeed, in a multithreaded setup it might
-    // never be current in the main thread.
-    fgMakeCurrent();
+FGRenderer::init( void )
+{
     osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
     osg::initNotifyLevel();
 
@@ -534,15 +540,8 @@ FGRenderer::init( void ) {
     stateSet->setUpdateCallback(new FGFogEnableUpdateCallback);
 
     // plug in the GUI
-    osg::Camera* guiCamera = new osg::Camera;
-    guiCamera->setRenderOrder(osg::Camera::POST_RENDER, 100);
-    guiCamera->setClearMask(0);
-    GLbitfield inheritanceMask = osg::CullSettings::ALL_VARIABLES;
-    inheritanceMask &= ~osg::CullSettings::COMPUTE_NEAR_FAR_MODE;
-    inheritanceMask &= ~osg::CullSettings::CULLING_MODE;
-    guiCamera->setInheritanceMask(inheritanceMask);
-    guiCamera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
-    guiCamera->setCullingMode(osg::CullSettings::NO_CULLING);
+    osg::Camera* guiCamera = makeSlaveCamera(osg::Camera::POST_RENDER, 100);
+    guiCamera->setName("GUI");
     osg::Geode* geode = new osg::Geode;
     geode->addDrawable(new SGPuDrawable);
     geode->addDrawable(new SGHUDAndPanelDrawable);