From Ulrich Hertlien with little bits from Robert Osfield and Chris Hanson, added provisionl support for controlling sync to vblank.

This commit is contained in:
Robert Osfield 2010-04-21 17:16:13 +00:00
parent 6e03d73efe
commit 9eebb2eb23
8 changed files with 160 additions and 91 deletions

View File

@ -134,6 +134,14 @@ class OSGVIEWER_EXPORT GraphicsWindow : public osg::GraphicsContext, public osgG
/** Create a new mouse cursor from the usual bitmap data.*/
//virtual MouseCursor createCursor(const char *data, const char *mask, unsigned w, unsigned h, unsigned hotx, unsigned hoty) { osg::notify(osg::NOTICE)<<"GraphicsWindow::createCursor(..) not implemented."<<std::endl; }
/** Set sync-to-vblank. */
virtual void setSyncToVBlank(bool on)
{
osg::notify(osg::NOTICE) << "GraphicsWindow::setSyncToVBlank(" << on << ") not implemented." << std::endl;
}
bool getSyncToVBlank() const { return _traits.valid() ? _traits->vsync : true; }
public:
/** Return whether a valid and usable GraphicsContext has been created.*/

View File

@ -68,7 +68,9 @@ class OSGVIEWER_EXPORT HelpHandler : public osgGA::GUIEventHandler
};
/** Event handler for adding on screen stats reporting to Viewers.*/
/**
* Event handler for adding on screen stats reporting to Viewers.
*/
class OSGVIEWER_EXPORT StatsHandler : public osgGA::GUIEventHandler
{
public:
@ -91,6 +93,9 @@ class OSGVIEWER_EXPORT StatsHandler : public osgGA::GUIEventHandler
void setKeyEventPrintsOutStats(int key) { _keyEventPrintsOutStats = key; }
int getKeyEventPrintsOutStats() const { return _keyEventPrintsOutStats; }
void setKeyEventToggleVSync(int key) { _keyEventToggleVSync = key; }
int getKeyEventToggleVSync() const { return _keyEventToggleVSync; }
double getBlockMultiplier() const { return _blockMultiplier; }
void reset();
@ -123,6 +128,7 @@ class OSGVIEWER_EXPORT StatsHandler : public osgGA::GUIEventHandler
int _keyEventTogglesOnScreenStats;
int _keyEventPrintsOutStats;
int _keyEventToggleVSync;
int _statsType;

View File

@ -36,7 +36,8 @@ class GraphicsWindowCarbon : public osgViewer::GraphicsWindow, public osgViewer:
_initialized(false),
_realized(false),
_ownsWindow(true),
_currentCursor(RightArrowCursor)
_currentCursor(RightArrowCursor),
_currentVSync(true)
{
_traits = traits;
@ -108,7 +109,10 @@ class GraphicsWindowCarbon : public osgViewer::GraphicsWindow, public osgViewer:
virtual void setWindowName (const std::string & name);
virtual void useCursor(bool cursorOn);
virtual void setCursor(MouseCursor mouseCursor);
/** Set sync-to-vblank. */
virtual void setSyncToVBlank(bool on);
WindowRef getNativeWindowRef() { return _window; }
bool handleMouseEvent(EventRef theEvent);
@ -168,6 +172,7 @@ class GraphicsWindowCarbon : public osgViewer::GraphicsWindow, public osgViewer:
bool _closeRequested;
UInt32 _lastModifierKeys;
MouseCursor _currentCursor;
bool _currentVSync;
};
}

View File

@ -86,7 +86,10 @@ class OSGVIEWER_EXPORT GraphicsWindowWin32 : public osgViewer::GraphicsWindow, p
/** Set mouse cursor to a specific shape.*/
virtual void setCursor(MouseCursor cursor);
/** Set sync-to-vblank. */
virtual void setSyncToVBlank(bool on);
/** Handle a native (Win32) windowing event as received from the system */
virtual LRESULT handleNativeWindowingEvent( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );

View File

@ -345,19 +345,18 @@ void GraphicsWindowCarbon::installEventHandler() {
bool GraphicsWindowCarbon::realizeImplementation()
{
if (!_initialized) init();
if (!_initialized) return false;
if (!_traits) return false;
OSG_NOTIFY(osg::INFO) << "GraphicsWindowCarbon:: realizeIMplementation" << std::endl;
osg::notify(osg::INFO) << "GraphicsWindowCarbon::realizeImplementation" << std::endl;
setWindowDecoration(_traits->windowDecoration);
useCursor(_traits->useCursor);
// move the window to the right screen
DarwinWindowingSystemInterface* wsi = dynamic_cast<DarwinWindowingSystemInterface*>(osg::GraphicsContext::getWindowingSystemInterface());
int screenLeft(0), screenTop(0);
int screenLeft = 0, screenTop = 0;
if (wsi)
{
wsi->getScreenTopLeft((*_traits), screenLeft, screenTop);
@ -377,10 +376,10 @@ bool GraphicsWindowCarbon::realizeImplementation()
err = CreateNewWindow(kDocumentWindowClass, attr, &bounds, &_window);
if (err) {
OSG_NOTIFY(osg::WARN) << "GraphicsWindowCarbon::realizeImplementation() failed creating a window: " << err << std::endl;
OSG_NOTIFY(osg::WARN) << "GraphicsWindowCarbon::realizeImplementation: failed to create window: " << err << std::endl;
return false;
} else {
OSG_NOTIFY(osg::INFO) << "GraphicsWindowCarbon::realizeImplementation() - window created with bounds(" << bounds.top << ", " << bounds.left << ", " << bounds.bottom << ", " << bounds.right << ")" << std::endl;
OSG_NOTIFY(osg::INFO) << "GraphicsWindowCarbon::realizeImplementation: window created with bounds(" << bounds.top << ", " << bounds.left << ", " << bounds.bottom << ", " << bounds.right << ")" << std::endl;
}
}
else {
@ -407,10 +406,8 @@ bool GraphicsWindowCarbon::realizeImplementation()
}
_context = aglCreateContext (_pixelFormat, sharedContextCarbon);
if (!_context) {
OSG_NOTIFY(osg::WARN) << "GraphicsWindowCarbon::realizeImplementation failed creating a context: " << aglGetError() << std::endl;
OSG_NOTIFY(osg::WARN) << "GraphicsWindowCarbon::realizeImplementation: failed to create context: " << aglGetError() << std::endl;
return false;
}
@ -441,17 +438,18 @@ bool GraphicsWindowCarbon::realizeImplementation()
#endif
if (cgerr != kCGLNoError )
{
OSG_NOTIFY(osg::INFO) << "GraphicsWindowCarbon:: Multi-threaded OpenGL Execution not available" << std::endl;
OSG_NOTIFY(osg::INFO) << "GraphicsWindowCarbon::realizeImplementation: multi-threaded OpenGL Execution not available" << std::endl;
}
}
InitCursor();
//enable vsync
// enable vsync
if (_traits->vsync) {
GLint swap = 1;
aglSetInteger (_context, AGL_SWAP_INTERVAL, &swap);
}
_currentVSync = _traits->vsync;
_realized = true;
return _realized;
@ -485,7 +483,7 @@ void GraphicsWindowCarbon::closeImplementation()
// OSG_NOTIFY(osg::INFO) << "GraphicsWindowCarbon::closeImplementation" << std::endl;
_valid = false;
_realized = false;
// there's a possibility that the MenubarController is destructed already, so prevent a crash:
MenubarController* mbc = MenubarController::instance();
if (mbc) mbc->detachWindow(this);
@ -495,7 +493,7 @@ void GraphicsWindowCarbon::closeImplementation()
aglDestroyPixelFormat(_pixelFormat);
_pixelFormat = NULL;
}
if (_context)
{
aglSetDrawable(_context, NULL);
@ -503,7 +501,7 @@ void GraphicsWindowCarbon::closeImplementation()
aglDestroyContext(_context);
_context = NULL;
}
if (_ownsWindow && _window) DisposeWindow(_window);
_window = NULL;
}
@ -512,6 +510,16 @@ void GraphicsWindowCarbon::closeImplementation()
void GraphicsWindowCarbon::swapBuffersImplementation()
{
// check for vsync change
if (_traits.valid() && _traits->vsync != _currentVSync)
{
const bool on = _traits->vsync;
GLint swap = (on ? 1 : 0);
aglSetInteger (_context, AGL_SWAP_INTERVAL, &swap);
osg::notify(osg::NOTICE) << "GraphicsWindowCarbon: VSync=" << (on ? "on" : "off") << std::endl;
_currentVSync = on;
}
aglSwapBuffers(_context);
}
@ -566,7 +574,7 @@ bool GraphicsWindowCarbon::handleMouseEvent(EventRef theEvent)
if (mouseButton==3) mouseButton = 2;
else if (mouseButton==2) mouseButton = 3;
// check tablet pointer device and map it to a musebutton
// check tablet pointer device and map it to a mouse button
TabletProximityRec theTabletRecord; // The Tablet Proximity Record
// Extract the Tablet Proximity reccord from the event.
if(noErr == GetEventParameter(theEvent, kEventParamTabletProximityRec,
@ -585,7 +593,7 @@ bool GraphicsWindowCarbon::handleMouseEvent(EventRef theEvent)
pointerType = osgGA::GUIEventAdapter::PUCK;
break;
case 3: //eraser
case 3: // eraser
pointerType = osgGA::GUIEventAdapter::ERASER;
break;
@ -615,8 +623,8 @@ bool GraphicsWindowCarbon::handleMouseEvent(EventRef theEvent)
{
case kEventMouseDown:
{
float mx =wheresMyMouse.h;
float my =wheresMyMouse.v;
float mx = wheresMyMouse.h;
float my = wheresMyMouse.v;
transformMouseXY(mx, my);
lastEmulatedMouseButton = 0;
@ -641,8 +649,8 @@ bool GraphicsWindowCarbon::handleMouseEvent(EventRef theEvent)
break;
case kEventMouseUp:
{
float mx =wheresMyMouse.h;
float my =wheresMyMouse.v;
float mx = wheresMyMouse.h;
float my = wheresMyMouse.v;
transformMouseXY(mx, my);
if (lastEmulatedMouseButton > 0) {
getEventQueue()->mouseButtonRelease(mx, my, lastEmulatedMouseButton);
@ -662,11 +670,10 @@ bool GraphicsWindowCarbon::handleMouseEvent(EventRef theEvent)
sizeof(TabletPointRec), NULL, (void *)&theTabletRecord)) {
getEventQueue()->penPressure(theTabletRecord.pressure / 65535.0f);
}
float mx =wheresMyMouse.h;
float my =wheresMyMouse.v;
float mx = wheresMyMouse.h;
float my = wheresMyMouse.v;
transformMouseXY(mx, my);
getEventQueue()->mouseMotion(mx, my);
}
@ -705,23 +712,23 @@ bool GraphicsWindowCarbon::handleMouseEvent(EventRef theEvent)
case 11:
{
enum
{
{
kEventParamMouseWheelSmoothVerticalDelta = 'saxy', // typeSInt32
kEventParamMouseWheelSmoothHorizontalDelta = 'saxx' // typeSInt32
};
};
SInt32 scroll_delta_x = 0;
SInt32 scroll_delta_y = 0;
OSErr err = noErr;
err = GetEventParameter( theEvent, kEventParamMouseWheelSmoothVerticalDelta, typeLongInteger, NULL, sizeof(scroll_delta_y), NULL, &scroll_delta_y );
err = GetEventParameter( theEvent, kEventParamMouseWheelSmoothHorizontalDelta, typeLongInteger, NULL, sizeof(scroll_delta_x), NULL, &scroll_delta_x );
if ((scroll_delta_x != 0) || (scroll_delta_y != 0)) {
getEventQueue()->mouseScroll2D( scroll_delta_x, scroll_delta_y);
}
}
break;
default:
return false;
}
@ -759,15 +766,16 @@ bool GraphicsWindowCarbon::handleKeyboardEvent(EventRef theEvent)
case kEventRawKeyDown:
case kEventRawKeyRepeat:
{
//osg::notify(osg::INFO) << "GraphicsWindowCarbon::keyPress Up" << std::endl;
//getEventQueue()->getCurrentEventState()->setModKeyMask(modifierMask);
OSG_NOTIFY(osg::INFO) << "GraphicsWindowCarbon::keyPress" << std::endl;
//OSG_NOTIFY(osg::INFO) << "GraphicsWindowCarbon::keyPress" << std::endl;
getEventQueue()->keyPress(keychar);
break;
}
case kEventRawKeyUp:
{
OSG_NOTIFY(osg::INFO) << "GraphicsWindowCarbon::keyPress" << std::endl;
//OSG_NOTIFY(osg::INFO) << "GraphicsWindowCarbon::keyPress" << std::endl;
//getEventQueue()->getCurrentEventState()->setModKeyMask(modifierMask);
getEventQueue()->keyRelease(keychar);
break;
@ -940,34 +948,24 @@ void GraphicsWindowCarbon::grabFocus()
void GraphicsWindowCarbon::grabFocusIfPointerInWindow()
{
// TODO: implement
OSG_NOTIFY(osg::ALWAYS) << "GraphicsWindowCarbon::grabFocusIfPointerInWindow" << std::endl;
OSG_NOTIFY(osg::ALWAYS) << "GraphicsWindowCarbon::grabFocusIfPointerInWindow: not implemented" << std::endl;
}
void GraphicsWindowCarbon::useCursor(bool cursorOn)
{
if (_traits.valid())
_traits->useCursor = cursorOn;
DarwinWindowingSystemInterface* wsi = dynamic_cast<DarwinWindowingSystemInterface*>(osg::GraphicsContext::getWindowingSystemInterface());
if (wsi == NULL) {
OSG_NOTIFY(osg::WARN) << "GraphicsWindowCarbon::useCursor :: could not get OSXCarbonWindowingSystemInterface" << std::endl;
OSG_NOTIFY(osg::WARN) << "GraphicsWindowCarbon::useCursor: could not get OSXCarbonWindowingSystemInterface" << std::endl;
return;
}
CGDirectDisplayID displayId = wsi->getDisplayID((*_traits));
CGDisplayErr err = kCGErrorSuccess;
switch (cursorOn)
{
case true:
err = CGDisplayShowCursor(displayId);
break;
case false:
err = CGDisplayHideCursor(displayId);
break;
}
CGDisplayErr err = (cursorOn ? CGDisplayShowCursor(displayId) : CGDisplayHideCursor(displayId));
if (err != kCGErrorSuccess) {
OSG_NOTIFY(osg::WARN) << "GraphicsWindowCarbon::useCursor failed with " << err << std::endl;
OSG_NOTIFY(osg::WARN) << "GraphicsWindowCarbon::useCursor: failed with " << err << std::endl;
}
}
@ -975,9 +973,10 @@ void GraphicsWindowCarbon::useCursor(bool cursorOn)
// FIXME: I used deprecated functions, but don't know if there are any substitutable newer functions...
void GraphicsWindowCarbon::setCursor(MouseCursor mouseCursor)
{
UInt32 cursor;
if (_currentCursor == mouseCursor)
return;
UInt32 cursor;
switch (mouseCursor)
{
case NoCursor:
@ -1009,6 +1008,12 @@ void GraphicsWindowCarbon::setCursor(MouseCursor mouseCursor)
ShowCursor();
}
void GraphicsWindowCarbon::setSyncToVBlank(bool on)
{
if (_traits.valid()) {
_traits->vsync = on;
}
}
void GraphicsWindowCarbon::setWindowName (const std::string& name)
{
@ -1026,7 +1031,7 @@ void GraphicsWindowCarbon::requestWarpPointer(float x,float y)
DarwinWindowingSystemInterface* wsi = dynamic_cast<DarwinWindowingSystemInterface*>(osg::GraphicsContext::getWindowingSystemInterface());
if (wsi == NULL) {
OSG_NOTIFY(osg::WARN) << "GraphicsWindowCarbon::useCursor :: could not get OSXCarbonWindowingSystemInterface" << std::endl;
OSG_NOTIFY(osg::WARN) << "GraphicsWindowCarbon::useCursor: could not get OSXCarbonWindowingSystemInterface" << std::endl;
return;
}

View File

@ -1778,46 +1778,53 @@ bool GraphicsWindowWin32::realizeImplementation()
init();
if (!_initialized) return false;
}
{
if (_traits.valid() && _traits->sharedContext)
{
GraphicsHandleWin32* graphicsHandleWin32 = dynamic_cast<GraphicsHandleWin32*>(_traits->sharedContext);
if (graphicsHandleWin32)
{
struct RestoreContext
{
RestoreContext()
{
_hdc = wglGetCurrentDC();
_hglrc = wglGetCurrentContext();
}
~RestoreContext()
{
if (_hdc)
{
wglMakeCurrent(_hdc,_hglrc);
}
}
protected:
HDC _hdc;
HGLRC _hglrc;
} restoreContext;
_realized = true;
bool result = makeCurrent();
_realized = false;
if (!result)
if (_traits.valid() && (_traits->sharedContext || _traits->vsync))
{
// make context current so we can test capabilities and set up context sharing
struct RestoreContext
{
RestoreContext()
{
_hdc = wglGetCurrentDC();
_hglrc = wglGetCurrentContext();
}
~RestoreContext()
{
if (_hdc)
{
return false;
}
if (!wglShareLists(graphicsHandleWin32->getWGLContext(), getWGLContext()))
{
reportErrorForScreen("GraphicsWindowWin32::realizeImplementation() - Unable to share OpenGL context", _traits->screenNum, ::GetLastError());
return false;
wglMakeCurrent(_hdc,_hglrc);
}
}
protected:
HDC _hdc;
HGLRC _hglrc;
} restoreContext;
_realized = true;
bool result = makeCurrent();
_realized = false;
if (!result)
{
return false;
}
// set up sharing of contexts if required
GraphicsHandleWin32* graphicsHandleWin32 = dynamic_cast<GraphicsHandleWin32*>(_traits->sharedContext);
if (graphicsHandleWin32)
{
if (!wglShareLists(graphicsHandleWin32->getWGLContext(), getWGLContext()))
{
reportErrorForScreen("GraphicsWindowWin32::realizeImplementation() - Unable to share OpenGL context", _traits->screenNum, ::GetLastError());
return false;
}
}
// if vysnc should be on then enable it.
if (_traits->vsync)
{
setSyncToVBlank(_traits->vsync);
}
}
@ -2164,6 +2171,36 @@ HCURSOR GraphicsWindowWin32::getOrCreateCursor(MouseCursor mouseCursor)
return _mouseCursorMap[mouseCursor];
}
void GraphicsWindowWin32::setSyncToVBlank( bool on )
{
if (_traits.valid())
{
_traits->vsync = on;
}
#if 0
// we ought to properly check if the extension is listed as supported rather than just
// if the function pointer resolves through wglGetProcAddress, but in practice everything
// supports this extension
typedef BOOL (APIENTRY *PFNWGLSWAPINTERVALFARPROC)( int );
PFNWGLSWAPINTERVALFARPROC wglSwapIntervalEXT = 0;
wglSwapIntervalEXT = (PFNWGLSWAPINTERVALFARPROC)wglGetProcAddress( "wglSwapIntervalEXT" );
if( wglSwapIntervalEXT )
{
int swapInterval = (on ? 1 : 0);
wglSwapIntervalEXT(swapInterval);
OSG_INFO << "GraphicsWindowWin32::setSyncToVBlank " << (on ? "on" : "off") << std::endl;
}
else
{
OSG_INFO << "GraphicsWindowWin32::setSyncToVBlank(bool) not supported" << std::endl;
}
#else
OSG_INFO << "GraphicsWindowWin32::setSyncToVBlank(bool) not yet implemented."<< std::endl;
#endf
}
void GraphicsWindowWin32::adaptKey( WPARAM wParam, LPARAM lParam, int& keySymbol, unsigned int& modifierMask )
{
modifierMask = 0;

View File

@ -1066,6 +1066,14 @@ void GraphicsWindowX11::swapBuffersImplementation()
eglSwapBuffers( _eglDisplay, _eglSurface );
checkEGLError("after eglSwapBuffers()");
#else
#if 0
if (_traits.valid() && _traits->vsync) {
unsigned int counter;
glXGetVideoSyncSGI(&counter);
glXWaitVideoSyncSGI(1, 0, &counter);
}
#endif
glXSwapBuffers( _display, _window );
#endif

View File

@ -211,13 +211,11 @@ Viewer::~Viewer()
{
//OSG_NOTIFY(osg::NOTICE)<<"Viewer::~Viewer()"<<std::endl;
Threads threads;
getAllThreads(threads);
OSG_NOTIFY(osg::INFO)<<"Viewer::~Viewer():: start destructor getThreads = "<<threads.size()<<std::endl;
stopThreading();
if (_scene.valid() && _scene->getDatabasePager())
@ -241,8 +239,7 @@ Viewer::~Viewer()
getAllThreads(threads);
OSG_NOTIFY(osg::INFO)<<"Viewer::~Viewer() end destrcutor getThreads = "<<threads.size()<<std::endl;
OSG_NOTIFY(osg::INFO)<<"Viewer::~Viewer() end destructor getThreads = "<<threads.size()<<std::endl;
}
void Viewer::take(View& rhs)