Panda3D
 All Classes Functions Variables Enumerations
renderState.cxx
00001 // Filename: renderState.cxx
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 #include "renderState.h"
00016 #include "transparencyAttrib.h"
00017 #include "cullBinAttrib.h"
00018 #include "cullBinManager.h"
00019 #include "fogAttrib.h"
00020 #include "clipPlaneAttrib.h"
00021 #include "scissorAttrib.h"
00022 #include "transparencyAttrib.h"
00023 #include "colorAttrib.h"
00024 #include "colorScaleAttrib.h"
00025 #include "textureAttrib.h"
00026 #include "texGenAttrib.h"
00027 #include "shaderAttrib.h"
00028 #include "pStatTimer.h"
00029 #include "config_pgraph.h"
00030 #include "bamReader.h"
00031 #include "bamWriter.h"
00032 #include "datagramIterator.h"
00033 #include "indent.h"
00034 #include "compareTo.h"
00035 #include "lightReMutexHolder.h"
00036 #include "lightMutexHolder.h"
00037 #include "thread.h"
00038 #include "renderAttribRegistry.h"
00039 #include "py_panda.h"
00040   
00041 LightReMutex *RenderState::_states_lock = NULL;
00042 RenderState::States *RenderState::_states = NULL;
00043 CPT(RenderState) RenderState::_empty_state;
00044 CPT(RenderState) RenderState::_full_default_state;
00045 UpdateSeq RenderState::_last_cycle_detect;
00046 int RenderState::_garbage_index = 0;
00047 
00048 PStatCollector RenderState::_cache_update_pcollector("*:State Cache:Update");
00049 PStatCollector RenderState::_garbage_collect_pcollector("*:State Cache:Garbage Collect");
00050 PStatCollector RenderState::_state_compose_pcollector("*:State Cache:Compose State");
00051 PStatCollector RenderState::_state_invert_pcollector("*:State Cache:Invert State");
00052 PStatCollector RenderState::_node_counter("RenderStates:On nodes");
00053 PStatCollector RenderState::_cache_counter("RenderStates:Cached");
00054 PStatCollector RenderState::_state_break_cycles_pcollector("*:State Cache:Break Cycles");
00055 PStatCollector RenderState::_state_validate_pcollector("*:State Cache:Validate");
00056 
00057 CacheStats RenderState::_cache_stats;
00058 
00059 TypeHandle RenderState::_type_handle;
00060 
00061 
00062 ////////////////////////////////////////////////////////////////////
00063 //     Function: RenderState::Constructor
00064 //       Access: Protected
00065 //  Description: Actually, this could be a private constructor, since
00066 //               no one inherits from RenderState, but gcc gives us a
00067 //               spurious warning if all constructors are private.
00068 ////////////////////////////////////////////////////////////////////
00069 RenderState::
00070 RenderState() : 
00071   _flags(0),
00072   _auto_shader_state(NULL),
00073   _lock("RenderState")
00074 {
00075   // Allocate the _attributes array.
00076   RenderAttribRegistry *reg = RenderAttribRegistry::get_global_ptr();
00077   _attributes = (Attribute *)reg->get_array_chain()->allocate(reg->get_max_slots() * sizeof(Attribute), get_class_type());
00078 
00079   // Also make sure each element gets initialized.
00080   for (int i = 0; i < reg->get_max_slots(); ++i) {
00081     new(&_attributes[i]) Attribute();
00082   }
00083 
00084   if (_states == (States *)NULL) {
00085     init_states();
00086   }
00087   _saved_entry = -1;
00088   _last_mi = _mungers.end();
00089   _cache_stats.add_num_states(1);
00090   _read_overrides = NULL;
00091   _generated_shader = NULL;
00092 }
00093 
00094 ////////////////////////////////////////////////////////////////////
00095 //     Function: RenderState::Copy Constructor
00096 //       Access: Private
00097 //  Description: RenderStates are only meant to be copied internally.
00098 ////////////////////////////////////////////////////////////////////
00099 RenderState::
00100 RenderState(const RenderState &copy) :
00101   _filled_slots(copy._filled_slots),
00102   _flags(0),
00103   _auto_shader_state(NULL),
00104   _lock("RenderState")
00105 {
00106   // Allocate the _attributes array.
00107   RenderAttribRegistry *reg = RenderAttribRegistry::get_global_ptr();
00108   _attributes = (Attribute *)reg->get_array_chain()->allocate(reg->get_max_slots() * sizeof(Attribute), get_class_type());
00109 
00110   // Also make sure each element gets initialized, as a copy.
00111   for (int i = 0; i < reg->get_max_slots(); ++i) {
00112     new(&_attributes[i]) Attribute(copy._attributes[i]);
00113   }
00114 
00115   _saved_entry = -1;
00116   _last_mi = _mungers.end();
00117   _cache_stats.add_num_states(1);
00118   _read_overrides = NULL;
00119   _generated_shader = NULL;
00120 }
00121 
00122 ////////////////////////////////////////////////////////////////////
00123 //     Function: RenderState::Copy Assignment Operator
00124 //       Access: Private
00125 //  Description: RenderStates are not meant to be copied.
00126 ////////////////////////////////////////////////////////////////////
00127 void RenderState::
00128 operator = (const RenderState &) {
00129   nassertv(false);
00130 }
00131 
00132 ////////////////////////////////////////////////////////////////////
00133 //     Function: RenderState::Destructor
00134 //       Access: Public, Virtual
00135 //  Description: The destructor is responsible for removing the
00136 //               RenderState from the global set if it is there.
00137 ////////////////////////////////////////////////////////////////////
00138 RenderState::
00139 ~RenderState() {
00140   // We'd better not call the destructor twice on a particular object.
00141   nassertv(!is_destructing());
00142   set_destructing();
00143 
00144   LightReMutexHolder holder(*_states_lock);
00145 
00146   // unref() should have cleared these.
00147   nassertv(_saved_entry == -1);
00148   nassertv(_composition_cache.is_empty() && _invert_composition_cache.is_empty());
00149 
00150   // Make sure the _auto_shader_state cache pointer is cleared.
00151   if (_auto_shader_state != (const RenderState *)NULL) {
00152     if (_auto_shader_state != this) {
00153       cache_unref_delete(_auto_shader_state);
00154     }
00155     _auto_shader_state = NULL;
00156   }
00157 
00158   // If this was true at the beginning of the destructor, but is no
00159   // longer true now, probably we've been double-deleted.
00160   nassertv(get_ref_count() == 0);
00161   _cache_stats.add_num_states(-1);
00162 
00163   // Free the _attributes array.
00164   RenderAttribRegistry *reg = RenderAttribRegistry::get_global_ptr();
00165   for (int i = 0; i < reg->get_max_slots(); ++i) {
00166     _attributes[i].~Attribute();
00167   }
00168   reg->get_array_chain()->deallocate(_attributes, get_class_type());
00169   _attributes = NULL;
00170 }
00171 
00172 ////////////////////////////////////////////////////////////////////
00173 //     Function: RenderState::compare_to
00174 //       Access: Published
00175 //  Description: Provides an arbitrary ordering among all unique
00176 //               RenderStates, so we can store the essentially
00177 //               different ones in a big set and throw away the rest.
00178 //
00179 //               This method is not needed outside of the RenderState
00180 //               class because all equivalent RenderState objects are
00181 //               guaranteed to share the same pointer; thus, a pointer
00182 //               comparison is always sufficient.
00183 ////////////////////////////////////////////////////////////////////
00184 int RenderState::
00185 compare_to(const RenderState &other) const {
00186   SlotMask mask = _filled_slots | other._filled_slots;
00187   int slot = mask.get_lowest_on_bit();
00188   while (slot >= 0) {
00189     int result = _attributes[slot].compare_to(other._attributes[slot]);
00190     if (result != 0) {
00191       return result;
00192     }
00193     mask.clear_bit(slot);
00194     slot = mask.get_lowest_on_bit();
00195   }
00196 
00197   return 0;
00198 }
00199 
00200 ////////////////////////////////////////////////////////////////////
00201 //     Function: RenderState::compare_sort
00202 //       Access: Published
00203 //  Description: Returns -1, 0, or 1 according to the relative sorting
00204 //               of these two RenderStates, with regards to rendering
00205 //               performance, so that "heavier" RenderAttribs (as
00206 //               defined by RenderAttribRegistry::get_slot_sort()) are
00207 //               more likely to be grouped together.  This is not
00208 //               related to the sorting order defined by compare_to.
00209 ////////////////////////////////////////////////////////////////////
00210 int RenderState::
00211 compare_sort(const RenderState &other) const {
00212   if (this == &other) {
00213     // Trivial case.
00214     return 0;
00215   }
00216 
00217   RenderAttribRegistry *reg = RenderAttribRegistry::quick_get_global_ptr();
00218   int num_sorted_slots = reg->get_num_sorted_slots();
00219   for (int n = 0; n < num_sorted_slots; ++n) {
00220     int slot = reg->get_sorted_slot(n);
00221     nassertr((_attributes[slot]._attrib != NULL) == _filled_slots.get_bit(slot), 0);
00222 
00223     const RenderAttrib *a = _attributes[slot]._attrib;
00224     const RenderAttrib *b = other._attributes[slot]._attrib;
00225     if (a != b) {
00226       return a < b ? -1 : 1;
00227     }
00228   }
00229 
00230   return 0;
00231 }
00232 
00233 ////////////////////////////////////////////////////////////////////
00234 //     Function: RenderState::cull_callback
00235 //       Access: Published
00236 //  Description: Calls cull_callback() on each attrib.  If any attrib
00237 //               returns false, interrupts the list and returns false
00238 //               immediately; otherwise, completes the list and
00239 //               returns true.
00240 ////////////////////////////////////////////////////////////////////
00241 bool RenderState::
00242 cull_callback(CullTraverser *trav, const CullTraverserData &data) const {
00243   SlotMask mask = _filled_slots;
00244   int slot = mask.get_lowest_on_bit();
00245   while (slot >= 0) {
00246     const Attribute &attrib = _attributes[slot];
00247     nassertr(attrib._attrib != NULL, false);
00248     if (!attrib._attrib->cull_callback(trav, data)) {
00249       return false;
00250     }
00251 
00252     mask.clear_bit(slot);
00253     slot = mask.get_lowest_on_bit();
00254   }
00255 
00256   return true;
00257 }
00258 
00259 ////////////////////////////////////////////////////////////////////
00260 //     Function: RenderState::make_empty
00261 //       Access: Published, Static
00262 //  Description: Returns a RenderState with no attributes set.
00263 ////////////////////////////////////////////////////////////////////
00264 CPT(RenderState) RenderState::
00265 make_empty() {
00266   // The empty state is asked for so often, we make it a special case
00267   // and store a pointer forever once we find it the first time.
00268   if (_empty_state == (RenderState *)NULL) {
00269     RenderState *state = new RenderState;
00270     _empty_state = return_unique(state);
00271   }
00272 
00273   return _empty_state;
00274 }
00275 
00276 ////////////////////////////////////////////////////////////////////
00277 //     Function: RenderState::make_full_default
00278 //       Access: Published, Static
00279 //  Description: Returns a RenderState with all possible attributes
00280 //               set to their default value.
00281 ////////////////////////////////////////////////////////////////////
00282 CPT(RenderState) RenderState::
00283 make_full_default() {
00284   // The empty state is asked for so often, we make it a special case
00285   // and store a pointer forever once we find it the first time.
00286   if (_full_default_state == (RenderState *)NULL) {
00287     RenderState *state = new RenderState;
00288     state->fill_default();
00289     _full_default_state = return_unique(state);
00290   }
00291 
00292   return _full_default_state;
00293 }
00294 
00295 ////////////////////////////////////////////////////////////////////
00296 //     Function: RenderState::make
00297 //       Access: Published, Static
00298 //  Description: Returns a RenderState with one attribute set.
00299 ////////////////////////////////////////////////////////////////////
00300 CPT(RenderState) RenderState::
00301 make(const RenderAttrib *attrib, int override) {
00302   RenderState *state = new RenderState;
00303   int slot = attrib->get_slot();
00304   state->_attributes[slot].set(attrib, override);
00305   state->_filled_slots.set_bit(slot);
00306   return return_new(state);
00307 }
00308 
00309 ////////////////////////////////////////////////////////////////////
00310 //     Function: RenderState::make
00311 //       Access: Published, Static
00312 //  Description: Returns a RenderState with two attributes set.
00313 ////////////////////////////////////////////////////////////////////
00314 CPT(RenderState) RenderState::
00315 make(const RenderAttrib *attrib1,
00316      const RenderAttrib *attrib2, int override) {
00317   RenderState *state = new RenderState;
00318   state->_attributes[attrib1->get_slot()].set(attrib1, override);
00319   state->_attributes[attrib2->get_slot()].set(attrib2, override);
00320   state->_filled_slots.set_bit(attrib1->get_slot());
00321   state->_filled_slots.set_bit(attrib2->get_slot());
00322   return return_new(state);
00323 }
00324 
00325 ////////////////////////////////////////////////////////////////////
00326 //     Function: RenderState::make
00327 //       Access: Published, Static
00328 //  Description: Returns a RenderState with three attributes set.
00329 ////////////////////////////////////////////////////////////////////
00330 CPT(RenderState) RenderState::
00331 make(const RenderAttrib *attrib1,
00332      const RenderAttrib *attrib2,
00333      const RenderAttrib *attrib3, int override) {
00334   RenderState *state = new RenderState;
00335   state->_attributes[attrib1->get_slot()].set(attrib1, override);
00336   state->_attributes[attrib2->get_slot()].set(attrib2, override);
00337   state->_attributes[attrib3->get_slot()].set(attrib3, override);
00338   state->_filled_slots.set_bit(attrib1->get_slot());
00339   state->_filled_slots.set_bit(attrib2->get_slot());
00340   state->_filled_slots.set_bit(attrib3->get_slot());
00341   return return_new(state);
00342 }
00343 
00344 ////////////////////////////////////////////////////////////////////
00345 //     Function: RenderState::make
00346 //       Access: Published, Static
00347 //  Description: Returns a RenderState with four attributes set.
00348 ////////////////////////////////////////////////////////////////////
00349 CPT(RenderState) RenderState::
00350 make(const RenderAttrib *attrib1,
00351      const RenderAttrib *attrib2,
00352      const RenderAttrib *attrib3,
00353      const RenderAttrib *attrib4, int override) {
00354   RenderState *state = new RenderState;
00355   state->_attributes[attrib1->get_slot()].set(attrib1, override);
00356   state->_attributes[attrib2->get_slot()].set(attrib2, override);
00357   state->_attributes[attrib3->get_slot()].set(attrib3, override);
00358   state->_attributes[attrib4->get_slot()].set(attrib4, override);
00359   state->_filled_slots.set_bit(attrib1->get_slot());
00360   state->_filled_slots.set_bit(attrib2->get_slot());
00361   state->_filled_slots.set_bit(attrib3->get_slot());
00362   state->_filled_slots.set_bit(attrib4->get_slot());
00363   return return_new(state);
00364 }
00365 
00366 ////////////////////////////////////////////////////////////////////
00367 //     Function: RenderState::make
00368 //       Access: Published, Static
00369 //  Description: Returns a RenderState with n attributes set.
00370 ////////////////////////////////////////////////////////////////////
00371 CPT(RenderState) RenderState::
00372 make(const RenderAttrib * const *attrib, int num_attribs, int override) {
00373   if (num_attribs == 0) {
00374     return make_empty();
00375   }
00376   RenderState *state = new RenderState;
00377   for (int i = 0; i < num_attribs; i++) {
00378     int slot = attrib[i]->get_slot();
00379     state->_attributes[slot].set(attrib[i], override);
00380     state->_filled_slots.set_bit(slot);
00381   }
00382   return return_new(state);
00383 }
00384 
00385 ////////////////////////////////////////////////////////////////////
00386 //     Function: RenderState::compose
00387 //       Access: Published
00388 //  Description: Returns a new RenderState object that represents the
00389 //               composition of this state with the other state.
00390 //
00391 //               The result of this operation is cached, and will be
00392 //               retained as long as both this RenderState object and
00393 //               the other RenderState object continue to exist.
00394 //               Should one of them destruct, the cached entry will be
00395 //               removed, and its pointer will be allowed to destruct
00396 //               as well.
00397 ////////////////////////////////////////////////////////////////////
00398 CPT(RenderState) RenderState::
00399 compose(const RenderState *other) const {
00400   // This method isn't strictly const, because it updates the cache,
00401   // but we pretend that it is because it's only a cache which is
00402   // transparent to the rest of the interface.
00403 
00404   // We handle empty state (identity) as a trivial special case.
00405   if (is_empty()) {
00406     return other;
00407   }
00408   if (other->is_empty()) {
00409     return this;
00410   }
00411 
00412   if (!state_cache) {
00413     return do_compose(other);
00414   }
00415 
00416   LightReMutexHolder holder(*_states_lock);
00417 
00418   // Is this composition already cached?
00419   int index = _composition_cache.find(other);
00420   if (index != -1) {
00421     Composition &comp = ((RenderState *)this)->_composition_cache.modify_data(index);
00422     if (comp._result == (const RenderState *)NULL) {
00423       // Well, it wasn't cached already, but we already had an entry
00424       // (probably created for the reverse direction), so use the same
00425       // entry to store the new result.
00426       CPT(RenderState) result = do_compose(other);
00427       comp._result = result;
00428 
00429       if (result != (const RenderState *)this) {
00430         // See the comments below about the need to up the reference
00431         // count only when the result is not the same as this.
00432         result->cache_ref();
00433       }
00434     }
00435     // Here's the cache!
00436     _cache_stats.inc_hits();
00437     return comp._result;
00438   }
00439   _cache_stats.inc_misses();
00440 
00441   // We need to make a new cache entry, both in this object and in the
00442   // other object.  We make both records so the other RenderState
00443   // object will know to delete the entry from this object when it
00444   // destructs, and vice-versa.
00445 
00446   // The cache entry in this object is the only one that indicates the
00447   // result; the other will be NULL for now.
00448   CPT(RenderState) result = do_compose(other);
00449 
00450   _cache_stats.add_total_size(1);
00451   _cache_stats.inc_adds(_composition_cache.get_size() == 0);
00452 
00453   ((RenderState *)this)->_composition_cache[other]._result = result;
00454 
00455   if (other != this) {
00456     _cache_stats.add_total_size(1);
00457     _cache_stats.inc_adds(other->_composition_cache.get_size() == 0);
00458     ((RenderState *)other)->_composition_cache[this]._result = NULL;
00459   }
00460 
00461   if (result != (const RenderState *)this) {
00462     // If the result of compose() is something other than this,
00463     // explicitly increment the reference count.  We have to be sure
00464     // to decrement it again later, when the composition entry is
00465     // removed from the cache.
00466     result->cache_ref();
00467     
00468     // (If the result was just this again, we still store the
00469     // result, but we don't increment the reference count, since
00470     // that would be a self-referential leak.)
00471   }
00472 
00473   _cache_stats.maybe_report("RenderState");
00474 
00475   return result;
00476 }
00477 
00478 ////////////////////////////////////////////////////////////////////
00479 //     Function: RenderState::invert_compose
00480 //       Access: Published
00481 //  Description: Returns a new RenderState object that represents the
00482 //               composition of this state's inverse with the other
00483 //               state.
00484 //
00485 //               This is similar to compose(), but is particularly
00486 //               useful for computing the relative state of a node as
00487 //               viewed from some other node.
00488 ////////////////////////////////////////////////////////////////////
00489 CPT(RenderState) RenderState::
00490 invert_compose(const RenderState *other) const {
00491   // This method isn't strictly const, because it updates the cache,
00492   // but we pretend that it is because it's only a cache which is
00493   // transparent to the rest of the interface.
00494 
00495   // We handle empty state (identity) as a trivial special case.
00496   if (is_empty()) {
00497     return other;
00498   }
00499   // Unlike compose(), the case of other->is_empty() is not quite as
00500   // trivial for invert_compose().
00501 
00502   if (other == this) {
00503     // a->invert_compose(a) always produces identity.
00504     return make_empty();
00505   }
00506 
00507   if (!state_cache) {
00508     return do_invert_compose(other);
00509   }
00510 
00511   LightReMutexHolder holder(*_states_lock);
00512 
00513   // Is this composition already cached?
00514   int index = _invert_composition_cache.find(other);
00515   if (index != -1) {
00516     Composition &comp = ((RenderState *)this)->_invert_composition_cache.modify_data(index);
00517     if (comp._result == (const RenderState *)NULL) {
00518       // Well, it wasn't cached already, but we already had an entry
00519       // (probably created for the reverse direction), so use the same
00520       // entry to store the new result.
00521       CPT(RenderState) result = do_invert_compose(other);
00522       comp._result = result;
00523 
00524       if (result != (const RenderState *)this) {
00525         // See the comments below about the need to up the reference
00526         // count only when the result is not the same as this.
00527         result->cache_ref();
00528       }
00529     }
00530     // Here's the cache!
00531     _cache_stats.inc_hits();
00532     return comp._result;
00533   }
00534   _cache_stats.inc_misses();
00535 
00536   // We need to make a new cache entry, both in this object and in the
00537   // other object.  We make both records so the other RenderState
00538   // object will know to delete the entry from this object when it
00539   // destructs, and vice-versa.
00540 
00541   // The cache entry in this object is the only one that indicates the
00542   // result; the other will be NULL for now.
00543   CPT(RenderState) result = do_invert_compose(other);
00544 
00545   _cache_stats.add_total_size(1);
00546   _cache_stats.inc_adds(_invert_composition_cache.get_size() == 0);
00547   ((RenderState *)this)->_invert_composition_cache[other]._result = result;
00548 
00549   if (other != this) {
00550     _cache_stats.add_total_size(1);
00551     _cache_stats.inc_adds(other->_invert_composition_cache.get_size() == 0);
00552     ((RenderState *)other)->_invert_composition_cache[this]._result = NULL;
00553   }
00554 
00555   if (result != (const RenderState *)this) {
00556     // If the result of compose() is something other than this,
00557     // explicitly increment the reference count.  We have to be sure
00558     // to decrement it again later, when the composition entry is
00559     // removed from the cache.
00560     result->cache_ref();
00561     
00562     // (If the result was just this again, we still store the
00563     // result, but we don't increment the reference count, since
00564     // that would be a self-referential leak.)
00565   }
00566 
00567   return result;
00568 }
00569 
00570 ////////////////////////////////////////////////////////////////////
00571 //     Function: RenderState::add_attrib
00572 //       Access: Published
00573 //  Description: Returns a new RenderState object that represents the
00574 //               same as the source state, with the new RenderAttrib
00575 //               added.  If there is already a RenderAttrib with the
00576 //               same type, it is replaced (unless the override is
00577 //               lower).
00578 ////////////////////////////////////////////////////////////////////
00579 CPT(RenderState) RenderState::
00580 add_attrib(const RenderAttrib *attrib, int override) const {
00581   int slot = attrib->get_slot();
00582   if (_filled_slots.get_bit(slot) &&
00583       _attributes[slot]._override > override) {
00584     // The existing attribute overrides.
00585     return this;
00586   }
00587 
00588   // The new attribute replaces.
00589   RenderState *new_state = new RenderState(*this);
00590   new_state->_attributes[slot].set(attrib, override);
00591   new_state->_filled_slots.set_bit(slot);
00592   return return_new(new_state);
00593 }
00594 
00595 ////////////////////////////////////////////////////////////////////
00596 //     Function: RenderState::set_attrib
00597 //       Access: Published
00598 //  Description: Returns a new RenderState object that represents the
00599 //               same as the source state, with the new RenderAttrib
00600 //               added.  If there is already a RenderAttrib with the
00601 //               same type, it is replaced unconditionally.  The
00602 //               override is not changed.
00603 ////////////////////////////////////////////////////////////////////
00604 CPT(RenderState) RenderState::
00605 set_attrib(const RenderAttrib *attrib) const {
00606   RenderState *new_state = new RenderState(*this);
00607   int slot = attrib->get_slot();
00608   new_state->_attributes[slot]._attrib = attrib;
00609   new_state->_filled_slots.set_bit(slot);
00610   return return_new(new_state);
00611 }
00612 
00613 ////////////////////////////////////////////////////////////////////
00614 //     Function: RenderState::set_attrib
00615 //       Access: Published
00616 //  Description: Returns a new RenderState object that represents the
00617 //               same as the source state, with the new RenderAttrib
00618 //               added.  If there is already a RenderAttrib with the
00619 //               same type, it is replaced unconditionally.  The
00620 //               override is also replaced unconditionally.
00621 ////////////////////////////////////////////////////////////////////
00622 CPT(RenderState) RenderState::
00623 set_attrib(const RenderAttrib *attrib, int override) const {
00624   RenderState *new_state = new RenderState(*this);
00625   int slot = attrib->get_slot();
00626   new_state->_attributes[slot].set(attrib, override);
00627   new_state->_filled_slots.set_bit(slot);
00628   return return_new(new_state);
00629 }
00630 
00631 ////////////////////////////////////////////////////////////////////
00632 //     Function: RenderState::remove_attrib
00633 //       Access: Published
00634 //  Description: Returns a new RenderState object that represents the
00635 //               same as the source state, with the indicated
00636 //               RenderAttrib removed.
00637 ////////////////////////////////////////////////////////////////////
00638 CPT(RenderState) RenderState::
00639 remove_attrib(int slot) const {
00640   if (_attributes[slot]._attrib == NULL) {
00641     // Already removed.
00642     return this;
00643   }
00644 
00645   // Will this bring us down to the empty state?
00646   if (_filled_slots.get_num_on_bits() == 1) {
00647     return make_empty();
00648   }
00649 
00650   RenderState *new_state = new RenderState(*this);
00651   new_state->_attributes[slot].set(NULL, 0);
00652   new_state->_filled_slots.clear_bit(slot);
00653   return return_new(new_state);
00654 }
00655 
00656 ////////////////////////////////////////////////////////////////////
00657 //     Function: RenderState::adjust_all_priorities
00658 //       Access: Published
00659 //  Description: Returns a new RenderState object that represents the
00660 //               same as the source state, with all attributes'
00661 //               override values incremented (or decremented, if
00662 //               negative) by the indicated amount.  If the override
00663 //               would drop below zero, it is set to zero.
00664 ////////////////////////////////////////////////////////////////////
00665 CPT(RenderState) RenderState::
00666 adjust_all_priorities(int adjustment) const {
00667   RenderState *new_state = new RenderState(*this);
00668 
00669   SlotMask mask = _filled_slots;
00670   int slot = mask.get_lowest_on_bit();
00671   while (slot >= 0) {
00672     Attribute &attrib = new_state->_attributes[slot];
00673     nassertr(attrib._attrib != (RenderAttrib *)NULL, this);
00674     attrib._override = max(attrib._override + adjustment, 0);
00675 
00676     mask.clear_bit(slot);
00677     slot = mask.get_lowest_on_bit();
00678   }
00679 
00680   return return_new(new_state);
00681 }
00682 
00683 ////////////////////////////////////////////////////////////////////
00684 //     Function: RenderState::unref
00685 //       Access: Published, Virtual
00686 //  Description: This method overrides ReferenceCount::unref() to
00687 //               check whether the remaining reference count is
00688 //               entirely in the cache, and if so, it checks for and
00689 //               breaks a cycle in the cache involving this object.
00690 //               This is designed to prevent leaks from cyclical
00691 //               references within the cache.
00692 ////////////////////////////////////////////////////////////////////
00693 bool RenderState::
00694 unref() const {
00695   if (!state_cache || garbage_collect_states) {
00696     // If we're not using the cache at all, or if we're relying on
00697     // garbage collection, just allow the pointer to unref normally.
00698     return ReferenceCount::unref();
00699   }
00700 
00701   // Here is the normal refcounting case, with a normal cache, and
00702   // without garbage collection in effect.  In this case we will pull
00703   // the object out of the cache when its reference count goes to 0.
00704 
00705   // We always have to grab the lock, since we will definitely need to
00706   // be holding it if we happen to drop the reference count to 0.
00707   // Having to grab the lock at every call to unref() is a big
00708   // limiting factor on parallelization.
00709   LightReMutexHolder holder(*_states_lock);
00710 
00711   if (auto_break_cycles && uniquify_states) {
00712     if (get_cache_ref_count() > 0 &&
00713         get_ref_count() == get_cache_ref_count() + 1) {
00714       // If we are about to remove the one reference that is not in the
00715       // cache, leaving only references in the cache, then we need to
00716       // check for a cycle involving this RenderState and break it if
00717       // it exists.
00718       ((RenderState *)this)->detect_and_break_cycles();
00719     }
00720   }
00721 
00722   if (ReferenceCount::unref()) {
00723     // The reference count is still nonzero.
00724     return true;
00725   }
00726 
00727   // The reference count has just reached zero.  Make sure the object
00728   // is removed from the global object pool, before anyone else finds
00729   // it and tries to ref it.
00730   ((RenderState *)this)->release_new();
00731   ((RenderState *)this)->remove_cache_pointers();
00732 
00733   return false;
00734 }
00735 
00736 #ifdef HAVE_PYTHON
00737 ////////////////////////////////////////////////////////////////////
00738 //     Function: RenderState::get_composition_cache
00739 //       Access: Published
00740 //  Description: Returns a list of 2-tuples that represents the
00741 //               composition cache.  For each tuple in the list, the
00742 //               first element is the source render, and the second
00743 //               is the result render.  If both are None, there is
00744 //               no entry in the cache at that slot.
00745 //
00746 //               In general, a->compose(source) == result.
00747 //
00748 //               This has no practical value other than for examining
00749 //               the cache for performance analysis.
00750 ////////////////////////////////////////////////////////////////////
00751 PyObject *RenderState::
00752 get_composition_cache() const {
00753   IMPORT_THIS struct Dtool_PyTypedObject Dtool_RenderState;
00754   LightReMutexHolder holder(*_states_lock);
00755   size_t cache_size = _composition_cache.get_size();
00756   PyObject *list = PyList_New(cache_size);
00757 
00758   for (size_t i = 0; i < cache_size; ++i) {
00759     PyObject *tuple = PyTuple_New(2);
00760     PyObject *a, *b;
00761     if (!_composition_cache.has_element(i)) {
00762       a = Py_None;
00763       Py_INCREF(a);
00764       b = Py_None;
00765       Py_INCREF(b);
00766     } else {
00767       const RenderState *source = _composition_cache.get_key(i);
00768       if (source == (RenderState *)NULL) {
00769         a = Py_None;
00770         Py_INCREF(a);
00771       } else {
00772         source->ref();
00773         a = DTool_CreatePyInstanceTyped((void *)source, Dtool_RenderState, 
00774                                         true, true, source->get_type_index());
00775       }
00776       const RenderState *result = _composition_cache.get_data(i)._result;
00777       if (result == (RenderState *)NULL) {
00778         b = Py_None;
00779         Py_INCREF(b);
00780       } else {
00781         result->ref();
00782         b = DTool_CreatePyInstanceTyped((void *)result, Dtool_RenderState, 
00783                                         true, true, result->get_type_index());
00784       }
00785     }
00786     PyTuple_SET_ITEM(tuple, 0, a);
00787     PyTuple_SET_ITEM(tuple, 1, b);
00788 
00789     PyList_SET_ITEM(list, i, tuple);
00790   }
00791 
00792   return list;
00793 }
00794 #endif  // HAVE_PYTHON
00795 
00796 #ifdef HAVE_PYTHON
00797 ////////////////////////////////////////////////////////////////////
00798 //     Function: RenderState::get_invert_composition_cache
00799 //       Access: Published
00800 //  Description: Returns a list of 2-tuples that represents the
00801 //               invert_composition cache.  For each tuple in the list, the
00802 //               first element is the source render, and the second
00803 //               is the result render.  If both are None, there is
00804 //               no entry in the cache at that slot.
00805 //
00806 //               In general, a->invert_compose(source) == result.
00807 //
00808 //               This has no practical value other than for examining
00809 //               the cache for performance analysis.
00810 ////////////////////////////////////////////////////////////////////
00811 PyObject *RenderState::
00812 get_invert_composition_cache() const {
00813   IMPORT_THIS struct Dtool_PyTypedObject Dtool_RenderState;
00814   LightReMutexHolder holder(*_states_lock);
00815   size_t cache_size = _invert_composition_cache.get_size();
00816   PyObject *list = PyList_New(cache_size);
00817 
00818   for (size_t i = 0; i < cache_size; ++i) {
00819     PyObject *tuple = PyTuple_New(2);
00820     PyObject *a, *b;
00821     if (!_invert_composition_cache.has_element(i)) {
00822       a = Py_None;
00823       Py_INCREF(a);
00824       b = Py_None;
00825       Py_INCREF(b);
00826     } else {
00827       const RenderState *source = _invert_composition_cache.get_key(i);
00828       if (source == (RenderState *)NULL) {
00829         a = Py_None;
00830         Py_INCREF(a);
00831       } else {
00832         source->ref();
00833         a = DTool_CreatePyInstanceTyped((void *)source, Dtool_RenderState, 
00834                                         true, true, source->get_type_index());
00835       }
00836       const RenderState *result = _invert_composition_cache.get_data(i)._result;
00837       if (result == (RenderState *)NULL) {
00838         b = Py_None;
00839         Py_INCREF(b);
00840       } else {
00841         result->ref();
00842         b = DTool_CreatePyInstanceTyped((void *)result, Dtool_RenderState, 
00843                                         true, true, result->get_type_index());
00844       }
00845     }
00846     PyTuple_SET_ITEM(tuple, 0, a);
00847     PyTuple_SET_ITEM(tuple, 1, b);
00848 
00849     PyList_SET_ITEM(list, i, tuple);
00850   }
00851 
00852   return list;
00853 }
00854 #endif  // HAVE_PYTHON
00855 
00856 ////////////////////////////////////////////////////////////////////
00857 //     Function: RenderState::get_auto_shader_state
00858 //       Access: Published
00859 //  Description: Returns the base RenderState that should have the
00860 //               generated_shader stored within it, for generated
00861 //               shader states.  The returned object might be the same
00862 //               as this object, or it might be a different
00863 //               RenderState with certain attributes removed, or set
00864 //               to their default values.
00865 //
00866 //               The point is to avoid needless regeneration of the
00867 //               shader attrib by storing the generated shader on a
00868 //               common RenderState object, with all irrelevant
00869 //               attributes removed.
00870 ////////////////////////////////////////////////////////////////////
00871 const RenderState *RenderState::
00872 get_auto_shader_state() const {
00873   if (_auto_shader_state == (const RenderState *)NULL) {
00874     ((RenderState *)this)->assign_auto_shader_state();
00875   }
00876   return _auto_shader_state;
00877 }
00878 
00879 ////////////////////////////////////////////////////////////////////
00880 //     Function: RenderState::output
00881 //       Access: Published
00882 //  Description: 
00883 ////////////////////////////////////////////////////////////////////
00884 void RenderState::
00885 output(ostream &out) const {
00886   out << "S:";
00887   if (is_empty()) {
00888     out << "(empty)";
00889 
00890   } else {
00891     out << "(";
00892     const char *sep = "";
00893 
00894     SlotMask mask = _filled_slots;
00895     int slot = mask.get_lowest_on_bit();
00896     while (slot >= 0) {
00897       const Attribute &attrib = _attributes[slot];
00898       nassertv(attrib._attrib != (RenderAttrib *)NULL);
00899       out << sep << attrib._attrib->get_type();
00900       sep = " ";
00901 
00902       mask.clear_bit(slot);
00903       slot = mask.get_lowest_on_bit();
00904     }
00905     out << ")";
00906   }
00907 }
00908 
00909 ////////////////////////////////////////////////////////////////////
00910 //     Function: RenderState::write
00911 //       Access: Published
00912 //  Description: 
00913 ////////////////////////////////////////////////////////////////////
00914 void RenderState::
00915 write(ostream &out, int indent_level) const {
00916   if (is_empty()) {
00917     indent(out, indent_level) 
00918       << "(empty)\n";
00919   }
00920 
00921   SlotMask mask = _filled_slots;
00922   int slot = mask.get_lowest_on_bit();
00923   while (slot >= 0) {
00924     const Attribute &attrib = _attributes[slot];
00925     nassertv(attrib._attrib != (RenderAttrib *)NULL);
00926     attrib._attrib->write(out, indent_level);
00927     
00928     mask.clear_bit(slot);
00929     slot = mask.get_lowest_on_bit();
00930   }
00931 }
00932 
00933 ////////////////////////////////////////////////////////////////////
00934 //     Function: RenderState::get_max_priority
00935 //       Access: Published, Static
00936 //  Description: Returns the maximum priority number (sometimes called
00937 //               override) that may be set on any node.  This may or
00938 //               may not be enforced, but the scene graph code assumes
00939 //               that no priority numbers will be larger than this,
00940 //               and some effects may not work properly if you use a
00941 //               larger number.
00942 ////////////////////////////////////////////////////////////////////
00943 int RenderState::
00944 get_max_priority() {
00945   return 1000000000;
00946 }
00947 
00948 ////////////////////////////////////////////////////////////////////
00949 //     Function: RenderState::get_num_states
00950 //       Access: Published, Static
00951 //  Description: Returns the total number of unique RenderState
00952 //               objects allocated in the world.  This will go up and
00953 //               down during normal operations.
00954 ////////////////////////////////////////////////////////////////////
00955 int RenderState::
00956 get_num_states() {
00957   if (_states == (States *)NULL) {
00958     return 0;
00959   }
00960   LightReMutexHolder holder(*_states_lock);
00961   return _states->get_num_entries();
00962 }
00963 
00964 ////////////////////////////////////////////////////////////////////
00965 //     Function: RenderState::get_num_unused_states
00966 //       Access: Published, Static
00967 //  Description: Returns the total number of RenderState objects that
00968 //               have been allocated but have no references outside of
00969 //               the internal RenderState cache.
00970 //
00971 //               A nonzero return value is not necessarily indicative
00972 //               of leaked references; it is normal for two
00973 //               RenderState objects, both of which have references
00974 //               held outside the cache, to have to result of their
00975 //               composition stored within the cache.  This result
00976 //               will be retained within the cache until one of the
00977 //               base RenderStates is released.
00978 //
00979 //               Use list_cycles() to get an idea of the number of
00980 //               actual "leaked" RenderState objects.
00981 ////////////////////////////////////////////////////////////////////
00982 int RenderState::
00983 get_num_unused_states() {
00984   if (_states == (States *)NULL) {
00985     return 0;
00986   }
00987   LightReMutexHolder holder(*_states_lock);
00988 
00989   // First, we need to count the number of times each RenderState
00990   // object is recorded in the cache.
00991   typedef pmap<const RenderState *, int> StateCount;
00992   StateCount state_count;
00993 
00994   int size = _states->get_size();
00995   for (int si = 0; si < size; ++si) {
00996     if (!_states->has_element(si)) {
00997       continue;
00998     }
00999     const RenderState *state = _states->get_key(si);
01000 
01001     int i;
01002     int cache_size = state->_composition_cache.get_size();
01003     for (i = 0; i < cache_size; ++i) {
01004       if (state->_composition_cache.has_element(i)) {
01005         const RenderState *result = state->_composition_cache.get_data(i)._result;
01006         if (result != (const RenderState *)NULL && result != state) {
01007           // Here's a RenderState that's recorded in the cache.
01008           // Count it.
01009           pair<StateCount::iterator, bool> ir =
01010             state_count.insert(StateCount::value_type(result, 1));
01011           if (!ir.second) {
01012             // If the above insert operation fails, then it's already in
01013             // the cache; increment its value.
01014             (*(ir.first)).second++;
01015           }
01016         }
01017       }
01018     }
01019     cache_size = state->_invert_composition_cache.get_size();
01020     for (i = 0; i < cache_size; ++i) {
01021       if (state->_invert_composition_cache.has_element(i)) {
01022         const RenderState *result = state->_invert_composition_cache.get_data(i)._result;
01023         if (result != (const RenderState *)NULL && result != state) {
01024           pair<StateCount::iterator, bool> ir =
01025             state_count.insert(StateCount::value_type(result, 1));
01026           if (!ir.second) {
01027             (*(ir.first)).second++;
01028           }
01029         }
01030       }
01031     }
01032   }
01033 
01034   // Now that we have the appearance count of each RenderState
01035   // object, we can tell which ones are unreferenced outside of the
01036   // RenderState cache, by comparing these to the reference counts.
01037   int num_unused = 0;
01038 
01039   StateCount::iterator sci;
01040   for (sci = state_count.begin(); sci != state_count.end(); ++sci) {
01041     const RenderState *state = (*sci).first;
01042     int count = (*sci).second;
01043     nassertr(count == state->get_cache_ref_count(), num_unused);
01044     nassertr(count <= state->get_ref_count(), num_unused);
01045     if (count == state->get_ref_count()) {
01046       num_unused++;
01047 
01048       if (pgraph_cat.is_debug()) {
01049         pgraph_cat.debug()
01050           << "Unused state: " << (void *)state << ":" 
01051           << state->get_ref_count() << " =\n";
01052         state->write(pgraph_cat.debug(false), 2);
01053       }
01054     }
01055   }
01056 
01057   return num_unused;
01058 }
01059 
01060 ////////////////////////////////////////////////////////////////////
01061 //     Function: RenderState::clear_cache
01062 //       Access: Published, Static
01063 //  Description: Empties the cache of composed RenderStates.  This
01064 //               makes every RenderState forget what results when
01065 //               it is composed with other RenderStates.
01066 //
01067 //               This will eliminate any RenderState objects that
01068 //               have been allocated but have no references outside of
01069 //               the internal RenderState map.  It will not
01070 //               eliminate RenderState objects that are still in
01071 //               use.
01072 //
01073 //               Nowadays, this method should not be necessary, as
01074 //               reference-count cycles in the composition cache
01075 //               should be automatically detected and broken.
01076 //
01077 //               The return value is the number of RenderStates
01078 //               freed by this operation.
01079 ////////////////////////////////////////////////////////////////////
01080 int RenderState::
01081 clear_cache() {
01082   if (_states == (States *)NULL) {
01083     return 0;
01084   }
01085   LightReMutexHolder holder(*_states_lock);
01086 
01087   PStatTimer timer(_cache_update_pcollector);
01088   int orig_size = _states->get_num_entries();
01089 
01090   // First, we need to copy the entire set of states to a temporary
01091   // vector, reference-counting each object.  That way we can walk
01092   // through the copy, without fear of dereferencing (and deleting)
01093   // the objects in the map as we go.
01094   {
01095     typedef pvector< CPT(RenderState) > TempStates;
01096     TempStates temp_states;
01097     temp_states.reserve(orig_size);
01098 
01099     int size = _states->get_size();
01100     for (int si = 0; si < size; ++si) {
01101       if (!_states->has_element(si)) {
01102         continue;
01103       }
01104       const RenderState *state = _states->get_key(si);
01105       temp_states.push_back(state);
01106     }
01107 
01108     // Now it's safe to walk through the list, destroying the cache
01109     // within each object as we go.  Nothing will be destructed till
01110     // we're done.
01111     TempStates::iterator ti;
01112     for (ti = temp_states.begin(); ti != temp_states.end(); ++ti) {
01113       RenderState *state = (RenderState *)(*ti).p();
01114 
01115       int i;
01116       int cache_size = state->_composition_cache.get_size();
01117       for (i = 0; i < cache_size; ++i) {
01118         if (state->_composition_cache.has_element(i)) {
01119           const RenderState *result = state->_composition_cache.get_data(i)._result;
01120           if (result != (const RenderState *)NULL && result != state) {
01121             result->cache_unref();
01122             nassertr(result->get_ref_count() > 0, 0);
01123           }
01124         }
01125       }
01126       _cache_stats.add_total_size(-state->_composition_cache.get_num_entries());
01127       state->_composition_cache.clear();
01128 
01129       cache_size = state->_invert_composition_cache.get_size();
01130       for (i = 0; i < cache_size; ++i) {
01131         if (state->_invert_composition_cache.has_element(i)) {
01132           const RenderState *result = state->_invert_composition_cache.get_data(i)._result;
01133           if (result != (const RenderState *)NULL && result != state) {
01134             result->cache_unref();
01135             nassertr(result->get_ref_count() > 0, 0);
01136           }
01137         }
01138       }
01139       _cache_stats.add_total_size(-state->_invert_composition_cache.get_num_entries());
01140       state->_invert_composition_cache.clear();
01141     }
01142 
01143     // Once this block closes and the temp_states object goes away,
01144     // all the destruction will begin.  Anything whose reference was
01145     // held only within the various objects' caches will go away.
01146   }
01147 
01148   int new_size = _states->get_num_entries();
01149   return orig_size - new_size;
01150 }
01151 
01152 ////////////////////////////////////////////////////////////////////
01153 //     Function: RenderState::garbage_collect
01154 //       Access: Published, Static
01155 //  Description: Performs a garbage-collection cycle.  This must be
01156 //               called periodically if garbage-collect-states is true
01157 //               to ensure that RenderStates get cleaned up
01158 //               appropriately.  It does no harm to call it even if
01159 //               this variable is not true, but there is probably no
01160 //               advantage in that case.
01161 //
01162 //               This automatically calls
01163 //               RenderAttrib::garbage_collect() as well.
01164 ////////////////////////////////////////////////////////////////////
01165 int RenderState::
01166 garbage_collect() {
01167   int num_attribs = RenderAttrib::garbage_collect();
01168 
01169   if (_states == (States *)NULL || !garbage_collect_states) {
01170     return num_attribs;
01171   }
01172   LightReMutexHolder holder(*_states_lock);
01173 
01174   PStatTimer timer(_garbage_collect_pcollector);
01175   int orig_size = _states->get_num_entries();
01176 
01177   // How many elements to process this pass?
01178   int size = _states->get_size();
01179   int num_this_pass = int(size * garbage_collect_states_rate);
01180   if (num_this_pass <= 0) {
01181     return num_attribs;
01182   }
01183   num_this_pass = min(num_this_pass, size);
01184   int stop_at_element = (_garbage_index + num_this_pass) % size;
01185   
01186   int num_elements = 0;
01187   int si = _garbage_index;
01188   do {
01189     if (_states->has_element(si)) {
01190       ++num_elements;
01191       RenderState *state = (RenderState *)_states->get_key(si);
01192       if (auto_break_cycles && uniquify_states) {
01193         if (state->get_cache_ref_count() > 0 &&
01194             state->get_ref_count() == state->get_cache_ref_count()) {
01195           // If we have removed all the references to this state not in
01196           // the cache, leaving only references in the cache, then we
01197           // need to check for a cycle involving this RenderState and
01198           // break it if it exists.
01199           state->detect_and_break_cycles();
01200         }
01201       }
01202 
01203       if (state->get_ref_count() == 1) {
01204         // This state has recently been unreffed to 1 (the one we
01205         // added when we stored it in the cache).  Now it's time to
01206         // delete it.  This is safe, because we're holding the
01207         // _states_lock, so it's not possible for some other thread to
01208         // find the state in the cache and ref it while we're doing
01209         // this.
01210         state->release_new();
01211         state->remove_cache_pointers();
01212         state->cache_unref();
01213         delete state;
01214       }
01215     }      
01216 
01217     si = (si + 1) % size;
01218   } while (si != stop_at_element);
01219   _garbage_index = si;
01220   nassertr(_states->validate(), 0);
01221 
01222   int new_size = _states->get_num_entries();
01223   return orig_size - new_size + num_attribs;
01224 }
01225 
01226 ////////////////////////////////////////////////////////////////////
01227 //     Function: RenderState::clear_munger_cache
01228 //       Access: Published, Static
01229 //  Description: Completely empties the cache of state + gsg ->
01230 //               munger, for all states and all gsg's.  Normally there
01231 //               is no need to empty this cache.
01232 ////////////////////////////////////////////////////////////////////
01233 void RenderState::
01234 clear_munger_cache() {
01235   LightReMutexHolder holder(*_states_lock);
01236 
01237   int size = _states->get_size();
01238   for (int si = 0; si < size; ++si) {
01239     if (!_states->has_element(si)) {
01240       continue;
01241     }
01242     RenderState *state = (RenderState *)(_states->get_key(si));
01243     state->_mungers.clear();
01244     state->_last_mi = state->_mungers.end();
01245   }
01246 }
01247 
01248 ////////////////////////////////////////////////////////////////////
01249 //     Function: RenderState::list_cycles
01250 //       Access: Published, Static
01251 //  Description: Detects all of the reference-count cycles in the
01252 //               cache and reports them to standard output.
01253 //
01254 //               These cycles may be inadvertently created when state
01255 //               compositions cycle back to a starting point.
01256 //               Nowadays, these cycles should be automatically
01257 //               detected and broken, so this method should never list
01258 //               any cycles unless there is a bug in that detection
01259 //               logic.
01260 //
01261 //               The cycles listed here are not leaks in the strictest
01262 //               sense of the word, since they can be reclaimed by a
01263 //               call to clear_cache(); but they will not be reclaimed
01264 //               automatically.
01265 ////////////////////////////////////////////////////////////////////
01266 void RenderState::
01267 list_cycles(ostream &out) {
01268   if (_states == (States *)NULL) {
01269     return;
01270   }
01271   LightReMutexHolder holder(*_states_lock);
01272 
01273   typedef pset<const RenderState *> VisitedStates;
01274   VisitedStates visited;
01275   CompositionCycleDesc cycle_desc;
01276 
01277   int size = _states->get_size();
01278   for (int si = 0; si < size; ++si) {
01279     if (!_states->has_element(si)) {
01280       continue;
01281     }
01282     const RenderState *state = _states->get_key(si);
01283 
01284     bool inserted = visited.insert(state).second;
01285     if (inserted) {
01286       ++_last_cycle_detect;
01287       if (r_detect_cycles(state, state, 1, _last_cycle_detect, &cycle_desc)) {
01288         // This state begins a cycle.
01289         CompositionCycleDesc::reverse_iterator csi;
01290 
01291         out << "\nCycle detected of length " << cycle_desc.size() + 1 << ":\n"
01292             << "state " << (void *)state << ":" << state->get_ref_count()
01293             << " =\n";
01294         state->write(out, 2);
01295         for (csi = cycle_desc.rbegin(); csi != cycle_desc.rend(); ++csi) {
01296           const CompositionCycleDescEntry &entry = (*csi);
01297           if (entry._inverted) {
01298             out << "invert composed with ";
01299           } else {
01300             out << "composed with ";
01301           }
01302           out << (const void *)entry._obj << ":" << entry._obj->get_ref_count()
01303               << " " << *entry._obj << "\n"
01304               << "produces " << (const void *)entry._result << ":"
01305               << entry._result->get_ref_count() << " =\n";
01306           entry._result->write(out, 2);
01307           visited.insert(entry._result);
01308         }
01309 
01310         cycle_desc.clear();
01311       } else {
01312         ++_last_cycle_detect;
01313         if (r_detect_reverse_cycles(state, state, 1, _last_cycle_detect, &cycle_desc)) {
01314           // This state begins a cycle.
01315           CompositionCycleDesc::iterator csi;
01316           
01317           out << "\nReverse cycle detected of length " << cycle_desc.size() + 1 << ":\n"
01318               << "state ";
01319           for (csi = cycle_desc.begin(); csi != cycle_desc.end(); ++csi) {
01320             const CompositionCycleDescEntry &entry = (*csi);
01321             out << (const void *)entry._result << ":"
01322                 << entry._result->get_ref_count() << " =\n";
01323             entry._result->write(out, 2);
01324             out << (const void *)entry._obj << ":"
01325                 << entry._obj->get_ref_count() << " =\n";
01326             entry._obj->write(out, 2);
01327             visited.insert(entry._result);
01328           }
01329           out << (void *)state << ":"
01330               << state->get_ref_count() << " =\n";
01331           state->write(out, 2);
01332           
01333           cycle_desc.clear();
01334         }
01335       }
01336     }
01337   }
01338 }
01339 
01340 
01341 ////////////////////////////////////////////////////////////////////
01342 //     Function: RenderState::list_states
01343 //       Access: Published, Static
01344 //  Description: Lists all of the RenderStates in the cache to the
01345 //               output stream, one per line.  This can be quite a lot
01346 //               of output if the cache is large, so be prepared.
01347 ////////////////////////////////////////////////////////////////////
01348 void RenderState::
01349 list_states(ostream &out) {
01350   if (_states == (States *)NULL) {
01351     out << "0 states:\n";
01352     return;
01353   }
01354   LightReMutexHolder holder(*_states_lock);
01355 
01356   out << _states->get_num_entries() << " states:\n";
01357 
01358   int size = _states->get_size();
01359   for (int si = 0; si < size; ++si) {
01360     if (!_states->has_element(si)) {
01361       continue;
01362     }
01363     const RenderState *state = _states->get_key(si);
01364     state->write(out, 2);
01365   }
01366 }
01367 
01368 ////////////////////////////////////////////////////////////////////
01369 //     Function: RenderState::validate_states
01370 //       Access: Published, Static
01371 //  Description: Ensures that the cache is still stored in sorted
01372 //               order, and that none of the cache elements have been
01373 //               inadvertently deleted.  Returns true if so, false if
01374 //               there is a problem (which implies someone has
01375 //               modified one of the supposedly-const RenderState
01376 //               objects).
01377 ////////////////////////////////////////////////////////////////////
01378 bool RenderState::
01379 validate_states() {
01380   if (_states == (States *)NULL) {
01381     return true;
01382   }
01383 
01384   PStatTimer timer(_state_validate_pcollector);
01385 
01386   LightReMutexHolder holder(*_states_lock);
01387   if (_states->is_empty()) {
01388     return true;
01389   }
01390 
01391   if (!_states->validate()) {
01392     pgraph_cat.error()
01393       << "RenderState::_states cache is invalid!\n";
01394     return false;
01395   }    
01396 
01397   int size = _states->get_size();
01398   int si = 0;
01399   while (si < size && !_states->has_element(si)) {
01400     ++si;
01401   }
01402   nassertr(si < size, false);
01403   nassertr(_states->get_key(si)->get_ref_count() >= 0, false);
01404   int snext = si;
01405   ++snext;
01406   while (snext < size && !_states->has_element(snext)) {
01407     ++snext;
01408   }
01409   while (snext < size) {
01410     nassertr(_states->get_key(snext)->get_ref_count() >= 0, false);
01411     const RenderState *ssi = _states->get_key(si);
01412     const RenderState *ssnext = _states->get_key(snext);
01413     int c = ssi->compare_to(*ssnext);
01414     int ci = ssnext->compare_to(*ssi);
01415     if ((ci < 0) != (c > 0) ||
01416         (ci > 0) != (c < 0) ||
01417         (ci == 0) != (c == 0)) {
01418       pgraph_cat.error()
01419         << "RenderState::compare_to() not defined properly!\n";
01420       pgraph_cat.error(false)
01421         << "(a, b): " << c << "\n";
01422       pgraph_cat.error(false)
01423         << "(b, a): " << ci << "\n";
01424       ssi->write(pgraph_cat.error(false), 2);
01425       ssnext->write(pgraph_cat.error(false), 2);
01426       return false;
01427     }
01428     si = snext;
01429     ++snext;
01430     while (snext < size && !_states->has_element(snext)) {
01431       ++snext;
01432     }
01433   }
01434 
01435   return true;
01436 }
01437 
01438 ////////////////////////////////////////////////////////////////////
01439 //     Function: RenderState::get_geom_rendering
01440 //       Access: Published
01441 //  Description: Returns the union of the Geom::GeomRendering bits
01442 //               that will be required once this RenderState is
01443 //               applied to a geom which includes the indicated
01444 //               geom_rendering bits.
01445 ////////////////////////////////////////////////////////////////////
01446 int RenderState::
01447 get_geom_rendering(int geom_rendering) const {
01448   const RenderModeAttrib *render_mode = DCAST(RenderModeAttrib, get_attrib(RenderModeAttrib::get_class_slot()));
01449   const TexGenAttrib *tex_gen = DCAST(TexGenAttrib, get_attrib(TexGenAttrib::get_class_slot()));
01450   const TexMatrixAttrib *tex_matrix = DCAST(TexMatrixAttrib, get_attrib(TexMatrixAttrib::get_class_slot()));
01451 
01452   if (render_mode != (const RenderModeAttrib *)NULL) {
01453     geom_rendering = render_mode->get_geom_rendering(geom_rendering);
01454   }
01455   if (tex_gen != (const TexGenAttrib *)NULL) {
01456     geom_rendering = tex_gen->get_geom_rendering(geom_rendering);
01457   }
01458   if (tex_matrix != (const TexMatrixAttrib *)NULL) {
01459     geom_rendering = tex_matrix->get_geom_rendering(geom_rendering);
01460   }
01461 
01462   return geom_rendering;
01463 }
01464 
01465 ////////////////////////////////////////////////////////////////////
01466 //     Function: RenderState::bin_removed
01467 //       Access: Public, Static
01468 //  Description: Intended to be called by
01469 //               CullBinManager::remove_bin(), this informs all the
01470 //               RenderStates in the world to remove the indicated
01471 //               bin_index from their cache if it has been cached.
01472 ////////////////////////////////////////////////////////////////////
01473 void RenderState::
01474 bin_removed(int bin_index) {
01475   // Do something here.
01476   nassertv(false);
01477 }
01478 
01479 ////////////////////////////////////////////////////////////////////
01480 //     Function: RenderState::validate_filled_slots
01481 //       Access: Private
01482 //  Description: Returns true if the _filled_slots bitmask is
01483 //               consistent with the table of RenderAttrib pointers,
01484 //               false otherwise.
01485 ////////////////////////////////////////////////////////////////////
01486 bool RenderState::
01487 validate_filled_slots() const {
01488   SlotMask mask;
01489 
01490   RenderAttribRegistry *reg = RenderAttribRegistry::quick_get_global_ptr();
01491   int max_slots = reg->get_max_slots();
01492   for (int slot = 1; slot < max_slots; ++slot) {
01493     const Attribute &attribute = _attributes[slot];
01494     if (attribute._attrib != (RenderAttrib *)NULL) {
01495       mask.set_bit(slot);
01496     }
01497   }
01498 
01499   return (mask == _filled_slots);
01500 }
01501 
01502 ////////////////////////////////////////////////////////////////////
01503 //     Function: RenderState::do_calc_hash
01504 //       Access: Private
01505 //  Description: Computes a suitable hash value for phash_map.
01506 ////////////////////////////////////////////////////////////////////
01507 void RenderState::
01508 do_calc_hash() {
01509   _hash = 0;
01510 
01511   SlotMask mask = _filled_slots;
01512   int slot = mask.get_lowest_on_bit();
01513   while (slot >= 0) {
01514     const Attribute &attrib = _attributes[slot];
01515     nassertv(attrib._attrib != (RenderAttrib *)NULL);
01516     _hash = pointer_hash::add_hash(_hash, attrib._attrib);
01517     _hash = int_hash::add_hash(_hash, attrib._override);
01518 
01519     mask.clear_bit(slot);
01520     slot = mask.get_lowest_on_bit();
01521   }
01522 
01523   _flags |= F_hash_known;
01524 }
01525 
01526 ////////////////////////////////////////////////////////////////////
01527 //     Function: RenderState::assign_auto_shader_state
01528 //       Access: Private
01529 //  Description: Sets _auto_shader_state to the appropriate
01530 //               RenderState object pointer, either the same pointer
01531 //               as this object, or some other (simpler) RenderState.
01532 ////////////////////////////////////////////////////////////////////
01533 void RenderState::
01534 assign_auto_shader_state() {
01535   CPT(RenderState) state = do_calc_auto_shader_state();
01536 
01537   {
01538     LightReMutexHolder holder(*_states_lock);
01539     if (_auto_shader_state == (const RenderState *)NULL) {
01540       _auto_shader_state = state;
01541       if (_auto_shader_state != this) {
01542         _auto_shader_state->cache_ref();
01543       }
01544     }
01545   }
01546 }
01547 
01548 ////////////////////////////////////////////////////////////////////
01549 //     Function: RenderState::do_calc_auto_shader_state
01550 //       Access: Private
01551 //  Description: Returns the appropriate RenderState that should be
01552 //               used to store the auto shader pointer for nodes that
01553 //               shader this RenderState.
01554 ////////////////////////////////////////////////////////////////////
01555 CPT(RenderState) RenderState::
01556 do_calc_auto_shader_state() {
01557   RenderState *state = new RenderState;
01558 
01559   SlotMask mask = _filled_slots;
01560   int slot = mask.get_lowest_on_bit();
01561   while (slot >= 0) {
01562     const Attribute &attrib = _attributes[slot];
01563     nassertr(attrib._attrib != (RenderAttrib *)NULL, this);
01564     CPT(RenderAttrib) new_attrib = attrib._attrib->get_auto_shader_attrib(this);
01565     if (new_attrib != NULL) {
01566       nassertr(new_attrib->get_slot() == slot, this);
01567       state->_attributes[slot].set(new_attrib, 0);
01568       state->_filled_slots.set_bit(slot);
01569     }
01570     
01571     mask.clear_bit(slot);
01572     slot = mask.get_lowest_on_bit();
01573   }
01574 
01575   return return_new(state);
01576 }
01577 
01578   
01579 ////////////////////////////////////////////////////////////////////
01580 //     Function: RenderState::return_new
01581 //       Access: Private, Static
01582 //  Description: This function is used to share a common RenderState
01583 //               pointer for all equivalent RenderState objects.
01584 //
01585 //               This is different from return_unique() in that it
01586 //               does not actually guarantee a unique pointer, unless
01587 //               uniquify-states is set.
01588 ////////////////////////////////////////////////////////////////////
01589 CPT(RenderState) RenderState::
01590 return_new(RenderState *state) {
01591   nassertr(state != (RenderState *)NULL, state);
01592 
01593   // Make sure we don't have anything in the 0 slot.  If we did, that
01594   // would indicate an uninitialized slot number.
01595 #ifndef NDEBUG
01596   if (state->_attributes[0]._attrib != (RenderAttrib *)NULL) {
01597     const RenderAttrib *attrib = state->_attributes[0]._attrib;
01598     if (attrib->get_type() == TypeHandle::none()) {
01599       ((RenderAttrib *)attrib)->force_init_type();
01600       pgraph_cat->error()
01601         << "Uninitialized RenderAttrib type: " << attrib->get_type()
01602         << "\n";
01603 
01604     } else {
01605       static pset<TypeHandle> already_reported;
01606       if (already_reported.insert(attrib->get_type()).second) {
01607         pgraph_cat->error()
01608           << attrib->get_type() << " did not initialize its slot number.\n";
01609       }
01610     }
01611   }
01612 #endif
01613   state->_attributes[0]._attrib = NULL;
01614   state->_filled_slots.clear_bit(0);
01615 
01616 #ifndef NDEBUG
01617   nassertr(state->validate_filled_slots(), state);
01618 #endif
01619 
01620   if (!uniquify_states && !state->is_empty()) {
01621     return state;
01622   }
01623 
01624   return return_unique(state);
01625 }
01626 
01627 ////////////////////////////////////////////////////////////////////
01628 //     Function: RenderState::return_unique
01629 //       Access: Private, Static
01630 //  Description: This function is used to share a common RenderState
01631 //               pointer for all equivalent RenderState objects.
01632 //
01633 //               See the similar logic in RenderAttrib.  The idea is
01634 //               to create a new RenderState object and pass it
01635 //               through this function, which will share the pointer
01636 //               with a previously-created RenderState object if it is
01637 //               equivalent.
01638 ////////////////////////////////////////////////////////////////////
01639 CPT(RenderState) RenderState::
01640 return_unique(RenderState *state) {
01641   nassertr(state != (RenderState *)NULL, state);
01642 
01643   if (!state_cache) {
01644     return state;
01645   }
01646 
01647 #ifndef NDEBUG
01648   if (paranoid_const) {
01649     nassertr(validate_states(), state);
01650   }
01651 #endif
01652 
01653   LightReMutexHolder holder(*_states_lock);
01654 
01655   if (state->_saved_entry != -1) {
01656     // This state is already in the cache.
01657     //nassertr(_states->find(state) == state->_saved_entry, state);
01658     return state;
01659   }
01660 
01661   // Save the state in a local PointerTo so that it will be freed at
01662   // the end of this function if no one else uses it.
01663   CPT(RenderState) pt_state = state;
01664 
01665   // Ensure each of the individual attrib pointers has been uniquified
01666   // before we add the state to the cache.
01667   if (!uniquify_attribs && !state->is_empty()) {
01668     SlotMask mask = state->_filled_slots;
01669     int slot = mask.get_lowest_on_bit();
01670     while (slot >= 0) {
01671       Attribute &attrib = state->_attributes[slot];
01672       nassertr(attrib._attrib != (RenderAttrib *)NULL, state);
01673       attrib._attrib = attrib._attrib->get_unique();
01674       mask.clear_bit(slot);
01675       slot = mask.get_lowest_on_bit();
01676     }    
01677   }
01678 
01679   int si = _states->find(state);
01680   if (si != -1) {
01681     // There's an equivalent state already in the set.  Return it.
01682     return _states->get_key(si);
01683   }
01684   
01685   // Not already in the set; add it.
01686   if (garbage_collect_states) {
01687     // If we'll be garbage collecting states explicitly, we'll
01688     // increment the reference count when we store it in the cache, so
01689     // that it won't be deleted while it's in it.
01690     state->cache_ref();
01691   }
01692   si = _states->store(state, Empty());
01693 
01694   // Save the index and return the input state.
01695   state->_saved_entry = si;
01696   return pt_state;
01697 }
01698 
01699 ////////////////////////////////////////////////////////////////////
01700 //     Function: RenderState::do_compose
01701 //       Access: Private
01702 //  Description: The private implemention of compose(); this actually
01703 //               composes two RenderStates, without bothering with the
01704 //               cache.
01705 ////////////////////////////////////////////////////////////////////
01706 CPT(RenderState) RenderState::
01707 do_compose(const RenderState *other) const {
01708   PStatTimer timer(_state_compose_pcollector);
01709 
01710   RenderState *new_state = new RenderState;
01711 
01712   SlotMask mask = _filled_slots | other->_filled_slots;
01713   new_state->_filled_slots = mask;
01714 
01715   int slot = mask.get_lowest_on_bit();
01716   while (slot >= 0) {
01717     const Attribute &a = _attributes[slot];
01718     const Attribute &b = other->_attributes[slot];
01719     Attribute &result = new_state->_attributes[slot];
01720 
01721     if (a._attrib == NULL) {
01722       nassertr(b._attrib != NULL, this);
01723       // B wins.
01724       result = b;
01725 
01726     } else if (b._attrib == NULL) {
01727       // A wins.
01728       result = a;
01729 
01730     } else if (b._override < a._override) {
01731       // A, the higher RenderAttrib, overrides.
01732       result = a;
01733 
01734     } else if (a._override < b._override &&
01735                a._attrib->lower_attrib_can_override()) {
01736       // B, the higher RenderAttrib, overrides.  This is a special
01737       // case; normally, a lower RenderAttrib does not override a
01738       // higher one, even if it has a higher override value.  But
01739       // certain kinds of RenderAttribs redefine
01740       // lower_attrib_can_override() to return true, allowing this
01741       // override.
01742       result = b;
01743 
01744     } else {
01745       // Either they have the same override value, or B is higher.
01746       // In either case, the result is the composition of the two,
01747       // with B's override value.
01748       result.set(a._attrib->compose(b._attrib), b._override);
01749     }
01750     
01751     mask.clear_bit(slot);
01752     slot = mask.get_lowest_on_bit();
01753   }
01754   
01755   // If we have any ShaderAttrib with auto-shader enabled,
01756   // remove any shader inputs on it. This is a workaround for an
01757   // issue that makes the shader-generator regenerate the shader
01758   // every time a shader input changes.
01759   CPT(ShaderAttrib) sattrib = DCAST(ShaderAttrib, new_state->get_attrib_def(ShaderAttrib::get_class_slot()));
01760   if (sattrib->auto_shader()) {
01761     sattrib = DCAST(ShaderAttrib, sattrib->clear_all_shader_inputs());
01762   }
01763   
01764   return return_new(new_state);
01765 }
01766 
01767 ////////////////////////////////////////////////////////////////////
01768 //     Function: RenderState::do_invert_compose
01769 //       Access: Private
01770 //  Description: The private implemention of invert_compose().
01771 ////////////////////////////////////////////////////////////////////
01772 CPT(RenderState) RenderState::
01773 do_invert_compose(const RenderState *other) const {
01774   PStatTimer timer(_state_invert_pcollector);
01775 
01776   RenderState *new_state = new RenderState;
01777 
01778   SlotMask mask = _filled_slots | other->_filled_slots;
01779   new_state->_filled_slots = mask;
01780 
01781   int slot = mask.get_lowest_on_bit();
01782   while (slot >= 0) {
01783     const Attribute &a = _attributes[slot];
01784     const Attribute &b = other->_attributes[slot];
01785     Attribute &result = new_state->_attributes[slot];
01786 
01787     if (a._attrib == NULL) {
01788       nassertr(b._attrib != NULL, this);
01789       // B wins.
01790       result = b;
01791 
01792     } else if (b._attrib == NULL) {
01793       // A wins.  Invert it.
01794       CPT(RenderState) full_default = make_full_default();
01795       CPT(RenderAttrib) default_attrib = full_default->get_attrib(slot);
01796       result.set(a._attrib->invert_compose(default_attrib), 0);
01797 
01798     } else {
01799       // Both are good.  (Overrides are not used in invert_compose.)
01800       // Compose.
01801       result.set(a._attrib->invert_compose(b._attrib), 0);
01802     }
01803     
01804     mask.clear_bit(slot);
01805     slot = mask.get_lowest_on_bit();
01806   }
01807   return return_new(new_state);
01808 }
01809 
01810 ////////////////////////////////////////////////////////////////////
01811 //     Function: RenderState::detect_and_break_cycles
01812 //       Access: Private
01813 //  Description: Detects whether there is a cycle in the cache that
01814 //               begins with this state.  If any are detected, breaks
01815 //               them by removing this state from the cache.
01816 ////////////////////////////////////////////////////////////////////
01817 void RenderState::
01818 detect_and_break_cycles() {
01819   PStatTimer timer(_state_break_cycles_pcollector);
01820       
01821   ++_last_cycle_detect;
01822   if (r_detect_cycles(this, this, 1, _last_cycle_detect, NULL)) {
01823     // Ok, we have a cycle.  This will be a leak unless we break the
01824     // cycle by freeing the cache on this object.
01825     if (pgraph_cat.is_debug()) {
01826       pgraph_cat.debug()
01827         << "Breaking cycle involving " << (*this) << "\n";
01828     }
01829     
01830     ((RenderState *)this)->remove_cache_pointers();
01831   } else {
01832     ++_last_cycle_detect;
01833     if (r_detect_reverse_cycles(this, this, 1, _last_cycle_detect, NULL)) {
01834       if (pgraph_cat.is_debug()) {
01835         pgraph_cat.debug()
01836           << "Breaking cycle involving " << (*this) << "\n";
01837       }
01838       
01839       ((RenderState *)this)->remove_cache_pointers();
01840     }
01841   }
01842 }
01843   
01844 ////////////////////////////////////////////////////////////////////
01845 //     Function: RenderState::r_detect_cycles
01846 //       Access: Private, Static
01847 //  Description: Detects whether there is a cycle in the cache that
01848 //               begins with the indicated state.  Returns true if at
01849 //               least one cycle is found, false if this state is not
01850 //               part of any cycles.  If a cycle is found and
01851 //               cycle_desc is not NULL, then cycle_desc is filled in
01852 //               with the list of the steps of the cycle, in reverse
01853 //               order.
01854 ////////////////////////////////////////////////////////////////////
01855 bool RenderState::
01856 r_detect_cycles(const RenderState *start_state,
01857                 const RenderState *current_state,
01858                 int length, UpdateSeq this_seq,
01859                 RenderState::CompositionCycleDesc *cycle_desc) {
01860   if (current_state->_cycle_detect == this_seq) {
01861     // We've already seen this state; therefore, we've found a cycle.
01862 
01863     // However, we only care about cycles that return to the starting
01864     // state and involve more than two steps.  If only one or two
01865     // nodes are involved, it doesn't represent a memory leak, so no
01866     // problem there.
01867     return (current_state == start_state && length > 2);
01868   }
01869   ((RenderState *)current_state)->_cycle_detect = this_seq;
01870     
01871   int i;
01872   int cache_size = current_state->_composition_cache.get_size();
01873   for (i = 0; i < cache_size; ++i) {
01874     if (current_state->_composition_cache.has_element(i)) {
01875       const RenderState *result = current_state->_composition_cache.get_data(i)._result;
01876       if (result != (const RenderState *)NULL) {
01877         if (r_detect_cycles(start_state, result, length + 1, 
01878                             this_seq, cycle_desc)) {
01879           // Cycle detected.
01880           if (cycle_desc != (CompositionCycleDesc *)NULL) {
01881             const RenderState *other = current_state->_composition_cache.get_key(i);
01882             CompositionCycleDescEntry entry(other, result, false);
01883             cycle_desc->push_back(entry);
01884           }
01885           return true;
01886         }
01887       }
01888     }
01889   }
01890 
01891   cache_size = current_state->_invert_composition_cache.get_size();
01892   for (i = 0; i < cache_size; ++i) {
01893     if (current_state->_invert_composition_cache.has_element(i)) {
01894       const RenderState *result = current_state->_invert_composition_cache.get_data(i)._result;
01895       if (result != (const RenderState *)NULL) {
01896         if (r_detect_cycles(start_state, result, length + 1,
01897                             this_seq, cycle_desc)) {
01898           // Cycle detected.
01899           if (cycle_desc != (CompositionCycleDesc *)NULL) {
01900             const RenderState *other = current_state->_invert_composition_cache.get_key(i);
01901             CompositionCycleDescEntry entry(other, result, true);
01902             cycle_desc->push_back(entry);
01903           }
01904           return true;
01905         }
01906       }
01907     }
01908   }
01909 
01910   // No cycle detected.
01911   return false;
01912 }
01913 
01914 ////////////////////////////////////////////////////////////////////
01915 //     Function: RenderState::r_detect_reverse_cycles
01916 //       Access: Private, Static
01917 //  Description: Works the same as r_detect_cycles, but checks for
01918 //               cycles in the reverse direction along the cache
01919 //               chain.  (A cycle may appear in either direction, and
01920 //               we must check both.)
01921 ////////////////////////////////////////////////////////////////////
01922 bool RenderState::
01923 r_detect_reverse_cycles(const RenderState *start_state,
01924                         const RenderState *current_state,
01925                         int length, UpdateSeq this_seq,
01926                         RenderState::CompositionCycleDesc *cycle_desc) {
01927   if (current_state->_cycle_detect == this_seq) {
01928     // We've already seen this state; therefore, we've found a cycle.
01929 
01930     // However, we only care about cycles that return to the starting
01931     // state and involve more than two steps.  If only one or two
01932     // nodes are involved, it doesn't represent a memory leak, so no
01933     // problem there.
01934     return (current_state == start_state && length > 2);
01935   }
01936   ((RenderState *)current_state)->_cycle_detect = this_seq;
01937 
01938   int i;
01939   int cache_size = current_state->_composition_cache.get_size();
01940   for (i = 0; i < cache_size; ++i) {
01941     if (current_state->_composition_cache.has_element(i)) {
01942       const RenderState *other = current_state->_composition_cache.get_key(i);
01943       if (other != current_state) {
01944         int oi = other->_composition_cache.find(current_state);
01945         nassertr(oi != -1, false);
01946 
01947         const RenderState *result = other->_composition_cache.get_data(oi)._result;
01948         if (result != (const RenderState *)NULL) {
01949           if (r_detect_reverse_cycles(start_state, result, length + 1, 
01950                                       this_seq, cycle_desc)) {
01951             // Cycle detected.
01952             if (cycle_desc != (CompositionCycleDesc *)NULL) {
01953               const RenderState *other = current_state->_composition_cache.get_key(i);
01954               CompositionCycleDescEntry entry(other, result, false);
01955               cycle_desc->push_back(entry);
01956             }
01957             return true;
01958           }
01959         }
01960       }
01961     }
01962   }
01963 
01964   cache_size = current_state->_invert_composition_cache.get_size();
01965   for (i = 0; i < cache_size; ++i) {
01966     if (current_state->_invert_composition_cache.has_element(i)) {
01967       const RenderState *other = current_state->_invert_composition_cache.get_key(i);
01968       if (other != current_state) {
01969         int oi = other->_invert_composition_cache.find(current_state);
01970         nassertr(oi != -1, false);
01971 
01972         const RenderState *result = other->_invert_composition_cache.get_data(oi)._result;
01973         if (result != (const RenderState *)NULL) {
01974           if (r_detect_reverse_cycles(start_state, result, length + 1, 
01975                                       this_seq, cycle_desc)) {
01976             // Cycle detected.
01977             if (cycle_desc != (CompositionCycleDesc *)NULL) {
01978               const RenderState *other = current_state->_invert_composition_cache.get_key(i);
01979               CompositionCycleDescEntry entry(other, result, false);
01980               cycle_desc->push_back(entry);
01981             }
01982             return true;
01983           }
01984         }
01985       }
01986     }
01987   }
01988 
01989   // No cycle detected.
01990   return false;
01991 }
01992 
01993 ////////////////////////////////////////////////////////////////////
01994 //     Function: RenderState::release_new
01995 //       Access: Private
01996 //  Description: This inverse of return_new, this releases this object
01997 //               from the global RenderState table.
01998 //
01999 //               You must already be holding _states_lock before you
02000 //               call this method.
02001 ////////////////////////////////////////////////////////////////////
02002 void RenderState::
02003 release_new() {
02004   nassertv(_states_lock->debug_is_locked());
02005 
02006   if (_saved_entry != -1) {
02007     //nassertv(_states->find(this) == _saved_entry);
02008     _saved_entry = _states->find(this);
02009     _states->remove_element(_saved_entry);
02010     _saved_entry = -1;
02011   }
02012 }
02013 
02014 ////////////////////////////////////////////////////////////////////
02015 //     Function: RenderState::remove_cache_pointers
02016 //       Access: Private
02017 //  Description: Remove all pointers within the cache from and to this
02018 //               particular RenderState.  The pointers to this
02019 //               object may be scattered around in the various
02020 //               CompositionCaches from other RenderState objects.
02021 //
02022 //               You must already be holding _states_lock before you
02023 //               call this method.
02024 ////////////////////////////////////////////////////////////////////
02025 void RenderState::
02026 remove_cache_pointers() {
02027   nassertv(_states_lock->debug_is_locked());
02028 
02029   // First, make sure the _auto_shader_state cache pointer is cleared.
02030   if (_auto_shader_state != (const RenderState *)NULL) {
02031     if (_auto_shader_state != this) {
02032       cache_unref_delete(_auto_shader_state);
02033     }
02034     _auto_shader_state = NULL;
02035   }
02036 
02037   // Fortunately, since we added CompositionCache records in pairs, we
02038   // know exactly the set of RenderState objects that have us in their
02039   // cache: it's the same set of RenderState objects that we have in
02040   // our own cache.
02041 
02042   // We do need to put considerable thought into this loop, because as
02043   // we clear out cache entries we'll cause other RenderState
02044   // objects to destruct, which could cause things to get pulled out
02045   // of our own _composition_cache map.  We want to allow this (so
02046   // that we don't encounter any just-destructed pointers in our
02047   // cache), but we don't want to get bitten by this cascading effect.
02048   // Instead of walking through the map from beginning to end,
02049   // therefore, we just pull out the first one each time, and erase
02050   // it.
02051 
02052 #ifdef DO_PSTATS
02053   if (_composition_cache.is_empty() && _invert_composition_cache.is_empty()) {
02054     return;
02055   }
02056   PStatTimer timer(_cache_update_pcollector);
02057 #endif  // DO_PSTATS
02058 
02059   // There are lots of ways to do this loop wrong.  Be very careful if
02060   // you need to modify it for any reason.
02061   int i = 0;
02062   while (!_composition_cache.is_empty()) {
02063     // Scan for the next used slot in the table.
02064     while (!_composition_cache.has_element(i)) {
02065       ++i;
02066     }
02067 
02068     // It is possible that the "other" RenderState object is
02069     // currently within its own destructor.  We therefore can't use a
02070     // PT() to hold its pointer; that could end up calling its
02071     // destructor twice.  Fortunately, we don't need to hold its
02072     // reference count to ensure it doesn't destruct while we process
02073     // this loop; as long as we ensure that no *other* RenderState
02074     // objects destruct, there will be no reason for that one to.
02075     RenderState *other = (RenderState *)_composition_cache.get_key(i);
02076 
02077     // We hold a copy of the composition result so we can dereference
02078     // it later.
02079     Composition comp = _composition_cache.get_data(i);
02080 
02081     // Now we can remove the element from our cache.  We do this now,
02082     // rather than later, before any other RenderState objects have
02083     // had a chance to destruct, so we are confident that our iterator
02084     // is still valid.
02085     _composition_cache.remove_element(i);
02086     _cache_stats.add_total_size(-1);
02087     _cache_stats.inc_dels();
02088 
02089     if (other != this) {
02090       int oi = other->_composition_cache.find(this);
02091 
02092       // We may or may not still be listed in the other's cache (it
02093       // might be halfway through pulling entries out, from within its
02094       // own destructor).
02095       if (oi != -1) {
02096         // Hold a copy of the other composition result, too.
02097         Composition ocomp = other->_composition_cache.get_data(oi);
02098         
02099         other->_composition_cache.remove_element(oi);
02100         _cache_stats.add_total_size(-1);
02101         _cache_stats.inc_dels();
02102         
02103         // It's finally safe to let our held pointers go away.  This may
02104         // have cascading effects as other RenderState objects are
02105         // destructed, but there will be no harm done if they destruct
02106         // now.
02107         if (ocomp._result != (const RenderState *)NULL && ocomp._result != other) {
02108           cache_unref_delete(ocomp._result);
02109         }
02110       }
02111     }
02112 
02113     // It's finally safe to let our held pointers go away.  (See
02114     // comment above.)
02115     if (comp._result != (const RenderState *)NULL && comp._result != this) {
02116       cache_unref_delete(comp._result);
02117     }
02118   }
02119 
02120   // A similar bit of code for the invert cache.
02121   i = 0;
02122   while (!_invert_composition_cache.is_empty()) {
02123     while (!_invert_composition_cache.has_element(i)) {
02124       ++i;
02125     }
02126 
02127     RenderState *other = (RenderState *)_invert_composition_cache.get_key(i);
02128     nassertv(other != this);
02129     Composition comp = _invert_composition_cache.get_data(i);
02130     _invert_composition_cache.remove_element(i);
02131     _cache_stats.add_total_size(-1);
02132     _cache_stats.inc_dels();
02133     if (other != this) {
02134       int oi = other->_invert_composition_cache.find(this);
02135       if (oi != -1) {
02136         Composition ocomp = other->_invert_composition_cache.get_data(oi);
02137         other->_invert_composition_cache.remove_element(oi);
02138         _cache_stats.add_total_size(-1);
02139         _cache_stats.inc_dels();
02140         if (ocomp._result != (const RenderState *)NULL && ocomp._result != other) {
02141           cache_unref_delete(ocomp._result);
02142         }
02143       }
02144     }
02145     if (comp._result != (const RenderState *)NULL && comp._result != this) {
02146       cache_unref_delete(comp._result);
02147     }
02148   }
02149 }
02150 
02151 ////////////////////////////////////////////////////////////////////
02152 //     Function: RenderState::determine_bin_index
02153 //       Access: Private
02154 //  Description: This is the private implementation of
02155 //               get_bin_index() and get_draw_order().
02156 ////////////////////////////////////////////////////////////////////
02157 void RenderState::
02158 determine_bin_index() {
02159   LightMutexHolder holder(_lock);
02160   if ((_flags & F_checked_bin_index) != 0) {
02161     // Someone else checked it first.
02162     return;
02163   }
02164 
02165   string bin_name;
02166   _draw_order = 0;
02167 
02168   const CullBinAttrib *bin = DCAST(CullBinAttrib, get_attrib(CullBinAttrib::get_class_slot()));
02169   if (bin != (const CullBinAttrib *)NULL) {
02170     bin_name = bin->get_bin_name();
02171     _draw_order = bin->get_draw_order();
02172   }
02173 
02174   if (bin_name.empty()) {
02175     // No explicit bin is specified; put in the in the default bin,
02176     // either opaque or transparent, based on the transparency
02177     // setting.
02178     bin_name = "opaque";
02179 
02180     const TransparencyAttrib *transparency = DCAST(TransparencyAttrib, get_attrib(TransparencyAttrib::get_class_slot()));
02181     if (transparency != (const TransparencyAttrib *)NULL) {
02182       switch (transparency->get_mode()) {
02183       case TransparencyAttrib::M_alpha:
02184       case TransparencyAttrib::M_dual:
02185         // These transparency modes require special back-to-front sorting.
02186         bin_name = "transparent";
02187         break;
02188 
02189       default:
02190         break;
02191       }
02192     }
02193   }
02194   
02195   CullBinManager *bin_manager = CullBinManager::get_global_ptr();
02196   _bin_index = bin_manager->find_bin(bin_name);
02197   if (_bin_index == -1) {
02198     pgraph_cat.warning()
02199       << "No bin named " << bin_name << "; creating default bin.\n";
02200     _bin_index = bin_manager->add_bin(bin_name, CullBinManager::BT_unsorted, 0);
02201   }
02202   _flags |= F_checked_bin_index;
02203 }
02204 
02205 ////////////////////////////////////////////////////////////////////
02206 //     Function: RenderState::determine_cull_callback
02207 //       Access: Private
02208 //  Description: This is the private implementation of has_cull_callback().
02209 ////////////////////////////////////////////////////////////////////
02210 void RenderState::
02211 determine_cull_callback() {
02212   LightMutexHolder holder(_lock);
02213   if ((_flags & F_checked_cull_callback) != 0) {
02214     // Someone else checked it first.
02215     return;
02216   }
02217 
02218   SlotMask mask = _filled_slots;
02219   int slot = mask.get_lowest_on_bit();
02220   while (slot >= 0) {
02221     const Attribute &attrib = _attributes[slot];
02222     nassertv(attrib._attrib != (RenderAttrib *)NULL);
02223     if (attrib._attrib->has_cull_callback()) {
02224       _flags |= F_has_cull_callback;
02225       break;
02226     }
02227     
02228     mask.clear_bit(slot);
02229     slot = mask.get_lowest_on_bit();
02230   }
02231 
02232   _flags |= F_checked_cull_callback;
02233 }
02234 
02235 ////////////////////////////////////////////////////////////////////
02236 //     Function: RenderState::fill_default
02237 //       Access: Private
02238 //  Description: Fills up the state with all of the default attribs.
02239 ////////////////////////////////////////////////////////////////////
02240 void RenderState::
02241 fill_default() {
02242   RenderAttribRegistry *reg = RenderAttribRegistry::quick_get_global_ptr();
02243   int num_slots = reg->get_num_slots();
02244   for (int slot = 1; slot < num_slots; ++slot) {
02245     _attributes[slot].set(reg->get_slot_default(slot), 0);
02246     _filled_slots.set_bit(slot);
02247   }
02248 }
02249 
02250 ////////////////////////////////////////////////////////////////////
02251 //     Function: RenderState::update_pstats
02252 //       Access: Private
02253 //  Description: Moves the RenderState object from one PStats category
02254 //               to another, so that we can track in PStats how many
02255 //               pointers are held by nodes, and how many are held in
02256 //               the cache only.
02257 ////////////////////////////////////////////////////////////////////
02258 void RenderState::
02259 update_pstats(int old_referenced_bits, int new_referenced_bits) {
02260 #ifdef DO_PSTATS
02261   if ((old_referenced_bits & R_node) != 0) {
02262     _node_counter.sub_level(1);
02263   } else if ((old_referenced_bits & R_cache) != 0) {
02264     _cache_counter.sub_level(1);
02265   }
02266   if ((new_referenced_bits & R_node) != 0) {
02267     _node_counter.add_level(1);
02268   } else if ((new_referenced_bits & R_cache) != 0) {
02269     _cache_counter.add_level(1);
02270   }
02271 #endif  // DO_PSTATS
02272 }
02273 
02274 #ifdef HAVE_PYTHON
02275 ////////////////////////////////////////////////////////////////////
02276 //     Function: RenderState::get_states
02277 //       Access: Published, Static
02278 //  Description: Returns a list of all of the RenderState objects
02279 //               in the state cache.  The order of elements in this
02280 //               cache is arbitrary.
02281 ////////////////////////////////////////////////////////////////////
02282 PyObject *RenderState::
02283 get_states() {
02284   IMPORT_THIS struct Dtool_PyTypedObject Dtool_RenderState;
02285   if (_states == (States *)NULL) {
02286     return PyList_New(0);
02287   }
02288   LightReMutexHolder holder(*_states_lock);
02289 
02290   size_t num_states = _states->get_num_entries();
02291   PyObject *list = PyList_New(num_states);
02292   size_t i = 0;
02293 
02294   int size = _states->get_size();
02295   for (int si = 0; si < size; ++si) {
02296     if (!_states->has_element(si)) {
02297       continue;
02298     }
02299     const RenderState *state = _states->get_key(si);
02300     state->ref();
02301     PyObject *a = 
02302       DTool_CreatePyInstanceTyped((void *)state, Dtool_RenderState, 
02303                                   true, true, state->get_type_index());
02304     nassertr(i < num_states, list);
02305     PyList_SET_ITEM(list, i, a);
02306     ++i;
02307   }
02308   nassertr(i == num_states, list);
02309   return list;
02310 }
02311 #endif  // HAVE_PYTHON
02312 
02313 ////////////////////////////////////////////////////////////////////
02314 //     Function: RenderState::init_states
02315 //       Access: Public, Static
02316 //  Description: Make sure the global _states map is allocated.  This
02317 //               only has to be done once.  We could make this map
02318 //               static, but then we run into problems if anyone
02319 //               creates a RenderState object at static init time;
02320 //               it also seems to cause problems when the Panda shared
02321 //               library is unloaded at application exit time.
02322 ////////////////////////////////////////////////////////////////////
02323 void RenderState::
02324 init_states() {
02325   _states = new States;
02326 
02327   // TODO: we should have a global Panda mutex to allow us to safely
02328   // create _states_lock without a startup race condition.  For the
02329   // meantime, this is OK because we guarantee that this method is
02330   // called at static init time, presumably when there is still only
02331   // one thread in the world.
02332   _states_lock = new LightReMutex("RenderState::_states_lock");
02333   _cache_stats.init();
02334   nassertv(Thread::get_current_thread() == Thread::get_main_thread());
02335 }
02336 
02337 
02338 ////////////////////////////////////////////////////////////////////
02339 //     Function: RenderState::register_with_read_factory
02340 //       Access: Public, Static
02341 //  Description: Tells the BamReader how to create objects of type
02342 //               RenderState.
02343 ////////////////////////////////////////////////////////////////////
02344 void RenderState::
02345 register_with_read_factory() {
02346   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
02347 }
02348 
02349 ////////////////////////////////////////////////////////////////////
02350 //     Function: RenderState::write_datagram
02351 //       Access: Public, Virtual
02352 //  Description: Writes the contents of this object to the datagram
02353 //               for shipping out to a Bam file.
02354 ////////////////////////////////////////////////////////////////////
02355 void RenderState::
02356 write_datagram(BamWriter *manager, Datagram &dg) {
02357   TypedWritable::write_datagram(manager, dg);
02358 
02359   int num_attribs = _filled_slots.get_num_on_bits();
02360   nassertv(num_attribs == (int)(PN_uint16)num_attribs);
02361   dg.add_uint16(num_attribs);
02362 
02363   // **** We should smarten up the writing of the override
02364   // number--most of the time these will all be zero.
02365   SlotMask mask = _filled_slots;
02366   int slot = mask.get_lowest_on_bit();
02367   while (slot >= 0) {
02368     const Attribute &attrib = _attributes[slot];
02369     nassertv(attrib._attrib != (RenderAttrib *)NULL);
02370     manager->write_pointer(dg, attrib._attrib);
02371     dg.add_int32(attrib._override);
02372     
02373     mask.clear_bit(slot);
02374     slot = mask.get_lowest_on_bit();
02375   }
02376 }
02377 
02378 ////////////////////////////////////////////////////////////////////
02379 //     Function: RenderState::complete_pointers
02380 //       Access: Public, Virtual
02381 //  Description: Receives an array of pointers, one for each time
02382 //               manager->read_pointer() was called in fillin().
02383 //               Returns the number of pointers processed.
02384 ////////////////////////////////////////////////////////////////////
02385 int RenderState::
02386 complete_pointers(TypedWritable **p_list, BamReader *manager) {
02387   int pi = TypedWritable::complete_pointers(p_list, manager);
02388 
02389   int num_attribs = 0;
02390 
02391   RenderAttribRegistry *reg = RenderAttribRegistry::quick_get_global_ptr();
02392   for (size_t i = 0; i < (*_read_overrides).size(); ++i) {
02393     int override = (*_read_overrides)[i];
02394 
02395     RenderAttrib *attrib = DCAST(RenderAttrib, p_list[pi++]);
02396     if (attrib != (RenderAttrib *)NULL) {
02397       int slot = attrib->get_slot();
02398       if (slot > 0 && slot < reg->get_max_slots()) {
02399         _attributes[slot].set(attrib, override);
02400         _filled_slots.set_bit(slot);
02401         ++num_attribs;
02402       }
02403     }
02404   }
02405 
02406   delete _read_overrides;
02407   _read_overrides = NULL;
02408 
02409   return pi;
02410 }
02411 
02412 ////////////////////////////////////////////////////////////////////
02413 //     Function: RenderState::change_this
02414 //       Access: Public, Static
02415 //  Description: Called immediately after complete_pointers(), this
02416 //               gives the object a chance to adjust its own pointer
02417 //               if desired.  Most objects don't change pointers after
02418 //               completion, but some need to.
02419 //
02420 //               Once this function has been called, the old pointer
02421 //               will no longer be accessed.
02422 ////////////////////////////////////////////////////////////////////
02423 TypedWritable *RenderState::
02424 change_this(TypedWritable *old_ptr, BamReader *manager) {
02425   // First, uniquify the pointer.
02426   RenderState *state = DCAST(RenderState, old_ptr);
02427   CPT(RenderState) pointer = return_unique(state);
02428 
02429   // But now we have a problem, since we have to hold the reference
02430   // count and there's no way to return a TypedWritable while still
02431   // holding the reference count!  We work around this by explicitly
02432   // upping the count, and also setting a finalize() callback to down
02433   // it later.
02434   if (pointer == state) {
02435     pointer->ref();
02436     manager->register_finalize(state);
02437   }
02438   
02439   // We have to cast the pointer back to non-const, because the bam
02440   // reader expects that.
02441   return (RenderState *)pointer.p();
02442 }
02443 
02444 ////////////////////////////////////////////////////////////////////
02445 //     Function: RenderState::finalize
02446 //       Access: Public, Virtual
02447 //  Description: Called by the BamReader to perform any final actions
02448 //               needed for setting up the object after all objects
02449 //               have been read and all pointers have been completed.
02450 ////////////////////////////////////////////////////////////////////
02451 void RenderState::
02452 finalize(BamReader *) {
02453   // Unref the pointer that we explicitly reffed in change_this().
02454   unref();
02455 
02456   // We should never get back to zero after unreffing our own count,
02457   // because we expect to have been stored in a pointer somewhere.  If
02458   // we do get to zero, it's a memory leak; the way to avoid this is
02459   // to call unref_delete() above instead of unref(), but this is
02460   // dangerous to do from within a virtual function.
02461   nassertv(get_ref_count() != 0);
02462 }
02463 
02464 ////////////////////////////////////////////////////////////////////
02465 //     Function: RenderState::make_from_bam
02466 //       Access: Protected, Static
02467 //  Description: This function is called by the BamReader's factory
02468 //               when a new object of type RenderState is encountered
02469 //               in the Bam file.  It should create the RenderState
02470 //               and extract its information from the file.
02471 ////////////////////////////////////////////////////////////////////
02472 TypedWritable *RenderState::
02473 make_from_bam(const FactoryParams &params) {
02474   RenderState *state = new RenderState;
02475   DatagramIterator scan;
02476   BamReader *manager;
02477 
02478   parse_params(params, scan, manager);
02479   state->fillin(scan, manager);
02480   manager->register_change_this(change_this, state);
02481 
02482   return state;
02483 }
02484 
02485 ////////////////////////////////////////////////////////////////////
02486 //     Function: RenderState::fillin
02487 //       Access: Protected
02488 //  Description: This internal function is called by make_from_bam to
02489 //               read in all of the relevant data from the BamFile for
02490 //               the new RenderState.
02491 ////////////////////////////////////////////////////////////////////
02492 void RenderState::
02493 fillin(DatagramIterator &scan, BamReader *manager) {
02494   TypedWritable::fillin(scan, manager);
02495 
02496   int num_attribs = scan.get_uint16();
02497   _read_overrides = new vector_int;
02498   (*_read_overrides).reserve(num_attribs);
02499 
02500   for (int i = 0; i < num_attribs; ++i) {
02501     manager->read_pointer(scan);
02502     int override = scan.get_int32();
02503     (*_read_overrides).push_back(override);
02504   }
02505 }
02506 
 All Classes Functions Variables Enumerations