renderState.I 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. /**
  2. * PANDA 3D SOFTWARE
  3. * Copyright (c) Carnegie Mellon University. All rights reserved.
  4. *
  5. * All use of this software is subject to the terms of the revised BSD
  6. * license. You should have received a copy of this license along
  7. * with this source code in a file named "LICENSE."
  8. *
  9. * @file renderState.I
  10. * @author drose
  11. * @date 2002-02-21
  12. */
  13. /**
  14. * Returns a suitable hash value for phash_map.
  15. */
  16. INLINE size_t RenderState::
  17. get_hash() const {
  18. check_hash();
  19. return _hash;
  20. }
  21. /**
  22. * Returns true if the state is empty, false otherwise.
  23. */
  24. INLINE bool RenderState::
  25. is_empty() const {
  26. return _filled_slots.is_zero();
  27. }
  28. /**
  29. * Returns true if any of the RenderAttribs in this state request a
  30. * cull_callback(), false if none of them do.
  31. */
  32. INLINE bool RenderState::
  33. has_cull_callback() const {
  34. if ((_flags & F_checked_cull_callback) == 0) {
  35. // We pretend this function is const, even though it transparently
  36. // modifies the internal shader cache.
  37. ((RenderState *)this)->determine_cull_callback();
  38. }
  39. return (_flags & F_has_cull_callback) != 0;
  40. }
  41. /**
  42. * Returns a RenderState with no attributes set.
  43. */
  44. INLINE CPT(RenderState) RenderState::
  45. make_empty() {
  46. return _empty_state;
  47. }
  48. /**
  49. * Returns a new RenderState object that represents the same as the source
  50. * state, with the indicated RenderAttrib removed.
  51. */
  52. INLINE CPT(RenderState) RenderState::
  53. remove_attrib(TypeHandle type) const {
  54. RenderAttribRegistry *reg = RenderAttribRegistry::quick_get_global_ptr();
  55. int slot = reg->get_slot(type);
  56. return remove_attrib(slot);
  57. }
  58. /**
  59. * Returns true if an attrib of the indicated type is present, false
  60. * otherwise.
  61. */
  62. INLINE bool RenderState::
  63. has_attrib(TypeHandle type) const {
  64. return get_attrib(type) != nullptr;
  65. }
  66. /**
  67. * Returns true if an attrib of the indicated type is present, false
  68. * otherwise.
  69. */
  70. INLINE bool RenderState::
  71. has_attrib(int slot) const {
  72. return get_attrib(slot) != nullptr;
  73. }
  74. /**
  75. * Looks for a RenderAttrib of the indicated type in the state, and returns it
  76. * if it is found, or NULL if it is not.
  77. */
  78. INLINE const RenderAttrib *RenderState::
  79. get_attrib(TypeHandle type) const {
  80. RenderAttribRegistry *reg = RenderAttribRegistry::get_global_ptr();
  81. int slot = reg->get_slot(type);
  82. return _attributes[slot]._attrib;
  83. }
  84. /**
  85. * Returns the RenderAttrib with the indicated slot index, or NULL if there is
  86. * no such RenderAttrib in the state.
  87. */
  88. ALWAYS_INLINE const RenderAttrib *RenderState::
  89. get_attrib(int slot) const {
  90. return _attributes[slot]._attrib;
  91. }
  92. /**
  93. * Returns the RenderAttrib with the indicated slot index, or the default
  94. * attrib for that slot if there is no such RenderAttrib in the state.
  95. */
  96. INLINE const RenderAttrib *RenderState::
  97. get_attrib_def(int slot) const {
  98. if (_attributes[slot]._attrib != nullptr) {
  99. return _attributes[slot]._attrib;
  100. }
  101. RenderAttribRegistry *reg = RenderAttribRegistry::quick_get_global_ptr();
  102. return reg->get_slot_default(slot);
  103. }
  104. /**
  105. * Looks for a RenderAttrib of the indicated type in the state, and returns
  106. * its override value if it is found, or 0 if it is not.
  107. */
  108. INLINE int RenderState::
  109. get_override(TypeHandle type) const {
  110. RenderAttribRegistry *reg = RenderAttribRegistry::get_global_ptr();
  111. int slot = reg->get_slot(type);
  112. return _attributes[slot]._override;
  113. }
  114. /**
  115. * Looks for a RenderAttrib of the indicated type in the state, and returns
  116. * its override value if it is found, or 0 if it is not.
  117. */
  118. INLINE int RenderState::
  119. get_override(int slot) const {
  120. return _attributes[slot]._override;
  121. }
  122. /**
  123. * Returns the pointer to the unique RenderState in the cache that is
  124. * equivalent to this one. This may be the same pointer as this object, or it
  125. * may be a different pointer; but it will be an equivalent object, and it
  126. * will be a shared pointer. This may be called from time to time to improve
  127. * cache benefits.
  128. */
  129. INLINE CPT(RenderState) RenderState::
  130. get_unique() const {
  131. return return_unique((RenderState *)this);
  132. }
  133. /**
  134. * Overrides this method to update PStats appropriately.
  135. */
  136. INLINE void RenderState::
  137. cache_ref() const {
  138. #ifdef DO_PSTATS
  139. int old_referenced_bits = get_referenced_bits();
  140. NodeCachedReferenceCount::cache_ref();
  141. consider_update_pstats(old_referenced_bits);
  142. #else // DO_PSTATS
  143. NodeCachedReferenceCount::cache_ref();
  144. #endif // DO_PSTATS
  145. }
  146. /**
  147. * Overrides this method to update PStats appropriately.
  148. */
  149. INLINE bool RenderState::
  150. cache_unref() const {
  151. #ifdef DO_PSTATS
  152. int old_referenced_bits = get_referenced_bits();
  153. bool result = do_cache_unref();
  154. consider_update_pstats(old_referenced_bits);
  155. return result;
  156. #else // DO_PSTATS
  157. return do_cache_unref();
  158. #endif // DO_PSTATS
  159. }
  160. /**
  161. * Overrides this method to update PStats appropriately.
  162. */
  163. INLINE void RenderState::
  164. node_ref() const {
  165. #ifdef DO_PSTATS
  166. int old_referenced_bits = get_referenced_bits();
  167. NodeCachedReferenceCount::node_ref();
  168. consider_update_pstats(old_referenced_bits);
  169. #else // DO_PSTATS
  170. NodeCachedReferenceCount::node_ref();
  171. #endif // DO_PSTATS
  172. }
  173. /**
  174. * Overrides this method to update PStats appropriately.
  175. */
  176. INLINE bool RenderState::
  177. node_unref() const {
  178. #ifdef DO_PSTATS
  179. int old_referenced_bits = get_referenced_bits();
  180. bool result = do_node_unref();
  181. consider_update_pstats(old_referenced_bits);
  182. return result;
  183. #else // DO_PSTATS
  184. return do_node_unref();
  185. #endif // DO_PSTATS
  186. }
  187. /**
  188. * Returns the number of entries in the composition cache for this
  189. * RenderState. This is the number of other RenderStates whose composition
  190. * with this one has been cached. This number is not useful for any practical
  191. * reason other than performance analysis.
  192. */
  193. INLINE size_t RenderState::
  194. get_composition_cache_num_entries() const {
  195. LightReMutexHolder holder(*_states_lock);
  196. return _composition_cache.get_num_entries();
  197. }
  198. /**
  199. * Returns the number of entries in the invert_composition cache for this
  200. * RenderState. This is similar to the composition cache, but it records
  201. * cache entries for the invert_compose() operation. See
  202. * get_composition_cache_num_entries().
  203. */
  204. INLINE size_t RenderState::
  205. get_invert_composition_cache_num_entries() const {
  206. LightReMutexHolder holder(*_states_lock);
  207. return _invert_composition_cache.get_num_entries();
  208. }
  209. /**
  210. * Returns the number of slots in the composition cache for this RenderState.
  211. * You may use this as an upper bound when walking through all of the
  212. * composition cache results via get_composition_cache_source() or result().
  213. *
  214. * This has no practical value other than for examining the cache for
  215. * performance analysis.
  216. */
  217. INLINE size_t RenderState::
  218. get_composition_cache_size() const {
  219. LightReMutexHolder holder(*_states_lock);
  220. return _composition_cache.get_num_entries();
  221. }
  222. /**
  223. * Returns the source RenderState of the nth element in the composition cache.
  224. * Returns NULL if there doesn't happen to be an entry in the nth element.
  225. * See get_composition_cache_result().
  226. *
  227. * This has no practical value other than for examining the cache for
  228. * performance analysis.
  229. */
  230. INLINE const RenderState *RenderState::
  231. get_composition_cache_source(size_t n) const {
  232. LightReMutexHolder holder(*_states_lock);
  233. return _composition_cache.get_key(n);
  234. }
  235. /**
  236. * Returns the result RenderState of the nth element in the composition cache.
  237. * Returns NULL if there doesn't happen to be an entry in the nth element.
  238. *
  239. * In general, a->compose(a->get_composition_cache_source(n)) ==
  240. * a->get_composition_cache_result(n).
  241. *
  242. * This has no practical value other than for examining the cache for
  243. * performance analysis.
  244. */
  245. INLINE const RenderState *RenderState::
  246. get_composition_cache_result(size_t n) const {
  247. LightReMutexHolder holder(*_states_lock);
  248. return _composition_cache.get_data(n)._result;
  249. }
  250. /**
  251. * Returns the number of slots in the composition cache for this RenderState.
  252. * You may use this as an upper bound when walking through all of the
  253. * composition cache results via get_invert_composition_cache_source() or
  254. * result().
  255. *
  256. * This has no practical value other than for examining the cache for
  257. * performance analysis.
  258. */
  259. INLINE size_t RenderState::
  260. get_invert_composition_cache_size() const {
  261. LightReMutexHolder holder(*_states_lock);
  262. return _invert_composition_cache.get_num_entries();
  263. }
  264. /**
  265. * Returns the source RenderState of the nth element in the invert composition
  266. * cache. Returns NULL if there doesn't happen to be an entry in the nth
  267. * element. See get_invert_composition_cache_result().
  268. *
  269. * This has no practical value other than for examining the cache for
  270. * performance analysis.
  271. */
  272. INLINE const RenderState *RenderState::
  273. get_invert_composition_cache_source(size_t n) const {
  274. LightReMutexHolder holder(*_states_lock);
  275. return _invert_composition_cache.get_key(n);
  276. }
  277. /**
  278. * Returns the result RenderState of the nth element in the invert composition
  279. * cache. Returns NULL if there doesn't happen to be an entry in the nth
  280. * element.
  281. *
  282. * In general, a->invert_compose(a->get_invert_composition_cache_source(n)) ==
  283. * a->get_invert_composition_cache_result(n).
  284. *
  285. * This has no practical value other than for examining the cache for
  286. * performance analysis.
  287. */
  288. INLINE const RenderState *RenderState::
  289. get_invert_composition_cache_result(size_t n) const {
  290. LightReMutexHolder holder(*_states_lock);
  291. return _invert_composition_cache.get_data(n)._result;
  292. }
  293. /**
  294. * Returns the draw order indicated by the CullBinAttrib, if any, associated
  295. * by this state (or 0 if there is no CullBinAttrib). See get_bin_index().
  296. */
  297. INLINE int RenderState::
  298. get_draw_order() const {
  299. if ((_flags & F_checked_bin_index) == 0) {
  300. // We pretend this function is const, even though it transparently
  301. // modifies the internal draw_order cache.
  302. ((RenderState *)this)->determine_bin_index();
  303. }
  304. return _draw_order;
  305. }
  306. /**
  307. * Returns the bin index indicated by the CullBinAttrib, if any, associated by
  308. * this state (or the default bin index if there is no CullBinAttrib). This
  309. * function is provided as an optimization for determining this at render
  310. * time.
  311. */
  312. INLINE int RenderState::
  313. get_bin_index() const {
  314. if ((_flags & F_checked_bin_index) == 0) {
  315. // We pretend this function is const, even though it transparently
  316. // modifies the internal bin_index cache.
  317. ((RenderState *)this)->determine_bin_index();
  318. }
  319. return _bin_index;
  320. }
  321. /**
  322. * This function should only be called from the destructor; it indicates that
  323. * this RenderState object is beginning destruction. It is only used as a
  324. * sanity check, and is only meaningful when NDEBUG is not defined.
  325. */
  326. INLINE void RenderState::
  327. set_destructing() {
  328. #ifndef NDEBUG
  329. _flags |= F_is_destructing;
  330. #endif
  331. }
  332. /**
  333. * Returns true if the RenderState object is currently within its destructor
  334. * (i.e. set_destructing() has been called). This is only used as a sanity
  335. * check, and is only meaningful when NDEBUG is not defined.
  336. */
  337. INLINE bool RenderState::
  338. is_destructing() const {
  339. #ifndef NDEBUG
  340. return (_flags & F_is_destructing) != 0;
  341. #else
  342. return false;
  343. #endif
  344. }
  345. /**
  346. * Calls update_pstats() if the state of the referenced bits has changed from
  347. * the indicated value.
  348. */
  349. INLINE void RenderState::
  350. consider_update_pstats(int old_referenced_bits) const {
  351. #ifdef DO_PSTATS
  352. int new_referenced_bits = get_referenced_bits();
  353. if (old_referenced_bits != new_referenced_bits) {
  354. update_pstats(old_referenced_bits, new_referenced_bits);
  355. }
  356. #endif // DO_PSTATS
  357. }
  358. /**
  359. *
  360. */
  361. INLINE RenderState::Composition::
  362. Composition() {
  363. }
  364. /**
  365. *
  366. */
  367. INLINE RenderState::Composition::
  368. Composition(const RenderState::Composition &copy) :
  369. _result(copy._result)
  370. {
  371. }
  372. /**
  373. *
  374. */
  375. INLINE RenderState::Attribute::
  376. Attribute(const RenderAttrib *attrib, int override) :
  377. _attrib(attrib),
  378. _override(override)
  379. {
  380. }
  381. /**
  382. *
  383. */
  384. INLINE RenderState::Attribute::
  385. Attribute(int override) :
  386. _override(override)
  387. {
  388. }
  389. /**
  390. *
  391. */
  392. INLINE RenderState::Attribute::
  393. Attribute(const Attribute &copy) :
  394. _attrib(copy._attrib),
  395. _override(copy._override)
  396. {
  397. }
  398. /**
  399. *
  400. */
  401. INLINE void RenderState::Attribute::
  402. operator = (const Attribute &copy) {
  403. _attrib = copy._attrib;
  404. _override = copy._override;
  405. }
  406. /**
  407. * Provides an indication of whether a particular attribute is equivalent to
  408. * another one, for purposes of generating unique RenderStates. This should
  409. * compare all properties of the Attribute.
  410. */
  411. INLINE int RenderState::Attribute::
  412. compare_to(const Attribute &other) const {
  413. if (_attrib != other._attrib) {
  414. if (_attrib == nullptr) {
  415. return -1;
  416. } else if (other._attrib == nullptr) {
  417. return 1;
  418. }
  419. int c = _attrib->compare_to(*other._attrib);
  420. if (c != 0) {
  421. return c;
  422. }
  423. }
  424. return _override - other._override;
  425. }
  426. /**
  427. *
  428. */
  429. INLINE void RenderState::Attribute::
  430. set(const RenderAttrib *attrib, int override) {
  431. _attrib = attrib;
  432. _override = override;
  433. }
  434. /**
  435. * Flushes the PStatCollectors used during traversal.
  436. */
  437. INLINE void RenderState::
  438. flush_level() {
  439. _node_counter.flush_level();
  440. _cache_counter.flush_level();
  441. }
  442. /**
  443. * Overrides this method to update PStats appropriately.
  444. */
  445. INLINE void RenderState::
  446. cache_ref_only() const {
  447. #ifdef DO_PSTATS
  448. int old_referenced_bits = get_referenced_bits();
  449. NodeCachedReferenceCount::cache_ref_only();
  450. consider_update_pstats(old_referenced_bits);
  451. #else // DO_PSTATS
  452. NodeCachedReferenceCount::cache_ref_only();
  453. #endif // DO_PSTATS
  454. }
  455. /**
  456. * Overrides this method to update PStats appropriately.
  457. */
  458. INLINE void RenderState::
  459. cache_unref_only() const {
  460. #ifdef DO_PSTATS
  461. int old_referenced_bits = get_referenced_bits();
  462. NodeCachedReferenceCount::cache_unref_only();
  463. consider_update_pstats(old_referenced_bits);
  464. #else // DO_PSTATS
  465. NodeCachedReferenceCount::cache_unref_only();
  466. #endif // DO_PSTATS
  467. }
  468. #ifndef CPPPARSER
  469. /**
  470. * Handy templated version of get_attrib that casts to the right type.
  471. * Returns true if the attribute was present, false otherwise.
  472. */
  473. template<class AttribType>
  474. INLINE bool RenderState::
  475. get_attrib(const AttribType *&attrib) const {
  476. attrib = (const AttribType *)get_attrib((int)AttribType::get_class_slot());
  477. return (attrib != nullptr);
  478. }
  479. template<class AttribType>
  480. INLINE bool RenderState::
  481. get_attrib(CPT(AttribType) &attrib) const {
  482. attrib = (const AttribType *)get_attrib((int)AttribType::get_class_slot());
  483. return (attrib != nullptr);
  484. }
  485. /**
  486. * Handy templated version of get_attrib_def that casts to the right type.
  487. */
  488. template<class AttribType>
  489. INLINE void RenderState::
  490. get_attrib_def(const AttribType *&attrib) const {
  491. attrib = (const AttribType *)get_attrib_def((int)AttribType::get_class_slot());
  492. }
  493. template<class AttribType>
  494. INLINE void RenderState::
  495. get_attrib_def(CPT(AttribType) &attrib) const {
  496. attrib = (const AttribType *)get_attrib_def((int)AttribType::get_class_slot());
  497. }
  498. #endif // CPPPARSER
  499. /**
  500. * Ensures that we know the hash value.
  501. */
  502. INLINE void RenderState::
  503. check_hash() const {
  504. // This pretends to be a const function, even though it's not, because it
  505. // only updates a transparent cache value.
  506. if ((_flags & F_hash_known) != 0) {
  507. } else {
  508. ((RenderState *)this)->calc_hash();
  509. }
  510. }
  511. /**
  512. * Reimplements CachedTypedWritableReferenceCount::cache_unref(). We do this
  513. * because we have a non-virtual unref() method.
  514. */
  515. INLINE bool RenderState::
  516. do_cache_unref() const {
  517. NodeCachedReferenceCount::cache_unref_only();
  518. return unref();
  519. }
  520. /**
  521. * Reimplements NodeReferenceCount::node_unref(). We do this because we have
  522. * a non-virtual unref() method.
  523. */
  524. INLINE bool RenderState::
  525. do_node_unref() const {
  526. node_unref_only();
  527. return unref();
  528. }
  529. /**
  530. * Computes the hash value.
  531. */
  532. INLINE void RenderState::
  533. calc_hash() {
  534. LightMutexHolder holder(_lock);
  535. do_calc_hash();
  536. }
  537. /**
  538. *
  539. */
  540. INLINE RenderState::CompositionCycleDescEntry::
  541. CompositionCycleDescEntry(const RenderState *obj,
  542. const RenderState *result,
  543. bool inverted) :
  544. _obj(obj),
  545. _result(result),
  546. _inverted(inverted)
  547. {
  548. }