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