From Stephan Huber, "attached you'll find a first implementation of pbuffer-support for os x.

I used osgprerender --pbuffer to test the carbon-implementation, for now
it works :)
"
This commit is contained in:
Robert Osfield
2007-06-27 20:44:12 +00:00
parent eac3dc1963
commit 49c15572a9
4 changed files with 316 additions and 138 deletions

View File

@@ -0,0 +1,124 @@
/* -*-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.
*/
#ifndef OSGVIEWER_PIXELBUFFERCARBON
#define OSGVIEWER_PIXELBUFFERCARBON 1
#ifdef __APPLE__
#include <osg/GraphicsContext>
#include <osgViewer/Export>
#include <Carbon/Carbon.h>
#include <AGL/agl.h>
namespace osgViewer
{
class OSGVIEWER_EXPORT PixelBufferCarbon : public osg::GraphicsContext
{
public:
PixelBufferCarbon(osg::GraphicsContext::Traits* traits):
_valid(false),
_initialized(false),
_realized(false),
_pixelformat(0),
_pbuffer(0),
_context(0)
{
_traits = traits;
init();
if (valid())
{
setState( new osg::State );
getState()->setGraphicsContext(this);
if (_traits.valid() && _traits->sharedContext)
{
getState()->setContextID( _traits->sharedContext->getState()->getContextID() );
incrementContextIDUsageCount( getState()->getContextID() );
}
else
{
getState()->setContextID( osg::GraphicsContext::createNewContextID() );
}
}
}
virtual bool isSameKindAs(const Object* object) const { return dynamic_cast<const PixelBufferCarbon*>(object)!=0; }
virtual const char* libraryName() const { return "osgViewer"; }
virtual const char* className() const { return "PixelBufferCarbon"; }
virtual bool valid() const { return _valid; }
/** Realise the GraphicsContext.*/
virtual bool realizeImplementation();
/** Return true if the graphics context has been realised and is ready to use.*/
virtual bool isRealizedImplementation() const { return _realized; }
/** Close the graphics context.*/
virtual void closeImplementation();
/** Make this graphics context current.*/
virtual bool makeCurrentImplementation();
/** Make this graphics context current with specified read context implementation. */
virtual bool makeContextCurrentImplementation(osg::GraphicsContext* readContext);
/** Release the graphics context.*/
virtual bool releaseContextImplementation();
/** Bind the graphics context to associated texture implementation.*/
virtual void bindPBufferToTextureImplementation( GLenum buffer );
/** Swap the front and back buffers.*/
virtual void swapBuffersImplementation();
static AGLPixelFormat createPixelFormat(osg::GraphicsContext::Traits* traits);
AGLContext getAGLContext() { return _context; }
public:
protected:
~PixelBufferCarbon();
void init();
bool _valid;
bool _initialized;
bool _realized;
AGLPixelFormat _pixelformat;
AGLPbuffer _pbuffer;
AGLContext _context;
};
}
#endif
#endif

View File

@@ -48,8 +48,14 @@ ELSE(WIN32)
IF(APPLE)
# FIXME: OS X needs selection mechanism for Cocoa, Carbon, X11
SET(LIB_PUBLIC_HEADERS ${LIB_PUBLIC_HEADERS} ${HEADER_PATH}/api/Carbon/GraphicsWindowCarbon)
SET(LIB_COMMON_FILES ${LIB_COMMON_FILES} GraphicsWindowCarbon.cpp)
SET(LIB_PUBLIC_HEADERS ${LIB_PUBLIC_HEADERS}
${HEADER_PATH}/api/Carbon/GraphicsWindowCarbon
${HEADER_PATH}/api/Carbon/PixelBufferCarbon
)
SET(LIB_COMMON_FILES ${LIB_COMMON_FILES}
GraphicsWindowCarbon.cpp
PixelBufferCarbon.cpp
)
ELSE(APPLE)

View File

@@ -13,6 +13,7 @@
#ifdef __APPLE__
#include <osg/observer_ptr>
#include <osgViewer/api/Carbon/PixelBufferCarbon>
#include <osgViewer/api/Carbon/GraphicsWindowCarbon>
#include <Carbon/Carbon.h>
#include <OpenGL/OpenGL.h>
@@ -194,138 +195,8 @@ static unsigned int remapOSXKey(unsigned int key, unsigned int rawkey)
return s_OSXKeyboardMap.remapKey(key,rawkey);
}
/** creates a pixelformat from a Trait */
static AGLPixelFormat createPixelFormat(osg::GraphicsContext::Traits* traits) {
std::vector<GLint> attributes;
if (!traits->pbuffer) attributes.push_back(AGL_NO_RECOVERY);
attributes.push_back(AGL_RGBA);
if (!traits->pbuffer) attributes.push_back(AGL_COMPLIANT);
if (traits->doubleBuffer) attributes.push_back(AGL_DOUBLEBUFFER);
if (traits->quadBufferStereo) attributes.push_back(AGL_STEREO);
attributes.push_back(AGL_RED_SIZE); attributes.push_back(traits->red);
attributes.push_back(AGL_GREEN_SIZE); attributes.push_back(traits->green);
attributes.push_back(AGL_BLUE_SIZE); attributes.push_back(traits->blue);
attributes.push_back(AGL_DEPTH_SIZE); attributes.push_back(traits->depth);
if (traits->alpha) { attributes.push_back(AGL_ALPHA_SIZE); attributes.push_back(traits->alpha); }
if (traits->stencil) { attributes.push_back(AGL_STENCIL_SIZE); attributes.push_back(traits->stencil); }
// TODO
// missing accumulation-buffer-stuff
#if defined(AGL_SAMPLE_BUFFERS_ARB) && defined (AGL_SAMPLES_ARB)
if (traits->sampleBuffers) { attributes.push_back(AGL_SAMPLE_BUFFERS_ARB); attributes.push_back(traits->sampleBuffers); }
if (traits->sampleBuffers) { attributes.push_back(AGL_SAMPLES_ARB); attributes.push_back(traits->samples); }
#endif
attributes.push_back(AGL_NONE);
return aglChoosePixelFormat(NULL, 0, &(attributes.front()));
}
#pragma mark * * * GraphicsContextCarbon * * *
/** This is the class we need to create for pbuffers, note its not a GraphicsWindow as it won't need any of the event handling and window mapping facilities.*/
class GraphicsContextCarbon : public osg::GraphicsContext
{
public:
GraphicsContextCarbon(osg::GraphicsContext::Traits* traits):
_valid(false),
_realized(false),
_context(NULL)
{
_traits = traits;
_valid = true;
}
virtual bool valid() const { return _valid; }
/** Realise the GraphicsContext implementation,
* Pure virtual - must be implemented by concrate implementations of GraphicsContext. */
virtual bool realizeImplementation()
{
AGLPixelFormat pixelformat = createPixelFormat(_traits.get());
if (!pixelformat) {
osg::notify(osg::WARN) << "GraphicsContext::realizeImplementation() aglChoosePixelFormat failed! " << aglErrorString(aglGetError()) << std::endl;
return false;
}
_context = aglCreateContext (pixelformat, NULL);
if (!_context) {
osg::notify(osg::WARN) << "GraphicsContext::realizeImplementation() aglCreateContext failed! " << aglErrorString(aglGetError()) << std::endl;
return false;
}
aglDestroyPixelFormat(pixelformat);
_realized = aglCreatePBuffer (_traits->width, _traits->height, _traits->target, GL_RGBA, _traits->level, &(_pbuffer));
if (!_realized) {
osg::notify(osg::WARN) << "GraphicsContext::realizeImplementation() aglCreatePBuffer failed! " << aglErrorString(aglGetError()) << std::endl;
}
return _realized;
}
/** Return true if the graphics context has been realised, and is ready to use, implementation.
* Pure virtual - must be implemented by concrate implementations of GraphicsContext. */
virtual bool isRealizedImplementation() const { return _realized; }
/** Close the graphics context implementation.
* Pure virtual - must be implemented by concrate implementations of GraphicsContext. */
virtual void closeImplementation()
{
if (_pbuffer) aglDestroyPBuffer(_pbuffer);
if (_context) aglDestroyContext(_context);
_valid = _realized = false;
}
/** Make this graphics context current implementation.
* Pure virtual - must be implemented by concrate implementations of GraphicsContext. */
virtual bool makeCurrentImplementation()
{
return (_realized) ? (aglSetCurrentContext(_context) == GL_TRUE) : false;
}
/** Make this graphics context current with specified read context implementation.
* Pure virtual - must be implemented by concrate implementations of GraphicsContext. */
virtual bool makeContextCurrentImplementation(GraphicsContext* /*readContext*/) { osg::notify(osg::NOTICE)<<"GraphicsWindow::makeContextCurrentImplementation(..) not implemented."<<std::endl; return false;}
/** Release the graphics context.*/
virtual bool releaseContextImplementation()
{
return (aglSetCurrentContext(NULL) == GL_TRUE);
}
/** Pure virtual, Bind the graphics context to associated texture implementation.
* Pure virtual - must be implemented by concrate implementations of GraphicsContext. */
virtual void bindPBufferToTextureImplementation(GLenum /*buffer*/) { osg::notify(osg::NOTICE)<<"GraphicsWindow::void bindPBufferToTextureImplementation(..) not implemented."<<std::endl; }
/** Swap the front and back buffers implementation.
* Pure virtual - must be implemented by Concrate implementations of GraphicsContext. */
virtual void swapBuffersImplementation()
{
aglSwapBuffers(_context);
}
protected:
bool _valid;
bool _realized;
AGLContext _context;
AGLPbuffer _pbuffer;
};
#pragma mark * * * MenubarController * * *
@@ -575,7 +446,7 @@ struct OSXCarbonWindowingSystemInterface : public osg::GraphicsContext::Windowin
{
if (traits->pbuffer)
{
osg::ref_ptr<osgViewer::GraphicsContextCarbon> pbuffer = new GraphicsContextCarbon(traits);
osg::ref_ptr<osgViewer::PixelBufferCarbon> pbuffer = new PixelBufferCarbon(traits);
if (pbuffer->valid()) return pbuffer.release();
else return 0;
}
@@ -609,7 +480,7 @@ void GraphicsWindowCarbon::init()
_ownsWindow = false;
_context = NULL;
_window = NULL;
_pixelFormat = createPixelFormat(_traits.get());
_pixelFormat = PixelBufferCarbon::createPixelFormat(_traits.get());
if (!_pixelFormat)
osg::notify(osg::WARN) << "GraphicsWindowCarbon::init could not create a valid pixelformat" << std::endl;
_valid = (_pixelFormat != NULL);
@@ -763,15 +634,21 @@ bool GraphicsWindowCarbon::realizeImplementation()
}
// create the context
GraphicsWindowCarbon* sharedContextCarbon = dynamic_cast<GraphicsWindowCarbon*>(_traits->sharedContext);
if (sharedContextCarbon)
AGLContext sharedContextCarbon = NULL;
GraphicsWindowCarbon* graphicsWindowCarbon = dynamic_cast<GraphicsWindowCarbon*>(_traits->sharedContext);
if (graphicsWindowCarbon)
{
_context = aglCreateContext (_pixelFormat, sharedContextCarbon->getAGLContext());
sharedContextCarbon = graphicsWindowCarbon->getAGLContext();
}
else
{
_context = aglCreateContext (_pixelFormat, NULL);
PixelBufferCarbon* pixelbuffer = dynamic_cast<PixelBufferCarbon*>(_traits->sharedContext);
if (pixelbuffer) {
sharedContextCarbon = pixelbuffer->getAGLContext();
}
}
_context = aglCreateContext (_pixelFormat, sharedContextCarbon);
if (!_context) {

View File

@@ -0,0 +1,171 @@
/*
* PixelBufferCarbon.cpp
* OpenSceneGraph
*
* Created by Stephan Huber on 27.06.07.
* Copyright 2007 __MyCompanyName__. All rights reserved.
*
*/
#ifdef __APPLE__
#include <osg/observer_ptr>
#include <osgViewer/api/Carbon/PixelBufferCarbon>
#include <osgViewer/api/Carbon/GraphicsWindowCarbon>
#include <Carbon/Carbon.h>
#include <OpenGL/OpenGL.h>
using namespace osgViewer;
/** creates a pixelformat from a Trait */
AGLPixelFormat PixelBufferCarbon::createPixelFormat(osg::GraphicsContext::Traits* traits) {
std::vector<GLint> attributes;
attributes.push_back(AGL_NO_RECOVERY);
attributes.push_back(AGL_RGBA);
if (!traits->pbuffer)
attributes.push_back(AGL_COMPLIANT);
else
attributes.push_back(AGL_CLOSEST_POLICY);
if (traits->doubleBuffer) attributes.push_back(AGL_DOUBLEBUFFER);
if (traits->quadBufferStereo) attributes.push_back(AGL_STEREO);
attributes.push_back(AGL_RED_SIZE); attributes.push_back(traits->red);
attributes.push_back(AGL_GREEN_SIZE); attributes.push_back(traits->green);
attributes.push_back(AGL_BLUE_SIZE); attributes.push_back(traits->blue);
attributes.push_back(AGL_DEPTH_SIZE); attributes.push_back(traits->depth);
if (traits->alpha) { attributes.push_back(AGL_ALPHA_SIZE); attributes.push_back(traits->alpha); }
if (traits->stencil) { attributes.push_back(AGL_STENCIL_SIZE); attributes.push_back(traits->stencil); }
// TODO
// missing accumulation-buffer-stuff
#if defined(AGL_SAMPLE_BUFFERS_ARB) && defined (AGL_SAMPLES_ARB)
if (traits->sampleBuffers) { attributes.push_back(AGL_SAMPLE_BUFFERS_ARB); attributes.push_back(traits->sampleBuffers); }
if (traits->sampleBuffers) { attributes.push_back(AGL_SAMPLES_ARB); attributes.push_back(traits->samples); }
#endif
attributes.push_back(AGL_NONE);
return aglChoosePixelFormat(NULL, 0, &(attributes.front()));
}
void PixelBufferCarbon::init()
{
_context = NULL;
_pixelformat = PixelBufferCarbon::createPixelFormat(_traits.get());
if (!_pixelformat)
osg::notify(osg::WARN) << "PixelBufferCarbon::init could not create a valid pixelformat" << std::endl;
_valid = (_pixelformat != NULL);
}
/** This is the class we need to create for pbuffers, note its not a GraphicsWindow as it won't need any of the event handling and window mapping facilities.*/
/** Realise the GraphicsContext implementation,
* Pure virtual - must be implemented by concrate implementations of GraphicsContext. */
bool PixelBufferCarbon::realizeImplementation()
{
if (!_valid) {
osg::notify(osg::WARN) << "PixelBufferCarbon::realizeImplementation() aglChoosePixelFormat failed! " << aglErrorString(aglGetError()) << std::endl;
return false;
}
AGLContext sharedContext = NULL;
// get any shared GLX contexts
GraphicsWindowCarbon* graphicsWindowCarbon = dynamic_cast<GraphicsWindowCarbon*>(_traits->sharedContext);
if (graphicsWindowCarbon)
{
sharedContext = graphicsWindowCarbon->getAGLContext();
}
else
{
PixelBufferCarbon* pixelBufferCarbon = dynamic_cast<PixelBufferCarbon*>(_traits->sharedContext);
if (pixelBufferCarbon)
{
sharedContext = pixelBufferCarbon->getAGLContext();
}
}
_context = aglCreateContext (_pixelformat, sharedContext);
if (!_context) {
osg::notify(osg::WARN) << "PixelBufferCarbon::realizeImplementation() aglCreateContext failed! " << aglErrorString(aglGetError()) << std::endl;
return false;
}
_realized = aglCreatePBuffer (_traits->width, _traits->height, _traits->target, GL_RGBA, _traits->level, &(_pbuffer));
if (!_realized) {
osg::notify(osg::WARN) << "PixelBufferCarbon::realizeImplementation() aglCreatePBuffer failed! " << aglErrorString(aglGetError()) << std::endl;
}
makeCurrentImplementation();
_realized = aglSetPBuffer(_context, _pbuffer, _traits->face, _traits->level, 0);
if (!_realized) {
osg::notify(osg::WARN) << "PixelBufferCarbon::realizeImplementation() aglSetPBuffer failed! " << aglErrorString(aglGetError()) << std::endl;
}
return _realized;
}
void PixelBufferCarbon::closeImplementation()
{
if (_pbuffer) aglDestroyPBuffer(_pbuffer);
if (_context) aglDestroyContext(_context);
if (_pixelformat) aglDestroyPixelFormat(_pixelformat);
_valid = _realized = false;
}
/** Make this graphics context current implementation.
* Pure virtual - must be implemented by concrate implementations of GraphicsContext. */
bool PixelBufferCarbon::makeCurrentImplementation()
{
return (_realized) ? (aglSetCurrentContext(_context) == GL_TRUE) : false;
}
/** Make this graphics context current with specified read context implementation.
* Pure virtual - must be implemented by concrate implementations of GraphicsContext. */
bool PixelBufferCarbon::makeContextCurrentImplementation(GraphicsContext* /*readContext*/) {
return makeCurrentImplementation();
}
/** Release the graphics context.*/
bool PixelBufferCarbon::releaseContextImplementation()
{
return (aglSetCurrentContext(NULL) == GL_TRUE);
}
/** Pure virtual, Bind the graphics context to associated texture implementation.
* Pure virtual - must be implemented by concrate implementations of GraphicsContext. */
void PixelBufferCarbon::bindPBufferToTextureImplementation( GLenum buffer ){
osg::notify(osg::NOTICE)<<"GraphicsWindow::void bindPBufferToTextureImplementation(..) not implemented."<<std::endl;
}
/** Swap the front and back buffers implementation.
* Pure virtual - must be implemented by Concrate implementations of GraphicsContext. */
void PixelBufferCarbon::swapBuffersImplementation()
{
aglSwapBuffers(_context);
}
PixelBufferCarbon::~PixelBufferCarbon()
{
close(true);
}
#endif