Panda3D

renderState.h

00001 // Filename: renderState.h
00002 // Created by:  drose (21Feb02)
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 RENDERSTATE_H
00016 #define RENDERSTATE_H
00017 
00018 #include "pandabase.h"
00019 
00020 #include "renderAttrib.h"
00021 #include "nodeCachedReferenceCount.h"
00022 #include "pointerTo.h"
00023 #include "pvector.h"
00024 #include "updateSeq.h"
00025 #include "pStatCollector.h"
00026 #include "renderModeAttrib.h"
00027 #include "texMatrixAttrib.h"
00028 #include "geomMunger.h"
00029 #include "weakPointerTo.h"
00030 #include "lightReMutex.h"
00031 #include "lightMutex.h"
00032 #include "deletedChain.h"
00033 #include "simpleHashMap.h"
00034 #include "cacheStats.h"
00035 #include "renderAttribRegistry.h"
00036 
00037 class GraphicsStateGuardianBase;
00038 class FactoryParams;
00039 class ShaderAttrib;
00040 
00041 ////////////////////////////////////////////////////////////////////
00042 //       Class : RenderState
00043 // Description : This represents a unique collection of RenderAttrib
00044 //               objects that correspond to a particular renderable
00045 //               state.
00046 //
00047 //               You should not attempt to create or modify a
00048 //               RenderState object directly.  Instead, call one of
00049 //               the make() functions to create one for you.  And
00050 //               instead of modifying a RenderState object, create a
00051 //               new one.
00052 ////////////////////////////////////////////////////////////////////
00053 class EXPCL_PANDA_PGRAPH RenderState : public NodeCachedReferenceCount {
00054 protected:
00055   RenderState();
00056 
00057 private:
00058   RenderState(const RenderState &copy);
00059   void operator = (const RenderState &copy);
00060 
00061 public:
00062   virtual ~RenderState();
00063   ALLOC_DELETED_CHAIN(RenderState);
00064 
00065   typedef RenderAttribRegistry::SlotMask SlotMask;
00066 
00067 PUBLISHED:
00068   int compare_to(const RenderState &other) const;
00069   int compare_sort(const RenderState &other) const;
00070   INLINE size_t get_hash() const;
00071 
00072   INLINE bool is_empty() const;
00073 
00074   INLINE bool has_cull_callback() const;
00075   bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const;
00076 
00077   static CPT(RenderState) make_empty();
00078   static CPT(RenderState) make_full_default();
00079   static CPT(RenderState) make(const RenderAttrib *attrib, int override = 0);
00080   static CPT(RenderState) make(const RenderAttrib *attrib1,
00081                                const RenderAttrib *attrib2, int override = 0);
00082   static CPT(RenderState) make(const RenderAttrib *attrib1,
00083                                const RenderAttrib *attrib2,
00084                                const RenderAttrib *attrib3, int override = 0);
00085   static CPT(RenderState) make(const RenderAttrib *attrib1,
00086                                const RenderAttrib *attrib2,
00087                                const RenderAttrib *attrib3,
00088                                const RenderAttrib *attrib4, int override = 0);
00089   static CPT(RenderState) make(const RenderAttrib * const *attrib,
00090                                int num_attribs, int override = 0);
00091   
00092   CPT(RenderState) compose(const RenderState *other) const;
00093   CPT(RenderState) invert_compose(const RenderState *other) const;
00094 
00095   CPT(RenderState) add_attrib(const RenderAttrib *attrib, int override = 0) const;
00096   CPT(RenderState) set_attrib(const RenderAttrib *attrib) const;
00097   CPT(RenderState) set_attrib(const RenderAttrib *attrib, int override) const;
00098   INLINE CPT(RenderState) remove_attrib(TypeHandle type) const;
00099   CPT(RenderState) remove_attrib(int slot) const;
00100 
00101   CPT(RenderState) adjust_all_priorities(int adjustment) const;
00102 
00103   INLINE bool has_attrib(TypeHandle type) const;
00104   INLINE bool has_attrib(int slot) const;
00105   INLINE const RenderAttrib *get_attrib(TypeHandle type) const;
00106   INLINE const RenderAttrib *get_attrib(int slot) const;
00107   INLINE const RenderAttrib *get_attrib_def(int slot) const;
00108   INLINE int get_override(TypeHandle type) const;
00109   INLINE int get_override(int slot) const;
00110 
00111   INLINE CPT(RenderState) get_unique() const;
00112 
00113   virtual bool unref() const;
00114 
00115   INLINE void cache_ref() const;
00116   INLINE bool cache_unref() const;
00117   INLINE void node_ref() const;
00118   INLINE bool node_unref() const;
00119 
00120   INLINE int get_composition_cache_num_entries() const;
00121   INLINE int get_invert_composition_cache_num_entries() const;
00122 
00123   INLINE int get_composition_cache_size() const;
00124   INLINE const RenderState *get_composition_cache_source(int n) const;
00125   INLINE const RenderState *get_composition_cache_result(int n) const;
00126   INLINE int get_invert_composition_cache_size() const;
00127   INLINE const RenderState *get_invert_composition_cache_source(int n) const;
00128   INLINE const RenderState *get_invert_composition_cache_result(int n) const;
00129 #ifdef HAVE_PYTHON
00130   PyObject *get_composition_cache() const;
00131   PyObject *get_invert_composition_cache() const;
00132 #endif  // HAVE_PYTHON
00133 
00134   const RenderState *get_auto_shader_state() const;
00135 
00136   void output(ostream &out) const;
00137   void write(ostream &out, int indent_level) const;
00138 
00139   static int get_max_priority();
00140 
00141   static int get_num_states();
00142   static int get_num_unused_states();
00143   static int clear_cache();
00144   static void clear_munger_cache();
00145   static int garbage_collect();
00146   static void list_cycles(ostream &out);
00147   static void list_states(ostream &out);
00148   static bool validate_states();
00149 #ifdef HAVE_PYTHON
00150   static PyObject *get_states();
00151 #endif  // HAVE_PYTHON
00152 
00153 PUBLISHED:
00154   // These methods are intended for use by low-level code, but they're
00155   // also handy enough to expose to high-level users.
00156   INLINE int get_draw_order() const;
00157   INLINE int get_bin_index() const;
00158   int get_geom_rendering(int geom_rendering) const;
00159   
00160 public:
00161   static void bin_removed(int bin_index);
00162   
00163   INLINE static void flush_level();
00164 
00165 private:
00166   INLINE void check_hash() const;
00167   bool validate_filled_slots() const;
00168   INLINE bool do_cache_unref() const;
00169   INLINE bool do_node_unref() const;
00170   INLINE void calc_hash();
00171   void do_calc_hash();
00172   void assign_auto_shader_state();
00173   CPT(RenderState) do_calc_auto_shader_state();
00174 
00175   class CompositionCycleDescEntry {
00176   public:
00177     INLINE CompositionCycleDescEntry(const RenderState *obj,
00178                                      const RenderState *result,
00179                                      bool inverted);
00180 
00181     const RenderState *_obj;
00182     const RenderState *_result;
00183     bool _inverted;
00184   };
00185   typedef pvector<CompositionCycleDescEntry> CompositionCycleDesc;
00186 
00187   static CPT(RenderState) return_new(RenderState *state);
00188   static CPT(RenderState) return_unique(RenderState *state);
00189   CPT(RenderState) do_compose(const RenderState *other) const;
00190   CPT(RenderState) do_invert_compose(const RenderState *other) const;
00191   void detect_and_break_cycles();
00192   static bool r_detect_cycles(const RenderState *start_state,
00193                               const RenderState *current_state,
00194                               int length, UpdateSeq this_seq,
00195                               CompositionCycleDesc *cycle_desc);
00196   static bool r_detect_reverse_cycles(const RenderState *start_state,
00197                                       const RenderState *current_state,
00198                                       int length, UpdateSeq this_seq,
00199                                       CompositionCycleDesc *cycle_desc);
00200 
00201   void release_new();
00202   void remove_cache_pointers();
00203 
00204   void determine_bin_index();
00205   void determine_cull_callback();
00206   void fill_default();
00207 
00208   INLINE void set_destructing();
00209   INLINE bool is_destructing() const;
00210 
00211   INLINE void consider_update_pstats(int old_referenced_bits) const;
00212   static void update_pstats(int old_referenced_bits, int new_referenced_bits);
00213 
00214 public:
00215   static void init_states();
00216 
00217   // If this state contains an "auto" ShaderAttrib, then an explicit
00218   // ShaderAttrib will be synthesized by the runtime and stored here.
00219   // I can't declare this as a ShaderAttrib because that would create
00220   // a circular include-file dependency problem.  Aaargh.
00221   CPT(RenderAttrib) _generated_shader;
00222 
00223 private:
00224   // This mutex protects _states.  It also protects any modification
00225   // to the cache, which is encoded in _composition_cache and
00226   // _invert_composition_cache.
00227   static LightReMutex *_states_lock;
00228   class Empty {
00229   };
00230   typedef SimpleHashMap<const RenderState *, Empty, indirect_compare_to_hash<const RenderState *> > States;
00231   static States *_states;
00232   static CPT(RenderState) _empty_state;
00233   static CPT(RenderState) _full_default_state;
00234 
00235   // This iterator records the entry corresponding to this
00236   // RenderState object in the above global set.  We keep the index
00237   // around so we can remove it when the RenderState destructs.
00238   int _saved_entry;
00239 
00240   // This data structure manages the job of caching the composition of
00241   // two RenderStates.  It's complicated because we have to be sure to
00242   // remove the entry if *either* of the input RenderStates destructs.
00243   // To implement this, we always record Composition entries in pairs,
00244   // one in each of the two involved RenderState objects.
00245   class Composition {
00246   public:
00247     INLINE Composition();
00248     INLINE Composition(const Composition &copy);
00249 
00250     // _result is reference counted if and only if it is not the same
00251     // pointer as this.
00252     const RenderState *_result;
00253   };
00254 
00255   // The first element of the map is the object we compose with.  This
00256   // is not reference counted within this map; instead we store a
00257   // companion pointer in the other object, and remove the references
00258   // explicitly when either object destructs.
00259   typedef SimpleHashMap<const RenderState *, Composition, pointer_hash> CompositionCache;
00260   CompositionCache _composition_cache;
00261   CompositionCache _invert_composition_cache;
00262 
00263   // This is here to provide a quick cache of GSG + RenderState ->
00264   // GeomMunger for the cull phase.  It is here because it is faster
00265   // to look up the GSG in the RenderState pointer than vice-versa,
00266   // since there are likely to be far fewer GSG's than RenderStates.
00267   // The code to manage this map lives in
00268   // GraphicsStateGuardian::get_geom_munger().
00269   typedef pmap<WCPT(GraphicsStateGuardianBase), PT(GeomMunger) > Mungers;
00270   Mungers _mungers;
00271   Mungers::const_iterator _last_mi;
00272 
00273   // This is used to mark nodes as we visit them to detect cycles.
00274   UpdateSeq _cycle_detect;
00275   static UpdateSeq _last_cycle_detect;
00276 
00277   // This keeps track of our current position through the garbage
00278   // collection cycle.
00279   static int _garbage_index;
00280 
00281   static PStatCollector _cache_update_pcollector;
00282   static PStatCollector _garbage_collect_pcollector;
00283   static PStatCollector _state_compose_pcollector;
00284   static PStatCollector _state_invert_pcollector;
00285   static PStatCollector _state_break_cycles_pcollector;
00286   static PStatCollector _state_validate_pcollector;
00287 
00288   static PStatCollector _node_counter;
00289   static PStatCollector _cache_counter;
00290 
00291 private:
00292   // This is the actual data within the RenderState: a set of
00293   // max_slots RenderAttribs.
00294   class Attribute {
00295   public:
00296     INLINE Attribute(const RenderAttrib *attrib, int override);
00297     INLINE Attribute(int override = 0);
00298     INLINE Attribute(const Attribute &copy);
00299     INLINE void operator = (const Attribute &copy);
00300     INLINE void set(const RenderAttrib *attrib, int override);
00301     INLINE int compare_to(const Attribute &other) const;
00302 
00303     CPT(RenderAttrib) _attrib;
00304     int _override;
00305   };
00306   Attribute *_attributes;
00307 
00308   // We also store a bitmask of the non-NULL attributes in the above
00309   // array.  This is redundant, but it is a useful cache.
00310   SlotMask _filled_slots;
00311 
00312   // We cache the index to the associated CullBin, if there happens to
00313   // be a CullBinAttrib in the state.
00314   int _bin_index;
00315   int _draw_order;
00316   size_t _hash;
00317 
00318   const RenderState *_auto_shader_state;
00319 
00320   enum Flags {
00321     F_checked_bin_index       = 0x000001,
00322     F_checked_cull_callback   = 0x000002,
00323     F_has_cull_callback       = 0x000004,
00324     F_is_destructing          = 0x000008,
00325     F_hash_known              = 0x000010,
00326   };
00327   unsigned int _flags;
00328 
00329   vector_int *_read_overrides;  // Only used during bam reading.
00330 
00331   // This mutex protects _flags, and all of the above computed values.
00332   LightMutex _lock;
00333 
00334   static CacheStats _cache_stats;
00335 
00336 public:
00337   static void register_with_read_factory();
00338   virtual void write_datagram(BamWriter *manager, Datagram &dg);
00339   virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
00340   static TypedWritable *change_this(TypedWritable *old_ptr, BamReader *manager);
00341   virtual void finalize(BamReader *manager);
00342 
00343 protected:
00344   static TypedWritable *make_from_bam(const FactoryParams &params);
00345   void fillin(DatagramIterator &scan, BamReader *manager);
00346   
00347 public:
00348   static TypeHandle get_class_type() {
00349     return _type_handle;
00350   }
00351   static void init_type() {
00352     NodeCachedReferenceCount::init_type();
00353     register_type(_type_handle, "RenderState",
00354                   NodeCachedReferenceCount::get_class_type());
00355   }
00356   virtual TypeHandle get_type() const {
00357     return get_class_type();
00358   }
00359   virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
00360 
00361 private:
00362   static TypeHandle _type_handle;
00363 
00364   friend class GraphicsStateGuardian;
00365   friend class RenderAttribRegistry;
00366 };
00367 
00368 INLINE ostream &operator << (ostream &out, const RenderState &state) {
00369   state.output(out);
00370   return out;
00371 }
00372 
00373 #include "renderState.I"
00374 
00375 #endif
00376 
 All Classes Functions Variables Enumerations