1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version. The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * OpenSceneGraph Public License for more details.
14#ifndef OSG_GRAPHICSCONTEXT
15#define OSG_GRAPHICSCONTEXT 1
18#include <osg/GraphicsThread>
25// forward declare osg::Camera
28/** Base class for providing Windowing API agnostic access to creating and managing graphics context.*/
29class OSG_EXPORT GraphicsContext : public Object
33 struct OSG_EXPORT ScreenIdentifier
37 ScreenIdentifier(int in_screenNum);
39 ScreenIdentifier(const std::string& in_hostName,int in_displayNum, int in_screenNum);
41 /** Return the display name in the form hostName::displayNum:screenNum. */
42 std::string displayName() const;
44 /** Read the DISPLAY environmental variable, and set the ScreenIdentifier accordingly.
45 * Note, if either of displayNum or screenNum are not defined then -1 is set respectively to
46 * signify that this parameter has not been set. When parameters are undefined one can call
47 * call setUndefinedScreenDetailsToDefaultScreen() after readDISPLAY() to ensure valid values. */
50 /** Set the screenIndentifier from the displayName string.
51 * Note, if either of displayNum or screenNum are not defined then -1 is set to
52 * signify that this parameter has not been set. When parameters are undefined one can call
53 * call setUndefinedScreenDetailsToDefaultScreen() after readDISPLAY() to ensure valid values. */
54 void setScreenIdentifier(const std::string& displayName);
56 /** Set any undefined displayNum or screenNum values (i.e. -1) to the default display & screen of 0 respectively.*/
57 void setUndefinedScreenDetailsToDefaultScreen()
59 if (displayNum<0) displayNum = 0;
60 if (screenNum<0) screenNum = 0;
68 /** GraphicsContext Traits object provides the specification of what type of graphics context is required.*/
69 struct OSG_EXPORT Traits : public osg::Referenced, public ScreenIdentifier
71 Traits(DisplaySettings* ds=0);
73 // graphics context original and size
79 // provide a hint as to which WindowingSystemInterface implementation to use, i.e. "X11", "Win32", "Cocoa", "Carbon" etc.
80 // if the windowingSystemPreference string is empty (default) then return the first available WindowingSystemInterface that
81 // has been registered with the osg::GraphiccsContext::WindowingSystemInterfaces singleton
82 // if the windowingSystemPreference string is not empty then return the first WindowingSystemInterface that matches
83 std::string windowingSystemPreference;
85 // window decoration and behaviour
86 std::string windowName;
87 bool windowDecoration;
90 // buffer depths, 0 equals off.
98 // multi sample parameters
99 unsigned int sampleBuffers;
100 unsigned int samples;
102 // buffer configuration
104 bool quadBufferStereo;
112 unsigned int mipMapGeneration;
118 bool swapGroupEnabled;
122 // use multithreaded OpenGL-engine (OS X only)
123 bool useMultiThreadedOpenGLEngine;
128 // settings used in set up of graphics context, only presently used by GL3 build of OSG.
129 std::string glContextVersion;
130 unsigned int glContextFlags;
131 unsigned int glContextProfileMask;
133 /** return true if glContextVersion is set in the form major.minor, and assign the appropriate major and minor values to the associated parameters.*/
134 bool getContextVersion(unsigned int& major, unsigned int& minor) const;
137 osg::observer_ptr<GraphicsContext> sharedContext;
139 osg::ref_ptr<osg::Referenced> inheritedWindowData;
141 // ask the GraphicsWindow implementation to set the pixel format of an inherited window
142 bool setInheritedWindowPixelFormat;
144 // X11 hint whether to override the window managers window size/position redirection
145 bool overrideRedirect;
147 DisplaySettings::SwapMethod swapMethod;
149 // hint of what affinity to use for any thrads associated with the graphics context created using these Traits
150 OpenThreads::Affinity affinity;
153 /** Simple resolution structure used by WindowingSystemInterface to get and set screen resolution.
154 * Note the '0' value stands for 'unset'. */
155 struct ScreenSettings {
163 ScreenSettings(int in_width, int in_height, double in_refreshRate=0, unsigned int in_colorDepth=0) :
166 refreshRate(in_refreshRate),
167 colorDepth(in_colorDepth)
172 double refreshRate; ///< Screen refresh rate, in Hz.
173 unsigned int colorDepth; ///< RGB(A) color buffer depth.
176 typedef std::vector<ScreenSettings> ScreenSettingsList;
178 /** Callback to be implemented to provide access to Windowing API's ability to create Windows/pbuffers.*/
179 struct WindowingSystemInterface : public osg::Referenced
181 void setName(const std::string& name) { _name = name; }
182 const std::string& getName() const { return _name; }
184 virtual unsigned int getNumScreens(const ScreenIdentifier& screenIdentifier = ScreenIdentifier()) = 0;
186 virtual void getScreenSettings(const ScreenIdentifier& screenIdentifier, ScreenSettings & resolution) = 0;
188 virtual bool setScreenSettings(const ScreenIdentifier& /*screenIdentifier*/, const ScreenSettings & /*resolution*/) { return false; }
190 virtual void enumerateScreenSettings(const ScreenIdentifier& screenIdentifier, ScreenSettingsList & resolutionList) = 0;
192 virtual void setDisplaySettings(DisplaySettings*) {}
194 virtual osg::DisplaySettings* getDisplaySettings() const { return 0; }
196 virtual GraphicsContext* createGraphicsContext(Traits* traits) = 0;
198 /** Gets screen resolution without using the ScreenResolution structure.
199 * \deprecated Provided only for backward compatibility. */
200 inline void getScreenResolution(const ScreenIdentifier& screenIdentifier, unsigned int& width, unsigned int& height)
202 ScreenSettings settings;
203 getScreenSettings(screenIdentifier, settings);
204 width = settings.width;
205 height = settings.height;
208 /** Sets screen resolution without using the ScreenSettings structure.
209 * \deprecated Provided only for backward compatibility. */
210 inline bool setScreenResolution(const ScreenIdentifier& screenIdentifier, unsigned int width, unsigned int height)
212 return setScreenSettings(screenIdentifier, ScreenSettings(width, height));
215 /** \deprecated Provided only for backward compatibility. */
216 inline bool setScreenRefreshRate(const ScreenIdentifier& screenIdentifier, double refreshRate)
218 ScreenSettings settings;
219 getScreenSettings(screenIdentifier, settings);
220 settings.refreshRate = refreshRate;
221 return setScreenSettings(screenIdentifier, settings);
224 WindowingSystemInterface() {}
225 virtual ~WindowingSystemInterface() {}
230 class OSG_EXPORT WindowingSystemInterfaces : public osg::Referenced
233 WindowingSystemInterfaces();
235 typedef std::vector< osg::ref_ptr<GraphicsContext::WindowingSystemInterface> > Interfaces;
237 Interfaces& getInterfaces() { return _interfaces; }
239 void addWindowingSystemInterface(WindowingSystemInterface* wsInterface);
241 void removeWindowingSystemInterface(WindowingSystemInterface* wsInterface);
243 /** get named WindowingSystemInterface if one is available, otherwise return 0; */
244 WindowingSystemInterface* getWindowingSystemInterface(const std::string& name = "");
247 virtual ~WindowingSystemInterfaces();
248 Interfaces _interfaces;
251 static osg::ref_ptr<WindowingSystemInterfaces>& getWindowingSystemInterfaces();
253 /** Get the default WindowingSystemInterface for this OS*/
254 static WindowingSystemInterface* getWindowingSystemInterface(const std::string& name = "");
256 /** Create a graphics context for a specified set of traits.*/
257 static GraphicsContext* createGraphicsContext(Traits* traits);
259 /** Create a contextID for a new graphics context, this contextID is used to set up the osg::State associate with context.
260 * Automatically increments the usage count of the contextID to 1.*/
261 static unsigned int createNewContextID();
263 /** Get the current max ContextID.*/
264 static unsigned int getMaxContextID();
266 /** Increment the usage count associate with a contextID. The usage count specifies how many graphics contexts a specific contextID is shared between.*/
267 static void incrementContextIDUsageCount(unsigned int contextID);
269 /** Decrement the usage count associate with a contextID. Once the contextID goes to 0 the contextID is then free to be reused.*/
270 static void decrementContextIDUsageCount(unsigned int contextID);
272 typedef std::vector<GraphicsContext*> GraphicsContexts;
274 /** Get all the registered graphics contexts.*/
275 static GraphicsContexts getAllRegisteredGraphicsContexts();
277 /** Get all the registered graphics contexts associated with a specific contextID.*/
278 static GraphicsContexts getRegisteredGraphicsContexts(unsigned int contextID);
280 /** Get the GraphicsContext for doing background compilation for GraphicsContexts associated with specified contextID.*/
281 static void setCompileContext(unsigned int contextID, GraphicsContext* gc);
283 /** Get existing or create a new GraphicsContext to do background compilation for GraphicsContexts associated with specified contextID.*/
284 static GraphicsContext* getOrCreateCompileContext(unsigned int contextID);
286 /** Get the GraphicsContext for doing background compilation for GraphicsContexts associated with specified contextID.*/
287 static GraphicsContext* getCompileContext(unsigned int contextID);
291 /** Add operation to end of OperationQueue.*/
292 void add(Operation* operation);
294 /** Remove operation from OperationQueue.*/
295 void remove(Operation* operation);
297 /** Remove named operation from OperationQueue.*/
298 void remove(const std::string& name);
300 /** Remove all operations from OperationQueue.*/
301 void removeAllOperations();
303 /** Run the operations. */
304 virtual void runOperations();
306 typedef std::list< ref_ptr<Operation> > GraphicsOperationQueue;
308 /** Get the operations queue, note you must use the OperationsMutex when accessing the queue.*/
309 GraphicsOperationQueue& getOperationsQueue() { return _operations; }
311 /** Get the operations queue mutex.*/
312 OpenThreads::Mutex* getOperationsMutex() { return &_operationsMutex; }
314 /** Get the operations queue block used to mark an empty queue, if you end items into the empty queue you must release this block.*/
315 osg::RefBlock* getOperationsBlock() { return _operationsBlock.get(); }
317 /** Get the current operations that is being run.*/
318 Operation* getCurrentOperation() { return _currentOperation.get(); }
323 /** Get the traits of the GraphicsContext.*/
324 inline const Traits* getTraits() const { return _traits.get(); }
326 /** Return whether a valid and usable GraphicsContext has been created.*/
327 virtual bool valid() const = 0;
330 /** Set the State object which tracks the current OpenGL state for this graphics context.*/
331 inline void setState(State* state) { _state = state; }
333 /** Get the State object which tracks the current OpenGL state for this graphics context.*/
334 inline State* getState() { return _state.get(); }
336 /** Get the const State object which tracks the current OpenGL state for this graphics context.*/
337 inline const State* getState() const { return _state.get(); }
340 /** Sets the clear color. */
341 inline void setClearColor(const Vec4& color) { _clearColor = color; }
343 /** Returns the clear color. */
344 inline const Vec4& getClearColor() const { return _clearColor; }
346 /** Set the clear mask used in glClear(..).
347 * Defaults to 0 - so no clear is done by default by the GraphicsContext, instead the Cameras attached to the GraphicsContext will do the clear.
348 * GraphicsContext::setClearMask() is useful for when the Camera Viewports don't cover the whole context, so the context will fill in the gaps. */
349 inline void setClearMask(GLbitfield mask) { _clearMask = mask; }
351 /** Get the clear mask.*/
352 inline GLbitfield getClearMask() const { return _clearMask; }
354 /** Do an OpenGL clear of the full graphics context/window.
355 * Note, must only be called from a thread with this context current.*/
356 virtual void clear();
358 double getTimeSinceLastClear() const { return osg::Timer::instance()->delta_s(_lastClearTick, osg::Timer::instance()->tick()); }
361 /** Realize the GraphicsContext.*/
364 /** close the graphics context.
365 * close(bool) stops any associated graphics threads, releases the contextID for the GraphicsContext then
366 * optional calls closeImplementation() to do the actual deletion of the graphics. This call is made optional
367 * as there are times when the graphics context has already been deleted externally and only the OSG side
368 * of the its data need to be closed down. */
369 void close(bool callCloseImplementation=true);
371 /** swap the front and back buffers.*/
374 /** Return true if the graphics context has been realized and is ready to use.*/
375 inline bool isRealized() const { return isRealizedImplementation(); }
378 /** Make this graphics context current.
379 * Implemented by calling makeCurrentImplementation().
380 * Returns true on success. */
383 /** Make this graphics context current with specified read context.
384 * Implemented by calling makeContextCurrentImplementation().
385 * Returns true on success. */
386 bool makeContextCurrent(GraphicsContext* readContext);
388 /** Release the graphics context.
389 * Returns true on success. */
390 bool releaseContext();
392 /** Return true if the current thread has this OpenGL graphics context.*/
393 inline bool isCurrent() const { return _threadOfLastMakeCurrent == OpenThreads::Thread::CurrentThreadId(); }
395 /** Bind the graphics context to associated texture.*/
396 inline void bindPBufferToTexture(GLenum buffer) { bindPBufferToTextureImplementation(buffer); }
400 /** Create a graphics thread to the graphics context, so that the thread handles all OpenGL operations.*/
401 void createGraphicsThread();
403 /** Assign a graphics thread to the graphics context, so that the thread handles all OpenGL operations.*/
404 void setGraphicsThread(GraphicsThread* gt);
406 /** Get the graphics thread assigned the graphics context.*/
407 GraphicsThread* getGraphicsThread() { return _graphicsThread.get(); }
409 /** Get the const graphics thread assigned the graphics context.*/
410 const GraphicsThread* getGraphicsThread() const { return _graphicsThread.get(); }
413 /** Realize the GraphicsContext implementation,
414 * Pure virtual - must be implemented by concrete implementations of GraphicsContext. */
415 virtual bool realizeImplementation() = 0;
417 /** Return true if the graphics context has been realized, and is ready to use, implementation.
418 * Pure virtual - must be implemented by concrete implementations of GraphicsContext. */
419 virtual bool isRealizedImplementation() const = 0;
421 /** Close the graphics context implementation.
422 * Pure virtual - must be implemented by concrete implementations of GraphicsContext. */
423 virtual void closeImplementation() = 0;
425 /** Make this graphics context current implementation.
426 * Pure virtual - must be implemented by concrete implementations of GraphicsContext. */
427 virtual bool makeCurrentImplementation() = 0;
429 /** Make this graphics context current with specified read context implementation.
430 * Pure virtual - must be implemented by concrete implementations of GraphicsContext. */
431 virtual bool makeContextCurrentImplementation(GraphicsContext* readContext) = 0;
433 /** Release the graphics context implementation.*/
434 virtual bool releaseContextImplementation() = 0;
436 /** Pure virtual, Bind the graphics context to associated texture implementation.
437 * Pure virtual - must be implemented by concrete implementations of GraphicsContext. */
438 virtual void bindPBufferToTextureImplementation(GLenum buffer) = 0;
440 struct SwapCallback : public osg::Referenced
442 virtual void swapBuffersImplementation(GraphicsContext* gc) = 0;
444 /** Set the swap callback which overrides the
445 * GraphicsContext::swapBuffersImplementation(), allowing
446 * developers to provide custom behavior for swap.
447 * The callback must call
448 * GraphicsContext::swapBuffersImplementation() */
449 void setSwapCallback(SwapCallback* rc) { _swapCallback = rc; }
451 /** Get the swap callback which overrides the GraphicsContext::swapBuffersImplementation().*/
452 SwapCallback* getSwapCallback() { return _swapCallback.get(); }
454 /** Get the const swap callback which overrides the GraphicsContext::swapBuffersImplementation().*/
455 const SwapCallback* getSwapCallback() const { return _swapCallback.get(); }
457 /** Convenience method for handling whether to call swapbuffers callback or the standard context swapBuffersImplementation.
458 * swapBuffersCallbackOrImplementation() is called by swapBuffers() and osg::SwapBuffersOperation, end users should normally
459 * call swapBuffers() rather than swapBuffersCallbackOrImplementation(). */
460 void swapBuffersCallbackOrImplementation()
462 if (_state.valid()) _state->frameCompleted();
464 if (_swapCallback.valid()) _swapCallback->swapBuffersImplementation(this);
465 else swapBuffersImplementation();
468 /** Swap the front and back buffers implementation.
469 * Pure virtual - must be implemented by concrete implementations of GraphicsContext. */
470 virtual void swapBuffersImplementation() = 0;
474 /** resized method should be called when the underlying window has been resized and the GraphicsWindow and associated Cameras must
475 be updated to keep in sync with the new size. */
476 void resized(int x, int y, int width, int height)
478 if (_resizedCallback.valid()) _resizedCallback->resizedImplementation(this, x, y, width, height);
479 else resizedImplementation(x, y, width, height);
482 struct ResizedCallback : public osg::Referenced
484 virtual void resizedImplementation(GraphicsContext* gc, int x, int y, int width, int height) = 0;
487 /** Set the resized callback which overrides the GraphicsConext::realizedImplementation(), allow developers to provide custom behavior
488 * in response to a window being resized.*/
489 void setResizedCallback(ResizedCallback* rc) { _resizedCallback = rc; }
491 /** Get the resized callback which overrides the GraphicsConext::realizedImplementation().*/
492 ResizedCallback* getResizedCallback() { return _resizedCallback.get(); }
494 /** Get the const resized callback which overrides the GraphicsConext::realizedImplementation().*/
495 const ResizedCallback* getResizedCallback() const { return _resizedCallback.get(); }
497 /** resized implementation, by default resizes the viewports and aspect ratios the cameras associated with the graphics Window. */
498 virtual void resizedImplementation(int x, int y, int width, int height);
501 typedef std::list< osg::Camera* > Cameras;
503 /** Get the list of cameras associated with this graphics context.*/
504 Cameras& getCameras() { return _cameras; }
506 /** Get the const list of cameras associated with this graphics context.*/
507 const Cameras& getCameras() const { return _cameras; }
509 /** set the default FBO-id, this id will be used when the rendering-backend is finished with RTT FBOs */
510 void setDefaultFboId(GLuint i) { _defaultFboId = i; }
512 GLuint getDefaultFboId() const { return _defaultFboId; }
516 virtual bool isSameKindAs(const Object* object) const { return dynamic_cast<const GraphicsContext*>(object)!=0; }
517 virtual const char* libraryName() const { return "osg"; }
518 virtual const char* className() const { return "GraphicsContext"; }
523 GraphicsContext(const GraphicsContext&, const osg::CopyOp&);
525 virtual ~GraphicsContext();
527 virtual Object* cloneType() const { return 0; }
528 virtual Object* clone(const CopyOp&) const { return 0; }
530 /** Register a GraphicsContext.*/
531 static void registerGraphicsContext(GraphicsContext* gc);
533 /** Unregister a GraphicsContext.*/
534 static void unregisterGraphicsContext(GraphicsContext* gc);
537 void addCamera(osg::Camera* camera);
538 void removeCamera(osg::Camera* camera);
542 friend class osg::Camera;
544 ref_ptr<Traits> _traits;
545 ref_ptr<State> _state;
548 GLbitfield _clearMask;
550 size_t _threadOfLastMakeCurrent;
552 OpenThreads::Mutex _operationsMutex;
553 osg::ref_ptr<osg::RefBlock> _operationsBlock;
554 GraphicsOperationQueue _operations;
555 osg::ref_ptr<Operation> _currentOperation;
557 ref_ptr<GraphicsThread> _graphicsThread;
559 ref_ptr<ResizedCallback> _resizedCallback;
560 ref_ptr<SwapCallback> _swapCallback;
562 Timer_t _lastClearTick;
564 GLuint _defaultFboId;
567//#include <osg/GLExtensions>
570class OSG_EXPORT SyncSwapBuffersCallback : public GraphicsContext::SwapCallback
573 SyncSwapBuffersCallback();
575 virtual void swapBuffersImplementation(GraphicsContext* gc);
577 GLsync _previousSync;
582struct WindowingSystemInterfaceProxy
584 WindowingSystemInterfaceProxy(const std::string& name)
589 osg::GraphicsContext::getWindowingSystemInterfaces()->addWindowingSystemInterface(_wsi.get());
592 ~WindowingSystemInterfaceProxy()
594 osg::GraphicsContext::getWindowingSystemInterfaces()->removeWindowingSystemInterface(_wsi.get());
597 osg::ref_ptr<T> _wsi;
600#define REGISTER_WINDOWINGSYSTEMINTERFACE(ext, classname) \
601 extern "C" void graphicswindow_##ext(void) {} \
602 static osg::WindowingSystemInterfaceProxy<classname> s_proxy_##classname(#ext);