summaryrefslogtreecommitdiffstats
path: root/src/video_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/engines/maxwell_3d.h29
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp18
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h3
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp20
-rw-r--r--src/video_core/renderer_opengl/gl_state.h5
-rw-r--r--src/video_core/renderer_opengl/maxwell_to_gl.h40
6 files changed, 108 insertions, 7 deletions
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 3c869d3a1..d03bc1c0c 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -311,6 +311,25 @@ public:
AlwaysOld = 8,
};
+ enum class LogicOperation : u32 {
+ Clear = 0x1500,
+ And = 0x1501,
+ AndReverse = 0x1502,
+ Copy = 0x1503,
+ AndInverted = 0x1504,
+ NoOp = 0x1505,
+ Xor = 0x1506,
+ Or = 0x1507,
+ Nor = 0x1508,
+ Equiv = 0x1509,
+ Invert = 0x150A,
+ OrReverse = 0x150B,
+ CopyInverted = 0x150C,
+ OrInverted = 0x150D,
+ Nand = 0x150E,
+ Set = 0x150F,
+ };
+
struct Cull {
enum class FrontFace : u32 {
ClockWise = 0x0900,
@@ -695,7 +714,14 @@ public:
Cull cull;
- INSERT_PADDING_WORDS(0x2B);
+ INSERT_PADDING_WORDS(0x28);
+
+ struct {
+ u32 enable;
+ LogicOperation operation;
+ } logic_op;
+
+ INSERT_PADDING_WORDS(0x1);
union {
u32 raw;
@@ -942,6 +968,7 @@ ASSERT_REG_POSITION(draw, 0x585);
ASSERT_REG_POSITION(index_array, 0x5F2);
ASSERT_REG_POSITION(instanced_arrays, 0x620);
ASSERT_REG_POSITION(cull, 0x646);
+ASSERT_REG_POSITION(logic_op, 0x671);
ASSERT_REG_POSITION(clear_buffers, 0x674);
ASSERT_REG_POSITION(query, 0x6C0);
ASSERT_REG_POSITION(vertex_array[0], 0x700);
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