43 const RenderState *RenderState::_empty_state =
nullptr;
44 UpdateSeq RenderState::_last_cycle_detect;
45 size_t RenderState::_garbage_index = 0;
47 PStatCollector RenderState::_cache_update_pcollector(
"*:State Cache:Update");
48 PStatCollector RenderState::_garbage_collect_pcollector(
"*:State Cache:Garbage Collect");
49 PStatCollector RenderState::_state_compose_pcollector(
"*:State Cache:Compose State");
50 PStatCollector RenderState::_state_invert_pcollector(
"*:State Cache:Invert State");
51 PStatCollector RenderState::_node_counter(
"RenderStates:On nodes");
53 PStatCollector RenderState::_state_break_cycles_pcollector(
"*:State Cache:Break Cycles");
54 PStatCollector RenderState::_state_validate_pcollector(
"*:State Cache:Validate");
71 if (_states ==
nullptr) {
76 _cache_stats.add_num_states(1);
77 _read_overrides =
nullptr;
78 _generated_shader =
nullptr;
80 #ifdef DO_MEMORY_USAGE
90 _filled_slots(copy._filled_slots),
95 for (
int i = 0; i < RenderAttribRegistry::_max_slots; ++i) {
96 _attributes[i] = copy._attributes[i];
101 _cache_stats.add_num_states(1);
102 _read_overrides =
nullptr;
103 _generated_shader =
nullptr;
105 #ifdef DO_MEMORY_USAGE
117 nassertv(!is_destructing());
123 nassertv(_saved_entry == -1);
124 nassertv(_composition_cache.
is_empty() && _invert_composition_cache.
is_empty());
142 SlotMask mask = _filled_slots | other._filled_slots;
145 int result = _attributes[slot].compare_to(other._attributes[slot]);
165 if (
this == &other) {
172 for (
int n = 0; n < num_sorted_slots; ++n) {
174 nassertr((_attributes[slot]._attrib !=
nullptr) == _filled_slots.
get_bit(slot), 0);
177 const RenderAttrib *b = other._attributes[slot]._attrib;
179 return a < b ? -1 : 1;
197 const RenderAttrib *b = other._attributes[slot]._attrib;
199 return a < b ? -1 : 1;
218 const Attribute &attrib = _attributes[slot];
219 nassertr(attrib._attrib !=
nullptr,
false);
220 if (!attrib._attrib->cull_callback(trav, data)) {
237 int slot = attrib->get_slot();
238 state->_attributes[slot].set(attrib,
override);
239 state->_filled_slots.
set_bit(slot);
240 return return_new(state);
250 state->_attributes[attrib1->get_slot()].set(attrib1,
override);
251 state->_attributes[attrib2->get_slot()].set(attrib2,
override);
252 state->_filled_slots.
set_bit(attrib1->get_slot());
253 state->_filled_slots.
set_bit(attrib2->get_slot());
254 return return_new(state);
265 state->_attributes[attrib1->get_slot()].set(attrib1,
override);
266 state->_attributes[attrib2->get_slot()].set(attrib2,
override);
267 state->_attributes[attrib3->get_slot()].set(attrib3,
override);
268 state->_filled_slots.
set_bit(attrib1->get_slot());
269 state->_filled_slots.
set_bit(attrib2->get_slot());
270 state->_filled_slots.
set_bit(attrib3->get_slot());
271 return return_new(state);
283 state->_attributes[attrib1->get_slot()].set(attrib1,
override);
284 state->_attributes[attrib2->get_slot()].set(attrib2,
override);
285 state->_attributes[attrib3->get_slot()].set(attrib3,
override);
286 state->_attributes[attrib4->get_slot()].set(attrib4,
override);
287 state->_filled_slots.
set_bit(attrib1->get_slot());
288 state->_filled_slots.
set_bit(attrib2->get_slot());
289 state->_filled_slots.
set_bit(attrib3->get_slot());
290 state->_filled_slots.
set_bit(attrib4->get_slot());
291 return return_new(state);
304 state->_attributes[attrib1->get_slot()].set(attrib1,
override);
305 state->_attributes[attrib2->get_slot()].set(attrib2,
override);
306 state->_attributes[attrib3->get_slot()].set(attrib3,
override);
307 state->_attributes[attrib4->get_slot()].set(attrib4,
override);
308 state->_attributes[attrib5->get_slot()].set(attrib5,
override);
309 state->_filled_slots.
set_bit(attrib1->get_slot());
310 state->_filled_slots.
set_bit(attrib2->get_slot());
311 state->_filled_slots.
set_bit(attrib3->get_slot());
312 state->_filled_slots.
set_bit(attrib4->get_slot());
313 state->_filled_slots.
set_bit(attrib5->get_slot());
314 return return_new(state);
321 make(
const RenderAttrib *
const *attrib,
int num_attribs,
int override) {
322 if (num_attribs == 0) {
326 for (
int i = 0; i < num_attribs; i++) {
327 int slot = attrib[i]->get_slot();
328 state->_attributes[slot].set(attrib[i],
override);
329 state->_filled_slots.
set_bit(slot);
331 return return_new(state);
358 return do_compose(other);
364 int index = _composition_cache.
find(other);
366 Composition &comp = ((
RenderState *)
this)->_composition_cache.modify_data(index);
367 if (comp._result ==
nullptr) {
372 comp._result = result;
397 ((
RenderState *)
this)->_composition_cache[other]._result = result;
402 ((
RenderState *)other)->_composition_cache[
this]._result =
nullptr;
447 return do_invert_compose(other);
453 int index = _invert_composition_cache.
find(other);
455 Composition &comp = ((
RenderState *)
this)->_invert_composition_cache.modify_data(index);
456 if (comp._result ==
nullptr) {
460 CPT(
RenderState) result = do_invert_compose(other);
461 comp._result = result;
481 CPT(
RenderState) result = do_invert_compose(other);
485 ((
RenderState *)
this)->_invert_composition_cache[other]._result = result;
490 ((
RenderState *)other)->_invert_composition_cache[
this]._result =
nullptr;
513 add_attrib(
const RenderAttrib *attrib,
int override)
const {
514 int slot = attrib->get_slot();
515 if (_filled_slots.
get_bit(slot) &&
516 _attributes[slot]._override >
override) {
523 new_state->_attributes[slot].set(attrib,
override);
524 new_state->_filled_slots.
set_bit(slot);
525 return return_new(new_state);
537 int slot = attrib->get_slot();
538 new_state->_attributes[slot]._attrib = attrib;
539 new_state->_filled_slots.
set_bit(slot);
540 return return_new(new_state);
550 set_attrib(
const RenderAttrib *attrib,
int override)
const {
552 int slot = attrib->get_slot();
553 new_state->_attributes[slot].set(attrib,
override);
554 new_state->_filled_slots.
set_bit(slot);
555 return return_new(new_state);
563 remove_attrib(
int slot)
const {
564 if (_attributes[slot]._attrib ==
nullptr) {
575 new_state->_attributes[slot].set(
nullptr, 0);
576 new_state->_filled_slots.
clear_bit(slot);
577 return return_new(new_state);
587 adjust_all_priorities(
int adjustment)
const {
590 SlotMask mask = _filled_slots;
593 Attribute &attrib = new_state->_attributes[slot];
594 nassertr(attrib._attrib !=
nullptr,
this);
595 attrib._override = std::max(attrib._override + adjustment, 0);
597 mask.clear_bit(slot);
598 slot = mask.get_lowest_on_bit();
601 return return_new(new_state);
612 if (garbage_collect_states || !state_cache) {
628 if (auto_break_cycles && uniquify_states) {
656 output(ostream &out)
const {
663 const char *sep =
"";
665 SlotMask mask = _filled_slots;
668 const Attribute &attrib = _attributes[slot];
669 nassertv(attrib._attrib !=
nullptr);
670 out << sep << attrib._attrib->get_type();
673 mask.clear_bit(slot);
674 slot = mask.get_lowest_on_bit();
684 write(ostream &out,
int indent_level)
const {
690 SlotMask mask = _filled_slots;
693 const Attribute &attrib = _attributes[slot];
694 nassertv(attrib._attrib !=
nullptr);
695 attrib._attrib->write(out, indent_level);
697 mask.clear_bit(slot);
698 slot = mask.get_lowest_on_bit();
719 if (_states ==
nullptr) {
741 if (_states ==
nullptr) {
749 StateCount state_count;
752 for (
size_t si = 0; si < size; ++si) {
757 for (i = 0; i < cache_size; ++i) {
759 if (result !=
nullptr && result != state) {
761 std::pair<StateCount::iterator, bool> ir =
762 state_count.insert(StateCount::value_type(result, 1));
766 (*(ir.first)).second++;
771 for (i = 0; i < cache_size; ++i) {
773 if (result !=
nullptr && result != state) {
774 std::pair<StateCount::iterator, bool> ir =
775 state_count.insert(StateCount::value_type(result, 1));
777 (*(ir.first)).second++;
788 StateCount::iterator sci;
789 for (sci = state_count.begin(); sci != state_count.end(); ++sci) {
791 int count = (*sci).second;
797 if (pgraph_cat.is_debug()) {
799 <<
"Unused state: " << (
void *)state <<
":"
801 state->write(pgraph_cat.debug(
false), 2);
824 if (_states ==
nullptr) {
838 TempStates temp_states;
839 temp_states.reserve(orig_size);
842 for (
size_t si = 0; si < size; ++si) {
844 temp_states.push_back(state);
849 TempStates::iterator ti;
850 for (ti = temp_states.begin(); ti != temp_states.end(); ++ti) {
855 for (i = 0; i < cache_size; ++i) {
857 if (result !=
nullptr && result != state) {
858 result->cache_unref();
863 state->_composition_cache.
clear();
866 for (i = 0; i < cache_size; ++i) {
868 if (result !=
nullptr && result != state) {
869 result->cache_unref();
874 state->_invert_composition_cache.
clear();
883 return orig_size - new_size;
898 if (_states ==
nullptr || !garbage_collect_states) {
904 PStatTimer timer(_garbage_collect_pcollector);
908 size_t size = orig_size;
909 size_t num_this_pass = std::max(0,
int(size * garbage_collect_states_rate));
910 if (num_this_pass <= 0) {
914 bool break_and_uniquify = (auto_break_cycles && uniquify_transforms);
916 size_t si = _garbage_index;
921 num_this_pass = std::min(num_this_pass, size);
922 size_t stop_at_element = (si + num_this_pass) % size;
926 if (break_and_uniquify) {
933 state->detect_and_break_cycles();
945 state->release_new();
946 state->remove_cache_pointers();
947 state->cache_unref_only();
955 if (stop_at_element > 0) {
960 si = (si + 1) % size;
961 }
while (si != stop_at_element);
974 return (
int)orig_size - (int)size + num_attribs;
986 for (
size_t si = 0; si < size; ++si) {
988 state->_mungers.
clear();
989 state->_munged_states.
clear();
990 state->_last_mi = -1;
1009 if (_states ==
nullptr) {
1015 VisitedStates visited;
1019 for (
size_t si = 0; si < size; ++si) {
1022 bool inserted = visited.insert(state).second;
1024 ++_last_cycle_detect;
1025 if (r_detect_cycles(state, state, 1, _last_cycle_detect, &cycle_desc)) {
1027 CompositionCycleDesc::reverse_iterator csi;
1029 out <<
"\nCycle detected of length " << cycle_desc.size() + 1 <<
":\n"
1030 <<
"state " << (
void *)state <<
":" << state->
get_ref_count()
1032 state->write(out, 2);
1033 for (csi = cycle_desc.rbegin(); csi != cycle_desc.rend(); ++csi) {
1034 const CompositionCycleDescEntry &entry = (*csi);
1035 if (entry._inverted) {
1036 out <<
"invert composed with ";
1038 out <<
"composed with ";
1040 out << (
const void *)entry._obj <<
":" << entry._obj->get_ref_count()
1041 <<
" " << *entry._obj <<
"\n"
1042 <<
"produces " << (
const void *)entry._result <<
":"
1043 << entry._result->get_ref_count() <<
" =\n";
1044 entry._result->write(out, 2);
1045 visited.insert(entry._result);
1050 ++_last_cycle_detect;
1051 if (r_detect_reverse_cycles(state, state, 1, _last_cycle_detect, &cycle_desc)) {
1053 CompositionCycleDesc::iterator csi;
1055 out <<
"\nReverse cycle detected of length " << cycle_desc.size() + 1 <<
":\n"
1057 for (csi = cycle_desc.begin(); csi != cycle_desc.end(); ++csi) {
1058 const CompositionCycleDescEntry &entry = (*csi);
1059 out << (
const void *)entry._result <<
":"
1060 << entry._result->get_ref_count() <<
" =\n";
1061 entry._result->write(out, 2);
1062 out << (
const void *)entry._obj <<
":"
1063 << entry._obj->get_ref_count() <<
" =\n";
1064 entry._obj->write(out, 2);
1065 visited.insert(entry._result);
1067 out << (
void *)state <<
":"
1069 state->write(out, 2);
1086 if (_states ==
nullptr) {
1087 out <<
"0 states:\n";
1093 out << size <<
" states:\n";
1094 for (
size_t si = 0; si < size; ++si) {
1096 state->write(out, 2);
1108 if (_states ==
nullptr) {
1112 PStatTimer timer(_state_validate_pcollector);
1121 <<
"RenderState::_states cache is invalid!\n";
1127 nassertr(si < size,
false);
1128 nassertr(_states->
get_key(si)->get_ref_count() >= 0,
false);
1131 while (snext < size) {
1132 nassertr(_states->
get_key(snext)->get_ref_count() >= 0,
false);
1137 if ((ci < 0) != (c > 0) ||
1138 (ci > 0) != (c < 0) ||
1139 (ci == 0) != (c == 0)) {
1141 <<
"RenderState::compare_to() not defined properly!\n";
1142 pgraph_cat.error(
false)
1143 <<
"(a, b): " << c <<
"\n";
1144 pgraph_cat.error(
false)
1145 <<
"(b, a): " << ci <<
"\n";
1146 ssi->write(pgraph_cat.error(
false), 2);
1147 ssnext->write(pgraph_cat.error(
false), 2);
1168 if (get_attrib(render_mode)) {
1171 if (get_attrib(tex_gen)) {
1174 if (get_attrib(tex_matrix)) {
1178 return geom_rendering;
1197 validate_filled_slots()
const {
1201 int max_slots = reg->get_max_slots();
1202 for (
int slot = 1; slot < max_slots; ++slot) {
1203 const Attribute &attribute = _attributes[slot];
1204 if (attribute._attrib !=
nullptr) {
1209 return (mask == _filled_slots);
1219 SlotMask mask = _filled_slots;
1222 const Attribute &attrib = _attributes[slot];
1223 nassertv(attrib._attrib !=
nullptr);
1227 mask.clear_bit(slot);
1228 slot = mask.get_lowest_on_bit();
1231 _flags |= F_hash_known;
1243 nassertr(state !=
nullptr, state);
1248 if (state->_attributes[0]._attrib !=
nullptr) {
1249 const RenderAttrib *attrib = state->_attributes[0]._attrib;
1250 if (attrib->get_type() == TypeHandle::none()) {
1253 <<
"Uninitialized RenderAttrib type: " << attrib->get_type()
1258 if (already_reported.insert(attrib->get_type()).second) {
1260 << attrib->get_type() <<
" did not initialize its slot number.\n";
1265 state->_attributes[0]._attrib =
nullptr;
1269 nassertr(state->validate_filled_slots(), state);
1272 if (!uniquify_states && !state->
is_empty()) {
1276 return return_unique(state);
1289 nassertr(state !=
nullptr,
nullptr);
1296 if (paranoid_const) {
1303 if (state->_saved_entry != -1) {
1311 if (!uniquify_attribs && !state->
is_empty()) {
1312 SlotMask mask = state->_filled_slots;
1315 Attribute &attrib = state->_attributes[slot];
1316 nassertd(attrib._attrib !=
nullptr) continue;
1317 attrib._attrib = attrib._attrib->get_unique();
1318 mask.clear_bit(slot);
1323 int si = _states->find(state);
1328 if (state->get_ref_count() == 0) {
1335 if (garbage_collect_states) {
1341 si = _states->
store(state,
nullptr);
1344 state->_saved_entry = si;
1358 SlotMask mask = _filled_slots | other->_filled_slots;
1359 new_state->_filled_slots = mask;
1363 const Attribute &a = _attributes[slot];
1364 const Attribute &b = other->_attributes[slot];
1365 Attribute &result = new_state->_attributes[slot];
1367 if (a._attrib ==
nullptr) {
1368 nassertr(b._attrib !=
nullptr,
this);
1372 }
else if (b._attrib ==
nullptr) {
1376 }
else if (b._override < a._override) {
1380 }
else if (a._override < b._override &&
1381 a._attrib->lower_attrib_can_override()) {
1393 result.set(a._attrib->compose(b._attrib), b._override);
1396 mask.clear_bit(slot);
1397 slot = mask.get_lowest_on_bit();
1400 return return_new(new_state);
1407 do_invert_compose(
const RenderState *other)
const {
1412 SlotMask mask = _filled_slots | other->_filled_slots;
1413 new_state->_filled_slots = mask;
1417 const Attribute &a = _attributes[slot];
1418 const Attribute &b = other->_attributes[slot];
1419 Attribute &result = new_state->_attributes[slot];
1421 if (a._attrib ==
nullptr) {
1422 nassertr(b._attrib !=
nullptr,
this);
1426 }
else if (b._attrib ==
nullptr) {
1433 result.set(a._attrib->invert_compose(b._attrib), 0);
1436 mask.clear_bit(slot);
1437 slot = mask.get_lowest_on_bit();
1439 return return_new(new_state);
1447 detect_and_break_cycles() {
1448 PStatTimer timer(_state_break_cycles_pcollector);
1450 ++_last_cycle_detect;
1451 if (r_detect_cycles(
this,
this, 1, _last_cycle_detect,
nullptr)) {
1454 if (pgraph_cat.is_debug()) {
1456 <<
"Breaking cycle involving " << (*this) <<
"\n";
1461 ++_last_cycle_detect;
1462 if (r_detect_reverse_cycles(
this,
this, 1, _last_cycle_detect,
nullptr)) {
1463 if (pgraph_cat.is_debug()) {
1465 <<
"Breaking cycle involving " << (*this) <<
"\n";
1485 if (current_state->_cycle_detect == this_seq) {
1491 return (current_state == start_state && length > 2);
1493 ((
RenderState *)current_state)->_cycle_detect = this_seq;
1496 size_t cache_size = current_state->_composition_cache.
get_num_entries();
1497 for (i = 0; i < cache_size; ++i) {
1499 if (result !=
nullptr) {
1500 if (r_detect_cycles(start_state, result, length + 1,
1501 this_seq, cycle_desc)) {
1503 if (cycle_desc !=
nullptr) {
1505 CompositionCycleDescEntry entry(other, result,
false);
1506 cycle_desc->push_back(entry);
1513 cache_size = current_state->_invert_composition_cache.
get_num_entries();
1514 for (i = 0; i < cache_size; ++i) {
1516 if (result !=
nullptr) {
1517 if (r_detect_cycles(start_state, result, length + 1,
1518 this_seq, cycle_desc)) {
1520 if (cycle_desc !=
nullptr) {
1522 CompositionCycleDescEntry entry(other, result,
true);
1523 cycle_desc->push_back(entry);
1540 r_detect_reverse_cycles(
const RenderState *start_state,
1544 if (current_state->_cycle_detect == this_seq) {
1550 return (current_state == start_state && length > 2);
1552 ((
RenderState *)current_state)->_cycle_detect = this_seq;
1555 size_t cache_size = current_state->_composition_cache.
get_num_entries();
1556 for (i = 0; i < cache_size; ++i) {
1558 if (other != current_state) {
1559 int oi = other->_composition_cache.
find(current_state);
1560 nassertr(oi != -1,
false);
1563 if (result !=
nullptr) {
1564 if (r_detect_reverse_cycles(start_state, result, length + 1,
1565 this_seq, cycle_desc)) {
1567 if (cycle_desc !=
nullptr) {
1569 CompositionCycleDescEntry entry(other, result,
false);
1570 cycle_desc->push_back(entry);
1578 cache_size = current_state->_invert_composition_cache.
get_num_entries();
1579 for (i = 0; i < cache_size; ++i) {
1581 if (other != current_state) {
1582 int oi = other->_invert_composition_cache.
find(current_state);
1583 nassertr(oi != -1,
false);
1586 if (result !=
nullptr) {
1587 if (r_detect_reverse_cycles(start_state, result, length + 1,
1588 this_seq, cycle_desc)) {
1590 if (cycle_desc !=
nullptr) {
1592 CompositionCycleDescEntry entry(other, result,
false);
1593 cycle_desc->push_back(entry);
1615 if (_saved_entry != -1) {
1617 nassertv_always(_states->
remove(
this));
1629 remove_cache_pointers() {
1647 if (_composition_cache.
is_empty() && _invert_composition_cache.
is_empty()) {
1656 while (!_composition_cache.
is_empty()) {
1667 Composition comp = _composition_cache.
get_data(i);
1676 if (other !=
this) {
1677 int oi = other->_composition_cache.
find(
this);
1683 Composition ocomp = other->_composition_cache.
get_data(oi);
1692 if (ocomp._result !=
nullptr && ocomp._result != other) {
1700 if (comp._result !=
nullptr && comp._result !=
this) {
1707 while (!_invert_composition_cache.
is_empty()) {
1709 nassertv(other !=
this);
1710 Composition comp = _invert_composition_cache.
get_data(i);
1714 if (other !=
this) {
1715 int oi = other->_invert_composition_cache.
find(
this);
1717 Composition ocomp = other->_invert_composition_cache.
get_data(oi);
1721 if (ocomp._result !=
nullptr && ocomp._result != other) {
1726 if (comp._result !=
nullptr && comp._result !=
this) {
1736 determine_bin_index() {
1738 if ((_flags & F_checked_bin_index) != 0) {
1743 std::string bin_name;
1747 if (get_attrib(bin)) {
1752 if (bin_name.empty()) {
1755 bin_name =
"opaque";
1758 if (get_attrib(transparency)) {
1759 switch (transparency->
get_mode()) {
1760 case TransparencyAttrib::M_alpha:
1761 case TransparencyAttrib::M_premultiplied_alpha:
1762 case TransparencyAttrib::M_dual:
1764 bin_name =
"transparent";
1774 _bin_index = bin_manager->
find_bin(bin_name);
1775 if (_bin_index == -1) {
1776 pgraph_cat.warning()
1777 <<
"No bin named " << bin_name <<
"; creating default bin.\n";
1778 _bin_index = bin_manager->
add_bin(bin_name, CullBinManager::BT_unsorted, 0);
1780 _flags |= F_checked_bin_index;
1787 determine_cull_callback() {
1789 if ((_flags & F_checked_cull_callback) != 0) {
1794 SlotMask mask = _filled_slots;
1797 const Attribute &attrib = _attributes[slot];
1798 nassertv(attrib._attrib !=
nullptr);
1799 if (attrib._attrib->has_cull_callback()) {
1800 _flags |= F_has_cull_callback;
1804 mask.clear_bit(slot);
1805 slot = mask.get_lowest_on_bit();
1808 _flags |= F_checked_cull_callback;
1818 for (
int slot = 1; slot < num_slots; ++slot) {
1830 update_pstats(
int old_referenced_bits,
int new_referenced_bits) {
1832 if ((old_referenced_bits & R_node) != 0) {
1833 _node_counter.sub_level(1);
1834 }
else if ((old_referenced_bits & R_cache) != 0) {
1835 _cache_counter.sub_level(1);
1837 if ((new_referenced_bits & R_node) != 0) {
1838 _node_counter.add_level(1);
1839 }
else if ((new_referenced_bits & R_cache) != 0) {
1840 _cache_counter.add_level(1);
1860 _states_lock =
new LightReMutex(
"RenderState::_states_lock");
1861 _cache_stats.
init();
1868 state->_saved_entry = _states->
store(state,
nullptr);
1869 _empty_state = state;
1889 nassertv(num_attribs == (
int)(uint16_t)num_attribs);
1897 const Attribute &attrib = _attributes[slot];
1898 nassertv(attrib._attrib !=
nullptr);
1915 int num_attribs = 0;
1918 for (
size_t i = 0; i < (*_read_overrides).size(); ++i) {
1919 int override = (*_read_overrides)[i];
1922 if (attrib !=
nullptr) {
1923 int slot = attrib->get_slot();
1924 if (slot > 0 && slot < reg->get_max_slots()) {
1925 _attributes[slot].set(attrib,
override);
1932 delete _read_overrides;
1933 _read_overrides =
nullptr;
1956 if (pointer == state) {
1996 state->fillin(scan, manager);
2011 _read_overrides =
new vector_int;
2012 (*_read_overrides).reserve(num_attribs);
2014 for (
int i = 0; i < num_attribs; ++i) {
2017 (*_read_overrides).push_back(
override);
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void parse_params(const FactoryParams ¶ms, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void cache_unref_delete(RefCountType *ptr)
This global helper function will unref the given ReferenceCount object, and if the reference count re...
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
void register_finalize(TypedWritable *whom)
Should be called by an object reading itself from the Bam file to indicate that this particular objec...
void register_change_this(ChangeThisFunc func, TypedWritable *whom)
Called by an object reading itself from the bam file to indicate that the object pointer that will be...
bool read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.
int get_lowest_on_bit() const
Returns the index of the lowest 1 bit in the mask.
void set_bit(int index)
Sets the nth bit on.
bool get_bit(int index) const
Returns true if the nth bit is set, false if it is cleared.
void clear_bit(int index)
Sets the nth bit off.
int get_num_on_bits() const
Returns the number of bits that are set to 1 in the mask.
This is used to track the utilization of the TransformState and RenderState caches,...
void inc_adds(bool is_new)
Increments by 1 the count of elements added to the cache.
void add_total_size(int count)
Adds the indicated count (positive or negative) to the total number of entries for the cache (net occ...
void add_num_states(int count)
Adds the indicated count (positive or negative) to the total count of individual RenderState or Trans...
void maybe_report(const char *name)
Outputs a report if enough time has elapsed.
void inc_dels()
Increments by 1 the count of elements removed from the cache.
void init()
Initializes the CacheStats for the first time.
void inc_hits()
Increments by 1 the count of cache hits.
void inc_misses()
Increments by 1 the count of cache misses.
get_cache_ref_count
Returns the current reference count.
Assigns geometry to a particular bin by name.
get_draw_order
Returns the draw order this attribute specifies.
get_bin_name
Returns the name of the bin this attribute specifies.
This is a global object that maintains the collection of named CullBins in the world.
static CullBinManager * get_global_ptr()
Returns the pointer to the global CullBinManager object.
int add_bin(const std::string &name, BinType type, int sort)
Defines a new bin with the indicated name, and returns the new bin_index.
int find_bin(const std::string &name) const
Returns the bin_index associated with the bin of the given name, or -1 if no bin has that name.
This collects together the pieces of data that are accumulated for each node while walking the scene ...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
A class to retrieve the individual data elements previously stored in a Datagram.
uint16_t get_uint16()
Extracts an unsigned 16-bit integer.
int32_t get_int32()
Extracts a signed 32-bit integer.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
void add_int32(int32_t value)
Adds a signed 32-bit integer to the datagram.
void add_uint16(uint16_t value)
Adds an unsigned 16-bit integer to the datagram.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
void register_factory(TypeHandle handle, CreateFunc *func, void *user_data=nullptr)
Registers a new kind of thing the Factory will be able to create.
Similar to MutexHolder, but for a light mutex.
bool debug_is_locked() const
Returns true if the current thread has locked the LightReMutex, false otherwise.
Similar to MutexHolder, but for a light reentrant mutex.
A lightweight reentrant mutex.
static void update_type(ReferenceCount *ptr, TypeHandle type)
Associates the indicated type with the given pointer.
A lightweight class that represents a single element that may be timed and/or counted via stats.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
void local_object()
This function should be called, once, immediately after creating a new instance of some ReferenceCoun...
bool unref_if_one() const
Atomically decreases the reference count of this object if it is one.
get_ref_count
Returns the current reference count.
virtual bool unref() const
Explicitly decrements the reference count.
This class is used to associate each RenderAttrib with a different slot index at runtime,...
const RenderAttrib * get_slot_default(int slot) const
Returns the default RenderAttrib object associated with slot n.
static RenderAttribRegistry * quick_get_global_ptr()
Returns the global_ptr without first ensuring it has been initialized.
int get_sorted_slot(int n) const
Returns the nth slot in sorted order.
int get_num_slots() const
Returns the number of RenderAttrib slots that have been allocated.
int get_num_sorted_slots() const
Returns the number of entries in the sorted_slots list.
This is the base class for a number of render attributes (other than transform) that may be set on sc...
static int garbage_collect()
Performs a garbage-collection cycle.
Specifies how polygons are to be drawn.
int get_geom_rendering(int geom_rendering) const
Returns the union of the Geom::GeomRendering bits that will be required once this RenderModeAttrib is...
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
int compare_to(const RenderState &other) const
Provides an arbitrary ordering among all unique RenderStates, so we can store the essentially differe...
int compare_mask(const RenderState &other, SlotMask compare_mask) const
This version of compare_to takes a slot mask that indicates which attributes to include in the compar...
static void register_with_read_factory()
Tells the BamReader how to create objects of type RenderState.
static int get_num_states()
Returns the total number of unique RenderState objects allocated in the world.
static void list_states(std::ostream &out)
Lists all of the RenderStates in the cache to the output stream, one per line.
bool is_empty() const
Returns true if the state is empty, false otherwise.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
virtual int complete_pointers(TypedWritable **plist, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
static int garbage_collect()
Performs a garbage-collection cycle.
bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const
Calls cull_callback() on each attrib.
static void bin_removed(int bin_index)
Intended to be called by CullBinManager::remove_bin(), this informs all the RenderStates in the world...
int compare_sort(const RenderState &other) const
Returns -1, 0, or 1 according to the relative sorting of these two RenderStates, with regards to rend...
virtual bool unref() const
Explicitly decrements the reference count.
static void init_states()
Make sure the global _states map is allocated.
static void clear_munger_cache()
Completely empties the cache of state + gsg -> munger, for all states and all gsg's.
static bool validate_states()
Ensures that the cache is still stored in sorted order, and that none of the cache elements have been...
static TypedWritable * change_this(TypedWritable *old_ptr, BamReader *manager)
Called immediately after complete_pointers(), this gives the object a chance to adjust its own pointe...
static void list_cycles(std::ostream &out)
Detects all of the reference-count cycles in the cache and reports them to standard output.
static int clear_cache()
Empties the cache of composed RenderStates.
virtual void finalize(BamReader *manager)
Called by the BamReader to perform any final actions needed for setting up the object after all objec...
virtual ~RenderState()
The destructor is responsible for removing the RenderState from the global set if it is there.
int get_geom_rendering(int geom_rendering) const
Returns the union of the Geom::GeomRendering bits that will be required once this RenderState is appl...
static int get_num_unused_states()
Returns the total number of RenderState objects that have been allocated but have no references outsi...
This template class implements an unordered map of keys to data, implemented as a hashtable.
const Key & get_key(size_t n) const
Returns the key in the nth entry of the table.
int store(const Key &key, const Value &data)
Records the indicated key/data pair in the map.
bool validate() const
Returns true if the internal table appears to be consistent, false if there are some internal errors.
void clear()
Completely empties the table.
const Value & get_data(size_t n) const
Returns the data in the nth entry of the table.
int find(const Key &key) const
Searches for the indicated key in the table.
bool remove(const Key &key)
Removes the indicated key and its associated data from the table.
bool consider_shrink_table()
Shrinks the table if the allocated storage is significantly larger than the number of elements in it.
void remove_element(size_t n)
Removes the nth entry from the table.
bool is_empty() const
Returns true if the table is empty; i.e.
size_t get_num_entries() const
Returns the number of active entries in the table.
Computes texture coordinates for geometry automatically based on vertex position and/or normal.
int get_geom_rendering(int geom_rendering) const
Returns the union of the Geom::GeomRendering bits that will be required once this TexGenAttrib is app...
Applies a transform matrix to UV's before they are rendered.
int get_geom_rendering(int geom_rendering) const
Returns the union of the Geom::GeomRendering bits that will be required once this TexMatrixAttrib is ...
get_main_thread
Returns a pointer to the "main" Thread object–this is the Thread that started the whole process.
get_current_thread
Returns a pointer to the currently-executing Thread object.
This controls the enabling of transparency.
get_mode
Returns the transparency mode.
TypeHandle is the identifier used to differentiate C++ class types.
Base class for objects that can be written to and read from Bam files.
virtual void fillin(DatagramIterator &scan, BamReader *manager)
This internal function is intended to be called by each class's make_from_bam() method to read in all...
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
This is a sequence number that increments monotonically.
static size_t add_hash(size_t start, const Key &key)
Adds the indicated key into a running hash.
This is our own Panda specialization on the default STL map.
static size_t add_hash(size_t start, const void *key)
Adds the indicated key into a running hash.
This is our own Panda specialization on the default STL set.
This is our own Panda specialization on the default STL vector.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_lowest_on_bit(unsigned short x)
Returns the index of the lowest 1 bit in the word.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CPT(RenderState) RenderState
Returns a RenderState with one attribute set.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.