issue #127: make screen shots work with OSG multi-threading
Make sure actual snap shot is executed in graphics context. (Revert the revert :) - since the basic issue in simgear is solved now) (patch requires simgear+fgdata update!)
This commit is contained in:
parent
25fdbebd57
commit
702d323a39
1 changed files with 133 additions and 3 deletions
|
@ -42,6 +42,7 @@
|
||||||
#include <simgear/debug/logstream.hxx>
|
#include <simgear/debug/logstream.hxx>
|
||||||
#include <simgear/misc/sg_path.hxx>
|
#include <simgear/misc/sg_path.hxx>
|
||||||
#include <simgear/screen/screen-dump.hxx>
|
#include <simgear/screen/screen-dump.hxx>
|
||||||
|
#include <simgear/structure/event_mgr.hxx>
|
||||||
|
|
||||||
#include <Cockpit/panel.hxx>
|
#include <Cockpit/panel.hxx>
|
||||||
#include <Main/globals.hxx>
|
#include <Main/globals.hxx>
|
||||||
|
@ -49,8 +50,11 @@
|
||||||
#include <Main/fg_os.hxx>
|
#include <Main/fg_os.hxx>
|
||||||
#include <Main/renderer.hxx>
|
#include <Main/renderer.hxx>
|
||||||
#include <Main/viewmgr.hxx>
|
#include <Main/viewmgr.hxx>
|
||||||
|
#include <Main/WindowSystemAdapter.hxx>
|
||||||
|
#include <Main/CameraGroup.hxx>
|
||||||
#include <GUI/new_gui.hxx>
|
#include <GUI/new_gui.hxx>
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# include <shellapi.h>
|
# include <shellapi.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -406,9 +410,134 @@ void fgHiResDumpWrapper () {
|
||||||
fgHiResDump();
|
fgHiResDump();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
using namespace flightgear;
|
||||||
|
|
||||||
|
class GUISnapShotOperation :
|
||||||
|
public GraphicsContextOperation
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// start new snap shot
|
||||||
|
static bool start()
|
||||||
|
{
|
||||||
|
// allow only one snapshot at a time
|
||||||
|
if (_snapShotOp.valid())
|
||||||
|
return false;
|
||||||
|
_snapShotOp = new GUISnapShotOperation();
|
||||||
|
/* register with graphics context so actual snap shot is done
|
||||||
|
* in the graphics context (thread) */
|
||||||
|
osg::Camera* guiCamera = getGUICamera(CameraGroup::getDefault());
|
||||||
|
WindowSystemAdapter* wsa = WindowSystemAdapter::getWSA();
|
||||||
|
osg::GraphicsContext* gc = 0;
|
||||||
|
if (guiCamera)
|
||||||
|
gc = guiCamera->getGraphicsContext();
|
||||||
|
if (gc) {
|
||||||
|
gc->add(_snapShotOp.get());
|
||||||
|
} else {
|
||||||
|
wsa->windows[0]->gc->add(_snapShotOp.get());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// constructor to be executed in main loop's thread
|
||||||
|
GUISnapShotOperation() :
|
||||||
|
flightgear::GraphicsContextOperation(std::string("GUI snap shot")),
|
||||||
|
_master_freeze(fgGetNode("/sim/freeze/master", true)),
|
||||||
|
_freeze(_master_freeze->getBoolValue()),
|
||||||
|
_result(false),
|
||||||
|
_mouse(fgGetMouseCursor())
|
||||||
|
{
|
||||||
|
if (!_freeze)
|
||||||
|
_master_freeze->setBoolValue(true);
|
||||||
|
|
||||||
|
fgSetMouseCursor(MOUSE_CURSOR_NONE);
|
||||||
|
|
||||||
|
string dir = fgGetString("/sim/paths/screenshot-dir");
|
||||||
|
if (dir.empty())
|
||||||
|
dir = fgGetString("/sim/fg-current");
|
||||||
|
|
||||||
|
_path.set(dir + '/');
|
||||||
|
if (_path.create_dir( 0755 )) {
|
||||||
|
SG_LOG(SG_GENERAL, SG_ALERT, "Cannot create screenshot directory '"
|
||||||
|
<< dir << "'. Trying home directory.");
|
||||||
|
dir = fgGetString("/sim/fg-home");
|
||||||
|
}
|
||||||
|
|
||||||
|
char filename[24];
|
||||||
|
static int count = 1;
|
||||||
|
while (count < 1000) {
|
||||||
|
snprintf(filename, 24, "fgfs-screen-%03d.png", count++);
|
||||||
|
|
||||||
|
SGPath p(dir);
|
||||||
|
p.append(filename);
|
||||||
|
if (!p.exists()) {
|
||||||
|
_path.set(p.str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_xsize = fgGetInt("/sim/startup/xsize");
|
||||||
|
_ysize = fgGetInt("/sim/startup/ysize");
|
||||||
|
|
||||||
|
FGRenderer *renderer = globals->get_renderer();
|
||||||
|
renderer->resize(_xsize, _ysize);
|
||||||
|
globals->get_event_mgr()->addTask("SnapShotTimer",
|
||||||
|
this, &GUISnapShotOperation::timerExpired,
|
||||||
|
0.1, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// to be executed in graphics context (maybe separate thread)
|
||||||
|
void run(osg::GraphicsContext* gc)
|
||||||
|
{
|
||||||
|
_result = sg_glDumpWindow(_path.c_str(),
|
||||||
|
_xsize,
|
||||||
|
_ysize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// timer method, to be executed in main loop's thread
|
||||||
|
virtual void timerExpired()
|
||||||
|
{
|
||||||
|
if (isFinished())
|
||||||
|
{
|
||||||
|
globals->get_event_mgr()->removeTask("SnapShotTimer");
|
||||||
|
|
||||||
|
fgSetString("/sim/paths/screenshot-last", _path.c_str());
|
||||||
|
fgSetBool("/sim/signals/screenshot", _result);
|
||||||
|
|
||||||
|
fgSetMouseCursor(_mouse);
|
||||||
|
|
||||||
|
if ( !_freeze )
|
||||||
|
_master_freeze->setBoolValue(false);
|
||||||
|
|
||||||
|
_snapShotOp = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static osg::ref_ptr<GUISnapShotOperation> _snapShotOp;
|
||||||
|
SGPropertyNode_ptr _master_freeze;
|
||||||
|
bool _freeze;
|
||||||
|
bool _result;
|
||||||
|
int _mouse;
|
||||||
|
int _xsize, _ysize;
|
||||||
|
SGPath _path;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::ref_ptr<GUISnapShotOperation> GUISnapShotOperation::_snapShotOp;
|
||||||
|
|
||||||
// do a screen snap shot
|
// do a screen snap shot
|
||||||
bool fgDumpSnapShot () {
|
bool fgDumpSnapShot ()
|
||||||
|
{
|
||||||
|
#if 1
|
||||||
|
// start snap shot operation, while needs to be executed in
|
||||||
|
// graphics context
|
||||||
|
return GUISnapShotOperation::start();
|
||||||
|
#else
|
||||||
|
// obsolete code => remove when new code is stable
|
||||||
static SGConstPropertyNode_ptr master_freeze = fgGetNode("/sim/freeze/master");
|
static SGConstPropertyNode_ptr master_freeze = fgGetNode("/sim/freeze/master");
|
||||||
|
|
||||||
bool freeze = master_freeze->getBoolValue();
|
bool freeze = master_freeze->getBoolValue();
|
||||||
|
@ -455,7 +584,7 @@ bool fgDumpSnapShot () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int result = sg_glDumpWindow(path.c_str(),
|
bool result = sg_glDumpWindow(path.c_str(),
|
||||||
fgGetInt("/sim/startup/xsize"),
|
fgGetInt("/sim/startup/xsize"),
|
||||||
fgGetInt("/sim/startup/ysize"));
|
fgGetInt("/sim/startup/ysize"));
|
||||||
|
|
||||||
|
@ -467,7 +596,8 @@ bool fgDumpSnapShot () {
|
||||||
if ( !freeze ) {
|
if ( !freeze ) {
|
||||||
fgSetBool("/sim/freeze/master", false);
|
fgSetBool("/sim/freeze/master", false);
|
||||||
}
|
}
|
||||||
return result != 0;
|
return result;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// do an entire scenegraph dump
|
// do an entire scenegraph dump
|
||||||
|
|
Loading…
Reference in a new issue