Files
OpenSceneGraph/src/osg/GraphicsThread.cpp
Robert Osfield 9d0c950bb0 From Colin McDonald, "Attached is an updated to osgViewer::PixelBufferWin32.
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().
"
2008-03-04 16:39:44 +00:00

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();
}