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