Panda3D
|
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 ©); 00059 void operator = (const RenderState ©); 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 ©); 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 ©); 00299 INLINE void operator = (const Attribute ©); 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 ¶ms); 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