GraphicsContext 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
  2. *
  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.
  7. *
  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.
  12. */
  13. #ifndef OSG_GRAPHICSCONTEXT
  14. #define OSG_GRAPHICSCONTEXT 1
  15. #include <osg/State>
  16. #include <osg/GraphicsThread>
  17. #include <osg/Timer>
  18. #include <vector>
  19. namespace osg {
  20. // forward declare osg::Camera
  21. class Camera;
  22. /** Base class for providing Windowing API agnostic access to creating and managing graphics context.*/
  23. class OSG_EXPORT GraphicsContext : public Object
  24. {
  25. public:
  26. struct OSG_EXPORT ScreenIdentifier
  27. {
  28. ScreenIdentifier();
  29. ScreenIdentifier(int in_screenNum);
  30. ScreenIdentifier(const std::string& in_hostName,int in_displayNum, int in_screenNum);
  31. /** Return the display name in the form hostName::displayNum:screenNum. */
  32. std::string displayName() const;
  33. /** Read the DISPLAY environmental variable, and set the ScreenIdentifier accordingly.
  34. * Note, if either of displayNum or screenNum are not defined then -1 is set respectively to
  35. * signify that this parameter has not been set. When parameters are undefined one can call
  36. * call setUndefinedScreenDetailsToDefaultScreen() after readDISPLAY() to ensure valid values. */
  37. void readDISPLAY();
  38. /** Set the screenIndentifier from the displayName string.
  39. * Note, if either of displayNum or screenNum are not defined then -1 is set to
  40. * signify that this parameter has not been set. When parameters are undefined one can call
  41. * call setUndefinedScreenDetailsToDefaultScreen() after readDISPLAY() to ensure valid values. */
  42. void setScreenIdentifier(const std::string& displayName);
  43. /** Set any undefined displayNum or screenNum values (i.e. -1) to the default display & screen of 0 respectively.*/
  44. void setUndefinedScreenDetailsToDefaultScreen()
  45. {
  46. if (displayNum<0) displayNum = 0;
  47. if (screenNum<0) screenNum = 0;
  48. }
  49. std::string hostName;
  50. int displayNum;
  51. int screenNum;
  52. };
  53. /** GraphicsContext Traits object provides the specification of what type of graphics context is required.*/
  54. struct OSG_EXPORT Traits : public osg::Referenced, public ScreenIdentifier
  55. {
  56. Traits(DisplaySettings* ds=0);
  57. // graphics context original and size
  58. int x;
  59. int y;
  60. int width;
  61. int height;
  62. // provide a hint as to which WindowingSystemInterface implementation to use, i.e. "X11", "Win32", "Cocoa", "Carbon" etc.
  63. // if the windowingSystemPreference string is empty (default) then return the first available WindowingSystemInterface that
  64. // has been registered with the osg::GraphiccsContext::WindowingSystemInterfaces singleton
  65. // if the windowingSystemPreference string is not empty then return the first WindowingSystemInterface that matches
  66. std::string windowingSystemPreference;
  67. // window decoration and behaviour
  68. std::string windowName;
  69. bool windowDecoration;
  70. bool supportsResize;
  71. // buffer depths, 0 equals off.
  72. unsigned int red;
  73. unsigned int blue;
  74. unsigned int green;
  75. unsigned int alpha;
  76. unsigned int depth;
  77. unsigned int stencil;
  78. // multi sample parameters
  79. unsigned int sampleBuffers;
  80. unsigned int samples;
  81. // buffer configuration
  82. bool pbuffer;
  83. bool quadBufferStereo;
  84. bool doubleBuffer;
  85. // render to texture
  86. GLenum target;
  87. GLenum format;
  88. unsigned int level;
  89. unsigned int face;
  90. unsigned int mipMapGeneration;
  91. // V-sync
  92. bool vsync;
  93. // Swap Group
  94. bool swapGroupEnabled;
  95. GLuint swapGroup;
  96. GLuint swapBarrier;
  97. // use multithreaded OpenGL-engine (OS X only)
  98. bool useMultiThreadedOpenGLEngine;
  99. // enable cursor
  100. bool useCursor;
  101. // settings used in set up of graphics context, only presently used by GL3 build of OSG.
  102. std::string glContextVersion;
  103. unsigned int glContextFlags;
  104. unsigned int glContextProfileMask;
  105. /** return true if glContextVersion is set in the form major.minor, and assign the appropriate major and minor values to the associated parameters.*/
  106. bool getContextVersion(unsigned int& major, unsigned int& minor) const;
  107. // shared context
  108. osg::observer_ptr<GraphicsContext> sharedContext;
  109. osg::ref_ptr<osg::Referenced> inheritedWindowData;
  110. // ask the GraphicsWindow implementation to set the pixel format of an inherited window
  111. bool setInheritedWindowPixelFormat;
  112. // X11 hint whether to override the window managers window size/position redirection
  113. bool overrideRedirect;
  114. DisplaySettings::SwapMethod swapMethod;
  115. // hint of what affinity to use for any thrads associated with the graphics context created using these Traits
  116. OpenThreads::Affinity affinity;
  117. };
  118. /** Simple resolution structure used by WindowingSystemInterface to get and set screen resolution.
  119. * Note the '0' value stands for 'unset'. */
  120. struct ScreenSettings {
  121. ScreenSettings() :
  122. width(0),
  123. height(0),
  124. refreshRate(0),
  125. colorDepth(0)
  126. {}
  127. ScreenSettings(int in_width, int in_height, double in_refreshRate=0, unsigned int in_colorDepth=0) :
  128. width(in_width),
  129. height(in_height),
  130. refreshRate(in_refreshRate),
  131. colorDepth(in_colorDepth)
  132. {}
  133. int width;
  134. int height;
  135. double refreshRate; ///< Screen refresh rate, in Hz.
  136. unsigned int colorDepth; ///< RGB(A) color buffer depth.
  137. };
  138. typedef std::vector<ScreenSettings> ScreenSettingsList;
  139. /** Callback to be implemented to provide access to Windowing API's ability to create Windows/pbuffers.*/
  140. struct WindowingSystemInterface : public osg::Referenced
  141. {
  142. void setName(const std::string& name) { _name = name; }
  143. const std::string& getName() const { return _name; }
  144. virtual unsigned int getNumScreens(const ScreenIdentifier& screenIdentifier = ScreenIdentifier()) = 0;
  145. virtual void getScreenSettings(const ScreenIdentifier& screenIdentifier, ScreenSettings & resolution) = 0;
  146. virtual bool setScreenSettings(const ScreenIdentifier& /*screenIdentifier*/, const ScreenSettings & /*resolution*/) { return false; }
  147. virtual void enumerateScreenSettings(const ScreenIdentifier& screenIdentifier, ScreenSettingsList & resolutionList) = 0;
  148. virtual void setDisplaySettings(DisplaySettings*) {}
  149. virtual osg::DisplaySettings* getDisplaySettings() const { return 0; }
  150. virtual GraphicsContext* createGraphicsContext(Traits* traits) = 0;
  151. /** Gets screen resolution without using the ScreenResolution structure.
  152. * \deprecated Provided only for backward compatibility. */
  153. inline void getScreenResolution(const ScreenIdentifier& screenIdentifier, unsigned int& width, unsigned int& height)
  154. {
  155. ScreenSettings settings;
  156. getScreenSettings(screenIdentifier, settings);
  157. width = settings.width;
  158. height = settings.height;
  159. }
  160. /** Sets screen resolution without using the ScreenSettings structure.
  161. * \deprecated Provided only for backward compatibility. */
  162. inline bool setScreenResolution(const ScreenIdentifier& screenIdentifier, unsigned int width, unsigned int height)
  163. {
  164. return setScreenSettings(screenIdentifier, ScreenSettings(width, height));
  165. }
  166. /** \deprecated Provided only for backward compatibility. */
  167. inline bool setScreenRefreshRate(const ScreenIdentifier& screenIdentifier, double refreshRate)
  168. {
  169. ScreenSettings settings;
  170. getScreenSettings(screenIdentifier, settings);
  171. settings.refreshRate = refreshRate;
  172. return setScreenSettings(screenIdentifier, settings);
  173. }
  174. protected:
  175. WindowingSystemInterface() {}
  176. virtual ~WindowingSystemInterface() {}
  177. std::string _name;
  178. };
  179. class OSG_EXPORT WindowingSystemInterfaces : public osg::Referenced
  180. {
  181. public:
  182. WindowingSystemInterfaces();
  183. typedef std::vector< osg::ref_ptr<GraphicsContext::WindowingSystemInterface> > Interfaces;
  184. Interfaces& getInterfaces() { return _interfaces; }
  185. void addWindowingSystemInterface(WindowingSystemInterface* wsInterface);
  186. void removeWindowingSystemInterface(WindowingSystemInterface* wsInterface);
  187. /** get named WindowingSystemInterface if one is available, otherwise return 0; */
  188. WindowingSystemInterface* getWindowingSystemInterface(const std::string& name = "");
  189. private:
  190. virtual ~WindowingSystemInterfaces();
  191. Interfaces _interfaces;
  192. };
  193. static osg::ref_ptr<WindowingSystemInterfaces>& getWindowingSystemInterfaces();
  194. /** Get the default WindowingSystemInterface for this OS*/
  195. static WindowingSystemInterface* getWindowingSystemInterface(const std::string& name = "");
  196. /** Create a graphics context for a specified set of traits.*/
  197. static GraphicsContext* createGraphicsContext(Traits* traits);
  198. /** Create a contextID for a new graphics context, this contextID is used to set up the osg::State associate with context.
  199. * Automatically increments the usage count of the contextID to 1.*/
  200. static unsigned int createNewContextID();
  201. /** Get the current max ContextID.*/
  202. static unsigned int getMaxContextID();
  203. /** Increment the usage count associate with a contextID. The usage count specifies how many graphics contexts a specific contextID is shared between.*/
  204. static void incrementContextIDUsageCount(unsigned int contextID);
  205. /** Decrement the usage count associate with a contextID. Once the contextID goes to 0 the contextID is then free to be reused.*/
  206. static void decrementContextIDUsageCount(unsigned int contextID);
  207. typedef std::vector<GraphicsContext*> GraphicsContexts;
  208. /** Get all the registered graphics contexts.*/
  209. static GraphicsContexts getAllRegisteredGraphicsContexts();
  210. /** Get all the registered graphics contexts associated with a specific contextID.*/
  211. static GraphicsContexts getRegisteredGraphicsContexts(unsigned int contextID);
  212. /** Get the GraphicsContext for doing background compilation for GraphicsContexts associated with specified contextID.*/
  213. static void setCompileContext(unsigned int contextID, GraphicsContext* gc);
  214. /** Get existing or create a new GraphicsContext to do background compilation for GraphicsContexts associated with specified contextID.*/
  215. static GraphicsContext* getOrCreateCompileContext(unsigned int contextID);
  216. /** Get the GraphicsContext for doing background compilation for GraphicsContexts associated with specified contextID.*/
  217. static GraphicsContext* getCompileContext(unsigned int contextID);
  218. public:
  219. /** Add operation to end of OperationQueue.*/
  220. void add(Operation* operation);
  221. /** Remove operation from OperationQueue.*/
  222. void remove(Operation* operation);
  223. /** Remove named operation from OperationQueue.*/
  224. void remove(const std::string& name);
  225. /** Remove all operations from OperationQueue.*/
  226. void removeAllOperations();
  227. /** Run the operations. */
  228. virtual void runOperations();
  229. typedef std::list< ref_ptr<Operation> > GraphicsOperationQueue;
  230. /** Get the operations queue, note you must use the OperationsMutex when accessing the queue.*/
  231. GraphicsOperationQueue& getOperationsQueue() { return _operations; }
  232. /** Get the operations queue mutex.*/
  233. OpenThreads::Mutex* getOperationsMutex() { return &_operationsMutex; }
  234. /** Get the operations queue block used to mark an empty queue, if you end items into the empty queue you must release this block.*/
  235. osg::RefBlock* getOperationsBlock() { return _operationsBlock.get(); }
  236. /** Get the current operations that is being run.*/
  237. Operation* getCurrentOperation() { return _currentOperation.get(); }
  238. public:
  239. /** Get the traits of the GraphicsContext.*/
  240. inline const Traits* getTraits() const { return _traits.get(); }
  241. /** Return whether a valid and usable GraphicsContext has been created.*/
  242. virtual bool valid() const = 0;
  243. /** Set the State object which tracks the current OpenGL state for this graphics context.*/
  244. inline void setState(State* state) { _state = state; }
  245. /** Get the State object which tracks the current OpenGL state for this graphics context.*/
  246. inline State* getState() { return _state.get(); }
  247. /** Get the const State object which tracks the current OpenGL state for this graphics context.*/
  248. inline const State* getState() const { return _state.get(); }
  249. /** Sets the clear color. */
  250. inline void setClearColor(const Vec4& color) { _clearColor = color; }
  251. /** Returns the clear color. */
  252. inline const Vec4& getClearColor() const { return _clearColor; }
  253. /** Set the clear mask used in glClear(..).
  254. * Defaults to 0 - so no clear is done by default by the GraphicsContext, instead the Cameras attached to the GraphicsContext will do the clear.
  255. * GraphicsContext::setClearMask() is useful for when the Camera Viewports don't cover the whole context, so the context will fill in the gaps. */
  256. inline void setClearMask(GLbitfield mask) { _clearMask = mask; }
  257. /** Get the clear mask.*/
  258. inline GLbitfield getClearMask() const { return _clearMask; }
  259. /** Do an OpenGL clear of the full graphics context/window.
  260. * Note, must only be called from a thread with this context current.*/
  261. virtual void clear();
  262. double getTimeSinceLastClear() const { return osg::Timer::instance()->delta_s(_lastClearTick, osg::Timer::instance()->tick()); }
  263. /** Realize the GraphicsContext.*/
  264. bool realize();
  265. /** close the graphics context.
  266. * close(bool) stops any associated graphics threads, releases the contextID for the GraphicsContext then
  267. * optional calls closeImplementation() to do the actual deletion of the graphics. This call is made optional
  268. * as there are times when the graphics context has already been deleted externally and only the OSG side
  269. * of the its data need to be closed down. */
  270. void close(bool callCloseImplementation=true);
  271. /** swap the front and back buffers.*/
  272. void swapBuffers();
  273. /** Return true if the graphics context has been realized and is ready to use.*/
  274. inline bool isRealized() const { return isRealizedImplementation(); }
  275. /** Make this graphics context current.
  276. * Implemented by calling makeCurrentImplementation().
  277. * Returns true on success. */
  278. bool makeCurrent();
  279. /** Make this graphics context current with specified read context.
  280. * Implemented by calling makeContextCurrentImplementation().
  281. * Returns true on success. */
  282. bool makeContextCurrent(GraphicsContext* readContext);
  283. /** Release the graphics context.
  284. * Returns true on success. */
  285. bool releaseContext();
  286. /** Return true if the current thread has this OpenGL graphics context.*/
  287. inline bool isCurrent() const { return _threadOfLastMakeCurrent == OpenThreads::Thread::CurrentThreadId(); }
  288. /** Bind the graphics context to associated texture.*/
  289. inline void bindPBufferToTexture(GLenum buffer) { bindPBufferToTextureImplementation(buffer); }
  290. /** Create a graphics thread to the graphics context, so that the thread handles all OpenGL operations.*/
  291. void createGraphicsThread();
  292. /** Assign a graphics thread to the graphics context, so that the thread handles all OpenGL operations.*/
  293. void setGraphicsThread(GraphicsThread* gt);
  294. /** Get the graphics thread assigned the graphics context.*/
  295. GraphicsThread* getGraphicsThread() { return _graphicsThread.get(); }
  296. /** Get the const graphics thread assigned the graphics context.*/
  297. const GraphicsThread* getGraphicsThread() const { return _graphicsThread.get(); }
  298. /** Realize the GraphicsContext implementation,
  299. * Pure virtual - must be implemented by concrete implementations of GraphicsContext. */
  300. virtual bool realizeImplementation() = 0;
  301. /** Return true if the graphics context has been realized, and is ready to use, implementation.
  302. * Pure virtual - must be implemented by concrete implementations of GraphicsContext. */
  303. virtual bool isRealizedImplementation() const = 0;
  304. /** Close the graphics context implementation.
  305. * Pure virtual - must be implemented by concrete implementations of GraphicsContext. */
  306. virtual void closeImplementation() = 0;
  307. /** Make this graphics context current implementation.
  308. * Pure virtual - must be implemented by concrete implementations of GraphicsContext. */
  309. virtual bool makeCurrentImplementation() = 0;
  310. /** Make this graphics context current with specified read context implementation.
  311. * Pure virtual - must be implemented by concrete implementations of GraphicsContext. */
  312. virtual bool makeContextCurrentImplementation(GraphicsContext* readContext) = 0;
  313. /** Release the graphics context implementation.*/
  314. virtual bool releaseContextImplementation() = 0;
  315. /** Pure virtual, Bind the graphics context to associated texture implementation.
  316. * Pure virtual - must be implemented by concrete implementations of GraphicsContext. */
  317. virtual void bindPBufferToTextureImplementation(GLenum buffer) = 0;
  318. struct SwapCallback : public osg::Referenced
  319. {
  320. virtual void swapBuffersImplementation(GraphicsContext* gc) = 0;
  321. };
  322. /** Set the swap callback which overrides the
  323. * GraphicsContext::swapBuffersImplementation(), allowing
  324. * developers to provide custom behavior for swap.
  325. * The callback must call
  326. * GraphicsContext::swapBuffersImplementation() */
  327. void setSwapCallback(SwapCallback* rc) { _swapCallback = rc; }
  328. /** Get the swap callback which overrides the GraphicsContext::swapBuffersImplementation().*/
  329. SwapCallback* getSwapCallback() { return _swapCallback.get(); }
  330. /** Get the const swap callback which overrides the GraphicsContext::swapBuffersImplementation().*/
  331. const SwapCallback* getSwapCallback() const { return _swapCallback.get(); }
  332. /** Convenience method for handling whether to call swapbuffers callback or the standard context swapBuffersImplementation.
  333. * swapBuffersCallbackOrImplementation() is called by swapBuffers() and osg::SwapBuffersOperation, end users should normally
  334. * call swapBuffers() rather than swapBuffersCallbackOrImplementation(). */
  335. void swapBuffersCallbackOrImplementation()
  336. {
  337. if (_state.valid()) _state->frameCompleted();
  338. if (_swapCallback.valid()) _swapCallback->swapBuffersImplementation(this);
  339. else swapBuffersImplementation();
  340. }
  341. /** Swap the front and back buffers implementation.
  342. * Pure virtual - must be implemented by concrete implementations of GraphicsContext. */
  343. virtual void swapBuffersImplementation() = 0;
  344. /** resized method should be called when the underlying window has been resized and the GraphicsWindow and associated Cameras must
  345. be updated to keep in sync with the new size. */
  346. void resized(int x, int y, int width, int height)
  347. {
  348. if (_resizedCallback.valid()) _resizedCallback->resizedImplementation(this, x, y, width, height);
  349. else resizedImplementation(x, y, width, height);
  350. }
  351. struct ResizedCallback : public osg::Referenced
  352. {
  353. virtual void resizedImplementation(GraphicsContext* gc, int x, int y, int width, int height) = 0;
  354. };
  355. /** Set the resized callback which overrides the GraphicsConext::realizedImplementation(), allow developers to provide custom behavior
  356. * in response to a window being resized.*/
  357. void setResizedCallback(ResizedCallback* rc) { _resizedCallback = rc; }
  358. /** Get the resized callback which overrides the GraphicsConext::realizedImplementation().*/
  359. ResizedCallback* getResizedCallback() { return _resizedCallback.get(); }
  360. /** Get the const resized callback which overrides the GraphicsConext::realizedImplementation().*/
  361. const ResizedCallback* getResizedCallback() const { return _resizedCallback.get(); }
  362. /** resized implementation, by default resizes the viewports and aspect ratios the cameras associated with the graphics Window. */
  363. virtual void resizedImplementation(int x, int y, int width, int height);
  364. typedef std::list< osg::Camera* > Cameras;
  365. /** Get the list of cameras associated with this graphics context.*/
  366. Cameras& getCameras() { return _cameras; }
  367. /** Get the const list of cameras associated with this graphics context.*/
  368. const Cameras& getCameras() const { return _cameras; }
  369. /** set the default FBO-id, this id will be used when the rendering-backend is finished with RTT FBOs */
  370. void setDefaultFboId(GLuint i) { _defaultFboId = i; }
  371. GLuint getDefaultFboId() const { return _defaultFboId; }
  372. public:
  373. virtual bool isSameKindAs(const Object* object) const { return dynamic_cast<const GraphicsContext*>(object)!=0; }
  374. virtual const char* libraryName() const { return "osg"; }
  375. virtual const char* className() const { return "GraphicsContext"; }
  376. protected:
  377. GraphicsContext();
  378. GraphicsContext(const GraphicsContext&, const osg::CopyOp&);
  379. virtual ~GraphicsContext();
  380. virtual Object* cloneType() const { return 0; }
  381. virtual Object* clone(const CopyOp&) const { return 0; }
  382. /** Register a GraphicsContext.*/
  383. static void registerGraphicsContext(GraphicsContext* gc);
  384. /** Unregister a GraphicsContext.*/
  385. static void unregisterGraphicsContext(GraphicsContext* gc);
  386. void addCamera(osg::Camera* camera);
  387. void removeCamera(osg::Camera* camera);
  388. Cameras _cameras;
  389. friend class osg::Camera;
  390. ref_ptr<Traits> _traits;
  391. ref_ptr<State> _state;
  392. Vec4 _clearColor;
  393. GLbitfield _clearMask;
  394. size_t _threadOfLastMakeCurrent;
  395. OpenThreads::Mutex _operationsMutex;
  396. osg::ref_ptr<osg::RefBlock> _operationsBlock;
  397. GraphicsOperationQueue _operations;
  398. osg::ref_ptr<Operation> _currentOperation;
  399. ref_ptr<GraphicsThread> _graphicsThread;
  400. ref_ptr<ResizedCallback> _resizedCallback;
  401. ref_ptr<SwapCallback> _swapCallback;
  402. Timer_t _lastClearTick;
  403. GLuint _defaultFboId;
  404. };
  405. //#include <osg/GLExtensions>
  406. class OSG_EXPORT SyncSwapBuffersCallback : public GraphicsContext::SwapCallback
  407. {
  408. public:
  409. SyncSwapBuffersCallback();
  410. virtual void swapBuffersImplementation(GraphicsContext* gc);
  411. GLsync _previousSync;
  412. };
  413. template<class T>
  414. struct WindowingSystemInterfaceProxy
  415. {
  416. WindowingSystemInterfaceProxy(const std::string& name)
  417. {
  418. _wsi = new T;
  419. _wsi->setName(name);
  420. osg::GraphicsContext::getWindowingSystemInterfaces()->addWindowingSystemInterface(_wsi.get());
  421. }
  422. ~WindowingSystemInterfaceProxy()
  423. {
  424. osg::GraphicsContext::getWindowingSystemInterfaces()->removeWindowingSystemInterface(_wsi.get());
  425. }
  426. osg::ref_ptr<T> _wsi;
  427. };
  428. #define REGISTER_WINDOWINGSYSTEMINTERFACE(ext, classname) \
  429. extern "C" void graphicswindow_##ext(void) {} \
  430. static osg::WindowingSystemInterfaceProxy<classname> s_proxy_##classname(#ext);
  431. }
  432. #endif