Panda3D

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