The win32 pbuffer implementation returned an error unless both the WGL_ARB_pbuffer and the WGL_ARB_render_texture functions were present. This was too restrictive, as a pbuffer can usefully be created without render-to-texture, e.g. for use with glReadPixels. The osg 1.2/Producer pbuffers worked without RTT, and osgUtil::RenderStage has all the code to handle both RTT and non-RTT pbuffers, doing a read and copy in the latter case. With these changes I have successfully tested the osgprerender example on a graphics card which supports RTT, and one which doesn't. Plus tested in my own application. In order to aid diagnostics I have also added more function status return checks, and associated error messages. I have included the win32 error text in all error messages output. And there were some errors with multi-threaded handling of "bind to texture" and a temporary window context which I have corrected. These is one (pre-existing) problem with multi-threaded use of pbuffers in osgViewer & osgprerender, which I have not been able to fix. A win32 device context (HDC) can only be destroyed from the thread that created it. The pbuffers for pre-render cameras are created in osgUtil::RenderStage::runCameraSetUp, from the draw thread. But closeImplementation is normally invoked from the destructor in the main application thread. With the additional error messages I have added, osgprerender will now output a couple of warnings from osgViewer::PixelBufferWin32::closeImplementation() at exit, after running multi-threaded on windows. I think that is a good thing, to highlight the problem. I looked into fixing it in osgViewer::Renderer & osgUtil::RenderStage, but it was too involved for me. My own application requirements are only single-threaded. Unrelated fix - an uninitialised variable in osg::GraphicsThread::FlushDeletedGLObjectsOperation(). "
151 lines
3.6 KiB
C++
151 lines
3.6 KiB
C++
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
|
|
*
|
|
* This library is open source and may be redistributed and/or modified under
|
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
|
* (at your option) any later version. The full license is in LICENSE file
|
|
* included with this distribution, and on the openscenegraph.org website.
|
|
*
|
|
* This library 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
|
|
* OpenSceneGraph Public License for more details.
|
|
*/
|
|
|
|
|
|
#include <osg/GraphicsThread>
|
|
#include <osg/GraphicsContext>
|
|
#include <osg/GLObjects>
|
|
#include <osg/Notify>
|
|
|
|
using namespace osg;
|
|
using namespace OpenThreads;
|
|
|
|
GraphicsThread::GraphicsThread()
|
|
{
|
|
}
|
|
|
|
void GraphicsThread::run()
|
|
{
|
|
// make the graphics context current.
|
|
GraphicsContext* graphicsContext = dynamic_cast<GraphicsContext*>(_parent.get());
|
|
if (graphicsContext)
|
|
{
|
|
graphicsContext->makeCurrent();
|
|
|
|
graphicsContext->getState()->initializeExtensionProcs();
|
|
}
|
|
|
|
OperationThread::run();
|
|
|
|
if (graphicsContext)
|
|
{
|
|
graphicsContext->releaseContext();
|
|
}
|
|
|
|
}
|
|
|
|
void GraphicsOperation::operator () (Object* object)
|
|
{
|
|
osg::GraphicsContext* context = dynamic_cast<osg::GraphicsContext*>(object);
|
|
if (context) operator() (context);
|
|
}
|
|
|
|
void SwapBuffersOperation::operator () (GraphicsContext* context)
|
|
{
|
|
context->swapBuffersImplementation();
|
|
context->clear();
|
|
}
|
|
|
|
void BarrierOperation::release()
|
|
{
|
|
Barrier::release();
|
|
}
|
|
|
|
void BarrierOperation::operator () (Object* object)
|
|
{
|
|
if (_preBlockOp!=NO_OPERATION)
|
|
{
|
|
if (_preBlockOp==GL_FLUSH) glFlush();
|
|
else if (_preBlockOp==GL_FINISH) glFinish();
|
|
}
|
|
|
|
block();
|
|
}
|
|
|
|
void ReleaseContext_Block_MakeCurrentOperation::release()
|
|
{
|
|
Block::release();
|
|
}
|
|
|
|
|
|
void ReleaseContext_Block_MakeCurrentOperation::operator () (GraphicsContext* context)
|
|
{
|
|
// release the graphics context.
|
|
context->releaseContext();
|
|
|
|
// reset the block so that it the next call to block()
|
|
reset();
|
|
|
|
// block this thread, until the block is released externally.
|
|
block();
|
|
|
|
// re acquire the graphics context.
|
|
context->makeCurrent();
|
|
}
|
|
|
|
|
|
BlockAndFlushOperation::BlockAndFlushOperation():
|
|
GraphicsOperation("Block",false)
|
|
{
|
|
reset();
|
|
}
|
|
|
|
void BlockAndFlushOperation::release()
|
|
{
|
|
Block::release();
|
|
}
|
|
|
|
void BlockAndFlushOperation::operator () (GraphicsContext*)
|
|
{
|
|
glFlush();
|
|
Block::release();
|
|
}
|
|
|
|
FlushDeletedGLObjectsOperation::FlushDeletedGLObjectsOperation(double availableTime, bool keep):
|
|
GraphicsOperation("FlushDeletedGLObjectsOperation",keep),
|
|
_availableTime(availableTime)
|
|
{
|
|
}
|
|
|
|
void FlushDeletedGLObjectsOperation::operator () (GraphicsContext* context)
|
|
{
|
|
State* state = context->getState();
|
|
unsigned int contextID = state ? state->getContextID() : 0;
|
|
const FrameStamp* frameStamp = state ? state->getFrameStamp() : 0;
|
|
double currentTime = frameStamp ? frameStamp->getReferenceTime() : 0.0;
|
|
double availableTime = _availableTime;
|
|
|
|
flushDeletedGLObjects(contextID, currentTime, availableTime);
|
|
}
|
|
|
|
|
|
void RunOperations::operator () (osg::GraphicsContext* context)
|
|
{
|
|
context->runOperations();
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// EndOfDynamicDrawBlock
|
|
//
|
|
EndOfDynamicDrawBlock::EndOfDynamicDrawBlock(unsigned int numberOfBlocks):
|
|
BlockCount(numberOfBlocks)
|
|
{
|
|
}
|
|
|
|
void EndOfDynamicDrawBlock::completed(osg::State* /*state*/)
|
|
{
|
|
BlockCount::completed();
|
|
}
|