Panda3D

geomMunger.cxx

00001 // Filename: geomMunger.cxx
00002 // Created by:  drose (10Mar05)
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 "geomMunger.h"
00016 #include "geom.h"
00017 #include "geomCacheManager.h"
00018 #include "lightMutexHolder.h"
00019 #include "lightReMutexHolder.h"
00020 #include "pStatTimer.h"
00021 
00022 GeomMunger::Registry *GeomMunger::_registry = NULL;
00023 TypeHandle GeomMunger::_type_handle;
00024 
00025 PStatCollector GeomMunger::_munge_pcollector("*:Munge");
00026 
00027 ////////////////////////////////////////////////////////////////////
00028 //     Function: GeomMunger::Constructor
00029 //       Access: Public
00030 //  Description: 
00031 ////////////////////////////////////////////////////////////////////
00032 GeomMunger::
00033 GeomMunger(GraphicsStateGuardianBase *gsg) :
00034   _gsg(gsg),
00035   _is_registered(false)
00036 {
00037 #ifndef NDEBUG
00038   Registry *registry = get_registry();
00039   LightReMutexHolder holder(registry->_registry_lock);
00040   _registered_key = registry->_mungers.end();
00041 #endif
00042 }
00043 
00044 ////////////////////////////////////////////////////////////////////
00045 //     Function: GeomMunger::Copy Constructor
00046 //       Access: Public
00047 //  Description: 
00048 ////////////////////////////////////////////////////////////////////
00049 GeomMunger::
00050 GeomMunger(const GeomMunger &copy) :
00051   _is_registered(false)
00052 {
00053 #ifndef NDEBUG
00054   Registry *registry = get_registry();
00055   LightReMutexHolder holder(registry->_registry_lock);
00056   _registered_key = registry->_mungers.end();
00057 #endif
00058 }
00059 
00060 ////////////////////////////////////////////////////////////////////
00061 //     Function: GeomMunger::Copy Assignment Operator
00062 //       Access: Public
00063 //  Description: 
00064 ////////////////////////////////////////////////////////////////////
00065 void GeomMunger::
00066 operator = (const GeomMunger &copy) {
00067   nassertv(!_is_registered);
00068 }
00069 
00070 ////////////////////////////////////////////////////////////////////
00071 //     Function: GeomMunger::Destructor
00072 //       Access: Public, Virtual
00073 //  Description: 
00074 ////////////////////////////////////////////////////////////////////
00075 GeomMunger::
00076 ~GeomMunger() {
00077   unregister_myself();
00078   nassertv(_formats_by_animation.empty());
00079 }
00080 
00081 ////////////////////////////////////////////////////////////////////
00082 //     Function: GeomMunger::remove_data
00083 //       Access: Public
00084 //  Description: Removes a prepared GeomVertexData from the cache.
00085 ////////////////////////////////////////////////////////////////////
00086 void GeomMunger::
00087 remove_data(const GeomVertexData *data) {
00088   // If this assertion is triggered, maybe we accidentally deleted a
00089   // GeomVertexData while we were in the process of unregistering,
00090   // causing a recursive re-entry.
00091   nassertv(_is_registered);
00092 }
00093 
00094 ////////////////////////////////////////////////////////////////////
00095 //     Function: GeomMunger::munge_geom
00096 //       Access: Public
00097 //  Description: Applies the indicated munger to the geom and its
00098 //               data, and returns a (possibly different) geom and
00099 //               data, according to the munger's whim.  
00100 //
00101 //               The assumption is that for a particular geom and a
00102 //               particular munger, the result will always be the
00103 //               same; so this result may be cached.
00104 //
00105 //               If force is false, this may do nothing and return
00106 //               false if the vertex data is nonresident.  If force is
00107 //               true, this will always return true, but it may have
00108 //               to block while the vertex data is paged in.
00109 ////////////////////////////////////////////////////////////////////
00110 bool GeomMunger::
00111 munge_geom(CPT(Geom) &geom, CPT(GeomVertexData) &data,
00112            bool force, Thread *current_thread) {
00113   CPT(GeomVertexData) source_data = data;
00114 
00115   // Look up the munger in the geom's cache--maybe we've recently
00116   // applied it.
00117   PT(Geom::CacheEntry) entry;
00118 
00119   Geom::CacheKey key(source_data, this);
00120 
00121   geom->_cache_lock.acquire();
00122   Geom::Cache::const_iterator ci = geom->_cache.find(&key);
00123   if (ci == geom->_cache.end()) {
00124     geom->_cache_lock.release();
00125   } else {
00126     entry = (*ci).second;
00127     geom->_cache_lock.release();
00128     nassertr(entry->_source == geom, false);
00129     
00130     // Here's an element in the cache for this computation.  Record a
00131     // cache hit, so this element will stay in the cache a while
00132     // longer.
00133     entry->refresh(current_thread);
00134     
00135     // Now check that it's fresh.
00136     Geom::CDCacheReader cdata(entry->_cycler, current_thread);
00137     if (cdata->_source == geom &&
00138         cdata->_geom_result != (Geom *)NULL &&
00139         geom->get_modified(current_thread) <= cdata->_geom_result->get_modified(current_thread) &&
00140         data->get_modified(current_thread) <= cdata->_data_result->get_modified(current_thread)) {
00141       // The cache entry is still good; use it.
00142       
00143       geom = cdata->_geom_result;
00144       data = cdata->_data_result;
00145       return true;
00146     }
00147     
00148     // The cache entry is stale, but we'll recompute it below.  Note
00149     // that there's a small race condition here; another thread might
00150     // recompute the cache at the same time.  No big deal, since it'll
00151     // compute the same result.
00152   }
00153 
00154   if (!force && (!geom->request_resident() || !data->request_resident())) {
00155     // Oh dear, the data isn't resident.  We can't munge it, so give up.
00156     return false;
00157   }
00158 
00159   // Ok, invoke the munger.
00160   PStatTimer timer(_munge_pcollector, current_thread);
00161 
00162   PT(Geom) orig_geom = (Geom *)geom.p();
00163   data = munge_data(data);
00164   munge_geom_impl(geom, data, current_thread);
00165 
00166   // Record the new result in the cache.
00167   if (entry == (Geom::CacheEntry *)NULL) {
00168     // Create a new entry for the result.
00169     entry = new Geom::CacheEntry(orig_geom, source_data, this);
00170     {
00171       LightMutexHolder holder(orig_geom->_cache_lock);
00172       bool inserted = orig_geom->_cache.insert(Geom::Cache::value_type(&entry->_key, entry)).second;
00173       if (!inserted) {
00174         // Some other thread must have beat us to the punch.  Never
00175         // mind.
00176         return true;
00177       }
00178     }
00179   
00180     // And tell the cache manager about the new entry.  (It might
00181     // immediately request a delete from the cache of the thing we
00182     // just added.)
00183     entry->record(current_thread);
00184   }
00185 
00186   // Finally, store the cached result on the entry.
00187   Geom::CDCacheWriter cdata(entry->_cycler, true, current_thread);
00188   cdata->_source = (Geom *)orig_geom.p();
00189   cdata->set_result(geom, data);
00190 
00191   return true;
00192 }
00193 
00194 ////////////////////////////////////////////////////////////////////
00195 //     Function: GeomMunger::do_munge_format
00196 //       Access: Protected
00197 //  Description: The protected implementation of munge_format().  This
00198 //               exists just to cast away the const pointer.
00199 ////////////////////////////////////////////////////////////////////
00200 CPT(GeomVertexFormat) GeomMunger::
00201 do_munge_format(const GeomVertexFormat *format, 
00202                 const GeomVertexAnimationSpec &animation) {
00203   nassertr(_is_registered, NULL);
00204   nassertr(format->is_registered(), NULL);
00205 
00206   LightMutexHolder holder(_formats_lock);
00207 
00208   Formats &formats = _formats_by_animation[animation];
00209 
00210   Formats::iterator fi;
00211   fi = formats.find(format);
00212   if (fi != formats.end()) {
00213     // This format was previously munged, so the answer will be the
00214     // same.
00215     return (*fi).second;
00216   }
00217 
00218   // We have to munge this format for the first time.
00219   CPT(GeomVertexFormat) derived_format = munge_format_impl(format, animation);
00220   nassertr(derived_format->is_registered(), NULL);
00221 
00222   // Store the answer in the map, so we can quickly get it next time.
00223   bool inserted = formats.insert(Formats::value_type(format, derived_format)).second;
00224   nassertr(inserted, NULL);
00225 
00226   return derived_format;
00227 }
00228 
00229 ////////////////////////////////////////////////////////////////////
00230 //     Function: GeomMunger::munge_format_impl
00231 //       Access: Protected, Virtual
00232 //  Description: Given a source GeomVertexFormat, converts it if
00233 //               necessary to the appropriate format for rendering.
00234 ////////////////////////////////////////////////////////////////////
00235 CPT(GeomVertexFormat) GeomMunger::
00236 munge_format_impl(const GeomVertexFormat *orig, const GeomVertexAnimationSpec &) {
00237   return orig;
00238 }
00239 
00240 ////////////////////////////////////////////////////////////////////
00241 //     Function: GeomMunger::munge_data_impl
00242 //       Access: Protected, Virtual
00243 //  Description: Given a source GeomVertexData, converts it as
00244 //               necessary for rendering.
00245 ////////////////////////////////////////////////////////////////////
00246 CPT(GeomVertexData) GeomMunger::
00247 munge_data_impl(const GeomVertexData *data) {
00248   nassertr(_is_registered, NULL);
00249 
00250   CPT(GeomVertexFormat) orig_format = data->get_format();
00251   CPT(GeomVertexFormat) new_format = 
00252     munge_format(orig_format, orig_format->get_animation());
00253 
00254   if (new_format == orig_format) {
00255     // Trivial case.
00256     return data;
00257   }
00258 
00259   return data->convert_to(new_format);
00260 }
00261 
00262 ////////////////////////////////////////////////////////////////////
00263 //     Function: GeomMunger::munge_geom_impl
00264 //       Access: Protected, Virtual
00265 //  Description: Converts a Geom and/or its data as necessary.
00266 ////////////////////////////////////////////////////////////////////
00267 void GeomMunger::
00268 munge_geom_impl(CPT(Geom) &, CPT(GeomVertexData) &, Thread *) {
00269   // The default implementation does nothing (the work has already
00270   // been done in munge_format_impl() and munge_data_impl()).
00271 }
00272 
00273 ////////////////////////////////////////////////////////////////////
00274 //     Function: GeomMunger::do_premunge_format
00275 //       Access: Protected
00276 //  Description: The protected implementation of premunge_format().  This
00277 //               exists just to cast away the const pointer.
00278 ////////////////////////////////////////////////////////////////////
00279 CPT(GeomVertexFormat) GeomMunger::
00280 do_premunge_format(const GeomVertexFormat *format) {
00281   nassertr(_is_registered, NULL);
00282   nassertr(format->is_registered(), NULL);
00283 
00284   LightMutexHolder holder(_formats_lock);
00285 
00286   Formats::iterator fi;
00287   fi = _premunge_formats.find(format);
00288   if (fi != _premunge_formats.end()) {
00289     // This format was previously munged, so the answer will be the
00290     // same.
00291     return (*fi).second;
00292   }
00293 
00294   // We have to munge this format for the first time.
00295   CPT(GeomVertexFormat) derived_format = premunge_format_impl(format);
00296   nassertr(derived_format->is_registered(), NULL);
00297 
00298   // Store the answer in the map, so we can quickly get it next time.
00299   bool inserted = _premunge_formats.insert(Formats::value_type(format, derived_format)).second;
00300   nassertr(inserted, NULL);
00301 
00302   return derived_format;
00303 }
00304 
00305 ////////////////////////////////////////////////////////////////////
00306 //     Function: GeomMunger::premunge_format_impl
00307 //       Access: Protected, Virtual
00308 //  Description: Given a source GeomVertexFormat, converts it if
00309 //               necessary to the appropriate format for rendering.
00310 ////////////////////////////////////////////////////////////////////
00311 CPT(GeomVertexFormat) GeomMunger::
00312 premunge_format_impl(const GeomVertexFormat *orig) {
00313   return orig;
00314 }
00315 
00316 ////////////////////////////////////////////////////////////////////
00317 //     Function: GeomMunger::premunge_data_impl
00318 //       Access: Protected, Virtual
00319 //  Description: Given a source GeomVertexData, converts it as
00320 //               necessary for rendering.
00321 ////////////////////////////////////////////////////////////////////
00322 CPT(GeomVertexData) GeomMunger::
00323 premunge_data_impl(const GeomVertexData *data) {
00324   nassertr(_is_registered, NULL);
00325 
00326   CPT(GeomVertexFormat) orig_format = data->get_format();
00327   CPT(GeomVertexFormat) new_format = premunge_format(orig_format);
00328 
00329   if (new_format == orig_format) {
00330     // Trivial case.
00331     return data;
00332   }
00333 
00334   return data->convert_to(new_format);
00335 }
00336 
00337 ////////////////////////////////////////////////////////////////////
00338 //     Function: GeomMunger::premunge_geom_impl
00339 //       Access: Protected, Virtual
00340 //  Description: Converts a Geom and/or its data as necessary.
00341 ////////////////////////////////////////////////////////////////////
00342 void GeomMunger::
00343 premunge_geom_impl(CPT(Geom) &, CPT(GeomVertexData) &) {
00344   // The default implementation does nothing (the work has already
00345   // been done in premunge_format_impl() and premunge_data_impl()).
00346 }
00347 
00348 ////////////////////////////////////////////////////////////////////
00349 //     Function: GeomMunger::compare_to_impl
00350 //       Access: Protected, Virtual
00351 //  Description: Called to compare two GeomMungers who are known to be
00352 //               of the same type, for an apples-to-apples comparison.
00353 //               This will never be called on two pointers of a
00354 //               different type.
00355 ////////////////////////////////////////////////////////////////////
00356 int GeomMunger::
00357 compare_to_impl(const GeomMunger *other) const {
00358   return 0;
00359 }
00360 
00361 ////////////////////////////////////////////////////////////////////
00362 //     Function: GeomMunger::geom_compare_to_impl
00363 //       Access: Protected, Virtual
00364 //  Description: Compares two GeomMungers, considering only whether
00365 //               they would produce a different answer to
00366 //               munge_format(), munge_data(), or munge_geom().  (They
00367 //               still might be different in other ways, but if they
00368 //               would produce the same answer, this function will
00369 //               consider them to be the same.)
00370 ////////////////////////////////////////////////////////////////////
00371 int GeomMunger::
00372 geom_compare_to_impl(const GeomMunger *other) const {
00373   return 0;
00374 }
00375 
00376 ////////////////////////////////////////////////////////////////////
00377 //     Function: GeomMunger::make_registry
00378 //       Access: Private
00379 //  Description: Returns the global registry object.
00380 ////////////////////////////////////////////////////////////////////
00381 void GeomMunger::
00382 make_registry() {
00383   if (_registry == (Registry *)NULL) {
00384     _registry = new Registry;
00385   }
00386 }
00387  
00388 ////////////////////////////////////////////////////////////////////
00389 //     Function: GeomMunger::do_register
00390 //       Access: Private
00391 //  Description: Called internally when the munger is registered.
00392 ////////////////////////////////////////////////////////////////////
00393 void GeomMunger::
00394 do_register(Thread *current_thread) {
00395   if (gobj_cat.is_debug()) {
00396     gobj_cat.debug()
00397       << "GeomMunger::do_register(): " << (void *)this << "\n";
00398   }
00399   nassertv(!_is_registered);
00400   nassertv(_formats_by_animation.empty());
00401 
00402   // Tell the cache manager to hang on to this new GeomMunger, so we
00403   // don't waste our time re-registering the same GeomMunger over and
00404   // over again.
00405   CacheEntry *entry = new CacheEntry;
00406   entry->_munger = this;
00407   entry->record(current_thread);
00408 
00409   _is_registered = true;
00410 }
00411  
00412 ////////////////////////////////////////////////////////////////////
00413 //     Function: GeomMunger::do_unregister
00414 //       Access: Private
00415 //  Description: Called internally when the munger is unregistered.
00416 ////////////////////////////////////////////////////////////////////
00417 void GeomMunger::
00418 do_unregister() {
00419   if (gobj_cat.is_debug()) {
00420     gobj_cat.debug()
00421       << "GeomMunger::do_unregister(): " << (void *)this << "\n";
00422   }
00423   nassertv(_is_registered);
00424   _is_registered = false;
00425 
00426   // Unregistering means we should blow away the cache.
00427   _formats_by_animation.clear();
00428 }
00429 
00430 ////////////////////////////////////////////////////////////////////
00431 //     Function: GeomMunger::CacheEntry::output
00432 //       Access: Public, Virtual
00433 //  Description: 
00434 ////////////////////////////////////////////////////////////////////
00435 void GeomMunger::CacheEntry::
00436 output(ostream &out) const {
00437   out << "munger " << _munger;
00438 }
00439 
00440 ////////////////////////////////////////////////////////////////////
00441 //     Function: GeomMunger::Registry::Constructor
00442 //       Access: Public
00443 //  Description: 
00444 ////////////////////////////////////////////////////////////////////
00445 GeomMunger::Registry::
00446 Registry() {
00447 }
00448 
00449 ////////////////////////////////////////////////////////////////////
00450 //     Function: GeomMunger::Registry::register_munger
00451 //       Access: Public
00452 //  Description: Adds the indicated munger to the registry, if there
00453 //               is not an equivalent munger already there; in either
00454 //               case, returns the pointer to the equivalent munger
00455 //               now in the registry.
00456 //
00457 //               This must be called before a munger may be used in a
00458 //               Geom.  After this call, you should discard the
00459 //               original pointer you passed in (which may or may not
00460 //               now be invalid) and let its reference count decrement
00461 //               normally; you should use only the returned value from
00462 //               this point on.
00463 ////////////////////////////////////////////////////////////////////
00464 PT(GeomMunger) GeomMunger::Registry::
00465 register_munger(GeomMunger *munger, Thread *current_thread) {
00466   if (munger->is_registered()) {
00467     return munger;
00468   }
00469 
00470   // Save the incoming pointer in a local PointerTo, so that if it has
00471   // a zero reference count and is not added into the map below, it
00472   // will be automatically deleted when this function returns.
00473   PT(GeomMunger) pt_munger = munger;
00474 
00475   LightReMutexHolder holder(_registry_lock);
00476 
00477   Mungers::iterator mi = _mungers.insert(munger).first;
00478   GeomMunger *new_munger = (*mi);
00479   if (!new_munger->is_registered()) {
00480     new_munger->_registered_key = mi;
00481     new_munger->do_register(current_thread);
00482   }
00483 
00484   return new_munger;
00485 }
00486 
00487 ////////////////////////////////////////////////////////////////////
00488 //     Function: GeomMunger::Registry::unregister_munger
00489 //       Access: Public
00490 //  Description: Removes the indicated munger from the registry.
00491 //               Normally this should not be done until the munger is
00492 //               destructing.
00493 ////////////////////////////////////////////////////////////////////
00494 void GeomMunger::Registry::
00495 unregister_munger(GeomMunger *munger) {
00496   LightReMutexHolder holder(_registry_lock);
00497 
00498   nassertv(munger->is_registered());
00499   nassertv(munger->_registered_key != _mungers.end());
00500   _mungers.erase(munger->_registered_key);
00501   munger->_registered_key = _mungers.end();
00502   munger->do_unregister();
00503 }
00504 
00505 ////////////////////////////////////////////////////////////////////
00506 //     Function: GeomMunger::Registry::unregister_mungers_for_gsg
00507 //       Access: Public
00508 //  Description: Removes all the mungers from the registry that are
00509 //               associated with the indicated GSG.
00510 ////////////////////////////////////////////////////////////////////
00511 void GeomMunger::Registry::
00512 unregister_mungers_for_gsg(GraphicsStateGuardianBase *gsg) {
00513   LightReMutexHolder holder(_registry_lock);
00514 
00515   Mungers::iterator mi = _mungers.begin();
00516   while (mi != _mungers.end()) {
00517     GeomMunger *munger = (*mi);
00518     Mungers::iterator mnext = mi;
00519     ++mnext;
00520 
00521     if (munger->get_gsg() == gsg) {
00522       nassertv(mi == munger->_registered_key);
00523       _mungers.erase(mi);
00524       munger->_registered_key = _mungers.end();
00525       munger->do_unregister();
00526     }
00527 
00528     mi = mnext;
00529   }
00530 }
 All Classes Functions Variables Enumerations