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