diff --git a/panda/src/gobj/materialPool.I b/panda/src/gobj/materialPool.I new file mode 100644 index 0000000000..18299ba63e --- /dev/null +++ b/panda/src/gobj/materialPool.I @@ -0,0 +1,68 @@ +// Filename: materialPool.I +// Created by: drose (30Apr01) +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: MaterialPool::get_material +// Access: Public, Static +// Description: Returns a const Material pointer that represents the +// same material described by temp, except that it is a +// shared pointer. +// +// Each call to get_material() passing an equivalent +// Material pointer will return the same shared pointer. +// +// This shared pointer must not be further modified. +// Doing so will (a) cause global changes to other +// objects that may share this material, and (b) damage +// the sorted container that stores these things, so +// that future pointers may not be properly shared. +// +// Also, the return value may be a different pointer +// than that passed in, or it may be the same pointer. +// In either case, the passed in pointer has now been +// sacrificed to the greater good and should not be used +// again (like any other PointerTo, it will be freed +// when the last reference count is removed). +//////////////////////////////////////////////////////////////////// +INLINE const Material *MaterialPool:: +get_material(const CPT(Material) &temp) { + return get_ptr()->ns_get_material(temp); +} + +//////////////////////////////////////////////////////////////////// +// Function: MaterialPool::garbage_collect +// Access: Public, Static +// Description: Releases only those materials in the pool that have a +// reference count of exactly 1; i.e. only those +// materials that are not being used outside of the pool. +// Returns the number of materials released. +//////////////////////////////////////////////////////////////////// +INLINE int MaterialPool:: +garbage_collect() { + return get_ptr()->ns_garbage_collect(); +} + +//////////////////////////////////////////////////////////////////// +// Function: MaterialPool::list_contents +// Access: Public, Static +// Description: Lists the contents of the material pool to the +// indicated output stream. +//////////////////////////////////////////////////////////////////// +INLINE void MaterialPool:: +list_contents(ostream &out) { + get_ptr()->ns_list_contents(out); +} + +//////////////////////////////////////////////////////////////////// +// Function: MaterialPool::Constructor +// Access: Private +// Description: The constructor is not intended to be called +// directly; there's only supposed to be one MaterialPool +// in the universe and it constructs itself. +//////////////////////////////////////////////////////////////////// +INLINE MaterialPool:: +MaterialPool() { +} diff --git a/panda/src/gobj/materialPool.cxx b/panda/src/gobj/materialPool.cxx new file mode 100644 index 0000000000..38b55646cd --- /dev/null +++ b/panda/src/gobj/materialPool.cxx @@ -0,0 +1,80 @@ +// Filename: materialPool.cxx +// Created by: drose (30Apr01) +// +//////////////////////////////////////////////////////////////////// + +#include "materialPool.h" +#include "config_gobj.h" + + +MaterialPool *MaterialPool::_global_ptr = (MaterialPool *)NULL; + + +//////////////////////////////////////////////////////////////////// +// Function: MaterialPool::ns_get_material +// Access: Public +// Description: The nonstatic implementation of get_material(). +//////////////////////////////////////////////////////////////////// +const Material *MaterialPool:: +ns_get_material(const CPT(Material) &temp) { + Materials::iterator mi = _materials.insert(temp).first; + return (*mi); +} + +//////////////////////////////////////////////////////////////////// +// Function: MaterialPool::ns_garbage_collect +// Access: Private +// Description: The nonstatic implementation of garbage_collect(). +//////////////////////////////////////////////////////////////////// +int MaterialPool:: +ns_garbage_collect() { + int num_released = 0; + Materials new_set; + + Materials::iterator mi; + for (mi = _materials.begin(); mi != _materials.end(); ++mi) { + const Material *mat = (*mi); + if (mat->get_ref_count() == 1) { + if (gobj_cat.is_debug()) { + gobj_cat.debug() + << "Releasing " << *mat << "\n"; + } + num_released++; + } else { + new_set.insert(new_set.end(), *mi); + } + } + + _materials.swap(new_set); + return num_released; +} + +//////////////////////////////////////////////////////////////////// +// Function: MaterialPool::ns_list_contents +// Access: Private +// Description: The nonstatic implementation of list_contents(). +//////////////////////////////////////////////////////////////////// +void MaterialPool:: +ns_list_contents(ostream &out) { + out << _materials.size() << " materials:\n"; + Materials::iterator mi; + for (mi = _materials.begin(); mi != _materials.end(); ++mi) { + const Material *mat = (*mi); + out << " " << *mat + << " (count = " << mat->get_ref_count() << ")\n"; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: MaterialPool::get_ptr +// Access: Private, Static +// Description: Initializes and/or returns the global pointer to the +// one MaterialPool object in the system. +//////////////////////////////////////////////////////////////////// +MaterialPool *MaterialPool:: +get_ptr() { + if (_global_ptr == (MaterialPool *)NULL) { + _global_ptr = new MaterialPool; + } + return _global_ptr; +} diff --git a/panda/src/gobj/materialPool.h b/panda/src/gobj/materialPool.h new file mode 100644 index 0000000000..ec9da0097d --- /dev/null +++ b/panda/src/gobj/materialPool.h @@ -0,0 +1,61 @@ +// Filename: materialPool.h +// Created by: drose (30Apr01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef MATERIALPOOL_H +#define MATERIALPOOL_H + +#include + +#include "material.h" + +#include +#include + +#include + +//////////////////////////////////////////////////////////////////// +// Class : MaterialPool +// Description : The MaterialPool (there is only one in the universe) +// serves to unify different pointers to the same +// Material, so we do not (a) waste memory with many +// different Material objects that are all equivalent, +// and (b) waste time switching the graphics engine +// between different Material states that are really the +// same thing. +// +// The idea is to create a temporary Material +// representing the lighting state you want to apply, +// then call get_material(), passing in your temporary +// Material. The return value will be a constant +// Material object that should be modified (because it +// is now shared among many different geometries), that +// is the same as the temporary Material pointer you +// supplied but may be a different pointer. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA MaterialPool { +PUBLISHED: + INLINE static const Material *get_material(const CPT(Material) &temp); + INLINE static int garbage_collect(); + INLINE static void list_contents(ostream &out); + +private: + INLINE MaterialPool(); + + const Material *ns_get_material(const CPT(Material) &temp); + int ns_garbage_collect(); + void ns_list_contents(ostream &out); + + static MaterialPool *get_ptr(); + + static MaterialPool *_global_ptr; + typedef set< CPT(Material), IndirectCompareTo > Materials; + Materials _materials; +}; + +#include "materialPool.I" + +#endif + +