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   bool operator < (const RenderState &other) const;
00069   int compare_sort(const RenderState &other) const;
00070   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   void output(ostream &out) const;
00135   void write(ostream &out, int indent_level) const;
00136 
00137   static int get_max_priority();
00138 
00139   static int get_num_states();
00140   static int get_num_unused_states();
00141   static int clear_cache();
00142   static void clear_munger_cache();
00143   static void list_cycles(ostream &out);
00144   static void list_states(ostream &out);
00145   static bool validate_states();
00146 #ifdef HAVE_PYTHON
00147   static PyObject *get_states();
00148 #endif  // HAVE_PYTHON
00149 
00150 PUBLISHED:
00151   // These methods are intended for use by low-level code, but they're
00152   // also handy enough to expose to high-level users.
00153   INLINE int get_draw_order() const;
00154   INLINE int get_bin_index() const;
00155   int get_geom_rendering(int geom_rendering) const;
00156   
00157 public:
00158   static void bin_removed(int bin_index);
00159   
00160   INLINE static void flush_level();
00161 
00162 private:
00163   bool validate_filled_slots() const;
00164   INLINE bool do_cache_unref() const;
00165   INLINE bool do_node_unref() const;
00166 
00167   class CompositionCycleDescEntry {
00168   public:
00169     INLINE CompositionCycleDescEntry(const RenderState *obj,
00170                                      const RenderState *result,
00171                                      bool inverted);
00172 
00173     const RenderState *_obj;
00174     const RenderState *_result;
00175     bool _inverted;
00176   };
00177   typedef pvector<CompositionCycleDescEntry> CompositionCycleDesc;
00178 
00179   static CPT(RenderState) return_new(RenderState *state);
00180   static CPT(RenderState) return_unique(RenderState *state);
00181   CPT(RenderState) do_compose(const RenderState *other) const;
00182   CPT(RenderState) do_invert_compose(const RenderState *other) const;
00183   static bool r_detect_cycles(const RenderState *start_state,
00184                               const RenderState *current_state,
00185                               int length, UpdateSeq this_seq,
00186                               CompositionCycleDesc *cycle_desc);
00187   static bool r_detect_reverse_cycles(const RenderState *start_state,
00188                                       const RenderState *current_state,
00189                                       int length, UpdateSeq this_seq,
00190                                       CompositionCycleDesc *cycle_desc);
00191 
00192   void release_new();
00193   void remove_cache_pointers();
00194 
00195   void determine_bin_index();
00196   void determine_cull_callback();
00197   void fill_default();
00198 
00199   INLINE void set_destructing();
00200   INLINE bool is_destructing() const;
00201 
00202   INLINE void consider_update_pstats(int old_referenced_bits) const;
00203   static void update_pstats(int old_referenced_bits, int new_referenced_bits);
00204 
00205 public:
00206   static void init_states();
00207 
00208   // If this state contains an "auto" ShaderAttrib, then an explicit
00209   // ShaderAttrib will be synthesized by the runtime and stored here.
00210   // I can't declare this as a ShaderAttrib because that would create
00211   // a circular include-file dependency problem.  Aaargh.
00212   CPT(RenderAttrib) _generated_shader;
00213 
00214 private:
00215   // This mutex protects _states.  It also protects any modification
00216   // to the cache, which is encoded in _composition_cache and
00217   // _invert_composition_cache.
00218   static LightReMutex *_states_lock;
00219   typedef phash_set<const RenderState *, indirect_less_hash<const RenderState *> > States;
00220   static States *_states;
00221   static CPT(RenderState) _empty_state;
00222   static CPT(RenderState) _full_default_state;
00223 
00224   // This iterator records the entry corresponding to this RenderState
00225   // object in the above global set.  We keep the iterator around so
00226   // we can remove it when the RenderState destructs.
00227   States::iterator _saved_entry;
00228 
00229   // This data structure manages the job of caching the composition of
00230   // two RenderStates.  It's complicated because we have to be sure to
00231   // remove the entry if *either* of the input RenderStates destructs.
00232   // To implement this, we always record Composition entries in pairs,
00233   // one in each of the two involved RenderState objects.
00234   class Composition {
00235   public:
00236     INLINE Composition();
00237     INLINE Composition(const Composition &copy);
00238 
00239     // _result is reference counted if and only if it is not the same
00240     // pointer as this.
00241     const RenderState *_result;
00242   };
00243 
00244   // The first element of the map is the object we compose with.  This
00245   // is not reference counted within this map; instead we store a
00246   // companion pointer in the other object, and remove the references
00247   // explicitly when either object destructs.
00248   typedef SimpleHashMap<const RenderState *, Composition, pointer_hash> CompositionCache;
00249   CompositionCache _composition_cache;
00250   CompositionCache _invert_composition_cache;
00251 
00252   // This is here to provide a quick cache of GSG + RenderState ->
00253   // GeomMunger for the cull phase.  It is here because it is faster
00254   // to look up the GSG in the RenderState pointer than vice-versa,
00255   // since there are likely to be far fewer GSG's than RenderStates.
00256   // The code to manage this map lives in
00257   // GraphicsStateGuardian::get_geom_munger().
00258   typedef pmap<WCPT(GraphicsStateGuardianBase), PT(GeomMunger) > Mungers;
00259   Mungers _mungers;
00260   Mungers::const_iterator _last_mi;
00261 
00262   // This is used to mark nodes as we visit them to detect cycles.
00263   UpdateSeq _cycle_detect;
00264   static UpdateSeq _last_cycle_detect;
00265 
00266   static PStatCollector _cache_update_pcollector;
00267   static PStatCollector _state_compose_pcollector;
00268   static PStatCollector _state_invert_pcollector;
00269 
00270   static PStatCollector _node_counter;
00271   static PStatCollector _cache_counter;
00272 
00273 private:
00274   // This is the actual data within the RenderState: a set of
00275   // max_slots RenderAttribs.
00276   class Attribute {
00277   public:
00278     INLINE Attribute(const RenderAttrib *attrib, int override);
00279     INLINE Attribute(int override = 0);
00280     INLINE Attribute(const Attribute &copy);
00281     INLINE void operator = (const Attribute &copy);
00282     INLINE void set(const RenderAttrib *attrib, int override);
00283     INLINE int compare_to(const Attribute &other) const;
00284 
00285     CPT(RenderAttrib) _attrib;
00286     int _override;
00287   };
00288   Attribute *_attributes;
00289 
00290   // We also store a bitmask of the non-NULL attributes in the above
00291   // array.  This is redundant, but it is a useful cache.
00292   SlotMask _filled_slots;
00293 
00294   // We cache the index to the associated CullBin, if there happens to
00295   // be a CullBinAttrib in the state.
00296   int _bin_index;
00297   int _draw_order;
00298 
00299   enum Flags {
00300     F_checked_bin_index     = 0x000001,
00301     F_checked_cull_callback = 0x000002,
00302     F_has_cull_callback     = 0x000004,
00303     F_is_destructing        = 0x000008,
00304   };
00305   unsigned int _flags;
00306 
00307   vector_int *_read_overrides;  // Only used during bam reading.
00308 
00309   // This mutex protects _flags, and all of the above computed values.
00310   LightMutex _lock;
00311 
00312   static CacheStats _cache_stats;
00313 
00314 public:
00315   static void register_with_read_factory();
00316   virtual void write_datagram(BamWriter *manager, Datagram &dg);
00317   virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
00318   static TypedWritable *change_this(TypedWritable *old_ptr, BamReader *manager);
00319   virtual void finalize(BamReader *manager);
00320 
00321 protected:
00322   static TypedWritable *make_from_bam(const FactoryParams &params);
00323   void fillin(DatagramIterator &scan, BamReader *manager);
00324   
00325 public:
00326   static TypeHandle get_class_type() {
00327     return _type_handle;
00328   }
00329   static void init_type() {
00330     NodeCachedReferenceCount::init_type();
00331     register_type(_type_handle, "RenderState",
00332                   NodeCachedReferenceCount::get_class_type());
00333   }
00334   virtual TypeHandle get_type() const {
00335     return get_class_type();
00336   }
00337   virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
00338 
00339 private:
00340   static TypeHandle _type_handle;
00341 
00342   friend class GraphicsStateGuardian;
00343   friend class RenderAttribRegistry;
00344 };
00345 
00346 INLINE ostream &operator << (ostream &out, const RenderState &state) {
00347   state.output(out);
00348   return out;
00349 }
00350 
00351 #include "renderState.I"
00352 
00353 #endif
00354 
 All Classes Functions Variables Enumerations