Panda3D
|
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 ©) : 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 ¶ms) { 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