summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp4
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp246
-rw-r--r--src/video_core/renderer_opengl/gl_state.h13
3 files changed, 158 insertions, 105 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index bf381271e..8976c77c6 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -104,7 +104,7 @@ RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window, ScreenInfo
}
ASSERT_MSG(has_ARB_separate_shader_objects, "has_ARB_separate_shader_objects is unsupported");
-
+ OpenGLState::ApplyDefaultState();
// Clipping plane 0 is always enabled for PICA fixed clip plane z <= 0
state.clip_distance[0] = true;
@@ -115,8 +115,6 @@ RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window, ScreenInfo
state.draw.shader_program = 0;
state.Apply();
- glEnable(GL_BLEND);
-
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &uniform_buffer_alignment);
LOG_CRITICAL(Render_OpenGL, "Sync fixed function OpenGL state here!");
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index d8a43cc94..b6b426f34 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -89,7 +89,18 @@ OpenGLState::OpenGLState() {
point.size = 1;
}
-void OpenGLState::Apply() const {
+void OpenGLState::ApplyDefaultState() {
+ glDisable(GL_FRAMEBUFFER_SRGB);
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_PRIMITIVE_RESTART);
+ glDisable(GL_STENCIL_TEST);
+ glEnable(GL_BLEND);
+ glDisable(GL_COLOR_LOGIC_OP);
+ glDisable(GL_SCISSOR_TEST);
+}
+
+void OpenGLState::ApplySRgb() const {
// sRGB
if (framebuffer_srgb.enabled != cur_state.framebuffer_srgb.enabled) {
if (framebuffer_srgb.enabled) {
@@ -100,96 +111,122 @@ void OpenGLState::Apply() const {
glDisable(GL_FRAMEBUFFER_SRGB);
}
}
+}
+
+void OpenGLState::ApplyCulling() const {
// Culling
- if (cull.enabled != cur_state.cull.enabled) {
+ const bool cull_changed = cull.enabled != cur_state.cull.enabled;
+ if (cull_changed) {
if (cull.enabled) {
glEnable(GL_CULL_FACE);
} else {
glDisable(GL_CULL_FACE);
}
}
+ if (cull.enabled) {
+ if (cull_changed || cull.mode != cur_state.cull.mode) {
+ glCullFace(cull.mode);
+ }
- if (cull.mode != cur_state.cull.mode) {
- glCullFace(cull.mode);
- }
-
- if (cull.front_face != cur_state.cull.front_face) {
- glFrontFace(cull.front_face);
+ if (cull_changed || cull.front_face != cur_state.cull.front_face) {
+ glFrontFace(cull.front_face);
+ }
}
+}
+void OpenGLState::ApplyDepth() const {
// Depth test
- if (depth.test_enabled != cur_state.depth.test_enabled) {
+ const bool depth_test_changed = depth.test_enabled != cur_state.depth.test_enabled;
+ if (depth_test_changed) {
if (depth.test_enabled) {
glEnable(GL_DEPTH_TEST);
} else {
glDisable(GL_DEPTH_TEST);
}
}
-
- if (depth.test_func != cur_state.depth.test_func) {
+ if (depth.test_enabled &&
+ (depth_test_changed || depth.test_func != cur_state.depth.test_func)) {
glDepthFunc(depth.test_func);
}
-
// Depth mask
if (depth.write_mask != cur_state.depth.write_mask) {
glDepthMask(depth.write_mask);
}
-
// Depth range
if (depth.depth_range_near != cur_state.depth.depth_range_near ||
depth.depth_range_far != cur_state.depth.depth_range_far) {
glDepthRange(depth.depth_range_near, depth.depth_range_far);
}
+}
- // Primitive restart
- if (primitive_restart.enabled != cur_state.primitive_restart.enabled) {
+void OpenGLState::ApplyPrimitiveRestart() const {
+ const bool primitive_restart_changed =
+ primitive_restart.enabled != cur_state.primitive_restart.enabled;
+ if (primitive_restart_changed) {
if (primitive_restart.enabled) {
glEnable(GL_PRIMITIVE_RESTART);
} else {
glDisable(GL_PRIMITIVE_RESTART);
}
}
- if (primitive_restart.index != cur_state.primitive_restart.index) {
+ if (primitive_restart_changed ||
+ (primitive_restart.enabled &&
+ primitive_restart.index != cur_state.primitive_restart.index)) {
glPrimitiveRestartIndex(primitive_restart.index);
}
+}
- // Color mask
- if (color_mask.red_enabled != cur_state.color_mask.red_enabled ||
- color_mask.green_enabled != cur_state.color_mask.green_enabled ||
- color_mask.blue_enabled != cur_state.color_mask.blue_enabled ||
- color_mask.alpha_enabled != cur_state.color_mask.alpha_enabled) {
- glColorMask(color_mask.red_enabled, color_mask.green_enabled, color_mask.blue_enabled,
- color_mask.alpha_enabled);
- }
-
- // Stencil test
- if (stencil.test_enabled != cur_state.stencil.test_enabled) {
+void OpenGLState::ApplyStencilTest() const {
+ const bool stencil_test_changed = stencil.test_enabled != cur_state.stencil.test_enabled;
+ if (stencil_test_changed) {
if (stencil.test_enabled) {
glEnable(GL_STENCIL_TEST);
} else {
glDisable(GL_STENCIL_TEST);
}
}
- auto config_stencil = [](GLenum face, const auto& config, const auto& prev_config) {
- if (config.test_func != prev_config.test_func || config.test_ref != prev_config.test_ref ||
- config.test_mask != prev_config.test_mask) {
- glStencilFuncSeparate(face, config.test_func, config.test_ref, config.test_mask);
- }
- if (config.action_depth_fail != prev_config.action_depth_fail ||
- config.action_depth_pass != prev_config.action_depth_pass ||
- config.action_stencil_fail != prev_config.action_stencil_fail) {
- glStencilOpSeparate(face, config.action_stencil_fail, config.action_depth_fail,
- config.action_depth_pass);
- }
- if (config.write_mask != prev_config.write_mask) {
- glStencilMaskSeparate(face, config.write_mask);
+ if (stencil.test_enabled) {
+ auto config_stencil = [stencil_test_changed](GLenum face, const auto& config,
+ const auto& prev_config) {
+ if (stencil_test_changed || config.test_func != prev_config.test_func ||
+ config.test_ref != prev_config.test_ref ||
+ config.test_mask != prev_config.test_mask) {
+ glStencilFuncSeparate(face, config.test_func, config.test_ref, config.test_mask);
+ }
+ if (stencil_test_changed || config.action_depth_fail != prev_config.action_depth_fail ||
+ config.action_depth_pass != prev_config.action_depth_pass ||
+ config.action_stencil_fail != prev_config.action_stencil_fail) {
+ glStencilOpSeparate(face, config.action_stencil_fail, config.action_depth_fail,
+ config.action_depth_pass);
+ }
+ if (config.write_mask != prev_config.write_mask) {
+ glStencilMaskSeparate(face, config.write_mask);
+ }
+ };
+ config_stencil(GL_FRONT, stencil.front, cur_state.stencil.front);
+ config_stencil(GL_BACK, stencil.back, cur_state.stencil.back);
+ }
+}
+
+void OpenGLState::ApplyScissorTest() const {
+ const bool scissor_changed = scissor.enabled != cur_state.scissor.enabled;
+ if (scissor_changed) {
+ if (scissor.enabled) {
+ glEnable(GL_SCISSOR_TEST);
+ } else {
+ glDisable(GL_SCISSOR_TEST);
}
- };
- config_stencil(GL_FRONT, stencil.front, cur_state.stencil.front);
- config_stencil(GL_BACK, stencil.back, cur_state.stencil.back);
+ }
+ if (scissor_changed || scissor_changed || scissor.x != cur_state.scissor.x ||
+ scissor.y != cur_state.scissor.y || scissor.width != cur_state.scissor.width ||
+ scissor.height != cur_state.scissor.height) {
+ glScissor(scissor.x, scissor.y, scissor.width, scissor.height);
+ }
+}
- // Blending
- if (blend.enabled != cur_state.blend.enabled) {
+void OpenGLState::ApplyBlending() const {
+ const bool blend_changed = blend.enabled != cur_state.blend.enabled;
+ if (blend_changed) {
if (blend.enabled) {
ASSERT(!logic_op.enabled);
glEnable(GL_BLEND);
@@ -197,29 +234,32 @@ void OpenGLState::Apply() const {
glDisable(GL_BLEND);
}
}
+ if (blend.enabled) {
+ if (blend_changed || blend.color.red != cur_state.blend.color.red ||
+ blend.color.green != cur_state.blend.color.green ||
+ blend.color.blue != cur_state.blend.color.blue ||
+ blend.color.alpha != cur_state.blend.color.alpha) {
+ glBlendColor(blend.color.red, blend.color.green, blend.color.blue, blend.color.alpha);
+ }
- if (blend.color.red != cur_state.blend.color.red ||
- blend.color.green != cur_state.blend.color.green ||
- blend.color.blue != cur_state.blend.color.blue ||
- blend.color.alpha != cur_state.blend.color.alpha) {
- glBlendColor(blend.color.red, blend.color.green, blend.color.blue, blend.color.alpha);
- }
-
- if (blend.src_rgb_func != cur_state.blend.src_rgb_func ||
- blend.dst_rgb_func != cur_state.blend.dst_rgb_func ||
- blend.src_a_func != cur_state.blend.src_a_func ||
- blend.dst_a_func != cur_state.blend.dst_a_func) {
- glBlendFuncSeparate(blend.src_rgb_func, blend.dst_rgb_func, blend.src_a_func,
- blend.dst_a_func);
- }
+ if (blend_changed || blend.src_rgb_func != cur_state.blend.src_rgb_func ||
+ blend.dst_rgb_func != cur_state.blend.dst_rgb_func ||
+ blend.src_a_func != cur_state.blend.src_a_func ||
+ blend.dst_a_func != cur_state.blend.dst_a_func) {
+ glBlendFuncSeparate(blend.src_rgb_func, blend.dst_rgb_func, blend.src_a_func,
+ blend.dst_a_func);
+ }
- if (blend.rgb_equation != cur_state.blend.rgb_equation ||
- blend.a_equation != cur_state.blend.a_equation) {
- glBlendEquationSeparate(blend.rgb_equation, blend.a_equation);
+ if (blend_changed || blend.rgb_equation != cur_state.blend.rgb_equation ||
+ blend.a_equation != cur_state.blend.a_equation) {
+ glBlendEquationSeparate(blend.rgb_equation, blend.a_equation);
+ }
}
+}
- // Logic Operation
- if (logic_op.enabled != cur_state.logic_op.enabled) {
+void OpenGLState::ApplyLogicOp() const {
+ const bool logic_op_changed = logic_op.enabled != cur_state.logic_op.enabled;
+ if (logic_op_changed) {
if (logic_op.enabled) {
ASSERT(!blend.enabled);
glEnable(GL_COLOR_LOGIC_OP);
@@ -228,11 +268,13 @@ void OpenGLState::Apply() const {
}
}
- if (logic_op.operation != cur_state.logic_op.operation) {
+ if (logic_op.enabled &&
+ (logic_op_changed || logic_op.operation != cur_state.logic_op.operation)) {
glLogicOp(logic_op.operation);
}
+}
- // Textures
+void OpenGLState::ApplyTextures() const {
for (std::size_t i = 0; i < std::size(texture_units); ++i) {
const auto& texture_unit = texture_units[i];
const auto& cur_state_texture_unit = cur_state.texture_units[i];
@@ -251,28 +293,29 @@ void OpenGLState::Apply() const {
glTexParameteriv(texture_unit.target, GL_TEXTURE_SWIZZLE_RGBA, mask.data());
}
}
+}
- // Samplers
- {
- bool has_delta{};
- std::size_t first{}, last{};
- std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> samplers;
- for (std::size_t i = 0; i < std::size(samplers); ++i) {
- samplers[i] = texture_units[i].sampler;
- if (samplers[i] != cur_state.texture_units[i].sampler) {
- if (!has_delta) {
- first = i;
- has_delta = true;
- }
- last = i;
+void OpenGLState::ApplySamplers() const {
+ bool has_delta{};
+ std::size_t first{}, last{};
+ std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> samplers;
+ for (std::size_t i = 0; i < std::size(samplers); ++i) {
+ samplers[i] = texture_units[i].sampler;
+ if (samplers[i] != cur_state.texture_units[i].sampler) {
+ if (!has_delta) {
+ first = i;
+ has_delta = true;
}
- }
- if (has_delta) {
- glBindSamplers(static_cast<GLuint>(first), static_cast<GLsizei>(last - first + 1),
- samplers.data());
+ last = i;
}
}
+ if (has_delta) {
+ glBindSamplers(static_cast<GLuint>(first), static_cast<GLsizei>(last - first + 1),
+ samplers.data());
+ }
+}
+void OpenGLState::Apply() const {
// Framebuffer
if (draw.read_framebuffer != cur_state.draw.read_framebuffer) {
glBindFramebuffer(GL_READ_FRAMEBUFFER, draw.read_framebuffer);
@@ -305,27 +348,12 @@ void OpenGLState::Apply() const {
if (draw.program_pipeline != cur_state.draw.program_pipeline) {
glBindProgramPipeline(draw.program_pipeline);
}
-
- // Scissor test
- if (scissor.enabled != cur_state.scissor.enabled) {
- if (scissor.enabled) {
- glEnable(GL_SCISSOR_TEST);
- } else {
- glDisable(GL_SCISSOR_TEST);
- }
- }
-
- if (scissor.x != cur_state.scissor.x || scissor.y != cur_state.scissor.y ||
- scissor.width != cur_state.scissor.width || scissor.height != cur_state.scissor.height) {
- glScissor(scissor.x, scissor.y, scissor.width, scissor.height);
- }
-
+ // Viewport
if (viewport.x != cur_state.viewport.x || viewport.y != cur_state.viewport.y ||
viewport.width != cur_state.viewport.width ||
viewport.height != cur_state.viewport.height) {
glViewport(viewport.x, viewport.y, viewport.width, viewport.height);
}
-
// Clip distance
for (std::size_t i = 0; i < clip_distance.size(); ++i) {
if (clip_distance[i] != cur_state.clip_distance[i]) {
@@ -336,12 +364,28 @@ void OpenGLState::Apply() const {
}
}
}
-
+ // Color mask
+ if (color_mask.red_enabled != cur_state.color_mask.red_enabled ||
+ color_mask.green_enabled != cur_state.color_mask.green_enabled ||
+ color_mask.blue_enabled != cur_state.color_mask.blue_enabled ||
+ color_mask.alpha_enabled != cur_state.color_mask.alpha_enabled) {
+ glColorMask(color_mask.red_enabled, color_mask.green_enabled, color_mask.blue_enabled,
+ color_mask.alpha_enabled);
+ }
// Point
if (point.size != cur_state.point.size) {
glPointSize(point.size);
}
-
+ ApplyScissorTest();
+ ApplyStencilTest();
+ ApplySRgb();
+ ApplyCulling();
+ ApplyDepth();
+ ApplyPrimitiveRestart();
+ ApplyBlending();
+ ApplyLogicOp();
+ ApplyTextures();
+ ApplySamplers();
cur_state = *this;
}
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index 9e2c573b5..fe648aff6 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -173,7 +173,8 @@ public:
}
/// Apply this state as the current OpenGL state
void Apply() const;
-
+ /// Set the initial OpenGL state
+ static void ApplyDefaultState();
/// Resets any references to the given resource
OpenGLState& UnbindTexture(GLuint handle);
OpenGLState& ResetSampler(GLuint handle);
@@ -188,6 +189,16 @@ private:
// Workaround for sRGB problems caused by
// QT not supporting srgb output
static bool s_rgb_used;
+ void ApplySRgb() const;
+ void ApplyCulling() const;
+ void ApplyDepth() const;
+ void ApplyPrimitiveRestart() const;
+ void ApplyStencilTest() const;
+ void ApplyScissorTest() const;
+ void ApplyBlending() const;
+ void ApplyLogicOp() const;
+ void ApplyTextures() const;
+ void ApplySamplers() const;
};
} // namespace OpenGL