Panda3D

graphicsEngine.h

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 
 All Classes Functions Variables Enumerations