Fixup: all-state resets

This commit is contained in:
tfarley 2016-04-29 14:34:51 -04:00
parent 6c42c2cd72
commit e2c74e8ea5
2 changed files with 100 additions and 38 deletions

View File

@ -2,15 +2,18 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <set>
#include <glad/glad.h> #include <glad/glad.h>
#include "common/assert.h"
#include "common/common_funcs.h" #include "common/common_funcs.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "video_core/renderer_opengl/gl_state.h" #include "video_core/renderer_opengl/gl_state.h"
static OpenGLState default_state; std::set<OpenGLState*> states;
OpenGLState* OpenGLState::cur_state = &default_state; OpenGLState default_state;
OpenGLState* cur_state = &default_state;
OpenGLState::OpenGLState() { OpenGLState::OpenGLState() {
// These all match default OpenGL values // These all match default OpenGL values
@ -62,6 +65,12 @@ OpenGLState::OpenGLState() {
draw.vertex_buffer = 0; draw.vertex_buffer = 0;
draw.uniform_buffer = 0; draw.uniform_buffer = 0;
draw.shader_program = 0; draw.shader_program = 0;
states.insert(this);
}
OpenGLState::~OpenGLState() {
states.erase(this);
} }
OpenGLState* OpenGLState::GetCurrentState() { OpenGLState* OpenGLState::GetCurrentState() {
@ -94,12 +103,16 @@ void OpenGLState::MakeCurrent() {
SetLogicOp(logic_op); SetLogicOp(logic_op);
GLenum prev_active_texture_unit = active_texture_unit;
for (unsigned i = 0; i < ARRAY_SIZE(texture_units); ++i) { for (unsigned i = 0; i < ARRAY_SIZE(texture_units); ++i) {
SetActiveTextureUnit(GL_TEXTURE0 + i); glActiveTexture(GL_TEXTURE0 + i);
active_texture_unit = GL_TEXTURE0 + i;
SetTexture1D(texture_units[i].texture_1d); SetTexture1D(texture_units[i].texture_1d);
SetTexture2D(texture_units[i].texture_2d); SetTexture2D(texture_units[i].texture_2d);
SetSampler(texture_units[i].sampler); SetSampler(texture_units[i].sampler);
} }
active_texture_unit = prev_active_texture_unit;
glActiveTexture(cur_state->active_texture_unit);
SetActiveTextureUnit(active_texture_unit); SetActiveTextureUnit(active_texture_unit);
@ -347,61 +360,111 @@ void OpenGLState::SetShaderProgram(GLuint n_shader_program) {
} }
void OpenGLState::ResetTexture(GLuint handle) { void OpenGLState::ResetTexture(GLuint handle) {
for (unsigned i = 0; i < ARRAY_SIZE(texture_units); ++i) { for (OpenGLState* state : states) {
if (cur_state->texture_units[i].texture_1d == handle) { for (unsigned i = 0; i < ARRAY_SIZE(texture_units); ++i) {
GLenum prev_active_texture_unit = cur_state->active_texture_unit; if (state->texture_units[i].texture_1d == handle) {
cur_state->SetActiveTextureUnit(GL_TEXTURE0 + i); if (state == cur_state) {
cur_state->SetTexture1D(0); GLenum prev_active_texture_unit = state->active_texture_unit;
cur_state->SetActiveTextureUnit(prev_active_texture_unit); state->SetActiveTextureUnit(GL_TEXTURE0 + i);
} state->SetTexture1D(0);
state->SetActiveTextureUnit(prev_active_texture_unit);
} else {
state->texture_units[i].texture_1d = 0;
}
}
if (cur_state->texture_units[i].texture_2d == handle) { if (state->texture_units[i].texture_2d == handle) {
GLenum prev_active_texture_unit = cur_state->active_texture_unit; if (state == cur_state) {
cur_state->SetActiveTextureUnit(GL_TEXTURE0 + i); GLenum prev_active_texture_unit = state->active_texture_unit;
cur_state->SetTexture2D(0); state->SetActiveTextureUnit(GL_TEXTURE0 + i);
cur_state->SetActiveTextureUnit(prev_active_texture_unit); state->SetTexture2D(0);
state->SetActiveTextureUnit(prev_active_texture_unit);
} else {
state->texture_units[i].texture_2d = 0;
}
}
} }
} }
} }
void OpenGLState::ResetSampler(GLuint handle) { void OpenGLState::ResetSampler(GLuint handle) {
for (unsigned i = 0; i < ARRAY_SIZE(texture_units); ++i) { for (OpenGLState* state : states) {
if (cur_state->texture_units[i].sampler == handle) { for (unsigned i = 0; i < ARRAY_SIZE(texture_units); ++i) {
GLenum prev_active_texture_unit = cur_state->active_texture_unit; if (state->texture_units[i].sampler == handle) {
cur_state->SetActiveTextureUnit(GL_TEXTURE0 + i); if (state == cur_state) {
cur_state->SetSampler(0); GLenum prev_active_texture_unit = state->active_texture_unit;
cur_state->SetActiveTextureUnit(prev_active_texture_unit); state->SetActiveTextureUnit(GL_TEXTURE0 + i);
state->SetSampler(0);
state->SetActiveTextureUnit(prev_active_texture_unit);
} else {
state->texture_units[i].sampler = 0;
}
}
} }
} }
} }
void OpenGLState::ResetProgram(GLuint handle) { void OpenGLState::ResetProgram(GLuint handle) {
if (cur_state->draw.shader_program == handle) { for (OpenGLState* state : states) {
cur_state->SetShaderProgram(0); if (state->draw.shader_program == handle) {
if (state == cur_state) {
state->SetShaderProgram(0);
} else {
state->draw.shader_program = 0;
}
}
} }
} }
void OpenGLState::ResetBuffer(GLuint handle) { void OpenGLState::ResetBuffer(GLuint handle) {
if (cur_state->draw.vertex_buffer == handle) { for (OpenGLState* state : states) {
cur_state->SetVertexBuffer(0); if (state->draw.vertex_buffer == handle) {
} if (state == cur_state) {
if (cur_state->draw.uniform_buffer == handle) { state->SetVertexBuffer(0);
cur_state->SetUniformBuffer(0); } else {
state->draw.vertex_buffer = 0;
}
}
if (state->draw.uniform_buffer == handle) {
if (state == cur_state) {
state->SetUniformBuffer(0);
} else {
state->draw.uniform_buffer = 0;
}
}
} }
} }
void OpenGLState::ResetVertexArray(GLuint handle) { void OpenGLState::ResetVertexArray(GLuint handle) {
if (cur_state->draw.vertex_array == handle) { for (OpenGLState* state : states) {
cur_state->SetVertexArray(0); if (state->draw.vertex_array == handle) {
if (state == cur_state) {
state->SetVertexArray(0);
} else {
state->draw.vertex_array = 0;
}
}
} }
} }
void OpenGLState::ResetFramebuffer(GLuint handle) { void OpenGLState::ResetFramebuffer(GLuint handle) {
if (cur_state->draw.read_framebuffer == handle) { for (OpenGLState* state : states) {
cur_state->SetReadFramebuffer(0); if (state->draw.read_framebuffer == handle) {
} if (state == cur_state) {
if (cur_state->draw.draw_framebuffer == handle) { state->SetReadFramebuffer(0);
cur_state->SetDrawFramebuffer(0); } else {
state->draw.read_framebuffer = 0;
}
}
if (state->draw.draw_framebuffer == handle) {
if (state == cur_state) {
state->SetDrawFramebuffer(0);
} else {
state->draw.draw_framebuffer = 0;
}
}
} }
} }

View File

@ -9,6 +9,7 @@
class OpenGLState { class OpenGLState {
public: public:
OpenGLState(); OpenGLState();
~OpenGLState();
/// Get a pointer to the currently bound state tracker object /// Get a pointer to the currently bound state tracker object
static OpenGLState* GetCurrentState(); static OpenGLState* GetCurrentState();
@ -51,7 +52,7 @@ public:
void SetUniformBuffer(GLuint n_uniform_buffer); void SetUniformBuffer(GLuint n_uniform_buffer);
void SetShaderProgram(GLuint n_shader_program); void SetShaderProgram(GLuint n_shader_program);
/// Resets and unbinds any references to the given resource in the current OpenGL state /// Resets and unbinds any references to the given resource across all existing states
static void ResetTexture(GLuint handle); static void ResetTexture(GLuint handle);
static void ResetSampler(GLuint handle); static void ResetSampler(GLuint handle);
static void ResetProgram(GLuint handle); static void ResetProgram(GLuint handle);
@ -127,6 +128,4 @@ private:
GLuint uniform_buffer; // GL_UNIFORM_BUFFER_BINDING GLuint uniform_buffer; // GL_UNIFORM_BUFFER_BINDING
GLuint shader_program; // GL_CURRENT_PROGRAM GLuint shader_program; // GL_CURRENT_PROGRAM
} draw; } draw;
static OpenGLState* cur_state;
}; };