diff --git a/panda/src/dxgsg8/dxGeomMunger8.I b/panda/src/dxgsg8/dxGeomMunger8.I index 431a6ae2c6..4b048c755d 100644 --- a/panda/src/dxgsg8/dxGeomMunger8.I +++ b/panda/src/dxgsg8/dxGeomMunger8.I @@ -28,7 +28,17 @@ DXGeomMunger8(GraphicsStateGuardian *gsg, const RenderState *state) : _texture(state->get_texture()), _tex_gen(state->get_tex_gen()) { + _filtered_texture = (TextureAttrib *)NULL; + _reffed_filtered_texture = false; if (_texture != (TextureAttrib *)NULL) { - _texture = _texture->filter_to_max(gsg->get_max_texture_stages()); + _filtered_texture = _texture->filter_to_max(gsg->get_max_texture_stages()); + if (_filtered_texture != _texture) { + _filtered_texture->ref(); + _reffed_filtered_texture = true; + } } + // Set a callback to unregister ourselves when either the Texture or + // the TexGen object gets deleted. + _texture.set_callback(this); + _tex_gen.set_callback(this); } diff --git a/panda/src/dxgsg8/dxGeomMunger8.cxx b/panda/src/dxgsg8/dxGeomMunger8.cxx index 35f16eeb7c..66a7d5335c 100644 --- a/panda/src/dxgsg8/dxGeomMunger8.cxx +++ b/panda/src/dxgsg8/dxGeomMunger8.cxx @@ -24,6 +24,37 @@ GeomMunger *DXGeomMunger8::_deleted_chain = NULL; TypeHandle DXGeomMunger8::_type_handle; +//////////////////////////////////////////////////////////////////// +// Function: DXGeomMunger8::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +DXGeomMunger8:: +~DXGeomMunger8() { + if (_reffed_filtered_texture) { + unref_delete(_filtered_texture); + _reffed_filtered_texture = false; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: DXGeomMunger8::wp_callback +// Access: Public, Virtual +// Description: This callback is set to be made whenever the +// associated _texture or _tex_gen attributes are +// destructed, in which case the GeomMunger is invalid +// and should no longer be used. +//////////////////////////////////////////////////////////////////// +void DXGeomMunger8:: +wp_callback(void *) { + unregister_myself(); + + if (_reffed_filtered_texture) { + unref_delete(_filtered_texture); + _reffed_filtered_texture = false; + } +} + //////////////////////////////////////////////////////////////////// // Function: DXGeomMunger8::munge_format_impl // Access: Protected, Virtual @@ -110,13 +141,13 @@ munge_format_impl(const GeomVertexFormat *orig, // Now copy all of the texture coordinates in, in order by stage // index. But we have to reuse previous columns. - if (_texture != (TextureAttrib *)NULL) { + if (_filtered_texture != (TextureAttrib *)NULL) { typedef pset UsedStages; UsedStages used_stages; - int num_stages = _texture->get_num_on_stages(); + int num_stages = _filtered_texture->get_num_on_stages(); for (int i = 0; i < num_stages; ++i) { - TextureStage *stage = _texture->get_on_stage(i); + TextureStage *stage = _filtered_texture->get_on_stage(i); InternalName *name = stage->get_texcoord_name(); if (used_stages.insert(name).second) { @@ -154,8 +185,8 @@ munge_format_impl(const GeomVertexFormat *orig, int DXGeomMunger8:: compare_to_impl(const GeomMunger *other) const { const DXGeomMunger8 *om = DCAST(DXGeomMunger8, other); - if (_texture != om->_texture) { - return _texture < om->_texture ? -1 : 1; + if (_filtered_texture != om->_filtered_texture) { + return _filtered_texture < om->_filtered_texture ? -1 : 1; } if (_tex_gen != om->_tex_gen) { return _tex_gen < om->_tex_gen ? -1 : 1; @@ -174,12 +205,13 @@ compare_to_impl(const GeomMunger *other) const { //////////////////////////////////////////////////////////////////// int DXGeomMunger8:: geom_compare_to_impl(const GeomMunger *other) const { - // Unlike GLGeomMunger, we do consider _texture and _tex_gen - // important for this purpose, since they control the number and - // order of texture coordinates we might put into the FVF. + // Unlike GLGeomMunger, we do consider _filtered_texture and + // _tex_gen important for this purpose, since they control the + // number and order of texture coordinates we might put into the + // FVF. const DXGeomMunger8 *om = DCAST(DXGeomMunger8, other); - if (_texture != om->_texture) { - return _texture < om->_texture ? -1 : 1; + if (_filtered_texture != om->_filtered_texture) { + return _filtered_texture < om->_filtered_texture ? -1 : 1; } if (_tex_gen != om->_tex_gen) { return _tex_gen < om->_tex_gen ? -1 : 1; diff --git a/panda/src/dxgsg8/dxGeomMunger8.h b/panda/src/dxgsg8/dxGeomMunger8.h index 17479391f0..f1d90df349 100644 --- a/panda/src/dxgsg8/dxGeomMunger8.h +++ b/panda/src/dxgsg8/dxGeomMunger8.h @@ -22,6 +22,8 @@ #include "pandabase.h" #include "standardMunger.h" #include "graphicsStateGuardian.h" +#include "weakPointerTo.h" +#include "weakPointerCallback.h" //////////////////////////////////////////////////////////////////// // Class : DXGeomMunger8 @@ -31,11 +33,14 @@ // and that all relevant components are packed into a // single array, in the correct order. //////////////////////////////////////////////////////////////////// -class EXPCL_PANDADX DXGeomMunger8 : public StandardMunger { +class EXPCL_PANDADX DXGeomMunger8 : public StandardMunger, public WeakPointerCallback { public: INLINE DXGeomMunger8(GraphicsStateGuardian *gsg, const RenderState *state); + virtual ~DXGeomMunger8(); ALLOC_DELETED_CHAIN(DXGeomMunger8); + virtual void wp_callback(void *); + protected: virtual CPT(GeomVertexFormat) munge_format_impl(const GeomVertexFormat *orig, const GeomVertexAnimationSpec &animation); @@ -44,8 +49,16 @@ protected: virtual int geom_compare_to_impl(const GeomMunger *other) const; private: - CPT(TextureAttrib) _texture; - CPT(TexGenAttrib) _tex_gen; + WCPT(TextureAttrib) _texture; + WCPT(TexGenAttrib) _tex_gen; + + // This pointer is derived from _texture, above. In the case that + // it is a different pointer, we maintain its reference count + // explicitly. If it is the same pointer, we don't reference count + // it at all (so we won't hold on to the reference count + // unnecessarily). + const TextureAttrib *_filtered_texture; + bool _reffed_filtered_texture; static GeomMunger *_deleted_chain; diff --git a/panda/src/dxgsg9/dxGeomMunger9.I b/panda/src/dxgsg9/dxGeomMunger9.I index 94b63c528f..41de236f9c 100755 --- a/panda/src/dxgsg9/dxGeomMunger9.I +++ b/panda/src/dxgsg9/dxGeomMunger9.I @@ -28,8 +28,18 @@ DXGeomMunger9(GraphicsStateGuardian *gsg, const RenderState *state) : _texture(state->get_texture()), _tex_gen(state->get_tex_gen()) { + _filtered_texture = (TextureAttrib *)NULL; + _reffed_filtered_texture = false; if (_texture != (TextureAttrib *)NULL) { - _texture = _texture->filter_to_max(gsg->get_max_texture_stages()); + _filtered_texture = _texture->filter_to_max(gsg->get_max_texture_stages()); + if (_filtered_texture != _texture) { + _filtered_texture->ref(); + _reffed_filtered_texture = true; + } } + // Set a callback to unregister ourselves when either the Texture or + // the TexGen object gets deleted. + _texture.set_callback(this); + _tex_gen.set_callback(this); } diff --git a/panda/src/dxgsg9/dxGeomMunger9.cxx b/panda/src/dxgsg9/dxGeomMunger9.cxx index a2af7350a4..671e593244 100755 --- a/panda/src/dxgsg9/dxGeomMunger9.cxx +++ b/panda/src/dxgsg9/dxGeomMunger9.cxx @@ -24,6 +24,37 @@ GeomMunger *DXGeomMunger9::_deleted_chain = NULL; TypeHandle DXGeomMunger9::_type_handle; +//////////////////////////////////////////////////////////////////// +// Function: DXGeomMunger9::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +DXGeomMunger9:: +~DXGeomMunger9() { + if (_reffed_filtered_texture) { + unref_delete(_filtered_texture); + _reffed_filtered_texture = false; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: DXGeomMunger9::wp_callback +// Access: Public, Virtual +// Description: This callback is set to be made whenever the +// associated _texture or _tex_gen attributes are +// destructed, in which case the GeomMunger is invalid +// and should no longer be used. +//////////////////////////////////////////////////////////////////// +void DXGeomMunger9:: +wp_callback(void *) { + unregister_myself(); + + if (_reffed_filtered_texture) { + unref_delete(_filtered_texture); + _reffed_filtered_texture = false; + } +} + //////////////////////////////////////////////////////////////////// // Function: DXGeomMunger9::munge_format_impl // Access: Protected, Virtual @@ -37,7 +68,7 @@ munge_format_impl(const GeomVertexFormat *orig, if (animation.get_animation_type() != AT_none) { dxgsg9_cat.debug() << "preparing animation type " << animation << " for " << *orig - << "\n"; + << "\n"; } } // We have to build a completely new format that includes only the @@ -110,13 +141,13 @@ munge_format_impl(const GeomVertexFormat *orig, // Now copy all of the texture coordinates in, in order by stage // index. But we have to reuse previous columns. - if (_texture != (TextureAttrib *)NULL) { + if (_filtered_texture != (TextureAttrib *)NULL) { typedef pset UsedStages; UsedStages used_stages; - int num_stages = _texture->get_num_on_stages(); + int num_stages = _filtered_texture->get_num_on_stages(); for (int i = 0; i < num_stages; ++i) { - TextureStage *stage = _texture->get_on_stage(i); + TextureStage *stage = _filtered_texture->get_on_stage(i); InternalName *name = stage->get_texcoord_name(); if (used_stages.insert(name).second) { @@ -154,8 +185,8 @@ munge_format_impl(const GeomVertexFormat *orig, int DXGeomMunger9:: compare_to_impl(const GeomMunger *other) const { const DXGeomMunger9 *om = DCAST(DXGeomMunger9, other); - if (_texture != om->_texture) { - return _texture < om->_texture ? -1 : 1; + if (_filtered_texture != om->_filtered_texture) { + return _filtered_texture < om->_filtered_texture ? -1 : 1; } if (_tex_gen != om->_tex_gen) { return _tex_gen < om->_tex_gen ? -1 : 1; @@ -174,12 +205,13 @@ compare_to_impl(const GeomMunger *other) const { //////////////////////////////////////////////////////////////////// int DXGeomMunger9:: geom_compare_to_impl(const GeomMunger *other) const { - // Unlike GLGeomMunger, we do consider _texture and _tex_gen - // important for this purpose, since they control the number and - // order of texture coordinates we might put into the FVF. + // Unlike GLGeomMunger, we do consider _filtered_texture and + // _tex_gen important for this purpose, since they control the + // number and order of texture coordinates we might put into the + // FVF. const DXGeomMunger9 *om = DCAST(DXGeomMunger9, other); - if (_texture != om->_texture) { - return _texture < om->_texture ? -1 : 1; + if (_filtered_texture != om->_filtered_texture) { + return _filtered_texture < om->_filtered_texture ? -1 : 1; } if (_tex_gen != om->_tex_gen) { return _tex_gen < om->_tex_gen ? -1 : 1; diff --git a/panda/src/dxgsg9/dxGeomMunger9.h b/panda/src/dxgsg9/dxGeomMunger9.h index 55b52cc9b2..34b2345c33 100755 --- a/panda/src/dxgsg9/dxGeomMunger9.h +++ b/panda/src/dxgsg9/dxGeomMunger9.h @@ -22,6 +22,8 @@ #include "pandabase.h" #include "standardMunger.h" #include "graphicsStateGuardian.h" +#include "weakPointerTo.h" +#include "weakPointerCallback.h" //////////////////////////////////////////////////////////////////// // Class : DXGeomMunger9 @@ -31,11 +33,14 @@ // and that all relevant components are packed into a // single array, in the correct order. //////////////////////////////////////////////////////////////////// -class EXPCL_PANDADX DXGeomMunger9 : public StandardMunger { +class EXPCL_PANDADX DXGeomMunger9 : public StandardMunger, public WeakPointerCallback { public: INLINE DXGeomMunger9(GraphicsStateGuardian *gsg, const RenderState *state); + virtual ~DXGeomMunger9(); ALLOC_DELETED_CHAIN(DXGeomMunger9); + virtual void wp_callback(void *); + protected: virtual CPT(GeomVertexFormat) munge_format_impl(const GeomVertexFormat *orig, const GeomVertexAnimationSpec &animation); @@ -44,8 +49,16 @@ protected: virtual int geom_compare_to_impl(const GeomMunger *other) const; private: - CPT(TextureAttrib) _texture; - CPT(TexGenAttrib) _tex_gen; + WCPT(TextureAttrib) _texture; + WCPT(TexGenAttrib) _tex_gen; + + // This pointer is derived from _texture, above. In the case that + // it is a different pointer, we maintain its reference count + // explicitly. If it is the same pointer, we don't reference count + // it at all (so we won't hold on to the reference count + // unnecessarily). + const TextureAttrib *_filtered_texture; + bool _reffed_filtered_texture; static GeomMunger *_deleted_chain;