summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_opengl/gl_state.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/renderer_opengl/gl_state.cpp')
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp205
1 files changed, 143 insertions, 62 deletions
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index b6b426f34..2e1f81e26 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -22,8 +22,6 @@ OpenGLState::OpenGLState() {
depth.test_enabled = false;
depth.test_func = GL_LESS;
depth.write_mask = GL_TRUE;
- depth.depth_range_near = 0.0f;
- depth.depth_range_far = 1.0f;
primitive_restart.enabled = false;
primitive_restart.index = 0;
@@ -45,19 +43,33 @@ OpenGLState::OpenGLState() {
};
reset_stencil(stencil.front);
reset_stencil(stencil.back);
-
- blend.enabled = true;
- blend.rgb_equation = GL_FUNC_ADD;
- blend.a_equation = GL_FUNC_ADD;
- blend.src_rgb_func = GL_ONE;
- blend.dst_rgb_func = GL_ZERO;
- blend.src_a_func = GL_ONE;
- blend.dst_a_func = GL_ZERO;
- blend.color.red = 0.0f;
- blend.color.green = 0.0f;
- blend.color.blue = 0.0f;
- blend.color.alpha = 0.0f;
-
+ for (auto& item : viewports) {
+ item.x = 0;
+ item.y = 0;
+ item.width = 0;
+ item.height = 0;
+ item.depth_range_near = 0.0f;
+ item.depth_range_far = 1.0f;
+ }
+ scissor.enabled = false;
+ scissor.x = 0;
+ scissor.y = 0;
+ scissor.width = 0;
+ scissor.height = 0;
+ for (auto& item : blend) {
+ item.enabled = true;
+ item.rgb_equation = GL_FUNC_ADD;
+ item.a_equation = GL_FUNC_ADD;
+ item.src_rgb_func = GL_ONE;
+ item.dst_rgb_func = GL_ZERO;
+ item.src_a_func = GL_ONE;
+ item.dst_a_func = GL_ZERO;
+ }
+ independant_blend.enabled = false;
+ blend_color.red = 0.0f;
+ blend_color.green = 0.0f;
+ blend_color.blue = 0.0f;
+ blend_color.alpha = 0.0f;
logic_op.enabled = false;
logic_op.operation = GL_COPY;
@@ -73,17 +85,6 @@ OpenGLState::OpenGLState() {
draw.shader_program = 0;
draw.program_pipeline = 0;
- scissor.enabled = false;
- scissor.x = 0;
- scissor.y = 0;
- scissor.width = 0;
- scissor.height = 0;
-
- viewport.x = 0;
- viewport.y = 0;
- viewport.width = 0;
- viewport.height = 0;
-
clip_distance = {};
point.size = 1;
@@ -152,11 +153,6 @@ void OpenGLState::ApplyDepth() const {
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);
- }
}
void OpenGLState::ApplyPrimitiveRestart() const {
@@ -208,7 +204,7 @@ void OpenGLState::ApplyStencilTest() const {
}
}
-void OpenGLState::ApplyScissorTest() const {
+void OpenGLState::ApplyScissor() const {
const bool scissor_changed = scissor.enabled != cur_state.scissor.enabled;
if (scissor_changed) {
if (scissor.enabled) {
@@ -217,43 +213,134 @@ void OpenGLState::ApplyScissorTest() const {
glDisable(GL_SCISSOR_TEST);
}
}
- 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) {
+ if (scissor.enabled &&
+ (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);
}
}
-void OpenGLState::ApplyBlending() const {
- const bool blend_changed = blend.enabled != cur_state.blend.enabled;
+void OpenGLState::ApplyViewport() const {
+ if (GLAD_GL_ARB_viewport_array) {
+ for (GLuint i = 0;
+ i < static_cast<GLuint>(Tegra::Engines::Maxwell3D::Regs::NumRenderTargets); i++) {
+ const auto& current = cur_state.viewports[i];
+ const auto& updated = viewports[i];
+ if (updated.x != current.x || updated.y != current.y ||
+ updated.width != current.width || updated.height != current.height) {
+ glViewportIndexedf(i, updated.x, updated.y, updated.width, updated.height);
+ }
+ if (updated.depth_range_near != current.depth_range_near ||
+ updated.depth_range_far != current.depth_range_far) {
+ glDepthRangeIndexed(i, updated.depth_range_near, updated.depth_range_far);
+ }
+ }
+ } else {
+ const auto& current = cur_state.viewports[0];
+ const auto& updated = viewports[0];
+ if (updated.x != current.x || updated.y != current.y || updated.width != current.width ||
+ updated.height != current.height) {
+ glViewport(updated.x, updated.y, updated.width, updated.height);
+ }
+ if (updated.depth_range_near != current.depth_range_near ||
+ updated.depth_range_far != current.depth_range_far) {
+ glDepthRange(updated.depth_range_near, updated.depth_range_far);
+ }
+ }
+}
+
+void OpenGLState::ApplyGlobalBlending() const {
+ const Blend& current = cur_state.blend[0];
+ const Blend& updated = blend[0];
+ const bool blend_changed = updated.enabled != current.enabled;
if (blend_changed) {
- if (blend.enabled) {
- ASSERT(!logic_op.enabled);
+ if (updated.enabled) {
glEnable(GL_BLEND);
} else {
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 (!updated.enabled) {
+ return;
+ }
+ if (updated.separate_alpha) {
+ if (blend_changed || updated.src_rgb_func != current.src_rgb_func ||
+ updated.dst_rgb_func != current.dst_rgb_func ||
+ updated.src_a_func != current.src_a_func || updated.dst_a_func != current.dst_a_func) {
+ glBlendFuncSeparate(updated.src_rgb_func, updated.dst_rgb_func, updated.src_a_func,
+ updated.dst_a_func);
+ }
+
+ if (blend_changed || updated.rgb_equation != current.rgb_equation ||
+ updated.a_equation != current.a_equation) {
+ glBlendEquationSeparate(updated.rgb_equation, updated.a_equation);
+ }
+ } else {
+ if (blend_changed || updated.src_rgb_func != current.src_rgb_func ||
+ updated.dst_rgb_func != current.dst_rgb_func) {
+ glBlendFunc(updated.src_rgb_func, updated.dst_rgb_func);
+ }
+
+ if (blend_changed || updated.rgb_equation != current.rgb_equation) {
+ glBlendEquation(updated.rgb_equation);
+ }
+ }
+}
+
+void OpenGLState::ApplyTargetBlending(int target, bool force) const {
+ const Blend& updated = blend[target];
+ const Blend& current = cur_state.blend[target];
+ const bool blend_changed = updated.enabled != current.enabled || force;
+ if (blend_changed) {
+ if (updated.enabled) {
+ glEnablei(GL_BLEND, static_cast<GLuint>(target));
+ } else {
+ glDisablei(GL_BLEND, static_cast<GLuint>(target));
+ }
+ }
+ if (!updated.enabled) {
+ return;
+ }
+ if (updated.separate_alpha) {
+ if (blend_changed || updated.src_rgb_func != current.src_rgb_func ||
+ updated.dst_rgb_func != current.dst_rgb_func ||
+ updated.src_a_func != current.src_a_func || updated.dst_a_func != current.dst_a_func) {
+ glBlendFuncSeparateiARB(static_cast<GLuint>(target), updated.src_rgb_func,
+ updated.dst_rgb_func, updated.src_a_func, updated.dst_a_func);
+ }
+
+ if (blend_changed || updated.rgb_equation != current.rgb_equation ||
+ updated.a_equation != current.a_equation) {
+ glBlendEquationSeparateiARB(static_cast<GLuint>(target), updated.rgb_equation,
+ updated.a_equation);
+ }
+ } else {
+ if (blend_changed || updated.src_rgb_func != current.src_rgb_func ||
+ updated.dst_rgb_func != current.dst_rgb_func) {
+ glBlendFunciARB(static_cast<GLuint>(target), updated.src_rgb_func,
+ updated.dst_rgb_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_changed || updated.rgb_equation != current.rgb_equation) {
+ glBlendEquationiARB(static_cast<GLuint>(target), updated.rgb_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);
+void OpenGLState::ApplyBlending() const {
+ if (independant_blend.enabled) {
+ for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {
+ ApplyTargetBlending(i,
+ independant_blend.enabled != cur_state.independant_blend.enabled);
}
+ } else {
+ ApplyGlobalBlending();
+ }
+ 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);
}
}
@@ -261,7 +348,6 @@ 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);
} else {
glDisable(GL_COLOR_LOGIC_OP);
@@ -348,12 +434,6 @@ void OpenGLState::Apply() const {
if (draw.program_pipeline != cur_state.draw.program_pipeline) {
glBindProgramPipeline(draw.program_pipeline);
}
- // 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]) {
@@ -376,7 +456,8 @@ void OpenGLState::Apply() const {
if (point.size != cur_state.point.size) {
glPointSize(point.size);
}
- ApplyScissorTest();
+ ApplyViewport();
+ ApplyScissor();
ApplyStencilTest();
ApplySRgb();
ApplyCulling();