The OpenGL wrapper now handles context change

Fixed some bugs
Thanks to Raakz


Former-commit-id: f156ba7aa3307cccd83c9c02987dadad02cd8185
This commit is contained in:
Lynix 2013-06-21 01:28:11 +02:00
parent cca920e597
commit 00c2e824d1
7 changed files with 208 additions and 79 deletions

View File

@ -32,13 +32,13 @@ class NAZARA_API NzContext : public NzResource
const NzContextParameters& GetParameters() const; const NzContextParameters& GetParameters() const;
bool IsActive() const; bool IsActive() const;
bool SetActive(bool active) const; bool SetActive(bool active);
void SwapBuffers(); void SwapBuffers();
static bool EnsureContext(); static bool EnsureContext();
static const NzContext* GetCurrent(); static NzContext* GetCurrent();
static const NzContext* GetReference(); static NzContext* GetReference();
static const NzContext* GetThreadContext(); static NzContext* GetThreadContext();
static bool Initialize(); static bool Initialize();
static void Uninitialize(); static void Uninitialize();

View File

@ -44,10 +44,13 @@ enum nzOpenGLExtension
nzOpenGLExtension_Max = nzOpenGLExtension_VertexArrayObjects nzOpenGLExtension_Max = nzOpenGLExtension_VertexArrayObjects
}; };
class NzContext;
using NzOpenGLFunc = void (*)(); using NzOpenGLFunc = void (*)();
class NAZARA_API NzOpenGL class NAZARA_API NzOpenGL
{ {
friend NzContext;
public: public:
enum FormatType enum FormatType
{ {
@ -120,6 +123,10 @@ class NAZARA_API NzOpenGL
static GLenum TextureTarget[nzImageType_Max+1]; static GLenum TextureTarget[nzImageType_Max+1];
static GLenum TextureTargetBinding[nzImageType_Max+1]; static GLenum TextureTargetBinding[nzImageType_Max+1];
static GLenum TextureTargetProxy[nzImageType_Max+1]; static GLenum TextureTargetProxy[nzImageType_Max+1];
private:
static void OnContextDestruction(NzContext* context);
static void OnContextChange(NzContext* newContext);
}; };
NAZARA_API extern PFNGLACTIVETEXTUREPROC glActiveTexture; NAZARA_API extern PFNGLACTIVETEXTUREPROC glActiveTexture;

View File

@ -43,6 +43,6 @@ Wiki : http://wiki.digitalpulsesoftware.com/index.php?title=Nazara
Forum : http://forum.digitalpulsesoftware.com Forum : http://forum.digitalpulsesoftware.com
Thanks to Thanks to
-RafBill: Finding bugs -RafBill/Raakz: Finding bugs and/or testing
-Fissal "DrFisher" Hannoun: Helped a lot in architecture design -Fissal "DrFisher" Hannoun: Helped a lot in architecture design
-Alexandre "Danman" Janniaux: Made the core POSIX port -Alexandre "Danman" Janniaux: Made the core POSIX port

View File

@ -43,6 +43,6 @@ Wiki : http://wiki.digitalpulsesoftware.com/index.php?title=Nazara
Forum : http://forum.digitalpulsesoftware.com Forum : http://forum.digitalpulsesoftware.com
Merci à Merci à
-RafBill: Recherche de bugs -RafBill/Raakz: Recherche de bugs et/ou testeur
-Fissal "DrFisher" Hannoun: Beaucoup d'aide dans la conception de l'architecture du moteur -Fissal "DrFisher" Hannoun: Beaucoup d'aide dans la conception de l'architecture du moteur
-Alexandre "Danman" Janniaux: À fait le port POSIX du noyau -Alexandre "Danman" Janniaux: À fait le port POSIX du noyau

View File

@ -22,8 +22,8 @@
namespace namespace
{ {
thread_local const NzContext* currentContext = nullptr; thread_local NzContext* currentContext = nullptr;
thread_local const NzContext* threadContext = nullptr; thread_local NzContext* threadContext = nullptr;
std::vector<NzContext*> contexts; std::vector<NzContext*> contexts;
@ -153,7 +153,7 @@ bool NzContext::Create(const NzContextParameters& parameters)
return false; return false;
} }
if (!m_impl->Activate()) if (!SetActive(true))
{ {
NazaraError("Failed to activate context"); NazaraError("Failed to activate context");
@ -186,9 +186,13 @@ void NzContext::Destroy()
if (m_impl) if (m_impl)
{ {
NotifyDestroy(); NotifyDestroy();
NzOpenGL::OnContextDestruction(this);
if (currentContext == this) if (currentContext == this)
{
NzContextImpl::Desactivate(); NzContextImpl::Desactivate();
currentContext = nullptr;
}
m_impl->Destroy(); m_impl->Destroy();
delete m_impl; delete m_impl;
@ -219,7 +223,7 @@ bool NzContext::IsActive() const
return currentContext == this; return currentContext == this;
} }
bool NzContext::SetActive(bool active) const bool NzContext::SetActive(bool active)
{ {
#ifdef NAZARA_RENDERER_SAFE #ifdef NAZARA_RENDERER_SAFE
if (!m_impl) if (!m_impl)
@ -248,6 +252,8 @@ bool NzContext::SetActive(bool active) const
currentContext = nullptr; currentContext = nullptr;
} }
NzOpenGL::OnContextChange(currentContext);
return true; return true;
} }
@ -300,17 +306,17 @@ bool NzContext::EnsureContext()
return true; return true;
} }
const NzContext* NzContext::GetCurrent() NzContext* NzContext::GetCurrent()
{ {
return currentContext; return currentContext;
} }
const NzContext* NzContext::GetReference() NzContext* NzContext::GetReference()
{ {
return s_reference; return s_reference;
} }
const NzContext* NzContext::GetThreadContext() NzContext* NzContext::GetThreadContext()
{ {
EnsureContext(); EnsureContext();

View File

@ -10,6 +10,7 @@
#include <set> #include <set>
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
#include <unordered_map>
#include <Nazara/Renderer/Debug.hpp> #include <Nazara/Renderer/Debug.hpp>
namespace namespace
@ -59,17 +60,23 @@ namespace
#endif #endif
} }
struct ContextStates
{
GLuint buffersBinding[nzBufferType_Max+1] = {0};
GLuint currentProgram = 0;
GLuint texturesBinding[32] = {0}; // 32 est pour l'instant la plus haute limite (GL_TEXTURE31)
NzRenderStates renderStates; // Toujours synchronisé avec OpenGL
unsigned int textureUnit = 0;
};
std::set<NzString> s_openGLextensionSet; std::set<NzString> s_openGLextensionSet;
GLuint s_buffersBinding[nzBufferType_Max+1]; std::unordered_map<NzContext*, ContextStates> s_contexts;
GLuint s_currentProgram; ContextStates* s_contextStates = nullptr;
GLuint s_texturesBinding[32]; // 32 est pour l'instant la plus haute limite (GL_TEXTURE31)
NzRenderStates s_states; // Toujours synchronisé avec OpenGL
const char* s_rendererName = nullptr; const char* s_rendererName = nullptr;
const char* s_vendorName = nullptr; const char* s_vendorName = nullptr;
bool s_initialized = false; bool s_initialized = false;
bool s_openGLextensions[nzOpenGLExtension_Max+1] = {false}; bool s_openGLextensions[nzOpenGLExtension_Max+1] = {false};
unsigned int s_openglVersion = 0; unsigned int s_openglVersion = 0;
unsigned int s_textureUnit = 0;
bool LoadExtensionsString(const NzString& extensionString) bool LoadExtensionsString(const NzString& extensionString)
{ {
@ -118,191 +125,270 @@ namespace
void NzOpenGL::ApplyStates(const NzRenderStates& states) void NzOpenGL::ApplyStates(const NzRenderStates& states)
{ {
if (s_states.dstBlend != states.dstBlend || s_states.srcBlend != states.srcBlend) #ifdef NAZARA_DEBUG
if (!s_contextStates)
{
NazaraError("No context activated");
return;
}
#endif
NzRenderStates& currentRenderStates = s_contextStates->renderStates;
if (currentRenderStates.dstBlend != states.dstBlend ||
currentRenderStates.srcBlend != states.srcBlend)
{ {
glBlendFunc(BlendFunc[states.srcBlend], BlendFunc[states.dstBlend]); glBlendFunc(BlendFunc[states.srcBlend], BlendFunc[states.dstBlend]);
s_states.dstBlend = states.dstBlend; currentRenderStates.dstBlend = states.dstBlend;
s_states.srcBlend = states.srcBlend; currentRenderStates.srcBlend = states.srcBlend;
} }
if (s_states.depthFunc != states.depthFunc) if (currentRenderStates.depthFunc != states.depthFunc)
{ {
glDepthFunc(RendererComparison[states.depthFunc]); glDepthFunc(RendererComparison[states.depthFunc]);
s_states.depthFunc = states.depthFunc; currentRenderStates.depthFunc = states.depthFunc;
} }
if (s_states.faceCulling != states.faceCulling) if (currentRenderStates.faceCulling != states.faceCulling)
{ {
glCullFace(FaceCulling[states.faceCulling]); glCullFace(FaceCulling[states.faceCulling]);
s_states.faceCulling = states.faceCulling; currentRenderStates.faceCulling = states.faceCulling;
} }
if (s_states.faceFilling != states.faceFilling) if (currentRenderStates.faceFilling != states.faceFilling)
{ {
glPolygonMode(GL_FRONT_AND_BACK, FaceFilling[states.faceFilling]); glPolygonMode(GL_FRONT_AND_BACK, FaceFilling[states.faceFilling]);
s_states.faceFilling = states.faceFilling; currentRenderStates.faceFilling = states.faceFilling;
} }
if (s_states.stencilCompare != states.stencilCompare || s_states.stencilMask != states.stencilMask || s_states.stencilReference != states.stencilReference) if (currentRenderStates.stencilCompare != states.stencilCompare ||
currentRenderStates.stencilMask != states.stencilMask ||
currentRenderStates.stencilReference != states.stencilReference)
{ {
glStencilFunc(RendererComparison[states.stencilCompare], states.stencilReference, states.stencilMask); glStencilFunc(RendererComparison[states.stencilCompare], states.stencilReference, states.stencilMask);
s_states.stencilCompare = states.stencilCompare; currentRenderStates.stencilCompare = states.stencilCompare;
s_states.stencilMask = states.stencilMask; currentRenderStates.stencilMask = states.stencilMask;
s_states.stencilReference = states.stencilReference; currentRenderStates.stencilReference = states.stencilReference;
} }
if (s_states.stencilFail != states.stencilFail || s_states.stencilPass != states.stencilPass || s_states.stencilZFail != states.stencilZFail) if (currentRenderStates.stencilFail != states.stencilFail ||
currentRenderStates.stencilPass != states.stencilPass ||
currentRenderStates.stencilZFail != states.stencilZFail)
{ {
glStencilOp(StencilOperation[states.stencilFail], StencilOperation[states.stencilZFail], StencilOperation[states.stencilPass]); glStencilOp(StencilOperation[states.stencilFail], StencilOperation[states.stencilZFail], StencilOperation[states.stencilPass]);
s_states.stencilFail = states.stencilFail; currentRenderStates.stencilFail = states.stencilFail;
s_states.stencilPass = states.stencilPass; currentRenderStates.stencilPass = states.stencilPass;
s_states.stencilZFail = states.stencilZFail; currentRenderStates.stencilZFail = states.stencilZFail;
} }
if (!NzNumberEquals(s_states.lineWidth, states.lineWidth, 0.001f)) if (!NzNumberEquals(currentRenderStates.lineWidth, states.lineWidth, 0.001f))
{ {
glLineWidth(states.lineWidth); glLineWidth(states.lineWidth);
s_states.lineWidth = states.lineWidth; currentRenderStates.lineWidth = states.lineWidth;
} }
if (!NzNumberEquals(s_states.pointSize, states.pointSize, 0.001f)) if (!NzNumberEquals(currentRenderStates.pointSize, states.pointSize, 0.001f))
{ {
glPointSize(states.pointSize); glPointSize(states.pointSize);
s_states.pointSize = states.pointSize; currentRenderStates.pointSize = states.pointSize;
} }
// Paramètres de rendu // Paramètres de rendu
if (s_states.parameters[nzRendererParameter_Blend] != states.parameters[nzRendererParameter_Blend]) if (currentRenderStates.parameters[nzRendererParameter_Blend] != states.parameters[nzRendererParameter_Blend])
{ {
if (states.parameters[nzRendererParameter_Blend]) if (states.parameters[nzRendererParameter_Blend])
glEnable(GL_BLEND); glEnable(GL_BLEND);
else else
glDisable(GL_BLEND); glDisable(GL_BLEND);
s_states.parameters[nzRendererParameter_Blend] = states.parameters[nzRendererParameter_Blend]; currentRenderStates.parameters[nzRendererParameter_Blend] = states.parameters[nzRendererParameter_Blend];
} }
if (s_states.parameters[nzRendererParameter_ColorWrite] != states.parameters[nzRendererParameter_ColorWrite]) if (currentRenderStates.parameters[nzRendererParameter_ColorWrite] != states.parameters[nzRendererParameter_ColorWrite])
{ {
GLboolean param = (states.parameters[nzRendererParameter_ColorWrite]) ? GL_TRUE : GL_FALSE; GLboolean param = (states.parameters[nzRendererParameter_ColorWrite]) ? GL_TRUE : GL_FALSE;
glColorMask(param, param, param, param); glColorMask(param, param, param, param);
s_states.parameters[nzRendererParameter_ColorWrite] = states.parameters[nzRendererParameter_ColorWrite]; currentRenderStates.parameters[nzRendererParameter_ColorWrite] = states.parameters[nzRendererParameter_ColorWrite];
} }
if (s_states.parameters[nzRendererParameter_DepthBuffer] != states.parameters[nzRendererParameter_DepthBuffer]) if (currentRenderStates.parameters[nzRendererParameter_DepthBuffer] != states.parameters[nzRendererParameter_DepthBuffer])
{ {
if (states.parameters[nzRendererParameter_DepthBuffer]) if (states.parameters[nzRendererParameter_DepthBuffer])
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
else else
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
s_states.parameters[nzRendererParameter_DepthBuffer] = states.parameters[nzRendererParameter_DepthBuffer]; currentRenderStates.parameters[nzRendererParameter_DepthBuffer] = states.parameters[nzRendererParameter_DepthBuffer];
} }
if (s_states.parameters[nzRendererParameter_DepthWrite] != states.parameters[nzRendererParameter_DepthWrite]) if (currentRenderStates.parameters[nzRendererParameter_DepthWrite] != states.parameters[nzRendererParameter_DepthWrite])
{ {
glDepthMask((states.parameters[nzRendererParameter_DepthWrite]) ? GL_TRUE : GL_FALSE); glDepthMask((states.parameters[nzRendererParameter_DepthWrite]) ? GL_TRUE : GL_FALSE);
s_states.parameters[nzRendererParameter_DepthWrite] = states.parameters[nzRendererParameter_DepthWrite]; currentRenderStates.parameters[nzRendererParameter_DepthWrite] = states.parameters[nzRendererParameter_DepthWrite];
} }
if (s_states.parameters[nzRendererParameter_FaceCulling] != states.parameters[nzRendererParameter_FaceCulling]) if (currentRenderStates.parameters[nzRendererParameter_FaceCulling] != states.parameters[nzRendererParameter_FaceCulling])
{ {
if (states.parameters[nzRendererParameter_FaceCulling]) if (states.parameters[nzRendererParameter_FaceCulling])
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
else else
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
s_states.parameters[nzRendererParameter_FaceCulling] = states.parameters[nzRendererParameter_FaceCulling]; currentRenderStates.parameters[nzRendererParameter_FaceCulling] = states.parameters[nzRendererParameter_FaceCulling];
} }
if (s_states.parameters[nzRendererParameter_ScissorTest] != states.parameters[nzRendererParameter_ScissorTest]) if (currentRenderStates.parameters[nzRendererParameter_ScissorTest] != states.parameters[nzRendererParameter_ScissorTest])
{ {
if (states.parameters[nzRendererParameter_ScissorTest]) if (states.parameters[nzRendererParameter_ScissorTest])
glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST);
else else
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);
s_states.parameters[nzRendererParameter_ScissorTest] = states.parameters[nzRendererParameter_ScissorTest]; currentRenderStates.parameters[nzRendererParameter_ScissorTest] = states.parameters[nzRendererParameter_ScissorTest];
} }
if (s_states.parameters[nzRendererParameter_StencilTest] != states.parameters[nzRendererParameter_StencilTest]) if (currentRenderStates.parameters[nzRendererParameter_StencilTest] != states.parameters[nzRendererParameter_StencilTest])
{ {
if (states.parameters[nzRendererParameter_StencilTest]) if (states.parameters[nzRendererParameter_StencilTest])
glEnable(GL_STENCIL_TEST); glEnable(GL_STENCIL_TEST);
else else
glDisable(GL_STENCIL_TEST); glDisable(GL_STENCIL_TEST);
s_states.parameters[nzRendererParameter_StencilTest] = states.parameters[nzRendererParameter_StencilTest]; currentRenderStates.parameters[nzRendererParameter_StencilTest] = states.parameters[nzRendererParameter_StencilTest];
} }
} }
void NzOpenGL::BindBuffer(nzBufferType type, GLuint id) void NzOpenGL::BindBuffer(nzBufferType type, GLuint id)
{ {
if (s_buffersBinding[type] != id) #ifdef NAZARA_DEBUG
if (!s_contextStates)
{
NazaraError("No context activated");
return;
}
#endif
if (s_contextStates->buffersBinding[type] != id)
{ {
glBindBuffer(BufferTarget[type], id); glBindBuffer(BufferTarget[type], id);
s_buffersBinding[type] = id; s_contextStates->buffersBinding[type] = id;
} }
} }
void NzOpenGL::BindProgram(GLuint id) void NzOpenGL::BindProgram(GLuint id)
{ {
if (s_currentProgram != id) #ifdef NAZARA_DEBUG
if (!s_contextStates)
{
NazaraError("No context activated");
return;
}
#endif
if (s_contextStates->currentProgram != id)
{ {
glUseProgram(id); glUseProgram(id);
s_currentProgram = id; s_contextStates->currentProgram = id;
} }
} }
void NzOpenGL::BindTexture(nzImageType type, GLuint id) void NzOpenGL::BindTexture(nzImageType type, GLuint id)
{ {
if (s_texturesBinding[s_textureUnit] != id) #ifdef NAZARA_DEBUG
if (!s_contextStates)
{
NazaraError("No context activated");
return;
}
#endif
if (s_contextStates->texturesBinding[s_contextStates->textureUnit] != id)
{ {
glBindTexture(TextureTarget[type], id); glBindTexture(TextureTarget[type], id);
s_texturesBinding[s_textureUnit] = id; s_contextStates->texturesBinding[s_contextStates->textureUnit] = id;
} }
} }
void NzOpenGL::BindTexture(unsigned int textureUnit, nzImageType type, GLuint id) void NzOpenGL::BindTexture(unsigned int textureUnit, nzImageType type, GLuint id)
{ {
if (s_texturesBinding[textureUnit] != id) #ifdef NAZARA_DEBUG
if (!s_contextStates)
{
NazaraError("No context activated");
return;
}
#endif
if (s_contextStates->texturesBinding[textureUnit] != id)
{ {
SetTextureUnit(textureUnit); SetTextureUnit(textureUnit);
glBindTexture(TextureTarget[type], id); glBindTexture(TextureTarget[type], id);
s_texturesBinding[textureUnit] = id; s_contextStates->texturesBinding[textureUnit] = id;
} }
} }
void NzOpenGL::BindVertexArray(GLuint id) void NzOpenGL::BindVertexArray(GLuint id)
{ {
#ifdef NAZARA_DEBUG
if (!s_contextStates)
{
NazaraError("No context activated");
return;
}
#endif
// Je ne pense pas que ça soit une bonne idée de le mettre en cache, c'est un objet "spécial" // Je ne pense pas que ça soit une bonne idée de le mettre en cache, c'est un objet "spécial"
glBindVertexArray(id); glBindVertexArray(id);
// On invalide les bindings des buffers (Overridés par le VertexArray) // On invalide les bindings des buffers (Overridés par le VertexArray)
std::memset(s_buffersBinding, 0, (nzBufferType_Max+1)*sizeof(GLuint)); std::memset(s_contextStates->buffersBinding, 0, (nzBufferType_Max+1)*sizeof(GLuint));
} }
void NzOpenGL::DeleteBuffer(nzBufferType type, GLuint id) void NzOpenGL::DeleteBuffer(nzBufferType type, GLuint id)
{ {
#ifdef NAZARA_DEBUG
if (!s_contextStates)
{
NazaraError("No context activated");
return;
}
#endif
glDeleteBuffers(1, &id); glDeleteBuffers(1, &id);
if (s_buffersBinding[type] == id) if (s_contextStates->buffersBinding[type] == id)
s_buffersBinding[type] = 0; s_contextStates->buffersBinding[type] = 0;
} }
void NzOpenGL::DeleteProgram(GLuint id) void NzOpenGL::DeleteProgram(GLuint id)
{ {
#ifdef NAZARA_DEBUG
if (!s_contextStates)
{
NazaraError("No context activated");
return;
}
#endif
glDeleteProgram(id); glDeleteProgram(id);
if (s_currentProgram == id) if (s_contextStates->currentProgram == id)
s_currentProgram = 0; s_contextStates->currentProgram = 0;
} }
void NzOpenGL::DeleteTexture(GLuint id) void NzOpenGL::DeleteTexture(GLuint id)
{ {
#ifdef NAZARA_DEBUG
if (!s_contextStates)
{
NazaraError("No context activated");
return;
}
#endif
glDeleteTextures(1, &id); glDeleteTextures(1, &id);
for (GLuint& binding : s_texturesBinding) for (GLuint& binding : s_contextStates->texturesBinding)
{ {
if (binding == id) if (binding == id)
binding = 0; binding = 0;
@ -311,12 +397,28 @@ void NzOpenGL::DeleteTexture(GLuint id)
GLuint NzOpenGL::GetCurrentBuffer(nzBufferType type) GLuint NzOpenGL::GetCurrentBuffer(nzBufferType type)
{ {
return s_buffersBinding[type]; #ifdef NAZARA_DEBUG
if (!s_contextStates)
{
NazaraError("No context activated");
return 0;
}
#endif
return s_contextStates->buffersBinding[type];
} }
GLuint NzOpenGL::GetCurrentProgram() GLuint NzOpenGL::GetCurrentProgram()
{ {
return s_currentProgram; #ifdef NAZARA_DEBUG
if (!s_contextStates)
{
NazaraError("No context activated");
return 0;
}
#endif
return s_contextStates->currentProgram;
} }
NzOpenGLFunc NzOpenGL::GetEntry(const NzString& entryPoint) NzOpenGLFunc NzOpenGL::GetEntry(const NzString& entryPoint)
@ -331,7 +433,15 @@ NzString NzOpenGL::GetRendererName()
unsigned int NzOpenGL::GetTextureUnit() unsigned int NzOpenGL::GetTextureUnit()
{ {
return s_textureUnit; #ifdef NAZARA_DEBUG
if (!s_contextStates)
{
NazaraError("No context activated");
return 0;
}
#endif
return s_contextStates->textureUnit;
} }
NzString NzOpenGL::GetVendorName() NzString NzOpenGL::GetVendorName()
@ -844,12 +954,8 @@ bool NzOpenGL::Initialize()
return false; return false;
} }
std::memset(s_buffersBinding, 0, (nzBufferType_Max+1)*sizeof(GLuint));
std::memset(s_texturesBinding, 0, 32*sizeof(GLuint));
s_currentProgram = 0;
s_rendererName = reinterpret_cast<const char*>(glGetString(GL_RENDERER)); s_rendererName = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
s_textureUnit = 0; s_contextStates = nullptr;
s_vendorName = reinterpret_cast<const char*>(glGetString(GL_VENDOR)); s_vendorName = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
return true; return true;
@ -872,10 +978,10 @@ bool NzOpenGL::IsSupported(const NzString& string)
void NzOpenGL::SetTextureUnit(unsigned int textureUnit) void NzOpenGL::SetTextureUnit(unsigned int textureUnit)
{ {
if (s_textureUnit != textureUnit) if (s_contextStates->textureUnit != textureUnit)
{ {
glActiveTexture(GL_TEXTURE0 + textureUnit); glActiveTexture(GL_TEXTURE0 + textureUnit);
s_textureUnit = textureUnit; s_contextStates->textureUnit = textureUnit;
} }
} }
@ -1036,6 +1142,16 @@ void NzOpenGL::Uninitialize()
} }
} }
void NzOpenGL::OnContextDestruction(NzContext* context)
{
s_contexts.erase(context);
}
void NzOpenGL::OnContextChange(NzContext* newContext)
{
s_contextStates = (newContext) ? &s_contexts[newContext] : nullptr;
}
GLenum NzOpenGL::Attachment[nzAttachmentPoint_Max+1] = GLenum NzOpenGL::Attachment[nzAttachmentPoint_Max+1] =
{ {
GL_COLOR_ATTACHMENT0, // nzAttachmentPoint_Color GL_COLOR_ATTACHMENT0, // nzAttachmentPoint_Color

View File

@ -59,7 +59,7 @@ bool NzRenderWindow::CopyToImage(NzImage* image) const
} }
#endif #endif
const NzContext* currentContext = NzContext::GetCurrent(); NzContext* currentContext = NzContext::GetCurrent();
if (m_context != currentContext) if (m_context != currentContext)
{ {
if (!m_context->SetActive(true)) if (!m_context->SetActive(true))
@ -112,7 +112,7 @@ bool NzRenderWindow::CopyToTexture(NzTexture* texture) const
} }
#endif #endif
const NzContext* currentContext = NzContext::GetCurrent(); NzContext* currentContext = NzContext::GetCurrent();
if (m_context != currentContext) if (m_context != currentContext)
{ {
if (!m_context->SetActive(true)) if (!m_context->SetActive(true))