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