From 580ebf637b991bbc5bb6b9632e8e62845d23ea43 Mon Sep 17 00:00:00 2001 From: timoore Date: Mon, 19 May 2008 21:21:03 +0000 Subject: [PATCH] Clean up OSG camera setup and interface to plib PUI 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. --- configure.ac | 17 +- projects/VC7.1/FlightGear.vcproj | 4 +- src/Cockpit/cockpit.cxx | 2 +- src/GUI/gui.cxx | 109 +++++++---- src/GUI/gui.h | 3 +- src/Include/config.h-msvc8 | 6 - src/Include/config.h-msvc8.in | 3 - src/Input/input.cxx | 2 - src/Main/Makefile.am | 1 + src/Main/WindowSystemAdapter.cxx | 118 +++++++++++ src/Main/WindowSystemAdapter.hxx | 150 ++++++++++++++ src/Main/fg_os.cxx | 37 ++-- src/Main/fg_os.hxx | 25 ++- src/Main/fg_os_common.cxx | 6 + src/Main/fg_os_osgviewer.cxx | 324 ++++++++++++++++++------------- src/Main/fg_os_sdl.cxx | 41 ++-- src/Main/main.cxx | 31 +-- src/Main/renderer.cxx | 73 ++++--- 18 files changed, 653 insertions(+), 299 deletions(-) create mode 100644 src/Main/WindowSystemAdapter.cxx create mode 100644 src/Main/WindowSystemAdapter.hxx 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; - - // 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 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 -{ - 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) +// 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 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 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 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 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 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 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); -- 2.39.5