diff --git a/include/osgViewer/api/Carbon/PixelBufferCarbon b/include/osgViewer/api/Carbon/PixelBufferCarbon new file mode 100644 index 000000000..d47522229 --- /dev/null +++ b/include/osgViewer/api/Carbon/PixelBufferCarbon @@ -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 +#include + +#include +#include + + +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(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 diff --git a/src/osgViewer/CMakeLists.txt b/src/osgViewer/CMakeLists.txt index e61e75289..10778a006 100644 --- a/src/osgViewer/CMakeLists.txt +++ b/src/osgViewer/CMakeLists.txt @@ -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) diff --git a/src/osgViewer/GraphicsWindowCarbon.cpp b/src/osgViewer/GraphicsWindowCarbon.cpp index 438888e0a..c50ac6a66 100644 --- a/src/osgViewer/GraphicsWindowCarbon.cpp +++ b/src/osgViewer/GraphicsWindowCarbon.cpp @@ -13,6 +13,7 @@ #ifdef __APPLE__ #include +#include #include #include #include @@ -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 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."<pbuffer) { - osg::ref_ptr pbuffer = new GraphicsContextCarbon(traits); + osg::ref_ptr 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(_traits->sharedContext); - if (sharedContextCarbon) + AGLContext sharedContextCarbon = NULL; + + GraphicsWindowCarbon* graphicsWindowCarbon = dynamic_cast(_traits->sharedContext); + if (graphicsWindowCarbon) { - _context = aglCreateContext (_pixelFormat, sharedContextCarbon->getAGLContext()); + sharedContextCarbon = graphicsWindowCarbon->getAGLContext(); } else { - _context = aglCreateContext (_pixelFormat, NULL); + PixelBufferCarbon* pixelbuffer = dynamic_cast(_traits->sharedContext); + if (pixelbuffer) { + sharedContextCarbon = pixelbuffer->getAGLContext(); + } } + _context = aglCreateContext (_pixelFormat, sharedContextCarbon); if (!_context) { diff --git a/src/osgViewer/PixelBufferCarbon.cpp b/src/osgViewer/PixelBufferCarbon.cpp new file mode 100644 index 000000000..cf3f0d285 --- /dev/null +++ b/src/osgViewer/PixelBufferCarbon.cpp @@ -0,0 +1,171 @@ +/* + * PixelBufferCarbon.cpp + * OpenSceneGraph + * + * Created by Stephan Huber on 27.06.07. + * Copyright 2007 __MyCompanyName__. All rights reserved. + * + */ + + #ifdef __APPLE__ + +#include +#include +#include +#include +#include +using namespace osgViewer; + + + + +/** creates a pixelformat from a Trait */ +AGLPixelFormat PixelBufferCarbon::createPixelFormat(osg::GraphicsContext::Traits* traits) { + + std::vector 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(_traits->sharedContext); + if (graphicsWindowCarbon) + { + sharedContext = graphicsWindowCarbon->getAGLContext(); + } + else + { + PixelBufferCarbon* pixelBufferCarbon = dynamic_cast(_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."<