ViewerBase 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  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 OSGVIEWER_VIEWERBASE
  14. #define OSGVIEWER_VIEWERBASE 1
  15. #include <osg/Stats>
  16. #include <osgUtil/UpdateVisitor>
  17. #include <osgUtil/IncrementalCompileOperation>
  18. #include <osgGA/EventVisitor>
  19. #include <osgGA/EventQueue>
  20. #include <osgViewer/Scene>
  21. #include <osgViewer/GraphicsWindow>
  22. namespace osgViewer {
  23. #define USE_REFERENCE_TIME DBL_MAX
  24. class View;
  25. /** ViewerBase is the view base class that is inherited by both Viewer and CompositeViewer.*/
  26. class OSGVIEWER_EXPORT ViewerBase : public virtual osg::Object
  27. {
  28. public:
  29. ViewerBase();
  30. ViewerBase(const ViewerBase& vb);
  31. /** Set the Stats object used to collect various frame related timing and scene graph stats.*/
  32. virtual void setViewerStats(osg::Stats* stats) = 0;
  33. /** Get the Viewers Stats object.*/
  34. virtual osg::Stats* getViewerStats() = 0;
  35. /** Get the Viewers Stats object.*/
  36. virtual const osg::Stats* getViewerStats() const = 0;
  37. /** read the viewer configuration from a configuration file.*/
  38. virtual bool readConfiguration(const std::string& filename) = 0;
  39. /** Get whether at least of one of this viewers windows are realized.*/
  40. virtual bool isRealized() const = 0;
  41. /** set up windows and associated threads.*/
  42. virtual void realize() = 0;
  43. /** Set whether the setUpThreading() method should call configureAffinity() to set up up the processor affinity of viewer threads.*/
  44. void setUseConfigureAffinity(bool flag) { _useConfigureAffinity = flag; }
  45. /** get whether the setUpThreading() method should call configureAffinity() to set up up the processor affinity of viewer threads.*/
  46. bool getUseConfigureAffinity() const { return _useConfigureAffinity; }
  47. /** analyse the viewer configuration and select an appropriate Affinity for main thread, and any graphics, camera threads and database pagers that are required.*/
  48. virtual void configureAffinity();
  49. /** Set the processor affinity of main thread.*/
  50. virtual void setProcessorAffinity(const OpenThreads::Affinity& affinity) { _affinity = affinity; }
  51. OpenThreads::Affinity& getProcessorAffinity() { return _affinity; }
  52. const OpenThreads::Affinity& getProcessorAffinity() const { return _affinity; }
  53. enum ThreadingModel
  54. {
  55. SingleThreaded,
  56. CullDrawThreadPerContext,
  57. ThreadPerContext = CullDrawThreadPerContext,
  58. DrawThreadPerContext,
  59. CullThreadPerCameraDrawThreadPerContext,
  60. ThreadPerCamera = CullThreadPerCameraDrawThreadPerContext,
  61. AutomaticSelection
  62. };
  63. /** Set the threading model the rendering traversals will use.*/
  64. virtual void setThreadingModel(ThreadingModel threadingModel);
  65. /** Get the threading model the rendering traversals will use.*/
  66. ThreadingModel getThreadingModel() const { return _threadingModel; }
  67. /** Let the viewer suggest the best threading model for the viewers camera/window setup and the hardware available.*/
  68. virtual ThreadingModel suggestBestThreadingModel();
  69. /** Set up the threading and processor affinity as per the viewers threading model.*/
  70. virtual void setUpThreading();
  71. /** Return true if viewer threads are running. */
  72. bool areThreadsRunning() const { return _threadsRunning; }
  73. /** Stop any threads being run by viewer.*/
  74. virtual void stopThreading();
  75. /** Start any threads required by the viewer.*/
  76. virtual void startThreading();
  77. enum BarrierPosition
  78. {
  79. BeforeSwapBuffers,
  80. AfterSwapBuffers
  81. };
  82. /** Set the position of the end barrier.
  83. * AfterSwapBuffers may result in slightly higher framerates, but may
  84. * lead to inconsistent swapping between different windows.
  85. * BeforeSwapBuffers may lead to slightly lower framerate, but improve consistency in timing of swap buffers,
  86. * especially important if you are likely to consistently break frame.*/
  87. void setEndBarrierPosition(BarrierPosition bp);
  88. /** Get the end barrier position.*/
  89. BarrierPosition getEndBarrierPosition() const { return _endBarrierPosition; }
  90. /** Set the end barrier operation. \c op may be one of GL_FLUSH, GL_FINISH,
  91. * or NO_OPERATION. NO_OPERATION is the default. Per BarrierOperation::operator()(),
  92. * a glFlush() command, glFinish() command, or no additional OpenGL command will be
  93. * issued before entering the end barrier. */
  94. void setEndBarrierOperation(osg::BarrierOperation::PreBlockOp op);
  95. /** Get the end barrier operation. */
  96. osg::BarrierOperation::PreBlockOp getEndBarrierOperation() const { return _endBarrierOperation; }
  97. /** Set the done flag to signal the viewer's work is done and should exit the frame loop.*/
  98. void setDone(bool done) { _done = done; }
  99. /** Return true if viewer's work is done and should exit the frame loop.*/
  100. bool done() const { return _done; }
  101. /** Set the EventVisitor. */
  102. void setEventVisitor(osgGA::EventVisitor* eventVisitor) { _eventVisitor = eventVisitor; }
  103. /** Get the EventVisitor. */
  104. osgGA::EventVisitor* getEventVisitor() { return _eventVisitor.get(); }
  105. /** Get the const EventVisitor. */
  106. const osgGA::EventVisitor* getEventVisitor() const { return _eventVisitor.get(); }
  107. /** Set the key event that the viewer checks on each frame to see if the viewer's done flag should be set to
  108. * signal end of viewers main loop.
  109. * Default value is Escape (osgGA::GUIEVentAdapter::KEY_Escape).
  110. * Setting to 0 switches off the feature.*/
  111. void setKeyEventSetsDone(int key) { _keyEventSetsDone = key; }
  112. /** get the key event that the viewer checks on each frame to see if the viewer's done flag.*/
  113. int getKeyEventSetsDone() const { return _keyEventSetsDone; }
  114. /** if the flag is true, the viewer set its done flag when a QUIT_APPLICATION is received, false disables this feature */
  115. void setQuitEventSetsDone(bool flag) { _quitEventSetsDone = flag; }
  116. /** @return true if the viewer respond to the QUIT_APPLICATION-event */
  117. bool getQuitEventSetsDone() const { return _quitEventSetsDone; }
  118. /** Hint to tell the renderingTraversals() method whether to call releaseContext() on the last
  119. * context that was made current by the thread calling renderingTraverals(). Note, when
  120. * running multi-threaded viewer no threads will be made current or release current.
  121. * Setting this hint to false can enable the frame loop to be lazy about calling makeCurrent
  122. * and releaseContext on each new frame, helping performance. However, if you frame loop
  123. * is managing multiple graphics context all from the main frame thread then this hint must
  124. * be left on, otherwise the wrong context could be left active, introducing errors in rendering.*/
  125. void setReleaseContextAtEndOfFrameHint(bool hint) { _releaseContextAtEndOfFrameHint = hint; }
  126. /** Hint to tell the renderingTraversals() method whether to call releaseContext().*/
  127. bool getReleaseContextAtEndOfFrameHint() const { return _releaseContextAtEndOfFrameHint; }
  128. /** Set the UpdateVisitor. */
  129. void setUpdateVisitor(osgUtil::UpdateVisitor* updateVisitor) { _updateVisitor = updateVisitor; }
  130. /** Get the UpdateVisitor. */
  131. osgUtil::UpdateVisitor* getUpdateVisitor() { return _updateVisitor.get(); }
  132. /** Get the const UpdateVisitor. */
  133. const osgUtil::UpdateVisitor* getUpdateVisitor() const { return _updateVisitor.get(); }
  134. /** Set the Update OperationQueue. */
  135. void setUpdateOperations(osg::OperationQueue* operations) { _updateOperations = operations; }
  136. /** Get the Update OperationQueue. */
  137. osg::OperationQueue* getUpdateOperations() { return _updateOperations.get(); }
  138. /** Get the const Update OperationQueue. */
  139. const osg::OperationQueue* getUpdateOperations() const { return _updateOperations.get(); }
  140. /** Add an update operation.*/
  141. void addUpdateOperation(osg::Operation* operation);
  142. /** Remove an update operation.*/
  143. void removeUpdateOperation(osg::Operation* operation);
  144. /** Set the graphics operation to call on realization of the viewers graphics windows.*/
  145. void setRealizeOperation(osg::Operation* op) { _realizeOperation = op; }
  146. /** Get the graphics operation to call on realization of the viewers graphics windows.*/
  147. osg::Operation* getRealizeOperation() { return _realizeOperation.get(); }
  148. /** Set the graphics operation to call before the viewers graphics contexts close.*/
  149. void setCleanUpOperation(osg::Operation* op) { _cleanUpOperation = op; }
  150. /** Get the graphics operation to call before the viewers graphics contexts close.*/
  151. osg::Operation* getCleanUpOperation() { return _cleanUpOperation.get(); }
  152. /** Set the incremental compile operation.
  153. * Used to manage the OpenGL object compilation and merging of subgraphs in a way that avoids overloading
  154. * the rendering of frame with too many new objects in one frame. */
  155. void setIncrementalCompileOperation(osgUtil::IncrementalCompileOperation* ico);
  156. /** Get the incremental compile operation. */
  157. osgUtil::IncrementalCompileOperation* getIncrementalCompileOperation() { return _incrementalCompileOperation.get(); }
  158. enum FrameScheme
  159. {
  160. ON_DEMAND,
  161. CONTINUOUS
  162. };
  163. void setRunFrameScheme(FrameScheme fs) { _runFrameScheme = fs; }
  164. FrameScheme getRunFrameScheme() const { return _runFrameScheme; }
  165. void setRunMaxFrameRate(double frameRate) { _runMaxFrameRate = frameRate; }
  166. double getRunMaxFrameRate() const { return _runMaxFrameRate; }
  167. /** Execute a main frame loop.
  168. * Equivalent to while (!viewer.done()) viewer.frame();
  169. * Also calls realize() if the viewer is not already realized,
  170. * and installs trackball manipulator if one is not already assigned.
  171. */
  172. virtual int run();
  173. /** check to see if the new frame is required, called by run(..) when FrameScheme is set to ON_DEMAND.*/
  174. virtual bool checkNeedToDoFrame() = 0;
  175. /** check to see if events have been received, return true if events are now available.*/
  176. virtual bool checkEvents() = 0;
  177. /** Render a complete new frame.
  178. * Calls advance(), eventTraversal(), updateTraversal(), renderingTraversals(). */
  179. virtual void frame(double simulationTime=USE_REFERENCE_TIME);
  180. virtual void advance(double simulationTime=USE_REFERENCE_TIME) = 0;
  181. virtual void eventTraversal() = 0;
  182. virtual void updateTraversal() = 0;
  183. virtual void renderingTraversals();
  184. typedef std::vector<osg::Camera*> Cameras;
  185. virtual void getCameras(Cameras& cameras, bool onlyActive=true) = 0;
  186. typedef std::vector<osg::GraphicsContext*> Contexts;
  187. virtual void getContexts(Contexts& contexts, bool onlyValid=true) = 0;
  188. typedef std::vector<osgViewer::GraphicsWindow*> Windows;
  189. virtual void getWindows(Windows& windows, bool onlyValid=true);
  190. typedef std::vector<OpenThreads::Thread*> Threads;
  191. virtual void getAllThreads(Threads& threads, bool onlyActive=true) = 0;
  192. typedef std::vector<osg::OperationThread*> OperationThreads;
  193. virtual void getOperationThreads(OperationThreads& threads, bool onlyActive=true) = 0;
  194. typedef std::vector<osgViewer::Scene*> Scenes;
  195. virtual void getScenes(Scenes& scenes, bool onlyValid=true) = 0;
  196. typedef std::vector<osgViewer::View*> Views;
  197. virtual void getViews(Views& views, bool onlyValid=true) = 0;
  198. /** Check to see if any windows are still open. If not, set viewer done to true. */
  199. void checkWindowStatus();
  200. /** Check to see if windows are still open using the list of contexts given as a parameter.
  201. * If no windows are open, stop rendering threads and set viewer done to true.
  202. * This function is more effective than checkWindowStatus() as it does not query
  203. * the context list and should be used whenever context list is already available in your code.*/
  204. void checkWindowStatus(const Contexts& contexts);
  205. virtual double elapsedTime() = 0;
  206. virtual osg::FrameStamp* getViewerFrameStamp() = 0;
  207. /** Get the keyboard and mouse usage of this viewer.*/
  208. virtual void getUsage(osg::ApplicationUsage& usage) const = 0;
  209. bool getRequestRedraw() const { return _requestRedraw; }
  210. bool getRequestContinousUpdate() const { return _requestContinousUpdate; }
  211. protected:
  212. void viewerBaseInit();
  213. friend class osgViewer::View;
  214. inline void makeCurrent(osg::GraphicsContext* gc)
  215. {
  216. if (_currentContext==gc) return;
  217. releaseContext();
  218. if (gc && gc->valid() && gc->makeCurrent()) _currentContext = gc;
  219. }
  220. inline void releaseContext()
  221. {
  222. if (_currentContext.valid() && _currentContext->valid())
  223. {
  224. _currentContext->releaseContext();
  225. }
  226. _currentContext = 0;
  227. }
  228. virtual void viewerInit() = 0;
  229. bool _firstFrame;
  230. bool _done;
  231. int _keyEventSetsDone;
  232. bool _quitEventSetsDone;
  233. bool _releaseContextAtEndOfFrameHint;
  234. bool _useConfigureAffinity;
  235. OpenThreads::Affinity _affinity;
  236. ThreadingModel _threadingModel;
  237. bool _threadsRunning;
  238. bool _requestRedraw;
  239. bool _requestContinousUpdate;
  240. FrameScheme _runFrameScheme;
  241. double _runMaxFrameRate;
  242. BarrierPosition _endBarrierPosition;
  243. osg::BarrierOperation::PreBlockOp _endBarrierOperation;
  244. osg::ref_ptr<osg::BarrierOperation> _startRenderingBarrier;
  245. osg::ref_ptr<osg::BarrierOperation> _endRenderingDispatchBarrier;
  246. osg::ref_ptr<osg::EndOfDynamicDrawBlock> _endDynamicDrawBlock;
  247. osg::ref_ptr<osgGA::EventVisitor> _eventVisitor;
  248. osg::ref_ptr<osg::OperationQueue> _updateOperations;
  249. osg::ref_ptr<osgUtil::UpdateVisitor> _updateVisitor;
  250. osg::ref_ptr<osg::Operation> _realizeOperation;
  251. osg::ref_ptr<osg::Operation> _cleanUpOperation;
  252. osg::ref_ptr<osgUtil::IncrementalCompileOperation> _incrementalCompileOperation;
  253. osg::observer_ptr<osg::GraphicsContext> _currentContext;
  254. private:
  255. // Define private copy constructor
  256. // otherwsie VS2015 will construct it's own which will call the private copy operator from osg::Object resulting in an compile error.
  257. ViewerBase& operator = (const ViewerBase&) { return *this; }
  258. };
  259. }
  260. #endif