diff --git a/configure.ac b/configure.ac index 295578d3a..f854b750e 100644 --- a/configure.ac +++ b/configure.ac @@ -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"]) diff --git a/projects/VC7.1/FlightGear.vcproj b/projects/VC7.1/FlightGear.vcproj index be611d366..2741f318c 100755 --- a/projects/VC7.1/FlightGear.vcproj +++ b/projects/VC7.1/FlightGear.vcproj @@ -24,7 +24,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="..\..\..;..\..\src;..\..\src\include;..\..\..\SimGear;"..\..\..\pthreads-w32-2-7-0-release";..\..\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;"..\..\..\pthreads-w32-2-7-0-release";..\..\..\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" diff --git a/src/Cockpit/cockpit.cxx b/src/Cockpit/cockpit.cxx index 26b6b94dd..b9e97281e 100644 --- a/src/Cockpit/cockpit.cxx +++ b/src/Cockpit/cockpit.cxx @@ -566,7 +566,7 @@ void fgCockpitUpdate( osg::State* state ) { struct FuncTable { - char *name; + const char *name; FLTFNPTR func; } fn_table[] = { { "agl", get_agl }, diff --git a/src/GUI/gui.cxx b/src/GUI/gui.cxx index b34e135e2..b730270f5 100644 --- a/src/GUI/gui.cxx +++ b/src/GUI/gui.cxx @@ -34,6 +34,8 @@ # include #endif +#include + #include #include #include @@ -45,12 +47,15 @@ #include
#include
#include
+#include
#include #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; +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); - // 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(); - 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); + 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 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; +} + diff --git a/src/GUI/gui.h b/src/GUI/gui.h index 2385d1227..4897b0ed9 100644 --- a/src/GUI/gui.h +++ b/src/GUI/gui.h @@ -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); diff --git a/src/Include/config.h-msvc8 b/src/Include/config.h-msvc8 index b8d04051e..6f39a1702 100755 --- a/src/Include/config.h-msvc8 +++ b/src/Include/config.h-msvc8 @@ -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 diff --git a/src/Include/config.h-msvc8.in b/src/Include/config.h-msvc8.in index 46c1b9197..cc630a070 100644 --- a/src/Include/config.h-msvc8.in +++ b/src/Include/config.h-msvc8.in @@ -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 diff --git a/src/Input/input.cxx b/src/Input/input.cxx index 3ecf5142f..f4168b55d 100644 --- a/src/Input/input.cxx +++ b/src/Input/input.cxx @@ -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) && diff --git a/src/Main/Makefile.am b/src/Main/Makefile.am index 3d9d94db9..9be3ca374 100644 --- a/src/Main/Makefile.am +++ b/src/Main/Makefile.am @@ -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 index 000000000..14530b5bb --- /dev/null +++ b/src/Main/WindowSystemAdapter.cxx @@ -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 +#endif + +#include + +#include +#include + +#include "WindowSystemAdapter.hxx" + +using namespace osg; +using namespace std; + +using namespace flightgear; + +ref_ptr 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::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 index 000000000..5fe805278 --- /dev/null +++ b/src/Main/WindowSystemAdapter.hxx @@ -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 +#include + +#include +#include +#include +#include + +#include + +// 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 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 window; + osg::ref_ptr 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 > WindowVector; +typedef std::vector > 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 + class FlagTester : public std::unary_function, bool> + { + public: + FlagTester(unsigned flags_) : flags(flags_) {} + bool operator() (const osg::ref_ptr& 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 _puInitOp; + bool _isPuInitialized; + static osg::ref_ptr _wsa; + // Default callbacks for plib + static int puGetWindow(); + static void puGetWindowSize(int* width, int* height); + +}; +} +#endif diff --git a/src/Main/fg_os.cxx b/src/Main/fg_os.cxx index 7cf55792a..3aec6ab7f 100644 --- a/src/Main/fg_os.cxx +++ b/src/Main/fg_os.cxx @@ -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 camera = new osg::Camera; - osg::ref_ptr 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(); +} diff --git a/src/Main/fg_os.hxx b/src/Main/fg_os.hxx index 48a29cdc6..c12e79b7b 100644 --- a/src/Main/fg_os.hxx +++ b/src/Main/fg_os.hxx @@ -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 #endif +#include +#include + +#include +#include +#include + 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 diff --git a/src/Main/fg_os_common.cxx b/src/Main/fg_os_common.cxx index 5cc150d9d..5f1921df1 100644 --- a/src/Main/fg_os_common.cxx +++ b/src/Main/fg_os_common.cxx @@ -17,6 +17,10 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +#include +#include +#include + #include "fg_os.hxx" #include "globals.hxx" #include "renderer.hxx" @@ -60,3 +64,5 @@ void fgRegisterMouseMotionHandler(fgMouseMotionHandler func) void fgRequestRedraw() { } + + diff --git a/src/Main/fg_os_osgviewer.cxx b/src/Main/fg_os_osgviewer.cxx index 95bc447f2..bb09ab9e9 100644 --- a/src/Main/fg_os_osgviewer.cxx +++ b/src/Main/fg_os_osgviewer.cxx @@ -22,6 +22,11 @@ # include #endif +#include +#include +#include +#include + #include #include @@ -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 @@ -57,8 +63,12 @@ // fg_os implementation // +using namespace std; +using namespace flightgear; using namespace osg; + + static osg::ref_ptr viewer; static osg::ref_ptr mainCamera; @@ -67,59 +77,24 @@ static osg::ref_ptr mainCamera; namespace { -struct fgResizeCallback : public GraphicsContext::ResizedCallback +// silly function for making the default window and camera names +std::string makeName(const string& prefix, int num) { - fgResizeCallback(Camera* slaveCamera) - : mainSlaveCamera(slaveCamera) - {} - - virtual void resizedImplementation(GraphicsContext* gc, int x, int y, - int width, int height); - ref_ptr mainSlaveCamera; -}; - -void fgResizeCallback::resizedImplementation(GraphicsContext* gc, - int x, int y, - int width, int height) -{ - 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 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; +} - osg::Camera::ProjectionResizePolicy rsp = osg::Camera::VERTICAL; +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(); + + 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 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; + 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 cameraTraits; - cameraTraits = new osg::GraphicsContext::Traits(*traits); + // get a new copy of the traits struct + osg::ref_ptr 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; - 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; + // 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); + } } - // 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 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++; - } - } - if (nCameras > 1) - manipulator->setResizable(false); } - // now the main camera ... - osg::ref_ptr 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::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::GUI)); + if (contextIter == wsa->windows.end()) + return 0; + else + return (*contextIter)->gc.get(); +} + diff --git a/src/Main/fg_os_sdl.cxx b/src/Main/fg_os_sdl.cxx index 018b7dd91..917fff9a0 100644 --- a/src/Main/fg_os_sdl.cxx +++ b/src/Main/fg_os_sdl.cxx @@ -8,12 +8,15 @@ #include #include -#include #include #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 viewer; static osg::ref_ptr mainCamera; static osg::ref_ptr 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 camera = new osg::Camera; - osg::ref_ptr 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(); +} diff --git a/src/Main/main.cxx b/src/Main/main.cxx index 29f0d35ab..4a293ffb8 100644 --- a/src/Main/main.cxx +++ b/src/Main/main.cxx @@ -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(); diff --git a/src/Main/renderer.cxx b/src/Main/renderer.cxx index ed715a9d2..8840ca5bb 100644 --- a/src/Main/renderer.cxx +++ b/src/Main/renderer.cxx @@ -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 @@ -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);