From 1f0ae739cb952165488f13499f141ac3d20378e0 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sun, 9 Mar 2008 22:02:32 +0000 Subject: BGE memleak fix: OpenGL Display Lists not deleted when switching scene This fix also improves performance of Display List for replica objects: Display List ID caching is now enabled for replica objects which avoids a tree search on each frame and for each replica. --- .../gameengine/Rasterizer/RAS_MaterialBucket.cpp | 5 +++ source/gameengine/Rasterizer/RAS_MaterialBucket.h | 19 +++++++--- source/gameengine/Rasterizer/RAS_MeshObject.cpp | 2 ++ .../RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp | 42 ++++++++++++++++++---- .../RAS_OpenGLRasterizer/RAS_ListRasterizer.h | 6 +++- 5 files changed, 63 insertions(+), 11 deletions(-) (limited to 'source/gameengine/Rasterizer') diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp index 689772f51c4..757784be87f 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp @@ -69,6 +69,11 @@ bool KX_MeshSlot::Less(const KX_MeshSlot& lhs) const return result; } +KX_MeshSlot::~KX_MeshSlot() +{ + if (m_DisplayList) + m_DisplayList->Release(); +} RAS_MaterialBucket::RAS_MaterialBucket(RAS_IPolyMaterial* mat) diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.h b/source/gameengine/Rasterizer/RAS_MaterialBucket.h index 7d875242c2e..ded6af999c4 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.h +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.h @@ -69,10 +69,21 @@ public: */ class KX_ListSlot { +protected: + int m_refcount; public: - KX_ListSlot(){} - virtual ~KX_ListSlot(){} - + KX_ListSlot(){ m_refcount=1; } + virtual ~KX_ListSlot() {} + virtual int Release() { + if (--m_refcount > 0) + return m_refcount; + delete this; + return 0; + } + virtual KX_ListSlot* AddRef() { + m_refcount++; + return this; + } virtual void SetModified(bool mod)=0; }; @@ -96,7 +107,7 @@ public: m_DisplayList(0) { } - ~KX_MeshSlot(){} + ~KX_MeshSlot(); bool Less(const KX_MeshSlot& lhs) const; }; diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp index 4219b641b5c..b7147ea6c42 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp +++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp @@ -474,7 +474,9 @@ void RAS_MeshObject::ClearArrayData() { KX_ArrayOptimizer** ao = m_matVertexArrayS.at(i); if (ao) + { delete *ao; + } } } diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp index 7baa6c49656..afa98fdb274 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp @@ -25,13 +25,23 @@ #define spit(x) //#endif -RAS_ListSlot::RAS_ListSlot() +RAS_ListSlot::RAS_ListSlot(RAS_ListRasterizer* rasty) : KX_ListSlot(), m_flag(LIST_MODIFY|LIST_CREATE), - m_list(0) + m_list(0), + m_rasty(rasty) { } +int RAS_ListSlot::Release() +{ + if (--m_refcount > 0) + return m_refcount; + m_rasty->RemoveListSlot(this); + delete this; + return 0; +} + RAS_ListSlot::~RAS_ListSlot() { RemoveList(); @@ -108,6 +118,18 @@ RAS_ListRasterizer::~RAS_ListRasterizer() ReleaseAlloc(); } +void RAS_ListRasterizer::RemoveListSlot(RAS_ListSlot* list) +{ + RAS_Lists::iterator it = mLists.begin(); + while(it != mLists.end()) { + if (it->second == list) { + mLists.erase(it); + break; + } + it++; + } +} + RAS_ListSlot* RAS_ListRasterizer::FindOrAdd(const vecVertexArray& vertexarrays, KX_ListSlot** slot) { /* @@ -120,10 +142,10 @@ RAS_ListSlot* RAS_ListRasterizer::FindOrAdd(const vecVertexArray& vertexarrays, if(!localSlot) { RAS_Lists::iterator it = mLists.find(vertexarrays); if(it == mLists.end()) { - localSlot = new RAS_ListSlot(); + localSlot = new RAS_ListSlot(this); mLists.insert(std::pair(vertexarrays, localSlot)); } else { - localSlot = it->second; + localSlot = static_cast(it->second->AddRef()); } } MT_assert(localSlot); @@ -157,8 +179,12 @@ void RAS_ListRasterizer::IndexPrimitives( if(!useObjectColor) { localSlot = FindOrAdd(vertexarrays, slot); localSlot->DrawList(); - if(localSlot->End()) + if(localSlot->End()) { + // save slot here too, needed for replicas and object using same mesh + // => they have the same vertexarray but different mesh slot + *slot = localSlot; return; + } } if (mUseVertexArrays) { @@ -201,8 +227,12 @@ void RAS_ListRasterizer::IndexPrimitivesMulti( localSlot = FindOrAdd(vertexarrays, slot); localSlot->DrawList(); - if(localSlot->End()) + if(localSlot->End()) { + // save slot here too, needed for replicas and object using same mesh + // => they have the same vertexarray but different mesh slot + *slot = localSlot; return; + } } if (mUseVertexArrays) { diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h index f25f621f70c..4b3304d7396 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h @@ -5,14 +5,17 @@ #include "RAS_VAOpenGLRasterizer.h" #include +class RAS_ListRasterizer; class RAS_ListSlot : public KX_ListSlot { unsigned int m_list; unsigned int m_flag; + RAS_ListRasterizer* m_rasty; public: - RAS_ListSlot(); + RAS_ListSlot(RAS_ListRasterizer* rasty); virtual ~RAS_ListSlot(); virtual void SetModified(bool mod); + virtual int Release(); void RemoveList(); void DrawList(); @@ -42,6 +45,7 @@ class RAS_ListRasterizer : public RAS_VAOpenGLRasterizer void ReleaseAlloc(); public: + void RemoveListSlot(RAS_ListSlot* list); RAS_ListRasterizer(RAS_ICanvas* canvas, bool useVertexArrays=false, bool lock=false); virtual ~RAS_ListRasterizer(); -- cgit v1.2.3