Panda3D
|
00001 // Filename: graphicsEngine.h 00002 // Created by: drose (24Feb02) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #ifndef GRAPHICSENGINE_H 00016 #define GRAPHICSENGINE_H 00017 00018 #include "pandabase.h" 00019 #include "graphicsWindow.h" 00020 #include "graphicsBuffer.h" 00021 #include "frameBufferProperties.h" 00022 #include "graphicsThreadingModel.h" 00023 #include "sceneSetup.h" 00024 #include "pointerTo.h" 00025 #include "thread.h" 00026 #include "pmutex.h" 00027 #include "reMutex.h" 00028 #include "lightReMutex.h" 00029 #include "conditionVar.h" 00030 #include "pStatCollector.h" 00031 #include "pset.h" 00032 #include "ordered_vector.h" 00033 #include "indirectLess.h" 00034 #include "loader.h" 00035 #include "referenceCount.h" 00036 00037 class Pipeline; 00038 class DisplayRegion; 00039 class GraphicsPipe; 00040 class FrameBufferProperties; 00041 class Texture; 00042 00043 //////////////////////////////////////////////////////////////////// 00044 // Class : GraphicsEngine 00045 // Description : This class is the main interface to controlling the 00046 // render process. There is typically only one 00047 // GraphicsEngine in an application, and it synchronizes 00048 // rendering to all all of the active windows; although 00049 // it is possible to have multiple GraphicsEngine 00050 // objects if multiple synchronicity groups are 00051 // required. 00052 // 00053 // The GraphicsEngine is responsible for managing the 00054 // various cull and draw threads. The application 00055 // simply calls engine->render_frame() and considers it 00056 // done. 00057 //////////////////////////////////////////////////////////////////// 00058 class EXPCL_PANDA_DISPLAY GraphicsEngine : public ReferenceCount { 00059 PUBLISHED: 00060 GraphicsEngine(Pipeline *pipeline = NULL); 00061 ~GraphicsEngine(); 00062 00063 void set_threading_model(const GraphicsThreadingModel &threading_model); 00064 GraphicsThreadingModel get_threading_model() const; 00065 00066 INLINE const ReMutex &get_render_lock() const; 00067 00068 INLINE void set_auto_flip(bool auto_flip); 00069 INLINE bool get_auto_flip() const; 00070 00071 INLINE void set_portal_cull(bool value); 00072 INLINE bool get_portal_cull() const; 00073 00074 INLINE void set_default_loader(Loader *loader); 00075 INLINE Loader *get_default_loader() const; 00076 00077 GraphicsOutput *make_output(GraphicsPipe *pipe, 00078 const string &name, int sort, 00079 const FrameBufferProperties &fb_prop, 00080 const WindowProperties &win_prop, 00081 int flags, GraphicsStateGuardian *gsg = NULL, 00082 GraphicsOutput *host = NULL); 00083 00084 // Syntactic shorthand versions of make_output 00085 INLINE GraphicsOutput *make_buffer(GraphicsOutput *host, 00086 const string &name, int sort, 00087 int x_size, int y_size); 00088 INLINE GraphicsOutput *make_buffer(GraphicsStateGuardian *gsg, 00089 const string &name, int sort, 00090 int x_size, int y_size); 00091 INLINE GraphicsOutput *make_parasite(GraphicsOutput *host, 00092 const string &name, int sort, 00093 int x_size, int y_size); 00094 00095 bool remove_window(GraphicsOutput *window); 00096 void remove_all_windows(); 00097 void reset_all_windows(bool swapchain); 00098 00099 bool is_empty() const; 00100 int get_num_windows() const; 00101 GraphicsOutput *get_window(int n) const; 00102 MAKE_SEQ(get_windows, get_num_windows, get_window); 00103 00104 BLOCKING void render_frame(); 00105 BLOCKING void open_windows(); 00106 BLOCKING void sync_frame(); 00107 BLOCKING void ready_flip(); 00108 BLOCKING void flip_frame(); 00109 00110 bool extract_texture_data(Texture *tex, GraphicsStateGuardian *gsg); 00111 00112 static GraphicsEngine *get_global_ptr(); 00113 00114 public: 00115 enum ThreadState { 00116 TS_wait, 00117 TS_do_frame, 00118 TS_do_flip, 00119 TS_do_release, 00120 TS_do_windows, 00121 TS_terminate, 00122 TS_done 00123 }; 00124 00125 void texture_uploaded(Texture *tex); 00126 00127 public: 00128 static void do_cull(CullHandler *cull_handler, SceneSetup *scene_setup, 00129 GraphicsStateGuardian *gsg, Thread *current_thread); 00130 00131 private: 00132 typedef ov_set< PT(GraphicsOutput), IndirectLess<GraphicsOutput> > Windows; 00133 typedef pset< PT(GraphicsStateGuardian) > GSGs; 00134 00135 static bool scene_root_func(const PandaNode *node); 00136 bool is_scene_root(const PandaNode *node); 00137 00138 void set_window_sort(GraphicsOutput *window, int sort); 00139 00140 void cull_and_draw_together(const Windows &wlist, Thread *current_thread); 00141 void cull_and_draw_together(GraphicsOutput *win, DisplayRegion *dr, 00142 Thread *current_thread); 00143 00144 void cull_to_bins(const Windows &wlist, Thread *current_thread); 00145 void cull_to_bins(GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread); 00146 void draw_bins(const Windows &wlist, Thread *current_thread); 00147 void draw_bins(GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread); 00148 void make_contexts(const Windows &wlist, Thread *current_thread); 00149 00150 void process_events(const Windows &wlist, Thread *current_thread); 00151 void ready_flip_windows(const Windows &wlist, Thread *current_thread); 00152 void flip_windows(const Windows &wlist, Thread *current_thread); 00153 void do_sync_frame(Thread *current_thread); 00154 void do_ready_flip(Thread *current_thread); 00155 void do_flip_frame(Thread *current_thread); 00156 INLINE void close_gsg(GraphicsPipe *pipe, GraphicsStateGuardian *gsg); 00157 00158 PT(SceneSetup) setup_scene(GraphicsStateGuardian *gsg, 00159 DisplayRegionPipelineReader *dr); 00160 void do_draw(CullResult *cull_result, SceneSetup *scene_setup, 00161 GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread); 00162 00163 void do_add_window(GraphicsOutput *window, 00164 const GraphicsThreadingModel &threading_model); 00165 void do_add_gsg(GraphicsStateGuardian *gsg, GraphicsPipe *pipe, 00166 const GraphicsThreadingModel &threading_model); 00167 void do_remove_window(GraphicsOutput *window, Thread *current_thread); 00168 void do_resort_windows(); 00169 void terminate_threads(Thread *current_thread); 00170 void auto_adjust_capabilities(GraphicsStateGuardian *gsg); 00171 00172 #ifdef DO_PSTATS 00173 typedef map<TypeHandle, PStatCollector> CyclerTypeCounters; 00174 CyclerTypeCounters _all_cycler_types; 00175 CyclerTypeCounters _dirty_cycler_types; 00176 static void pstats_count_cycler_type(TypeHandle type, int count, void *data); 00177 static void pstats_count_dirty_cycler_type(TypeHandle type, int count, void *data); 00178 #endif // DO_PSTATS 00179 00180 static const RenderState *get_invert_polygon_state(); 00181 00182 // The WindowRenderer class records the stages of the pipeline that 00183 // each thread (including the main thread, a.k.a. "app") should 00184 // process, and the list of windows for each stage. 00185 00186 // There is one WindowRenderer instance for app, and another 00187 // instance for each thread (the thread-specific WindowRenderers are 00188 // actually instances of RenderThread, below, which inherits from 00189 // WindowRenderer). 00190 00191 // The idea is that each window is associated with one or more 00192 // WindowRenderer objects, according to the threads in which its 00193 // rendering tasks (window, cull, and draw) are divided into. 00194 00195 // The "window" task is responsible for doing any updates to the 00196 // window itself, such as size and placement, and is wholly 00197 // responsible for any API calls to the windowing system itself, 00198 // unrelated to OpenGL-type calls. This is normally done in app 00199 // (the design of X-Windows is such that all X calls must be issued 00200 // in the same thread). 00201 00202 // The "cull" task is responsible for crawling through the scene 00203 // graph and discovering all of the Geoms that are within the 00204 // viewing frustum. It assembles all such Geoms, along with their 00205 // computed net state and transform, in a linked list of 00206 // CullableObjects, which it stores for the "draw" task, next. 00207 00208 // The "draw" task is responsible for walking through the list of 00209 // CullableObjects recorded by the cull task, and issuing the 00210 // appropriate graphics commands to draw them. 00211 00212 // There is an additional task, not often used, called "cdraw". 00213 // This task, if activated, will crawl through the scene graph and 00214 // issue graphics commands immediately, as each Geom is discovered. 00215 // It is only rarely used because it cannot perform sorting beyond 00216 // basic scene graph order, making it less useful than a separate 00217 // cull and draw task. 00218 00219 // It is possible for all three of the normal tasks: window, cull, 00220 // and draw, to be handled by the same thread. This is the normal, 00221 // single-threaded model: all tasks are handled by the app thread. 00222 // In this case, the window will be added to _app's _window, _cull, 00223 // and _draw lists. 00224 00225 // On the other hand, a window's tasks may also be distributed among 00226 // as many as three threads. For instance, if the window is listed 00227 // on _app's _window list, but on thread A's _cull list, and thread 00228 // B's _draw list, then the window task will be handled in the app 00229 // thread, while the cull task will be handled by thread A, and the 00230 // draw task will be handled (in parallel) by thread B. (In order 00231 // for this to work, it will be necessary that thread A and B are 00232 // configured to view different stages of the graphics pipeline. 00233 // This is a more advanced topic than there is room to discuss in 00234 // this comment.) 00235 00236 // Manipulation of the various window lists in each WindowRenderer 00237 // object is always performed in the app thread. The auxiliary 00238 // threads are slaves to the app thread, and they can only perform 00239 // one of a handful of specified tasks, none of which includes 00240 // adding or removing windows from its lists. The full set of tasks 00241 // that a WindowRenderer may perform is enumerated in ThreadState, 00242 // above; see RenderThread::thread_main(). 00243 00244 // There is a pair of condition variables for each thread, _cv_start 00245 // and _cv_done, that is used to synchronize requests made by app to 00246 // a particular thread. The usual procedure to request a thread to 00247 // perform a particular task is the following: the app thread waits 00248 // on the thread's _cv_done variable, stores the value corresponding 00249 // to the desired task in the thread's _thread_state value, then 00250 // signals the thread's _cv_start variable. The thread, in turn, 00251 // will perform its requested task, set its _thread_state to 00252 // TS_wait, and signal _cv_done. See examples in the code, 00253 // e.g. open_windows(), for more details on this process. 00254 00255 // It is of course not necessary to signal any threads in order to 00256 // perform tasks listed in the _app WindowRenderer. For this object 00257 // only, we simply call the appropriate methods on _app when we want 00258 // the tasks to be performed. 00259 00260 class WindowRenderer { 00261 public: 00262 WindowRenderer(const string &name); 00263 00264 void add_gsg(GraphicsStateGuardian *gsg); 00265 void add_window(Windows &wlist, GraphicsOutput *window); 00266 void remove_window(GraphicsOutput *window); 00267 void resort_windows(); 00268 void do_frame(GraphicsEngine *engine, Thread *current_thread); 00269 void do_windows(GraphicsEngine *engine, Thread *current_thread); 00270 void do_ready_flip(GraphicsEngine *engine, Thread *current_thread); 00271 void do_flip(GraphicsEngine *engine, Thread *current_thread); 00272 void do_release(GraphicsEngine *engine, Thread *current_thread); 00273 void do_close(GraphicsEngine *engine, Thread *current_thread); 00274 void do_pending(GraphicsEngine *engine, Thread *current_thread); 00275 bool any_done_gsgs() const; 00276 00277 public: 00278 Windows _cull; // cull stage 00279 Windows _cdraw; // cull-and-draw-together stage 00280 Windows _draw; // draw stage 00281 Windows _window; // window stage, i.e. process windowing events 00282 00283 // These are not kept sorted. 00284 Windows _pending_close; // moved from _window, pending close. 00285 00286 GSGs _gsgs; // draw stage 00287 00288 LightReMutex _wl_lock; 00289 }; 00290 00291 class RenderThread : public Thread, public WindowRenderer { 00292 public: 00293 RenderThread(const string &name, GraphicsEngine *engine); 00294 virtual void thread_main(); 00295 00296 GraphicsEngine *_engine; 00297 Mutex _cv_mutex; 00298 ConditionVar _cv_start; 00299 ConditionVar _cv_done; 00300 ThreadState _thread_state; 00301 }; 00302 00303 WindowRenderer *get_window_renderer(const string &name, int pipeline_stage); 00304 00305 Pipeline *_pipeline; 00306 Windows _windows; 00307 bool _windows_sorted; 00308 unsigned int _window_sort_index; 00309 bool _needs_open_windows; 00310 00311 WindowRenderer _app; 00312 typedef pmap<string, PT(RenderThread) > Threads; 00313 Threads _threads; 00314 GraphicsThreadingModel _threading_model; 00315 bool _auto_flip; 00316 bool _portal_enabled; //toggle to portal culling on/off 00317 PT(Loader) _default_loader; 00318 00319 enum FlipState { 00320 FS_draw, // Still drawing. 00321 FS_sync, // All windows are done drawing. 00322 FS_flip, // All windows are done drawing and have flipped. 00323 }; 00324 FlipState _flip_state; 00325 00326 bool _singular_warning_last_frame; 00327 bool _singular_warning_this_frame; 00328 00329 ReMutex _lock; 00330 ReMutex _public_lock; 00331 00332 class LoadedTexture { 00333 public: 00334 PT(Texture) _tex; 00335 UpdateSeq _image_modified; 00336 }; 00337 typedef pvector<LoadedTexture> LoadedTextures; 00338 LoadedTextures _loaded_textures; 00339 Mutex _loaded_textures_lock; 00340 00341 static PT(GraphicsEngine) _global_ptr; 00342 00343 static PStatCollector _wait_pcollector; 00344 static PStatCollector _cycle_pcollector; 00345 static PStatCollector _app_pcollector; 00346 static PStatCollector _render_frame_pcollector; 00347 static PStatCollector _do_frame_pcollector; 00348 static PStatCollector _yield_pcollector; 00349 static PStatCollector _cull_pcollector; 00350 static PStatCollector _cull_setup_pcollector; 00351 static PStatCollector _cull_sort_pcollector; 00352 static PStatCollector _draw_pcollector; 00353 static PStatCollector _sync_pcollector; 00354 static PStatCollector _flip_pcollector; 00355 static PStatCollector _flip_begin_pcollector; 00356 static PStatCollector _flip_end_pcollector; 00357 static PStatCollector _transform_states_pcollector; 00358 static PStatCollector _transform_states_unused_pcollector; 00359 static PStatCollector _render_states_pcollector; 00360 static PStatCollector _render_states_unused_pcollector; 00361 static PStatCollector _cyclers_pcollector; 00362 static PStatCollector _dirty_cyclers_pcollector; 00363 static PStatCollector _delete_pcollector; 00364 00365 static PStatCollector _sw_sprites_pcollector; 00366 static PStatCollector _vertex_data_small_pcollector; 00367 static PStatCollector _vertex_data_independent_pcollector; 00368 static PStatCollector _vertex_data_pending_pcollector; 00369 static PStatCollector _vertex_data_resident_pcollector; 00370 static PStatCollector _vertex_data_compressed_pcollector; 00371 static PStatCollector _vertex_data_used_disk_pcollector; 00372 static PStatCollector _vertex_data_unused_disk_pcollector; 00373 00374 static PStatCollector _cnode_volume_pcollector; 00375 static PStatCollector _gnode_volume_pcollector; 00376 static PStatCollector _geom_volume_pcollector; 00377 static PStatCollector _node_volume_pcollector; 00378 static PStatCollector _volume_pcollector; 00379 static PStatCollector _test_pcollector; 00380 static PStatCollector _volume_polygon_pcollector; 00381 static PStatCollector _test_polygon_pcollector; 00382 static PStatCollector _volume_plane_pcollector; 00383 static PStatCollector _test_plane_pcollector; 00384 static PStatCollector _volume_sphere_pcollector; 00385 static PStatCollector _test_sphere_pcollector; 00386 static PStatCollector _volume_box_pcollector; 00387 static PStatCollector _test_box_pcollector; 00388 static PStatCollector _volume_tube_pcollector; 00389 static PStatCollector _test_tube_pcollector; 00390 static PStatCollector _volume_inv_sphere_pcollector; 00391 static PStatCollector _test_inv_sphere_pcollector; 00392 static PStatCollector _volume_geom_pcollector; 00393 static PStatCollector _test_geom_pcollector; 00394 00395 static PStatCollector _occlusion_untested_pcollector; 00396 static PStatCollector _occlusion_passed_pcollector; 00397 static PStatCollector _occlusion_failed_pcollector; 00398 static PStatCollector _occlusion_tests_pcollector; 00399 00400 friend class WindowRenderer; 00401 friend class GraphicsOutput; 00402 }; 00403 00404 #include "graphicsEngine.I" 00405 00406 #endif 00407