/* -*-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 OSG_GRAPHICSCONTEXT #define OSG_GRAPHICSCONTEXT 1 #include #include namespace osg { /** Base class for providing Windowing API agnostic access to creating and managing graphics context.*/ class OSG_EXPORT GraphicsContext : public Referenced { public: struct OSG_EXPORT ScreenIdentifier { ScreenIdentifier(): displayNum(0), screenNum(0) {} ScreenIdentifier(unsigned int in_screenNum): displayNum(0), screenNum(in_screenNum) {} ScreenIdentifier(const std::string& in_hostName,unsigned int in_displayNum, unsigned int in_screenNum): hostName(in_hostName), displayNum(in_displayNum), screenNum(in_screenNum) {} std::string displayName() const; std::string hostName; unsigned int displayNum; unsigned int screenNum; }; /** GraphicsContext Traits object provides the specification of what type of graphics context is required.*/ struct Traits : public osg::Referenced, public ScreenIdentifier { Traits(): x(0), y(0), width(0), height(0), windowDecoration(false), supportsResize(false), red(8), blue(8), green(8), alpha(0), depth(24), stencil(0), sampleBuffers(0), samples(0), pbuffer(false), quadBufferStereo(false), doubleBuffer(false), target(0), level(0), face(0), mipMapGeneration(false), sharedContext(0) {} // graphics context orginal and size unsigned int x; unsigned int y; unsigned int width; unsigned int height; // window decoration and baviour std::string windowName; bool windowDecoration; bool supportsResize; // buffer depths, 0 equals off. unsigned int red; unsigned int blue; unsigned int green; unsigned int alpha; unsigned int depth; unsigned int stencil; // multi sample parameters unsigned int sampleBuffers; unsigned int samples; // buffer configuration bool pbuffer; bool quadBufferStereo; bool doubleBuffer; // render to texture GLenum target; unsigned int level; unsigned int face; unsigned int mipMapGeneration; // shared context GraphicsContext* sharedContext; }; /** Callback to be implemented to provide access to Windowing API's ability to create Windows/pbuffers.*/ struct WindowingSystemInterface : public osg::Referenced { virtual unsigned int getNumScreens(const ScreenIdentifier& screenIdentifier = ScreenIdentifier()) = 0; virtual void getScreenResolution(const ScreenIdentifier& screenIdentifier, unsigned int& width, unsigned int& height) = 0; virtual GraphicsContext* createGraphicsContext(Traits* traits) = 0; virtual ~WindowingSystemInterface() {}; }; /** Set the querry the windowing system for screens and create graphics context - this functor should be supplied by the windows toolkit. */ static void setWindowingSystemInterface(WindowingSystemInterface* wsInterface); /** Get the WindowingSystemInterface*/ static WindowingSystemInterface* getWindowingSystemInterface(); /** Create a graphics context for a specified set of traits.*/ static GraphicsContext* createGraphicsContext(Traits* traits); /** Create a contextID for a new graphics context, this contextID is used to set up the osg::State associate with context. * Automatically increments the usage count of the contextID to 1.*/ static unsigned int createNewContextID(); /** Increment the usage count associate with a contextID. The usage count speficies how many graphics contexts a specific contextID is shared between.*/ static void incrementContextIDUsageCount(unsigned int contextID); /** Decrement the usage count associate with a contextID. Once the contextID goes to 0 the contextID is then free to be reused.*/ static void decrementContextIDUsageCount(unsigned int contextID); public: /** Add operation to end of OperationQueue.*/ void add(GraphicsOperation* operation); /** Remove operation from OperationQueue.*/ void remove(GraphicsOperation* operation); /** Remove named operation from OperationQueue.*/ void remove(const std::string& name); /** Remove all operations from OperationQueue.*/ void removeAllOperations(); /** Run the operations. */ void runOperations(); public: /** Get the traits of the GraphicsContext.*/ inline const Traits* getTraits() const { return _traits.get(); } /** Set the State object which tracks the current OpenGL state for this graphics context.*/ inline void setState(State* state) { _state = state; } /** Get the State object which tracks the current OpenGL state for this graphics context.*/ inline State* getState() { return _state.get(); } /** Get the const State object which tracks the current OpenGL state for this graphics context.*/ inline const State* getState() const { return _state.get(); } /** Return whether a valid and usable GraphicsContext has been created.*/ virtual bool valid() const { return false; } /** Realise the GraphicsContext.*/ bool realize(); /** close the graphics context. * close(bool) stops any associated graphics threads, releases the contextID for the GraphicsContext then * optional calls closeImplementation() to do the actual deletion of the graphics. This call is made optional * as there are times when the graphics context has already been deleted externally and only the OSG side * of the its data need to be closed down. */ void close(bool callCloseImplementation=true); /** swap the front and back buffers.*/ void swapBuffers(); /** Return true if the graphics context has been realised and is ready to use.*/ inline bool isRealized() const { return isRealizedImplementation(); } /** Make this graphics context current. * Implementated by first aquiring a lock of the GraphicsContext mutex, and then doing a call to makeCurrentImplementation(). */ void makeCurrent(); /** Make this graphics context current with specified read context. * Implementated by first aquiring a lock of the GraphicsContext mutex, and then doing a call to makeContextCurrentImplementation(). */ void makeContextCurrent(GraphicsContext* readContext); /** Release the graphics context by unlocking the GraphicsContext mutex.*/ void releaseContext(); /** Return true if the current thread has this OpenGL graphics context.*/ inline bool isCurrent() const { return _threadOfLastMakeCurrent == OpenThreads::Thread::CurrentThread(); } /** Bind the graphics context to associated texture.*/ inline void bindPBufferToTexture(GLenum buffer) { bindPBufferToTextureImplementation(buffer); } /** Create a graphics thread to the graphics context, so that the thread handles all OpenGL operations.*/ void createGraphicsThread(); /** Assign a graphics thread to the graphics context, so that the thread handles all OpenGL operations.*/ void setGraphicsThread(GraphicsThread* gt); /** Get the graphics thread assigned the graphics context.*/ GraphicsThread* getGraphicsThread() { return _graphicsThread.get(); } /** Get the const graphics thread assigned the graphics context.*/ const GraphicsThread* getGraphicsThread() const { return _graphicsThread.get(); } /** Realise the GraphicsContext implementation, * Pure virtual - must be implemented by concrate implementations of GraphicsContext. */ virtual bool realizeImplementation() = 0; /** 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 = 0; /** Close the graphics context implementation. * Pure virtual - must be implemented by concrate implementations of GraphicsContext. */ virtual void closeImplementation() = 0; /** Make this graphics context current implementation. * Pure virtual - must be implemented by concrate implementations of GraphicsContext. */ virtual void makeCurrentImplementation() = 0; /** Make this graphics context current with specified read context implementation. * Pure virtual - must be implemented by concrate implementations of GraphicsContext. */ virtual void makeContextCurrentImplementation(GraphicsContext* readContext) = 0; /** 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) = 0; /** Swap the front and back buffers implementation. * Pure virtual - must be implemented by Concrate implementations of GraphicsContext. */ virtual void swapBuffersImplementation() = 0; protected: GraphicsContext(); virtual ~GraphicsContext(); ref_ptr _traits; ref_ptr _state; OpenThreads::Mutex _mutex; OpenThreads::Thread* _threadOfLastMakeCurrent; typedef std::list< ref_ptr > OperationQueue; OpenThreads::Mutex _operationsMutex; osg::ref_ptr _operationsBlock; OperationQueue _operations; osg::ref_ptr _currentOperation; ref_ptr _graphicsThread; }; } #endif