Panda3D
|
00001 // Filename: renderAttrib.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 "renderAttrib.h" 00016 #include "bamReader.h" 00017 #include "indent.h" 00018 #include "config_pgraph.h" 00019 #include "lightReMutexHolder.h" 00020 00021 LightReMutex *RenderAttrib::_attribs_lock = NULL; 00022 RenderAttrib::Attribs *RenderAttrib::_attribs = NULL; 00023 TypeHandle RenderAttrib::_type_handle; 00024 00025 //////////////////////////////////////////////////////////////////// 00026 // Function: RenderAttrib::Constructor 00027 // Access: Protected 00028 // Description: 00029 //////////////////////////////////////////////////////////////////// 00030 RenderAttrib:: 00031 RenderAttrib() { 00032 if (_attribs == (Attribs *)NULL) { 00033 init_attribs(); 00034 } 00035 _saved_entry = _attribs->end(); 00036 00037 _always_reissue = false; 00038 } 00039 00040 //////////////////////////////////////////////////////////////////// 00041 // Function: RenderAttrib::Copy Constructor 00042 // Access: Private 00043 // Description: RenderAttribs are not meant to be copied. 00044 //////////////////////////////////////////////////////////////////// 00045 RenderAttrib:: 00046 RenderAttrib(const RenderAttrib &) { 00047 nassertv(false); 00048 } 00049 00050 //////////////////////////////////////////////////////////////////// 00051 // Function: RenderAttrib::Copy Assignment Operator 00052 // Access: Private 00053 // Description: RenderAttribs are not meant to be copied. 00054 //////////////////////////////////////////////////////////////////// 00055 void RenderAttrib:: 00056 operator = (const RenderAttrib &) { 00057 nassertv(false); 00058 } 00059 00060 //////////////////////////////////////////////////////////////////// 00061 // Function: RenderAttrib::Destructor 00062 // Access: Public, Virtual 00063 // Description: The destructor is responsible for removing the 00064 // RenderAttrib from the global set if it is there. 00065 //////////////////////////////////////////////////////////////////// 00066 RenderAttrib:: 00067 ~RenderAttrib() { 00068 LightReMutexHolder holder(*_attribs_lock); 00069 00070 // unref() should have cleared this. 00071 nassertv(_saved_entry == _attribs->end()); 00072 } 00073 00074 //////////////////////////////////////////////////////////////////// 00075 // Function: RenderAttrib::lower_attrib_can_override 00076 // Access: Public, Virtual 00077 // Description: Intended to be overridden by derived RenderAttrib 00078 // types to specify how two consecutive RenderAttrib 00079 // objects of the same type interact. 00080 // 00081 // This should return false if a RenderAttrib on a 00082 // higher node will compose into a RenderAttrib on a 00083 // lower node that has a higher override value, or true 00084 // if the lower RenderAttrib will completely replace the 00085 // state. 00086 // 00087 // The default behavior is false: normally, a 00088 // RenderAttrib in the graph cannot completely override 00089 // a RenderAttrib above it, regardless of its override 00090 // value--instead, the two attribs are composed. But 00091 // for some kinds of RenderAttribs, it is useful to 00092 // allow this kind of override. 00093 // 00094 // This method only handles the one special case of a 00095 // lower RenderAttrib with a higher override value. If 00096 // the higher RenderAttrib has a higher override value, 00097 // it always completely overrides. And if both 00098 // RenderAttribs have the same override value, they are 00099 // always composed. 00100 //////////////////////////////////////////////////////////////////// 00101 bool RenderAttrib:: 00102 lower_attrib_can_override() const { 00103 return false; 00104 } 00105 00106 //////////////////////////////////////////////////////////////////// 00107 // Function: RenderAttrib::has_cull_callback 00108 // Access: Public, Virtual 00109 // Description: Should be overridden by derived classes to return 00110 // true if cull_callback() has been defined. Otherwise, 00111 // returns false to indicate cull_callback() does not 00112 // need to be called for this node during the cull 00113 // traversal. 00114 //////////////////////////////////////////////////////////////////// 00115 bool RenderAttrib:: 00116 has_cull_callback() const { 00117 return false; 00118 } 00119 00120 //////////////////////////////////////////////////////////////////// 00121 // Function: RenderAttrib::cull_callback 00122 // Access: Public, Virtual 00123 // Description: If has_cull_callback() returns true, this function 00124 // will be called during the cull traversal to perform 00125 // any additional operations that should be performed at 00126 // cull time. 00127 // 00128 // This is called each time the RenderAttrib is 00129 // discovered applied to a Geom in the traversal. It 00130 // should return true if the Geom is visible, false if 00131 // it should be omitted. 00132 //////////////////////////////////////////////////////////////////// 00133 bool RenderAttrib:: 00134 cull_callback(CullTraverser *, const CullTraverserData &) const { 00135 return true; 00136 } 00137 00138 //////////////////////////////////////////////////////////////////// 00139 // Function: RenderAttrib::unref 00140 // Access: Published, Virtual 00141 // Description: This method overrides ReferenceCount::unref() to 00142 // clear the pointer from the global object pool when 00143 // its reference count goes to zero. 00144 //////////////////////////////////////////////////////////////////// 00145 bool RenderAttrib:: 00146 unref() const { 00147 // We always have to grab the lock, since we will definitely need to 00148 // be holding it if we happen to drop the reference count to 0. 00149 LightReMutexHolder holder(*_attribs_lock); 00150 00151 if (ReferenceCount::unref()) { 00152 // The reference count is still nonzero. 00153 return true; 00154 } 00155 00156 // The reference count has just reached zero. Make sure the object 00157 // is removed from the global object pool, before anyone else finds 00158 // it and tries to ref it. 00159 ((RenderAttrib *)this)->release_new(); 00160 00161 return false; 00162 } 00163 00164 //////////////////////////////////////////////////////////////////// 00165 // Function: RenderAttrib::output 00166 // Access: Published, Virtual 00167 // Description: 00168 //////////////////////////////////////////////////////////////////// 00169 void RenderAttrib:: 00170 output(ostream &out) const { 00171 out << get_type(); 00172 } 00173 00174 //////////////////////////////////////////////////////////////////// 00175 // Function: RenderAttrib::write 00176 // Access: Published, Virtual 00177 // Description: 00178 //////////////////////////////////////////////////////////////////// 00179 void RenderAttrib:: 00180 write(ostream &out, int indent_level) const { 00181 indent(out, indent_level) << *this << "\n"; 00182 } 00183 00184 //////////////////////////////////////////////////////////////////// 00185 // Function: RenderAttrib::get_num_attribs 00186 // Access: Published, Static 00187 // Description: Returns the total number of unique RenderAttrib 00188 // objects allocated in the world. This will go up and 00189 // down during normal operations. 00190 //////////////////////////////////////////////////////////////////// 00191 int RenderAttrib:: 00192 get_num_attribs() { 00193 LightReMutexHolder holder(*_attribs_lock); 00194 00195 if (_attribs == (Attribs *)NULL) { 00196 return 0; 00197 } 00198 return _attribs->size(); 00199 } 00200 00201 //////////////////////////////////////////////////////////////////// 00202 // Function: RenderAttrib::list_attribs 00203 // Access: Published, Static 00204 // Description: Lists all of the RenderAttribs in the cache to the 00205 // output stream, one per line. This can be quite a lot 00206 // of output if the cache is large, so be prepared. 00207 //////////////////////////////////////////////////////////////////// 00208 void RenderAttrib:: 00209 list_attribs(ostream &out) { 00210 LightReMutexHolder holder(*_attribs_lock); 00211 00212 out << _attribs->size() << " attribs:\n"; 00213 Attribs::const_iterator si; 00214 for (si = _attribs->begin(); si != _attribs->end(); ++si) { 00215 const RenderAttrib *attrib = (*si); 00216 attrib->write(out, 2); 00217 } 00218 } 00219 00220 //////////////////////////////////////////////////////////////////// 00221 // Function: RenderAttrib::validate_attribs 00222 // Access: Published, Static 00223 // Description: Ensures that the cache is still stored in sorted 00224 // order. Returns true if so, false if there is a 00225 // problem (which implies someone has modified one of 00226 // the supposedly-const RenderAttrib objects). 00227 //////////////////////////////////////////////////////////////////// 00228 bool RenderAttrib:: 00229 validate_attribs() { 00230 LightReMutexHolder holder(*_attribs_lock); 00231 00232 if (_attribs->empty()) { 00233 return true; 00234 } 00235 00236 Attribs::const_iterator si = _attribs->begin(); 00237 Attribs::const_iterator snext = si; 00238 ++snext; 00239 while (snext != _attribs->end()) { 00240 if ((*si)->compare_to(*(*snext)) >= 0) { 00241 pgraph_cat.error() 00242 << "RenderAttribs out of order!\n"; 00243 (*si)->write(pgraph_cat.error(false), 2); 00244 (*snext)->write(pgraph_cat.error(false), 2); 00245 return false; 00246 } 00247 si = snext; 00248 ++snext; 00249 } 00250 00251 return true; 00252 } 00253 00254 //////////////////////////////////////////////////////////////////// 00255 // Function: RenderAttrib::return_new 00256 // Access: Protected, Static 00257 // Description: This function is used by derived RenderAttrib types 00258 // to share a common RenderAttrib pointer for all 00259 // equivalent RenderAttrib objects. 00260 // 00261 // This is different from return_unique() in that it 00262 // does not actually guarantee a unique pointer, unless 00263 // uniquify-attribs is set. 00264 //////////////////////////////////////////////////////////////////// 00265 CPT(RenderAttrib) RenderAttrib:: 00266 return_new(RenderAttrib *attrib) { 00267 nassertr(attrib != (RenderAttrib *)NULL, attrib); 00268 if (!uniquify_attribs) { 00269 return attrib; 00270 } 00271 00272 return return_unique(attrib); 00273 } 00274 00275 //////////////////////////////////////////////////////////////////// 00276 // Function: RenderAttrib::return_unique 00277 // Access: Protected, Static 00278 // Description: This function is used by derived RenderAttrib types 00279 // to share a common RenderAttrib pointer for all 00280 // equivalent RenderAttrib objects. 00281 // 00282 // The make() function of the derived type should create 00283 // a new RenderAttrib and pass it through return_new(), 00284 // which will either save the pointer and return it 00285 // unchanged (if this is the first similar such object) 00286 // or delete it and return an equivalent pointer (if 00287 // there was already a similar object saved). 00288 //////////////////////////////////////////////////////////////////// 00289 CPT(RenderAttrib) RenderAttrib:: 00290 return_unique(RenderAttrib *attrib) { 00291 nassertr(attrib != (RenderAttrib *)NULL, attrib); 00292 00293 #ifndef NDEBUG 00294 if (!state_cache) { 00295 return attrib; 00296 } 00297 #endif 00298 00299 #ifndef NDEBUG 00300 if (paranoid_const) { 00301 nassertr(validate_attribs(), attrib); 00302 } 00303 #endif 00304 00305 LightReMutexHolder holder(*_attribs_lock); 00306 00307 if (attrib->_saved_entry != _attribs->end()) { 00308 // This attrib is already in the cache. 00309 nassertr(_attribs->find(attrib) == attrib->_saved_entry, attrib); 00310 return attrib; 00311 } 00312 00313 // Save the attrib in a local PointerTo so that it will be freed at 00314 // the end of this function if no one else uses it. 00315 CPT(RenderAttrib) pt_attrib = attrib; 00316 00317 pair<Attribs::iterator, bool> result = _attribs->insert(attrib); 00318 if (result.second) { 00319 // The attribute was inserted; save the iterator and return the 00320 // input attribute. 00321 attrib->_saved_entry = result.first; 00322 00323 return pt_attrib; 00324 } 00325 00326 // The attribute was not inserted; there must be an equivalent one 00327 // already in the set. Return that one. 00328 return *(result.first); 00329 } 00330 00331 //////////////////////////////////////////////////////////////////// 00332 // Function: RenderAttrib::compare_to_impl 00333 // Access: Protected, Virtual 00334 // Description: Intended to be overridden by derived RenderAttrib 00335 // types to return a unique number indicating whether 00336 // this RenderAttrib is equivalent to the other one. 00337 // 00338 // This should return 0 if the two RenderAttrib objects 00339 // are equivalent, a number less than zero if this one 00340 // should be sorted before the other one, and a number 00341 // greater than zero otherwise. 00342 // 00343 // This will only be called with two RenderAttrib 00344 // objects whose get_type() functions return the same. 00345 //////////////////////////////////////////////////////////////////// 00346 int RenderAttrib:: 00347 compare_to_impl(const RenderAttrib *other) const { 00348 return 0; 00349 } 00350 00351 //////////////////////////////////////////////////////////////////// 00352 // Function: RenderAttrib::compose_impl 00353 // Access: Protected, Virtual 00354 // Description: Intended to be overridden by derived RenderAttrib 00355 // types to specify how two consecutive RenderAttrib 00356 // objects of the same type interact. 00357 // 00358 // This should return the result of applying the other 00359 // RenderAttrib to a node in the scene graph below this 00360 // RenderAttrib, which was already applied. In most 00361 // cases, the result is the same as the other 00362 // RenderAttrib (that is, a subsequent RenderAttrib 00363 // completely replaces the preceding one). On the other 00364 // hand, some kinds of RenderAttrib (for instance, 00365 // ColorTransformAttrib) might combine in meaningful 00366 // ways. 00367 //////////////////////////////////////////////////////////////////// 00368 CPT(RenderAttrib) RenderAttrib:: 00369 compose_impl(const RenderAttrib *other) const { 00370 return other; 00371 } 00372 00373 //////////////////////////////////////////////////////////////////// 00374 // Function: RenderAttrib::invert_compose_impl 00375 // Access: Protected, Virtual 00376 // Description: Intended to be overridden by derived RenderAttrib 00377 // types to specify how two consecutive RenderAttrib 00378 // objects of the same type interact. 00379 // 00380 // See invert_compose() and compose_impl(). 00381 //////////////////////////////////////////////////////////////////// 00382 CPT(RenderAttrib) RenderAttrib:: 00383 invert_compose_impl(const RenderAttrib *other) const { 00384 return other; 00385 } 00386 00387 //////////////////////////////////////////////////////////////////// 00388 // Function: RenderAttrib::output_comparefunc 00389 // Access: Protected 00390 // Description: Outputs a string representation of the given 00391 // PandaCompareFunc object. 00392 //////////////////////////////////////////////////////////////////// 00393 void RenderAttrib:: 00394 output_comparefunc(ostream &out, PandaCompareFunc fn) const { 00395 switch (fn) { 00396 case M_none: 00397 out << "none"; 00398 break; 00399 00400 case M_never: 00401 out << "never"; 00402 break; 00403 00404 case M_less: 00405 out << "less"; 00406 break; 00407 00408 case M_equal: 00409 out << "equal"; 00410 break; 00411 00412 case M_less_equal: 00413 out << "less_equal"; 00414 break; 00415 00416 case M_greater: 00417 out << "greater"; 00418 break; 00419 00420 case M_not_equal: 00421 out << "not_equal"; 00422 break; 00423 00424 case M_greater_equal: 00425 out << "greater_equal"; 00426 break; 00427 00428 case M_always: 00429 out << "always"; 00430 break; 00431 } 00432 } 00433 00434 //////////////////////////////////////////////////////////////////// 00435 // Function: RenderAttrib::release_new 00436 // Access: Private 00437 // Description: This inverse of return_new, this releases this object 00438 // from the global RenderAttrib table. 00439 // 00440 // You must already be holding _attribs_lock before you 00441 // call this method. 00442 //////////////////////////////////////////////////////////////////// 00443 void RenderAttrib:: 00444 release_new() { 00445 nassertv(_attribs_lock->debug_is_locked()); 00446 00447 if (_saved_entry != _attribs->end()) { 00448 00449 #ifndef NDEBUG 00450 nassertd(_attribs->find(this) == _saved_entry) { 00451 cerr << "Tried to release " << *this << " (" << (void *)this << "), not found!\n"; 00452 validate_attribs(); 00453 Attribs::const_iterator si = _attribs->begin(); 00454 if (si == _attribs->end()) { 00455 cerr << " Attribs list is empty.\n"; 00456 } else { 00457 cerr << " Attribs list contains " << _attribs->size() << " entries.\n"; 00458 const RenderAttrib *attrib = (*si); 00459 cerr << " " << *attrib << " (" << (void *)attrib << ")\n"; 00460 00461 Attribs::const_iterator sprev = si; 00462 ++si; 00463 while (si != _attribs->end()) { 00464 const RenderAttrib *attrib = (*si); 00465 cerr << " " << *attrib << " (" << (void *)attrib << ")\n"; 00466 if (((*sprev)->compare_to(*attrib)) >= 0) { 00467 cerr << "*** above out of order!\n"; 00468 } 00469 sprev = si; 00470 ++si; 00471 } 00472 cerr << " Done.\n"; 00473 } 00474 } 00475 #endif // NDEBUG 00476 00477 _attribs->erase(_saved_entry); 00478 _saved_entry = _attribs->end(); 00479 } 00480 } 00481 00482 //////////////////////////////////////////////////////////////////// 00483 // Function: RenderAttrib::init_attribs 00484 // Access: Public, Static 00485 // Description: Make sure the global _attribs map is allocated. This 00486 // only has to be done once. We could make this map 00487 // static, but then we run into problems if anyone 00488 // creates a RenderAttrib object at static init time; 00489 // it also seems to cause problems when the Panda shared 00490 // library is unloaded at application exit time. 00491 //////////////////////////////////////////////////////////////////// 00492 void RenderAttrib:: 00493 init_attribs() { 00494 _attribs = new Attribs; 00495 00496 // TODO: we should have a global Panda mutex to allow us to safely 00497 // create _attribs_lock without a startup race condition. For the 00498 // meantime, this is OK because we guarantee that this method is 00499 // called at static init time, presumably when there is still only 00500 // one thread in the world. 00501 _attribs_lock = new LightReMutex("RenderAttrib::_attribs_lock"); 00502 nassertv(Thread::get_current_thread() == Thread::get_main_thread()); 00503 } 00504 00505 //////////////////////////////////////////////////////////////////// 00506 // Function: RenderAttrib::write_datagram 00507 // Access: Public, Virtual 00508 // Description: Writes the contents of this object to the datagram 00509 // for shipping out to a Bam file. 00510 //////////////////////////////////////////////////////////////////// 00511 void RenderAttrib:: 00512 write_datagram(BamWriter *manager, Datagram &dg) { 00513 TypedWritable::write_datagram(manager, dg); 00514 } 00515 00516 //////////////////////////////////////////////////////////////////// 00517 // Function: RenderAttrib::change_this 00518 // Access: Public, Static 00519 // Description: Called immediately after complete_pointers(), this 00520 // gives the object a chance to adjust its own pointer 00521 // if desired. Most objects don't change pointers after 00522 // completion, but some need to. 00523 // 00524 // Once this function has been called, the old pointer 00525 // will no longer be accessed. 00526 //////////////////////////////////////////////////////////////////// 00527 TypedWritable *RenderAttrib:: 00528 change_this(TypedWritable *old_ptr, BamReader *manager) { 00529 // First, uniquify the pointer. 00530 RenderAttrib *attrib = DCAST(RenderAttrib, old_ptr); 00531 CPT(RenderAttrib) pointer = return_unique(attrib); 00532 00533 // But now we have a problem, since we have to hold the reference 00534 // count and there's no way to return a TypedWritable while still 00535 // holding the reference count! We work around this by explicitly 00536 // upping the count, and also setting a finalize() callback to down 00537 // it later. 00538 if (pointer == attrib) { 00539 pointer->ref(); 00540 manager->register_finalize(attrib); 00541 } 00542 00543 // We have to cast the pointer back to non-const, because the bam 00544 // reader expects that. 00545 return (RenderAttrib *)pointer.p(); 00546 } 00547 00548 //////////////////////////////////////////////////////////////////// 00549 // Function: RenderAttrib::finalize 00550 // Access: Public, Virtual 00551 // Description: Called by the BamReader to perform any final actions 00552 // needed for setting up the object after all objects 00553 // have been read and all pointers have been completed. 00554 //////////////////////////////////////////////////////////////////// 00555 void RenderAttrib:: 00556 finalize(BamReader *) { 00557 // Unref the pointer that we explicitly reffed in change_this(). 00558 unref(); 00559 00560 // We should never get back to zero after unreffing our own count, 00561 // because we expect to have been stored in a pointer somewhere. If 00562 // we do get to zero, it's a memory leak; the way to avoid this is 00563 // to call unref_delete() above instead of unref(), but this is 00564 // dangerous to do from within a virtual function. 00565 nassertv(get_ref_count() != 0); 00566 } 00567 00568 //////////////////////////////////////////////////////////////////// 00569 // Function: RenderAttrib::fillin 00570 // Access: Protected 00571 // Description: This internal function is called by make_from_bam to 00572 // read in all of the relevant data from the BamFile for 00573 // the new RenderAttrib. 00574 //////////////////////////////////////////////////////////////////// 00575 void RenderAttrib:: 00576 fillin(DatagramIterator &scan, BamReader *manager) { 00577 TypedWritable::fillin(scan, manager); 00578 manager->register_change_this(change_this, this); 00579 }