diff options
Diffstat (limited to 'src/video_core/renderer_opengl')
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 18 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 3 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_state.cpp | 20 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_state.h | 5 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/maxwell_to_gl.h | 40 |
5 files changed, 80 insertions, 6 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index b653bb479..35056d9bd 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -450,6 +450,7 @@ void RasterizerOpenGL::DrawArrays() { SyncDepthTestState(); SyncBlendState(); + SyncLogicOpState(); SyncCullMode(); // TODO(bunnei): Sync framebuffer_scale uniform here @@ -847,6 +848,9 @@ void RasterizerOpenGL::SyncBlendState() { if (!state.blend.enabled) return; + ASSERT_MSG(regs.logic_op.enable == 0, + "Blending and logic op can't be enabled at the same time."); + ASSERT_MSG(regs.independent_blend_enable == 1, "Only independent blending is implemented"); ASSERT_MSG(!regs.independent_blend[0].separate_alpha, "Unimplemented"); state.blend.rgb_equation = MaxwellToGL::BlendEquation(regs.independent_blend[0].equation_rgb); @@ -856,3 +860,17 @@ void RasterizerOpenGL::SyncBlendState() { state.blend.src_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_source_a); state.blend.dst_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_dest_a); } + +void RasterizerOpenGL::SyncLogicOpState() { + const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; + + // TODO(Subv): Support more than just render target 0. + state.logic_op.enabled = regs.logic_op.enable != 0; + + if (!state.logic_op.enabled) + return; + + ASSERT_MSG(regs.blend.enable == 0, "Blending and logic op can't be enabled at the same time."); + + state.logic_op.operation = MaxwellToGL::LogicOp(regs.logic_op.operation); +} diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 394fc59f1..f40e70bf4 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -142,6 +142,9 @@ private: /// Syncs the blend state to match the guest state void SyncBlendState(); + /// Syncs the LogicOp state to match the guest state + void SyncLogicOpState(); + bool has_ARB_direct_state_access = false; bool has_ARB_separate_shader_objects = false; bool has_ARB_vertex_attrib_binding = false; diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index 1d1975179..13399ceb8 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp @@ -45,7 +45,8 @@ OpenGLState::OpenGLState() { blend.color.blue = 0.0f; blend.color.alpha = 0.0f; - logic_op = GL_COPY; + logic_op.enabled = false; + logic_op.operation = GL_COPY; for (auto& texture_unit : texture_units) { texture_unit.Reset(); @@ -148,11 +149,10 @@ void OpenGLState::Apply() const { // Blending if (blend.enabled != cur_state.blend.enabled) { if (blend.enabled) { + ASSERT(!logic_op.enabled); glEnable(GL_BLEND); - glDisable(GL_COLOR_LOGIC_OP); } else { glDisable(GL_BLEND); - glEnable(GL_COLOR_LOGIC_OP); } } @@ -176,8 +176,18 @@ void OpenGLState::Apply() const { glBlendEquationSeparate(blend.rgb_equation, blend.a_equation); } - if (logic_op != cur_state.logic_op) { - glLogicOp(logic_op); + // Logic Operation + if (logic_op.enabled != cur_state.logic_op.enabled) { + if (logic_op.enabled) { + ASSERT(!blend.enabled); + glEnable(GL_COLOR_LOGIC_OP); + } else { + glDisable(GL_COLOR_LOGIC_OP); + } + } + + if (logic_op.operation != cur_state.logic_op.operation) { + glLogicOp(logic_op.operation); } // Textures diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index bdb02ba25..219b65a8a 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h @@ -83,7 +83,10 @@ public: } color; // GL_BLEND_COLOR } blend; - GLenum logic_op; // GL_LOGIC_OP_MODE + struct { + bool enabled; // GL_LOGIC_OP_MODE + GLenum operation; + } logic_op; // 3 texture units - one for each that is used in PICA fragment shader emulation struct TextureUnit { diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h index 5d91a0c2f..ff2f7b8b6 100644 --- a/src/video_core/renderer_opengl/maxwell_to_gl.h +++ b/src/video_core/renderer_opengl/maxwell_to_gl.h @@ -317,4 +317,44 @@ inline GLenum CullFace(Maxwell::Cull::CullFace cull_face) { return {}; } +inline GLenum LogicOp(Maxwell::LogicOperation operation) { + switch (operation) { + case Maxwell::LogicOperation::Clear: + return GL_CLEAR; + case Maxwell::LogicOperation::And: + return GL_AND; + case Maxwell::LogicOperation::AndReverse: + return GL_AND_REVERSE; + case Maxwell::LogicOperation::Copy: + return GL_COPY; + case Maxwell::LogicOperation::AndInverted: + return GL_AND_INVERTED; + case Maxwell::LogicOperation::NoOp: + return GL_NOOP; + case Maxwell::LogicOperation::Xor: + return GL_XOR; + case Maxwell::LogicOperation::Or: + return GL_OR; + case Maxwell::LogicOperation::Nor: + return GL_NOR; + case Maxwell::LogicOperation::Equiv: + return GL_EQUIV; + case Maxwell::LogicOperation::Invert: + return GL_INVERT; + case Maxwell::LogicOperation::OrReverse: + return GL_OR_REVERSE; + case Maxwell::LogicOperation::CopyInverted: + return GL_COPY_INVERTED; + case Maxwell::LogicOperation::OrInverted: + return GL_OR_INVERTED; + case Maxwell::LogicOperation::Nand: + return GL_NAND; + case Maxwell::LogicOperation::Set: + return GL_SET; + } + LOG_CRITICAL(Render_OpenGL, "Unimplemented logic operation={}", static_cast<u32>(operation)); + UNREACHABLE(); + return {}; +} + } // namespace MaxwellToGL |