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();
943 state->release_new();
944 state->remove_cache_pointers();
945 state->cache_unref();
953 if (stop_at_element > 0) {
958 si = (si + 1) % size;
959 }
while (si != stop_at_element);
972 return (
int)orig_size - (int)size + num_attribs;
984 for (
size_t si = 0; si < size; ++si) {
986 state->_mungers.
clear();
987 state->_munged_states.
clear();
988 state->_last_mi = -1;
1007 if (_states ==
nullptr) {
1013 VisitedStates visited;
1017 for (
size_t si = 0; si < size; ++si) {
1020 bool inserted = visited.insert(state).second;
1022 ++_last_cycle_detect;
1023 if (r_detect_cycles(state, state, 1, _last_cycle_detect, &cycle_desc)) {
1025 CompositionCycleDesc::reverse_iterator csi;
1027 out <<
"\nCycle detected of length " << cycle_desc.size() + 1 <<
":\n" 1028 <<
"state " << (
void *)state <<
":" << state->
get_ref_count()
1030 state->write(out, 2);
1031 for (csi = cycle_desc.rbegin(); csi != cycle_desc.rend(); ++csi) {
1032 const CompositionCycleDescEntry &entry = (*csi);
1033 if (entry._inverted) {
1034 out <<
"invert composed with ";
1036 out <<
"composed with ";
1038 out << (
const void *)entry._obj <<
":" << entry._obj->get_ref_count()
1039 <<
" " << *entry._obj <<
"\n" 1040 <<
"produces " << (
const void *)entry._result <<
":" 1041 << entry._result->get_ref_count() <<
" =\n";
1042 entry._result->write(out, 2);
1043 visited.insert(entry._result);
1048 ++_last_cycle_detect;
1049 if (r_detect_reverse_cycles(state, state, 1, _last_cycle_detect, &cycle_desc)) {
1051 CompositionCycleDesc::iterator csi;
1053 out <<
"\nReverse cycle detected of length " << cycle_desc.size() + 1 <<
":\n" 1055 for (csi = cycle_desc.begin(); csi != cycle_desc.end(); ++csi) {
1056 const CompositionCycleDescEntry &entry = (*csi);
1057 out << (
const void *)entry._result <<
":" 1058 << entry._result->get_ref_count() <<
" =\n";
1059 entry._result->write(out, 2);
1060 out << (
const void *)entry._obj <<
":" 1061 << entry._obj->get_ref_count() <<
" =\n";
1062 entry._obj->write(out, 2);
1063 visited.insert(entry._result);
1065 out << (
void *)state <<
":" 1067 state->write(out, 2);
1084 if (_states ==
nullptr) {
1085 out <<
"0 states:\n";
1091 out << size <<
" states:\n";
1092 for (
size_t si = 0; si < size; ++si) {
1094 state->write(out, 2);
1106 if (_states ==
nullptr) {
1110 PStatTimer timer(_state_validate_pcollector);
1119 <<
"RenderState::_states cache is invalid!\n";
1125 nassertr(si < size,
false);
1126 nassertr(_states->
get_key(si)->get_ref_count() >= 0,
false);
1129 while (snext < size) {
1130 nassertr(_states->
get_key(snext)->get_ref_count() >= 0,
false);
1133 int c = ssi->compare_to(*ssnext);
1135 if ((ci < 0) != (c > 0) ||
1136 (ci > 0) != (c < 0) ||
1137 (ci == 0) != (c == 0)) {
1139 <<
"RenderState::compare_to() not defined properly!\n";
1140 pgraph_cat.error(
false)
1141 <<
"(a, b): " << c <<
"\n";
1142 pgraph_cat.error(
false)
1143 <<
"(b, a): " << ci <<
"\n";
1144 ssi->write(pgraph_cat.error(
false), 2);
1145 ssnext->write(pgraph_cat.error(
false), 2);
1166 if (get_attrib(render_mode)) {
1169 if (get_attrib(tex_gen)) {
1172 if (get_attrib(tex_matrix)) {
1176 return geom_rendering;
1195 validate_filled_slots()
const {
1199 int max_slots = reg->get_max_slots();
1200 for (
int slot = 1; slot < max_slots; ++slot) {
1201 const Attribute &attribute = _attributes[slot];
1202 if (attribute._attrib !=
nullptr) {
1207 return (mask == _filled_slots);
1217 SlotMask mask = _filled_slots;
1220 const Attribute &attrib = _attributes[slot];
1221 nassertv(attrib._attrib !=
nullptr);
1225 mask.clear_bit(slot);
1226 slot = mask.get_lowest_on_bit();
1229 _flags |= F_hash_known;
1241 nassertr(state !=
nullptr, state);
1246 if (state->_attributes[0]._attrib !=
nullptr) {
1247 const RenderAttrib *attrib = state->_attributes[0]._attrib;
1248 if (attrib->get_type() == TypeHandle::none()) {
1251 <<
"Uninitialized RenderAttrib type: " << attrib->get_type()
1256 if (already_reported.insert(attrib->get_type()).second) {
1258 << attrib->get_type() <<
" did not initialize its slot number.\n";
1263 state->_attributes[0]._attrib =
nullptr;
1267 nassertr(state->validate_filled_slots(), state);
1270 if (!uniquify_states && !state->
is_empty()) {
1274 return return_unique(state);
1287 nassertr(state !=
nullptr,
nullptr);
1294 if (paranoid_const) {
1301 if (state->_saved_entry != -1) {
1309 if (!uniquify_attribs && !state->
is_empty()) {
1310 SlotMask mask = state->_filled_slots;
1313 Attribute &attrib = state->_attributes[slot];
1314 nassertd(attrib._attrib !=
nullptr) continue;
1315 attrib._attrib = attrib._attrib->get_unique();
1316 mask.clear_bit(slot);
1321 int si = _states->find(state);
1326 if (state->get_ref_count() == 0) {
1333 if (garbage_collect_states) {
1339 si = _states->
store(state,
nullptr);
1342 state->_saved_entry = si;
1356 SlotMask mask = _filled_slots | other->_filled_slots;
1357 new_state->_filled_slots = mask;
1361 const Attribute &a = _attributes[slot];
1362 const Attribute &b = other->_attributes[slot];
1363 Attribute &result = new_state->_attributes[slot];
1365 if (a._attrib ==
nullptr) {
1366 nassertr(b._attrib !=
nullptr,
this);
1370 }
else if (b._attrib ==
nullptr) {
1374 }
else if (b._override < a._override) {
1378 }
else if (a._override < b._override &&
1379 a._attrib->lower_attrib_can_override()) {
1391 result.set(a._attrib->compose(b._attrib), b._override);
1394 mask.clear_bit(slot);
1395 slot = mask.get_lowest_on_bit();
1398 return return_new(new_state);
1405 do_invert_compose(
const RenderState *other)
const {
1410 SlotMask mask = _filled_slots | other->_filled_slots;
1411 new_state->_filled_slots = mask;
1415 const Attribute &a = _attributes[slot];
1416 const Attribute &b = other->_attributes[slot];
1417 Attribute &result = new_state->_attributes[slot];
1419 if (a._attrib ==
nullptr) {
1420 nassertr(b._attrib !=
nullptr,
this);
1424 }
else if (b._attrib ==
nullptr) {
1431 result.set(a._attrib->invert_compose(b._attrib), 0);
1434 mask.clear_bit(slot);
1435 slot = mask.get_lowest_on_bit();
1437 return return_new(new_state);
1445 detect_and_break_cycles() {
1446 PStatTimer timer(_state_break_cycles_pcollector);
1448 ++_last_cycle_detect;
1449 if (r_detect_cycles(
this,
this, 1, _last_cycle_detect,
nullptr)) {
1452 if (pgraph_cat.is_debug()) {
1454 <<
"Breaking cycle involving " << (*this) <<
"\n";
1459 ++_last_cycle_detect;
1460 if (r_detect_reverse_cycles(
this,
this, 1, _last_cycle_detect,
nullptr)) {
1461 if (pgraph_cat.is_debug()) {
1463 <<
"Breaking cycle involving " << (*this) <<
"\n";
1483 if (current_state->_cycle_detect == this_seq) {
1489 return (current_state == start_state && length > 2);
1491 ((
RenderState *)current_state)->_cycle_detect = this_seq;
1494 size_t cache_size = current_state->_composition_cache.
get_num_entries();
1495 for (i = 0; i < cache_size; ++i) {
1497 if (result !=
nullptr) {
1498 if (r_detect_cycles(start_state, result, length + 1,
1499 this_seq, cycle_desc)) {
1501 if (cycle_desc !=
nullptr) {
1503 CompositionCycleDescEntry entry(other, result,
false);
1504 cycle_desc->push_back(entry);
1511 cache_size = current_state->_invert_composition_cache.
get_num_entries();
1512 for (i = 0; i < cache_size; ++i) {
1514 if (result !=
nullptr) {
1515 if (r_detect_cycles(start_state, result, length + 1,
1516 this_seq, cycle_desc)) {
1518 if (cycle_desc !=
nullptr) {
1520 CompositionCycleDescEntry entry(other, result,
true);
1521 cycle_desc->push_back(entry);
1538 r_detect_reverse_cycles(
const RenderState *start_state,
1542 if (current_state->_cycle_detect == this_seq) {
1548 return (current_state == start_state && length > 2);
1550 ((
RenderState *)current_state)->_cycle_detect = this_seq;
1553 size_t cache_size = current_state->_composition_cache.
get_num_entries();
1554 for (i = 0; i < cache_size; ++i) {
1556 if (other != current_state) {
1557 int oi = other->_composition_cache.
find(current_state);
1558 nassertr(oi != -1,
false);
1561 if (result !=
nullptr) {
1562 if (r_detect_reverse_cycles(start_state, result, length + 1,
1563 this_seq, cycle_desc)) {
1565 if (cycle_desc !=
nullptr) {
1567 CompositionCycleDescEntry entry(other, result,
false);
1568 cycle_desc->push_back(entry);
1576 cache_size = current_state->_invert_composition_cache.
get_num_entries();
1577 for (i = 0; i < cache_size; ++i) {
1579 if (other != current_state) {
1580 int oi = other->_invert_composition_cache.
find(current_state);
1581 nassertr(oi != -1,
false);
1584 if (result !=
nullptr) {
1585 if (r_detect_reverse_cycles(start_state, result, length + 1,
1586 this_seq, cycle_desc)) {
1588 if (cycle_desc !=
nullptr) {
1590 CompositionCycleDescEntry entry(other, result,
false);
1591 cycle_desc->push_back(entry);
1613 if (_saved_entry != -1) {
1615 nassertv_always(_states->
remove(
this));
1627 remove_cache_pointers() {
1645 if (_composition_cache.
is_empty() && _invert_composition_cache.
is_empty()) {
1654 while (!_composition_cache.
is_empty()) {
1665 Composition comp = _composition_cache.
get_data(i);
1674 if (other !=
this) {
1675 int oi = other->_composition_cache.
find(
this);
1681 Composition ocomp = other->_composition_cache.
get_data(oi);
1690 if (ocomp._result !=
nullptr && ocomp._result != other) {
1698 if (comp._result !=
nullptr && comp._result !=
this) {
1705 while (!_invert_composition_cache.
is_empty()) {
1707 nassertv(other !=
this);
1708 Composition comp = _invert_composition_cache.
get_data(i);
1712 if (other !=
this) {
1713 int oi = other->_invert_composition_cache.
find(
this);
1715 Composition ocomp = other->_invert_composition_cache.
get_data(oi);
1719 if (ocomp._result !=
nullptr && ocomp._result != other) {
1724 if (comp._result !=
nullptr && comp._result !=
this) {
1734 determine_bin_index() {
1736 if ((_flags & F_checked_bin_index) != 0) {
1741 std::string bin_name;
1745 if (get_attrib(bin)) {
1750 if (bin_name.empty()) {
1753 bin_name =
"opaque";
1756 if (get_attrib(transparency)) {
1757 switch (transparency->
get_mode()) {
1758 case TransparencyAttrib::M_alpha:
1759 case TransparencyAttrib::M_premultiplied_alpha:
1760 case TransparencyAttrib::M_dual:
1762 bin_name =
"transparent";
1772 _bin_index = bin_manager->
find_bin(bin_name);
1773 if (_bin_index == -1) {
1774 pgraph_cat.warning()
1775 <<
"No bin named " << bin_name <<
"; creating default bin.\n";
1776 _bin_index = bin_manager->
add_bin(bin_name, CullBinManager::BT_unsorted, 0);
1778 _flags |= F_checked_bin_index;
1785 determine_cull_callback() {
1787 if ((_flags & F_checked_cull_callback) != 0) {
1792 SlotMask mask = _filled_slots;
1795 const Attribute &attrib = _attributes[slot];
1796 nassertv(attrib._attrib !=
nullptr);
1797 if (attrib._attrib->has_cull_callback()) {
1798 _flags |= F_has_cull_callback;
1802 mask.clear_bit(slot);
1803 slot = mask.get_lowest_on_bit();
1806 _flags |= F_checked_cull_callback;
1816 for (
int slot = 1; slot < num_slots; ++slot) {
1828 update_pstats(
int old_referenced_bits,
int new_referenced_bits) {
1830 if ((old_referenced_bits & R_node) != 0) {
1831 _node_counter.sub_level(1);
1832 }
else if ((old_referenced_bits & R_cache) != 0) {
1833 _cache_counter.sub_level(1);
1835 if ((new_referenced_bits & R_node) != 0) {
1836 _node_counter.add_level(1);
1837 }
else if ((new_referenced_bits & R_cache) != 0) {
1838 _cache_counter.add_level(1);
1858 _states_lock =
new LightReMutex(
"RenderState::_states_lock");
1859 _cache_stats.
init();
1860 nassertv(Thread::get_current_thread() == Thread::get_main_thread());
1866 state->_saved_entry = _states->
store(state,
nullptr);
1867 _empty_state = state;
1887 nassertv(num_attribs == (
int)(uint16_t)num_attribs);
1895 const Attribute &attrib = _attributes[slot];
1896 nassertv(attrib._attrib !=
nullptr);
1913 int num_attribs = 0;
1916 for (
size_t i = 0; i < (*_read_overrides).size(); ++i) {
1917 int override = (*_read_overrides)[i];
1920 if (attrib !=
nullptr) {
1921 int slot = attrib->get_slot();
1922 if (slot > 0 && slot < reg->get_max_slots()) {
1923 _attributes[slot].set(attrib,
override);
1930 delete _read_overrides;
1931 _read_overrides =
nullptr;
1954 if (pointer == state) {
1994 state->fillin(scan, manager);
2009 _read_overrides =
new vector_int;
2010 (*_read_overrides).reserve(num_attribs);
2012 for (
int i = 0; i < num_attribs; ++i) {
2015 (*_read_overrides).push_back(
override);
static void list_states(std::ostream &out)
Lists all of the RenderStates in the cache to the output stream, one per line.
void clear_bit(int index)
Sets the nth bit off.
bool is_empty() const
Returns true if the state is empty, false otherwise.
get_ref_count
Returns the current reference count.
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 map.
static int get_num_states()
Returns the total number of unique RenderState objects allocated in the world.
get_mode
Returns the transparency mode.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the base class for a number of render attributes (other than transform) that may be set on sc...
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...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void inc_dels()
Increments by 1 the count of elements removed from the cache.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
void cache_unref_delete(RefCountType *ptr)
This global helper function will unref the given ReferenceCount object, and if the reference count re...
This controls the enabling of transparency.
get_bin_name
Returns the name of the bin this attribute specifies.
Base class for objects that can be written to and read from Bam files.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static void clear_munger_cache()
Completely empties the cache of state + gsg -> munger, for all states and all gsg's.
bool debug_is_locked() const
Returns true if the current thread has locked the LightReMutex, false otherwise.
A lightweight reentrant mutex.
This collects together the pieces of data that are accumulated for each node while walking the scene ...
const Value & get_data(size_t n) const
Returns the data in the nth entry of the table.
int store(const Key &key, const Value &data)
Records the indicated key/data pair in the map.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
int get_num_slots() const
Returns the number of RenderAttrib slots that have been allocated.
This template class implements an unordered map of keys to data, implemented as a hashtable.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static void register_with_read_factory()
Tells the BamReader how to create objects of type RenderState.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
int get_lowest_on_bit(uint16_t x)
Returns the index of the lowest 1 bit in the word.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void clear()
Completely empties the table.
int32_t get_int32()
Extracts a signed 32-bit integer.
static int garbage_collect()
Performs a garbage-collection cycle.
virtual bool unref() const
Explicitly decrements the reference count.
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...
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...
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...
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static CullBinManager * get_global_ptr()
Returns the pointer to the global CullBinManager object.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is our own Panda specialization on the default STL vector.
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.
static size_t add_hash(size_t start, const Key &key)
Adds the indicated key into a running hash.
virtual ~RenderState()
The destructor is responsible for removing the RenderState from the global set if it is there.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
size_t get_num_entries() const
Returns the number of active entries in the table.
bool get_bit(int index) const
Returns true if the nth bit is set, false if it is cleared.
A lightweight class that represents a single element that may be timed and/or counted via stats.
void maybe_report(const char *name)
Outputs a report if enough time has elapsed.
void parse_params(const FactoryParams ¶ms, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function,...
void add_uint16(uint16_t value)
Adds an unsigned 16-bit integer to the datagram.
void inc_hits()
Increments by 1 the count of cache hits.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_lowest_on_bit() const
Returns the index of the lowest 1 bit in the mask.
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().
static int garbage_collect()
Performs a garbage-collection cycle.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
void inc_misses()
Increments by 1 the count of cache misses.
static bool validate_states()
Ensures that the cache is still stored in sorted order, and that none of the cache elements have been...
This class is used to associate each RenderAttrib with a different slot index at runtime,...
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
int get_sorted_slot(int n) const
Returns the nth slot in sorted order.
Similar to MutexHolder, but for a light mutex.
void init()
Initializes the CacheStats for the first time.
static int get_num_unused_states()
Returns the total number of RenderState objects that have been allocated but have no references outsi...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
const Key & get_key(size_t n) const
Returns the key in the nth entry of the table.
void add_total_size(int count)
Adds the indicated count (positive or negative) to the total number of entries for the cache (net occ...
bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const
Calls cull_callback() on each attrib.
void register_factory(TypeHandle handle, CreateFunc *func, void *user_data=nullptr)
Registers a new kind of thing the Factory will be able to create.
static void list_cycles(std::ostream &out)
Detects all of the reference-count cycles in the cache and reports them to standard output.
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...
virtual int complete_pointers(TypedWritable **plist, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
void register_finalize(TypedWritable *whom)
Should be called by an object reading itself from the Bam file to indicate that this particular objec...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool validate() const
Returns true if the internal table appears to be consistent, false if there are some internal errors.
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.
void set_bit(int index)
Sets the nth bit on.
Similar to MutexHolder, but for a light reentrant mutex.
void remove_element(size_t n)
Removes the nth entry from the table.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_num_sorted_slots() const
Returns the number of entries in the sorted_slots list.
bool consider_shrink_table()
Shrinks the table if the allocated storage is significantly larger than the number of elements in it.
static void update_type(ReferenceCount *ptr, TypeHandle type)
Associates the indicated type with the given pointer.
Assigns geometry to a particular bin by name.
void local_object()
This function should be called, once, immediately after creating a new instance of some ReferenceCoun...
Applies a transform matrix to UV's before they are rendered.
CPT(RenderState) RenderState
Returns a RenderState with one attribute set.
get_cache_ref_count
Returns the current reference count.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void add_int32(int32_t value)
Adds a signed 32-bit integer to the datagram.
uint16_t get_uint16()
Extracts an unsigned 16-bit integer.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
void add_num_states(int count)
Adds the indicated count (positive or negative) to the total count of individual RenderState or Trans...
This is used to track the utilization of the TransformState and RenderState caches,...
bool read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
bool is_empty() const
Returns true if the table is empty; i.e.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Specifies how polygons are to be drawn.
const RenderAttrib * get_slot_default(int slot) const
Returns the default RenderAttrib object associated with slot n.
This is our own Panda specialization on the default STL set.
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...
int get_num_on_bits() const
Returns the number of bits that are set to 1 in the mask.
A class to retrieve the individual data elements previously stored in a Datagram.
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...
int get_geom_rendering(int geom_rendering) const
Returns the union of the Geom::GeomRendering bits that will be required once this RenderModeAttrib is...
virtual void finalize(BamReader *manager)
Called by the BamReader to perform any final actions needed for setting up the object after all objec...
TypeHandle is the identifier used to differentiate C++ class types.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static int clear_cache()
Empties the cache of composed RenderStates.
This is a sequence number that increments monotonically.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is a global object that maintains the collection of named CullBins in the world.
void inc_adds(bool is_new)
Increments by 1 the count of elements added to the cache.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Computes texture coordinates for geometry automatically based on vertex position and/or normal.
int compare_to(const RenderState &other) const
Provides an arbitrary ordering among all unique RenderStates, so we can store the essentially differe...
get_draw_order
Returns the draw order this attribute specifies.
bool remove(const Key &key)
Removes the indicated key and its associated data from the table.
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
int get_geom_rendering(int geom_rendering) const
Returns the union of the Geom::GeomRendering bits that will be required once this TexMatrixAttrib is ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static RenderAttribRegistry * quick_get_global_ptr()
Returns the global_ptr without first ensuring it has been initialized.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual bool unref() const
Explicitly decrements the reference count.
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.
int find(const Key &key) const
Searches for the indicated key in the table.
static void init_states()
Make sure the global _states map is allocated.
static void bin_removed(int bin_index)
Intended to be called by CullBinManager::remove_bin(), this informs all the RenderStates in the world...