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:
124
include/osgViewer/api/Carbon/PixelBufferCarbon
Normal file
124
include/osgViewer/api/Carbon/PixelBufferCarbon
Normal 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
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
171
src/osgViewer/PixelBufferCarbon.cpp
Normal file
171
src/osgViewer/PixelBufferCarbon.cpp
Normal 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
|
||||
Reference in New Issue
Block a user