mirror of
https://github.com/edubart/otclient.git
synced 2025-10-19 05:53:26 +02:00
Fix memory leaks
* Fix recursive reference memory leak in UIWidget * Make Event/ScheduledEvent memory-leak safe * Fix exit crashs by freeing graphics resources before destroying GL context * Add many asserts to avoid any leak regression
This commit is contained in:
@@ -27,11 +27,13 @@
|
||||
#include "glutil.h"
|
||||
|
||||
class Texture;
|
||||
class TextureManager;
|
||||
class Image;
|
||||
class AnimatedTexture;
|
||||
class BitmapFont;
|
||||
class CachedText;
|
||||
class FrameBuffer;
|
||||
class FrameBufferManager;
|
||||
class Shader;
|
||||
class ShaderProgram;
|
||||
class PainterShaderProgram;
|
||||
|
@@ -32,10 +32,10 @@ FontManager::FontManager()
|
||||
m_defaultFont = BitmapFontPtr(new BitmapFont("emptyfont"));
|
||||
}
|
||||
|
||||
void FontManager::releaseFonts()
|
||||
void FontManager::terminate()
|
||||
{
|
||||
m_defaultFont.reset();
|
||||
m_fonts.clear();
|
||||
m_defaultFont = nullptr;
|
||||
}
|
||||
|
||||
bool FontManager::importFont(std::string fontFile)
|
||||
|
@@ -30,10 +30,8 @@ class FontManager
|
||||
public:
|
||||
FontManager();
|
||||
|
||||
/// Release fonts references, thus making possible to destruct them
|
||||
void releaseFonts();
|
||||
void terminate();
|
||||
|
||||
/// Import a font from .otfont file
|
||||
bool importFont(std::string fontFile);
|
||||
|
||||
bool fontExists(const std::string& fontName);
|
||||
|
@@ -23,7 +23,9 @@
|
||||
#include "framebuffer.h"
|
||||
#include "graphics.h"
|
||||
#include "texture.h"
|
||||
|
||||
#include <framework/platform/platformwindow.h>
|
||||
#include <framework/application.h>
|
||||
|
||||
uint FrameBuffer::boundFbo = 0;
|
||||
|
||||
@@ -32,12 +34,6 @@ FrameBuffer::FrameBuffer()
|
||||
internalCreate();
|
||||
}
|
||||
|
||||
FrameBuffer::FrameBuffer(const Size& size)
|
||||
{
|
||||
internalCreate();
|
||||
resize(size);
|
||||
}
|
||||
|
||||
void FrameBuffer::internalCreate()
|
||||
{
|
||||
m_prevBoundFbo = 0;
|
||||
@@ -51,14 +47,14 @@ void FrameBuffer::internalCreate()
|
||||
|
||||
FrameBuffer::~FrameBuffer()
|
||||
{
|
||||
if(m_fbo != 0)
|
||||
assert(!g_app->isTermianted());
|
||||
if(g_graphics.ok() && m_fbo != 0)
|
||||
glDeleteFramebuffers(1, &m_fbo);
|
||||
}
|
||||
|
||||
void FrameBuffer::resize(const Size& size)
|
||||
{
|
||||
if(!size.isValid())
|
||||
return;
|
||||
assert(size.isValid());
|
||||
|
||||
if(m_texture && m_texture->getSize() == size)
|
||||
return;
|
||||
|
@@ -28,9 +28,12 @@
|
||||
|
||||
class FrameBuffer
|
||||
{
|
||||
public:
|
||||
protected:
|
||||
FrameBuffer();
|
||||
FrameBuffer(const Size& size);
|
||||
|
||||
friend class FrameBufferManager;
|
||||
|
||||
public:
|
||||
virtual ~FrameBuffer();
|
||||
|
||||
void resize(const Size& size);
|
||||
|
44
src/framework/graphics/framebuffermanager.cpp
Normal file
44
src/framework/graphics/framebuffermanager.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include "framebuffermanager.h"
|
||||
|
||||
FrameBufferManager g_framebuffers;
|
||||
|
||||
void FrameBufferManager::init()
|
||||
{
|
||||
m_temporaryFramebuffer = FrameBufferPtr(new FrameBuffer());
|
||||
}
|
||||
|
||||
void FrameBufferManager::terminate()
|
||||
{
|
||||
m_framebuffers.clear();
|
||||
m_temporaryFramebuffer = nullptr;
|
||||
}
|
||||
|
||||
FrameBufferPtr FrameBufferManager::createFrameBuffer()
|
||||
{
|
||||
FrameBufferPtr fbo = FrameBufferPtr(new FrameBuffer());
|
||||
m_framebuffers.push_back(fbo);
|
||||
return fbo;
|
||||
}
|
46
src/framework/graphics/framebuffermanager.h
Normal file
46
src/framework/graphics/framebuffermanager.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FRAMEBUFFERMANAGER_H
|
||||
#define FRAMEBUFFERMANAGER_H
|
||||
|
||||
#include "framebuffer.h"
|
||||
|
||||
class FrameBufferManager
|
||||
{
|
||||
public:
|
||||
void init();
|
||||
void terminate();
|
||||
void clear();
|
||||
|
||||
FrameBufferPtr createFrameBuffer();
|
||||
const FrameBufferPtr& getTemporaryFrameBuffer() { return m_temporaryFramebuffer; }
|
||||
|
||||
protected:
|
||||
FrameBufferPtr m_temporaryFramebuffer;
|
||||
std::vector<FrameBufferPtr> m_framebuffers;
|
||||
};
|
||||
|
||||
extern FrameBufferManager g_framebuffers;
|
||||
|
||||
#endif
|
@@ -33,6 +33,8 @@
|
||||
|
||||
#include <framework/graphics/graphics.h>
|
||||
#include <framework/graphics/texture.h>
|
||||
#include "texturemanager.h"
|
||||
#include "framebuffermanager.h"
|
||||
#include <framework/platform/platformwindow.h>
|
||||
|
||||
Graphics g_graphics;
|
||||
@@ -88,13 +90,19 @@ void Graphics::init()
|
||||
m_alphaBits = 0;
|
||||
glGetIntegerv(GL_ALPHA_BITS, &m_alphaBits);
|
||||
|
||||
m_ok = true;
|
||||
|
||||
selectPainterEngine(m_prefferedPainterEngine);
|
||||
m_emptyTexture = TexturePtr(new Texture);
|
||||
|
||||
g_textures.init();
|
||||
g_framebuffers.init();
|
||||
}
|
||||
|
||||
void Graphics::terminate()
|
||||
{
|
||||
g_fonts.releaseFonts();
|
||||
g_fonts.terminate();
|
||||
g_framebuffers.terminate();
|
||||
g_textures.terminate();
|
||||
|
||||
#ifdef PAINTER_OGL2
|
||||
if(g_painterOGL2) {
|
||||
@@ -112,7 +120,7 @@ void Graphics::terminate()
|
||||
|
||||
g_painter = nullptr;
|
||||
|
||||
m_emptyTexture.reset();
|
||||
m_ok = false;
|
||||
}
|
||||
|
||||
bool Graphics::parseOption(const std::string& option)
|
||||
|
@@ -51,13 +51,13 @@ public:
|
||||
|
||||
int getMaxTextureSize() { return m_maxTextureSize; }
|
||||
const Size& getViewportSize() { return m_viewportSize; }
|
||||
TexturePtr& getEmptyTexture() { return m_emptyTexture; }
|
||||
|
||||
std::string getVendor() { return (const char*)glGetString(GL_VENDOR); }
|
||||
std::string getRenderer() { return (const char*)glGetString(GL_RENDERER); }
|
||||
std::string getVersion() { return (const char*)glGetString(GL_VERSION); }
|
||||
std::string getExtensions() { return (const char*)glGetString(GL_EXTENSIONS); }
|
||||
|
||||
bool ok() { return m_ok; }
|
||||
bool canUseDrawArrays();
|
||||
bool canUseShaders();
|
||||
bool canUseFBO();
|
||||
@@ -72,10 +72,10 @@ public:
|
||||
|
||||
private:
|
||||
Size m_viewportSize;
|
||||
TexturePtr m_emptyTexture;
|
||||
|
||||
int m_maxTextureSize;
|
||||
int m_alphaBits;
|
||||
Boolean<false> m_ok;
|
||||
Boolean<true> m_useDrawArrays;
|
||||
Boolean<true> m_useFBO;
|
||||
Boolean<false> m_useHardwareBuffers;
|
||||
|
43
src/framework/graphics/hardwarebuffer.cpp
Normal file
43
src/framework/graphics/hardwarebuffer.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "hardwarebuffer.h"
|
||||
#include "graphics.h"
|
||||
|
||||
#include <framework/application.h>
|
||||
#include <framework/core/logger.h>
|
||||
|
||||
HardwareBuffer::HardwareBuffer(Type type)
|
||||
{
|
||||
m_type = type;
|
||||
m_id = 0;
|
||||
glGenBuffers(1, &m_id);
|
||||
if(!m_id)
|
||||
g_logger.fatal("Unable to create hardware buffer.");
|
||||
}
|
||||
|
||||
HardwareBuffer::~HardwareBuffer()
|
||||
{
|
||||
assert(!g_app->isTermianted());
|
||||
if(g_graphics.ok())
|
||||
glDeleteBuffers(1, &m_id);
|
||||
}
|
@@ -40,15 +40,8 @@ public:
|
||||
DynamicDraw = GL_DYNAMIC_DRAW
|
||||
};
|
||||
|
||||
HardwareBuffer(Type type) {
|
||||
m_type = type;
|
||||
m_id = 0;
|
||||
glGenBuffers(1, &m_id);
|
||||
assert(m_id != 0);
|
||||
}
|
||||
~HardwareBuffer() {
|
||||
glDeleteBuffers(1, &m_id);
|
||||
}
|
||||
HardwareBuffer(Type type);
|
||||
~HardwareBuffer();
|
||||
|
||||
void bind() { glBindBuffer(m_type, m_id); }
|
||||
static void unbind(Type type) { glBindBuffer(type, 0); }
|
||||
|
@@ -48,12 +48,6 @@ PainterOGL2::PainterOGL2()
|
||||
PainterShaderProgram::release();
|
||||
}
|
||||
|
||||
PainterOGL2::~PainterOGL2()
|
||||
{
|
||||
m_drawTexturedProgram = nullptr;
|
||||
m_drawSolidColorProgram = nullptr;
|
||||
}
|
||||
|
||||
void PainterOGL2::bind()
|
||||
{
|
||||
Painter::bind();
|
||||
|
@@ -36,7 +36,6 @@ class PainterOGL2 : public Painter
|
||||
{
|
||||
public:
|
||||
PainterOGL2();
|
||||
~PainterOGL2();
|
||||
|
||||
void bind();
|
||||
void unbind();
|
||||
|
@@ -21,6 +21,9 @@
|
||||
*/
|
||||
|
||||
#include "shader.h"
|
||||
#include "graphics.h"
|
||||
|
||||
#include <framework/application.h>
|
||||
#include <framework/core/resourcemanager.h>
|
||||
|
||||
Shader::Shader(Shader::ShaderType shaderType)
|
||||
@@ -41,7 +44,9 @@ Shader::Shader(Shader::ShaderType shaderType)
|
||||
|
||||
Shader::~Shader()
|
||||
{
|
||||
glDeleteShader(m_shaderId);
|
||||
assert(!g_app->isTermianted());
|
||||
if(g_graphics.ok())
|
||||
glDeleteShader(m_shaderId);
|
||||
}
|
||||
|
||||
bool Shader::compileSourceCode(const std::string& sourceCode)
|
||||
|
@@ -21,6 +21,9 @@
|
||||
*/
|
||||
|
||||
#include "shaderprogram.h"
|
||||
#include "graphics.h"
|
||||
|
||||
#include <framework/application.h>
|
||||
|
||||
GLuint ShaderProgram::m_currentProgram = 0;
|
||||
|
||||
@@ -35,7 +38,9 @@ ShaderProgram::ShaderProgram()
|
||||
|
||||
ShaderProgram::~ShaderProgram()
|
||||
{
|
||||
glDeleteProgram(m_programId);
|
||||
assert(!g_app->isTermianted());
|
||||
if(g_graphics.ok())
|
||||
glDeleteProgram(m_programId);
|
||||
}
|
||||
|
||||
bool ShaderProgram::addShader(const ShaderPtr& shader) {
|
||||
|
@@ -25,6 +25,8 @@
|
||||
#include "framebuffer.h"
|
||||
#include "image.h"
|
||||
|
||||
#include <framework/application.h>
|
||||
|
||||
Texture::Texture()
|
||||
{
|
||||
m_id = 0;
|
||||
@@ -77,8 +79,9 @@ Texture::Texture(const ImagePtr& image, bool buildMipmaps)
|
||||
|
||||
Texture::~Texture()
|
||||
{
|
||||
assert(!g_app->isTermianted());
|
||||
// free texture from gl memory
|
||||
if(m_id > 0)
|
||||
if(g_graphics.ok() && m_id != 0)
|
||||
glDeleteTextures(1, &m_id);
|
||||
}
|
||||
|
||||
|
@@ -30,6 +30,26 @@
|
||||
|
||||
TextureManager g_textures;
|
||||
|
||||
void TextureManager::init()
|
||||
{
|
||||
m_emptyTexture = TexturePtr(new Texture);
|
||||
}
|
||||
|
||||
void TextureManager::terminate()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
// check for leaks
|
||||
int refs = 0;
|
||||
for(const auto& it : m_textures)
|
||||
if(it.second.use_count() > 1)
|
||||
refs++;
|
||||
if(refs > 0)
|
||||
g_logger.debug(stdext::format("%d textures references left", refs));
|
||||
#endif
|
||||
m_textures.clear();
|
||||
m_emptyTexture = nullptr;
|
||||
}
|
||||
|
||||
TexturePtr TextureManager::getTexture(const std::string& fileName)
|
||||
{
|
||||
TexturePtr texture;
|
||||
@@ -59,7 +79,7 @@ TexturePtr TextureManager::getTexture(const std::string& fileName)
|
||||
texture = loadPNG(fin);
|
||||
} catch(stdext::exception& e) {
|
||||
g_logger.error(stdext::format("unable to load texture '%s': %s", fileName, e.what()));
|
||||
texture = g_graphics.getEmptyTexture();
|
||||
texture = g_textures.getEmptyTexture();
|
||||
}
|
||||
|
||||
if(texture)
|
||||
|
@@ -28,12 +28,17 @@
|
||||
class TextureManager
|
||||
{
|
||||
public:
|
||||
TexturePtr getTexture(const std::string& fileName);
|
||||
void init();
|
||||
void terminate();
|
||||
|
||||
static TexturePtr loadPNG(std::stringstream& file);
|
||||
TexturePtr getTexture(const std::string& fileName);
|
||||
const TexturePtr& getEmptyTexture() { return m_emptyTexture; }
|
||||
|
||||
private:
|
||||
TexturePtr loadPNG(std::stringstream& file);
|
||||
|
||||
std::unordered_map<std::string, TextureWeakPtr> m_textures;
|
||||
TexturePtr m_emptyTexture;
|
||||
};
|
||||
|
||||
extern TextureManager g_textures;
|
||||
|
Reference in New Issue
Block a user