Added OpenGL::Delete[FrameBuffer|VertexArray]
Also renamed OpenGL::OnContextChange to OnContextChanged (since it happens after the context change) Also improved RenderTexture implementation Former-commit-id: d845b1405294dd3aa134d392585069bbb28a77a3
This commit is contained in:
parent
a3f877daf1
commit
7ac3fee3a5
|
|
@ -86,9 +86,11 @@ class NAZARA_API NzOpenGL
|
||||||
static void BindViewport(const NzRecti& viewport);
|
static void BindViewport(const NzRecti& viewport);
|
||||||
|
|
||||||
static void DeleteBuffer(nzBufferType type, GLuint id);
|
static void DeleteBuffer(nzBufferType type, GLuint id);
|
||||||
|
static void DeleteFrameBuffer(const NzContext* context, GLuint id);
|
||||||
static void DeleteProgram(GLuint id);
|
static void DeleteProgram(GLuint id);
|
||||||
static void DeleteSampler(GLuint id);
|
static void DeleteSampler(GLuint id);
|
||||||
static void DeleteTexture(GLuint id);
|
static void DeleteTexture(GLuint id);
|
||||||
|
static void DeleteVertexArray(const NzContext* context, GLuint id);
|
||||||
|
|
||||||
static GLuint GetCurrentBuffer(nzBufferType type);
|
static GLuint GetCurrentBuffer(nzBufferType type);
|
||||||
static GLuint GetCurrentProgram();
|
static GLuint GetCurrentProgram();
|
||||||
|
|
@ -149,7 +151,7 @@ class NAZARA_API NzOpenGL
|
||||||
static GLenum TextureTargetProxy[nzImageType_Max+1];
|
static GLenum TextureTargetProxy[nzImageType_Max+1];
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void OnContextChange(const NzContext* newContext);
|
static void OnContextChanged(const NzContext* newContext);
|
||||||
static void OnContextDestruction(const NzContext* context);
|
static void OnContextDestruction(const NzContext* context);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -248,7 +248,7 @@ bool NzContext::SetActive(bool active) const
|
||||||
currentContext = nullptr;
|
currentContext = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
NzOpenGL::OnContextChange(currentContext);
|
NzOpenGL::OnContextChanged(currentContext);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,8 +63,15 @@ namespace
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum GarbageResourceType
|
||||||
|
{
|
||||||
|
GarbageResourceType_FrameBuffer,
|
||||||
|
GarbageResourceType_VertexArray
|
||||||
|
};
|
||||||
|
|
||||||
struct ContextStates
|
struct ContextStates
|
||||||
{
|
{
|
||||||
|
std::vector<std::pair<GarbageResourceType, GLuint>> garbage; // Les ressources à supprimer dès que possible
|
||||||
GLuint buffersBinding[nzBufferType_Max+1] = {0};
|
GLuint buffersBinding[nzBufferType_Max+1] = {0};
|
||||||
GLuint currentProgram = 0;
|
GLuint currentProgram = 0;
|
||||||
GLuint samplers[32] = {0}; // 32 est pour l'instant la plus haute limite (GL_TEXTURE31)
|
GLuint samplers[32] = {0}; // 32 est pour l'instant la plus haute limite (GL_TEXTURE31)
|
||||||
|
|
@ -496,6 +503,15 @@ void NzOpenGL::DeleteBuffer(nzBufferType type, GLuint id)
|
||||||
s_contextStates->buffersBinding[type] = 0;
|
s_contextStates->buffersBinding[type] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NzOpenGL::DeleteFrameBuffer(const NzContext* context, GLuint id)
|
||||||
|
{
|
||||||
|
// Si le contexte est actif, ne nous privons pas
|
||||||
|
if (NzContext::GetCurrent() == context)
|
||||||
|
glDeleteFramebuffers(1, &id);
|
||||||
|
else
|
||||||
|
s_contexts[context].garbage.emplace_back(GarbageResourceType_FrameBuffer, id);
|
||||||
|
}
|
||||||
|
|
||||||
void NzOpenGL::DeleteProgram(GLuint id)
|
void NzOpenGL::DeleteProgram(GLuint id)
|
||||||
{
|
{
|
||||||
#ifdef NAZARA_DEBUG
|
#ifdef NAZARA_DEBUG
|
||||||
|
|
@ -555,6 +571,15 @@ void NzOpenGL::DeleteTexture(GLuint id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NzOpenGL::DeleteVertexArray(const NzContext* context, GLuint id)
|
||||||
|
{
|
||||||
|
// Si le contexte est actif, ne nous privons pas
|
||||||
|
if (NzContext::GetCurrent() == context)
|
||||||
|
glDeleteFramebuffers(1, &id);
|
||||||
|
else
|
||||||
|
s_contexts[context].garbage.emplace_back(GarbageResourceType_VertexArray, id);
|
||||||
|
}
|
||||||
|
|
||||||
GLuint NzOpenGL::GetCurrentBuffer(nzBufferType type)
|
GLuint NzOpenGL::GetCurrentBuffer(nzBufferType type)
|
||||||
{
|
{
|
||||||
#ifdef NAZARA_DEBUG
|
#ifdef NAZARA_DEBUG
|
||||||
|
|
@ -1778,9 +1803,27 @@ void NzOpenGL::Uninitialize()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzOpenGL::OnContextChange(const NzContext* newContext)
|
void NzOpenGL::OnContextChanged(const NzContext* newContext)
|
||||||
{
|
{
|
||||||
s_contextStates = (newContext) ? &s_contexts[newContext] : nullptr;
|
s_contextStates = (newContext) ? &s_contexts[newContext] : nullptr;
|
||||||
|
if (s_contextStates)
|
||||||
|
{
|
||||||
|
// On supprime les éventuelles ressources mortes-vivantes (Qui ne peuvent être libérées que dans notre contexte)
|
||||||
|
for (std::pair<GarbageResourceType, GLuint>& pair : s_contextStates->garbage)
|
||||||
|
{
|
||||||
|
switch (pair.first)
|
||||||
|
{
|
||||||
|
case GarbageResourceType_FrameBuffer:
|
||||||
|
glDeleteFramebuffers(1, &pair.second);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GarbageResourceType_VertexArray:
|
||||||
|
glDeleteVertexArrays(1, &pair.second);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s_contextStates->garbage.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzOpenGL::OnContextDestruction(const NzContext* context)
|
void NzOpenGL::OnContextDestruction(const NzContext* context)
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
#include <Nazara/Renderer/RenderTexture.hpp>
|
#include <Nazara/Renderer/RenderTexture.hpp>
|
||||||
|
#include <Nazara/Core/CallOnExit.hpp>
|
||||||
#include <Nazara/Core/Error.hpp>
|
#include <Nazara/Core/Error.hpp>
|
||||||
#include <Nazara/Renderer/Context.hpp>
|
#include <Nazara/Renderer/Context.hpp>
|
||||||
#include <Nazara/Renderer/OpenGL.hpp>
|
#include <Nazara/Renderer/OpenGL.hpp>
|
||||||
|
|
@ -325,31 +326,36 @@ bool NzRenderTexture::Create(bool lock)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NzRenderTextureImpl* impl = new NzRenderTextureImpl;
|
std::unique_ptr<NzRenderTextureImpl> impl(new NzRenderTextureImpl);
|
||||||
|
|
||||||
impl->context = NzContext::GetCurrent();
|
|
||||||
impl->context->AddResourceListener(this);
|
|
||||||
|
|
||||||
impl->fbo = 0;
|
impl->fbo = 0;
|
||||||
glGenFramebuffers(1, &impl->fbo);
|
glGenFramebuffers(1, &impl->fbo);
|
||||||
|
|
||||||
if (!impl->fbo)
|
if (!impl->fbo)
|
||||||
{
|
{
|
||||||
delete impl;
|
|
||||||
|
|
||||||
NazaraError("Failed to create framebuffer");
|
NazaraError("Failed to create framebuffer");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_impl = impl;
|
m_impl = impl.release();
|
||||||
|
m_impl->context = NzContext::GetCurrent();
|
||||||
|
m_impl->context->AddResourceListener(this);
|
||||||
|
|
||||||
if (lock && !Lock())
|
if (lock)
|
||||||
{
|
{
|
||||||
delete impl;
|
// En cas d'exception, la ressource sera quand même libérée
|
||||||
m_impl = nullptr;
|
NzCallOnExit onExit([this] ()
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
});
|
||||||
|
|
||||||
NazaraError("Failed to lock render texture");
|
if (!Lock())
|
||||||
return false;
|
{
|
||||||
|
NazaraError("Failed to lock render texture");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
onExit.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
NotifyParametersChange();
|
NotifyParametersChange();
|
||||||
|
|
@ -365,15 +371,6 @@ void NzRenderTexture::Destroy()
|
||||||
if (IsActive())
|
if (IsActive())
|
||||||
NzRenderer::SetTarget(nullptr);
|
NzRenderer::SetTarget(nullptr);
|
||||||
|
|
||||||
bool canFreeFBO = true;
|
|
||||||
#if NAZARA_RENDERER_SAFE
|
|
||||||
if (NzContext::GetCurrent() != m_impl->context)
|
|
||||||
{
|
|
||||||
NazaraWarning("RenderTexture should be destroyed by it's creation context, this will cause leaks");
|
|
||||||
canFreeFBO = false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
m_impl->context->RemoveResourceListener(this);
|
m_impl->context->RemoveResourceListener(this);
|
||||||
|
|
||||||
for (const Attachment& attachment : m_impl->attachments)
|
for (const Attachment& attachment : m_impl->attachments)
|
||||||
|
|
@ -387,10 +384,11 @@ void NzRenderTexture::Destroy()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canFreeFBO)
|
// Le FBO devant être supprimé dans son contexte d'origine, nous déléguons sa suppression à la classe OpenGL
|
||||||
glDeleteFramebuffers(1, &m_impl->fbo);
|
// Celle-ci va libérer le FBO dès que possible (la prochaine fois que son contexte d'origine sera actif)
|
||||||
|
NzOpenGL::DeleteFrameBuffer(m_impl->context, m_impl->fbo);
|
||||||
|
|
||||||
delete m_impl;
|
delete m_impl; // Enlève également une références sur les Texture/RenderBuffer
|
||||||
m_impl = nullptr;
|
m_impl = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue