From 14b5763408c9edf007d620c2150f79d4a53dac4d Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Tue, 12 Jul 2016 06:09:39 +0200 Subject: [PATCH] GRIM: Fix memory leaks related to EMI models --- engines/grim/actor.cpp | 3 +-- engines/grim/emi/modelemi.cpp | 2 ++ engines/grim/gfx_base.h | 2 ++ engines/grim/gfx_opengl_shaders.cpp | 33 +++++++++++++++++++++++++++++ engines/grim/gfx_opengl_shaders.h | 2 ++ 5 files changed, 40 insertions(+), 2 deletions(-) diff --git a/engines/grim/actor.cpp b/engines/grim/actor.cpp index 8b0fc37f0ce..8434823846c 100644 --- a/engines/grim/actor.cpp +++ b/engines/grim/actor.cpp @@ -1935,8 +1935,7 @@ void Actor::clearShadowPlane(int i) { shadow->active = false; shadow->dontNegate = false; - // TODO: Clean up the userData properly - shadow->userData = nullptr; + g_driver->destroyShadow(shadow); } void Actor::putInSet(const Common::String &set) { diff --git a/engines/grim/emi/modelemi.cpp b/engines/grim/emi/modelemi.cpp index 59af0b499be..791add352ce 100644 --- a/engines/grim/emi/modelemi.cpp +++ b/engines/grim/emi/modelemi.cpp @@ -465,6 +465,8 @@ EMIModel::EMIModel(const Common::String &filename, Common::SeekableReadStream *d } EMIModel::~EMIModel() { + g_driver->destroyEMIModel(this); + delete[] _vertices; delete[] _drawVertices; delete[] _normals; diff --git a/engines/grim/gfx_base.h b/engines/grim/gfx_base.h index 40b6b3eb04e..0d5287f81bc 100644 --- a/engines/grim/gfx_base.h +++ b/engines/grim/gfx_base.h @@ -133,6 +133,7 @@ public: virtual bool isShadowModeActive(); virtual void setShadowColor(byte r, byte g, byte b) = 0; virtual void getShadowColor(byte *r, byte *g, byte *b) = 0; + virtual void destroyShadow(Shadow *shadow) {} virtual void set3DMode() = 0; @@ -265,6 +266,7 @@ public: virtual void destroyMesh(const Mesh *mesh) {} virtual void createEMIModel(EMIModel *model) {} virtual void updateEMIModel(const EMIModel *model) {} + virtual void destroyEMIModel(EMIModel *model) {} virtual int genBuffer() { return 0; } virtual void delBuffer(int buffer) {} diff --git a/engines/grim/gfx_opengl_shaders.cpp b/engines/grim/gfx_opengl_shaders.cpp index 1caff2c336e..88315567c22 100644 --- a/engines/grim/gfx_opengl_shaders.cpp +++ b/engines/grim/gfx_opengl_shaders.cpp @@ -909,6 +909,17 @@ void GfxOpenGLS::getShadowColor(byte *r, byte *g, byte *b) { *b = _shadowColorB; } +void GfxOpenGLS::destroyShadow(Shadow *shadow) { + ShadowUserData *sud = static_cast(shadow->userData); + if (sud) { + OpenGL::Shader::freeBuffer(sud->_verticesVBO); + OpenGL::Shader::freeBuffer(sud->_indicesVBO); + delete sud; + } + + shadow->userData = nullptr; +} + void GfxOpenGLS::set3DMode() { } @@ -1992,6 +2003,28 @@ void GfxOpenGLS::createEMIModel(EMIModel *model) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } +void GfxOpenGLS::destroyEMIModel(EMIModel *model) { + for (uint32 i = 0; i < model->_numFaces; ++i) { + EMIMeshFace *face = &model->_faces[i]; + OpenGL::Shader::freeBuffer(face->_indicesEBO); + face->_indicesEBO = 0; + } + + EMIModelUserData *mud = static_cast(model->_userData); + + if (mud) { + OpenGL::Shader::freeBuffer(mud->_verticesVBO); + OpenGL::Shader::freeBuffer(mud->_normalsVBO); + OpenGL::Shader::freeBuffer(mud->_texCoordsVBO); + OpenGL::Shader::freeBuffer(mud->_colorMapVBO); + + delete mud->_shader; + delete mud; + } + + model->_userData = nullptr; +} + void GfxOpenGLS::createMesh(Mesh *mesh) { Common::Array meshInfo; meshInfo.reserve(mesh->_numVertices * 5); diff --git a/engines/grim/gfx_opengl_shaders.h b/engines/grim/gfx_opengl_shaders.h index 72e74fc33c8..3a220a7e115 100644 --- a/engines/grim/gfx_opengl_shaders.h +++ b/engines/grim/gfx_opengl_shaders.h @@ -80,6 +80,7 @@ public: virtual bool isShadowModeActive() override; virtual void setShadowColor(byte r, byte g, byte b) override; virtual void getShadowColor(byte *r, byte *g, byte *b) override; + virtual void destroyShadow(Shadow *shadow) override; virtual void set3DMode() override; @@ -206,6 +207,7 @@ public: virtual void destroyMesh(const Mesh *mesh) override; virtual void createEMIModel(EMIModel *model) override; virtual void updateEMIModel(const EMIModel* model) override; + virtual void destroyEMIModel(EMIModel *model) override; virtual void setBlendMode(bool additive) override;