summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2015-05-25 18:39:03 -0400
committerGravatar bunnei2015-05-31 01:52:41 -0400
commite6ace388156735d3f5e2942cafc3d5f5d46b121b (patch)
treea8e24a233560796c8ff3d496653c4ee26db229f8 /src
parentrasterizer: Implement AddSigned combiner function for alpha channel. (diff)
downloadyuzu-e6ace388156735d3f5e2942cafc3d5f5d46b121b.tar.gz
yuzu-e6ace388156735d3f5e2942cafc3d5f5d46b121b.tar.xz
yuzu-e6ace388156735d3f5e2942cafc3d5f5d46b121b.zip
Pica: Implement LogicOp function.
Diffstat (limited to 'src')
-rw-r--r--src/video_core/pica.h27
-rw-r--r--src/video_core/rasterizer.cpp59
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp10
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h3
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp11
-rw-r--r--src/video_core/renderer_opengl/gl_state.h2
-rw-r--r--src/video_core/renderer_opengl/pica_to_gl.h31
7 files changed, 135 insertions, 8 deletions
diff --git a/src/video_core/pica.h b/src/video_core/pica.h
index fbc95a4b6..f8313d20d 100644
--- a/src/video_core/pica.h
+++ b/src/video_core/pica.h
@@ -162,6 +162,25 @@ struct Regs {
162 ETC1A4 = 13, // compressed 162 ETC1A4 = 13, // compressed
163 }; 163 };
164 164
165 enum class LogicOp : u32 {
166 Clear = 0,
167 And = 1,
168 AndReverse = 2,
169 Copy = 3,
170 Set = 4,
171 CopyInverted = 5,
172 NoOp = 6,
173 Invert = 7,
174 Nand = 8,
175 Or = 9,
176 Nor = 10,
177 Xor = 11,
178 Equiv = 12,
179 AndInverted = 13,
180 OrReverse = 14,
181 OrInverted = 15,
182 };
183
165 static unsigned NibblesPerPixel(TextureFormat format) { 184 static unsigned NibblesPerPixel(TextureFormat format) {
166 switch (format) { 185 switch (format) {
167 case TextureFormat::RGBA8: 186 case TextureFormat::RGBA8:
@@ -413,12 +432,8 @@ struct Regs {
413 } alpha_blending; 432 } alpha_blending;
414 433
415 union { 434 union {
416 enum Op { 435 BitField<0, 4, LogicOp> logic_op;
417 Set = 4, 436 };
418 };
419
420 BitField<0, 4, Op> op;
421 } logic_op;
422 437
423 union { 438 union {
424 BitField< 0, 8, u32> r; 439 BitField< 0, 8, u32> r;
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp
index 8f39e609b..2613e398f 100644
--- a/src/video_core/rasterizer.cpp
+++ b/src/video_core/rasterizer.cpp
@@ -873,8 +873,63 @@ static void ProcessTriangleInternal(const VertexShader::OutputVertex& v0,
873 blend_output = EvaluateBlendEquation(combiner_output, srcfactor, dest, dstfactor, params.blend_equation_rgb); 873 blend_output = EvaluateBlendEquation(combiner_output, srcfactor, dest, dstfactor, params.blend_equation_rgb);
874 blend_output.a() = EvaluateBlendEquation(combiner_output, srcfactor, dest, dstfactor, params.blend_equation_a).a(); 874 blend_output.a() = EvaluateBlendEquation(combiner_output, srcfactor, dest, dstfactor, params.blend_equation_a).a();
875 } else { 875 } else {
876 LOG_CRITICAL(HW_GPU, "logic op: %x", output_merger.logic_op); 876 static auto LogicOp = [](u8 src, u8 dest, Regs::LogicOp op) -> u8 {
877 UNIMPLEMENTED(); 877 switch (op) {
878 case Regs::LogicOp::Clear:
879 return 0;
880
881 case Regs::LogicOp::And:
882 return src & dest;
883
884 case Regs::LogicOp::AndReverse:
885 return src & ~dest;
886
887 case Regs::LogicOp::Copy:
888 return src;
889
890 case Regs::LogicOp::Set:
891 return 255;
892
893 case Regs::LogicOp::CopyInverted:
894 return ~src;
895
896 case Regs::LogicOp::NoOp:
897 return dest;
898
899 case Regs::LogicOp::Invert:
900 return ~dest;
901
902 case Regs::LogicOp::Nand:
903 return ~(src & dest);
904
905 case Regs::LogicOp::Or:
906 return src | dest;
907
908 case Regs::LogicOp::Nor:
909 return ~(src | dest);
910
911 case Regs::LogicOp::Xor:
912 return src ^ dest;
913
914 case Regs::LogicOp::Equiv:
915 return ~(src ^ dest);
916
917 case Regs::LogicOp::AndInverted:
918 return ~src & dest;
919
920 case Regs::LogicOp::OrReverse:
921 return src | ~dest;
922
923 case Regs::LogicOp::OrInverted:
924 return ~src | dest;
925 }
926 };
927
928 blend_output = Math::MakeVec(
929 LogicOp(combiner_output.r(), dest.r(), output_merger.logic_op),
930 LogicOp(combiner_output.g(), dest.g(), output_merger.logic_op),
931 LogicOp(combiner_output.b(), dest.b(), output_merger.logic_op),
932 LogicOp(combiner_output.a(), dest.a(), output_merger.logic_op));
878 } 933 }
879 934
880 const Math::Vec4<u8> result = { 935 const Math::Vec4<u8> result = {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index bacdb7172..b51f8efdf 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -135,6 +135,7 @@ void RasterizerOpenGL::Reset() {
135 SyncBlendFuncs(); 135 SyncBlendFuncs();
136 SyncBlendColor(); 136 SyncBlendColor();
137 SyncAlphaTest(); 137 SyncAlphaTest();
138 SyncLogicOp();
138 SyncStencilTest(); 139 SyncStencilTest();
139 SyncDepthTest(); 140 SyncDepthTest();
140 141
@@ -249,6 +250,11 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
249 SyncDepthTest(); 250 SyncDepthTest();
250 break; 251 break;
251 252
253 // Logic op
254 case PICA_REG_INDEX(output_merger.logic_op):
255 SyncLogicOp();
256 break;
257
252 // TEV stage 0 258 // TEV stage 0
253 case PICA_REG_INDEX(tev_stage0.color_source1): 259 case PICA_REG_INDEX(tev_stage0.color_source1):
254 SyncTevSources(0, regs.tev_stage0); 260 SyncTevSources(0, regs.tev_stage0);
@@ -633,6 +639,10 @@ void RasterizerOpenGL::SyncAlphaTest() {
633 glUniform1f(uniform_alphatest_ref, regs.output_merger.alpha_test.ref / 255.0f); 639 glUniform1f(uniform_alphatest_ref, regs.output_merger.alpha_test.ref / 255.0f);
634} 640}
635 641
642void RasterizerOpenGL::SyncLogicOp() {
643 state.logic_op = PicaToGL::LogicOp(Pica::g_state.regs.output_merger.logic_op);
644}
645
636void RasterizerOpenGL::SyncStencilTest() { 646void RasterizerOpenGL::SyncStencilTest() {
637 // TODO: Implement stencil test, mask, and op 647 // TODO: Implement stencil test, mask, and op
638} 648}
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 9896f8d04..d7d422b1f 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -125,6 +125,9 @@ private:
125 /// Syncs the alpha test states to match the PICA register 125 /// Syncs the alpha test states to match the PICA register
126 void SyncAlphaTest(); 126 void SyncAlphaTest();
127 127
128 /// Syncs the logic op states to match the PICA register
129 void SyncLogicOp();
130
128 /// Syncs the stencil test states to match the PICA register 131 /// Syncs the stencil test states to match the PICA register
129 void SyncStencilTest(); 132 void SyncStencilTest();
130 133
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index 0d7ba1983..9c5f38f94 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -32,6 +32,8 @@ OpenGLState::OpenGLState() {
32 blend.color.blue = 0.0f; 32 blend.color.blue = 0.0f;
33 blend.color.alpha = 0.0f; 33 blend.color.alpha = 0.0f;
34 34
35 logic_op = GL_COPY;
36
35 for (auto& texture_unit : texture_units) { 37 for (auto& texture_unit : texture_units) {
36 texture_unit.enabled_2d = false; 38 texture_unit.enabled_2d = false;
37 texture_unit.texture_2d = 0; 39 texture_unit.texture_2d = 0;
@@ -99,8 +101,13 @@ void OpenGLState::Apply() {
99 if (blend.enabled != cur_state.blend.enabled) { 101 if (blend.enabled != cur_state.blend.enabled) {
100 if (blend.enabled) { 102 if (blend.enabled) {
101 glEnable(GL_BLEND); 103 glEnable(GL_BLEND);
104
105 cur_state.logic_op = GL_COPY;
106 glLogicOp(cur_state.logic_op);
107 glDisable(GL_COLOR_LOGIC_OP);
102 } else { 108 } else {
103 glDisable(GL_BLEND); 109 glDisable(GL_BLEND);
110 glEnable(GL_COLOR_LOGIC_OP);
104 } 111 }
105 } 112 }
106 113
@@ -118,6 +125,10 @@ void OpenGLState::Apply() {
118 glBlendFuncSeparate(blend.src_rgb_func, blend.dst_rgb_func, blend.src_a_func, blend.dst_a_func); 125 glBlendFuncSeparate(blend.src_rgb_func, blend.dst_rgb_func, blend.src_a_func, blend.dst_a_func);
119 } 126 }
120 127
128 if (logic_op != cur_state.logic_op) {
129 glLogicOp(logic_op);
130 }
131
121 // Textures 132 // Textures
122 for (unsigned texture_index = 0; texture_index < ARRAY_SIZE(texture_units); ++texture_index) { 133 for (unsigned texture_index = 0; texture_index < ARRAY_SIZE(texture_units); ++texture_index) {
123 if (texture_units[texture_index].enabled_2d != cur_state.texture_units[texture_index].enabled_2d) { 134 if (texture_units[texture_index].enabled_2d != cur_state.texture_units[texture_index].enabled_2d) {
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index 63dba2761..6b97721d6 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -42,6 +42,8 @@ public:
42 } color; // GL_BLEND_COLOR 42 } color; // GL_BLEND_COLOR
43 } blend; 43 } blend;
44 44
45 GLenum logic_op; // GL_LOGIC_OP_MODE
46
45 // 3 texture units - one for each that is used in PICA fragment shader emulation 47 // 3 texture units - one for each that is used in PICA fragment shader emulation
46 struct { 48 struct {
47 bool enabled_2d; // GL_TEXTURE_2D 49 bool enabled_2d; // GL_TEXTURE_2D
diff --git a/src/video_core/renderer_opengl/pica_to_gl.h b/src/video_core/renderer_opengl/pica_to_gl.h
index f8763e71b..e566f9f7a 100644
--- a/src/video_core/renderer_opengl/pica_to_gl.h
+++ b/src/video_core/renderer_opengl/pica_to_gl.h
@@ -71,6 +71,37 @@ inline GLenum BlendFunc(Pica::Regs::BlendFactor factor) {
71 return blend_func_table[(unsigned)factor]; 71 return blend_func_table[(unsigned)factor];
72} 72}
73 73
74inline GLenum LogicOp(Pica::Regs::LogicOp op) {
75 static const GLenum logic_op_table[] = {
76 GL_CLEAR, // Clear
77 GL_AND, // And
78 GL_AND_REVERSE, // AndReverse
79 GL_COPY, // Copy
80 GL_SET, // Set
81 GL_COPY_INVERTED, // CopyInverted
82 GL_NOOP, // NoOp
83 GL_INVERT, // Invert
84 GL_NAND, // Nand
85 GL_OR, // Or
86 GL_NOR, // Nor
87 GL_XOR, // Xor
88 GL_EQUIV, // Equiv
89 GL_AND_INVERTED, // AndInverted
90 GL_OR_REVERSE, // OrReverse
91 GL_OR_INVERTED, // OrInverted
92 };
93
94 // Range check table for input
95 if ((unsigned)op >= ARRAY_SIZE(logic_op_table)) {
96 LOG_CRITICAL(Render_OpenGL, "Unknown logic op %d", op);
97 UNREACHABLE();
98
99 return GL_COPY;
100 }
101
102 return logic_op_table[(unsigned)op];
103}
104
74inline GLenum CompareFunc(Pica::Regs::CompareFunc func) { 105inline GLenum CompareFunc(Pica::Regs::CompareFunc func) {
75 static const GLenum compare_func_table[] = { 106 static const GLenum compare_func_table[] = {
76 GL_NEVER, // CompareFunc::Never 107 GL_NEVER, // CompareFunc::Never