diff options
| author | 2015-08-20 10:11:09 -0500 | |
|---|---|---|
| committer | 2015-08-20 10:11:09 -0500 | |
| commit | 46f660a789ff02f9cd86600ed82e0936b049b176 (patch) | |
| tree | ddb2c54c86025ac338549922c7c548844e38a68e /src | |
| parent | GPU/Rasterizer: Corrected the stencil implementation. (diff) | |
| download | yuzu-46f660a789ff02f9cd86600ed82e0936b049b176.tar.gz yuzu-46f660a789ff02f9cd86600ed82e0936b049b176.tar.xz yuzu-46f660a789ff02f9cd86600ed82e0936b049b176.zip | |
GLRasterizer: Implemented stencil testing in the hw renderer.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 13 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.cpp | 9 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.h | 3 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/pica_to_gl.h | 21 |
4 files changed, 44 insertions, 2 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 9f1552adf..962c659e0 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -268,7 +268,8 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) { | |||
| 268 | break; | 268 | break; |
| 269 | 269 | ||
| 270 | // Stencil test | 270 | // Stencil test |
| 271 | case PICA_REG_INDEX(output_merger.stencil_test): | 271 | case PICA_REG_INDEX(output_merger.stencil_test.raw_func): |
| 272 | case PICA_REG_INDEX(output_merger.stencil_test.raw_op): | ||
| 272 | SyncStencilTest(); | 273 | SyncStencilTest(); |
| 273 | break; | 274 | break; |
| 274 | 275 | ||
| @@ -675,7 +676,15 @@ void RasterizerOpenGL::SyncLogicOp() { | |||
| 675 | } | 676 | } |
| 676 | 677 | ||
| 677 | void RasterizerOpenGL::SyncStencilTest() { | 678 | void RasterizerOpenGL::SyncStencilTest() { |
| 678 | // TODO: Implement stencil test, mask, and op | 679 | const auto& regs = Pica::g_state.regs; |
| 680 | state.stencil.test_enabled = regs.output_merger.stencil_test.enable && regs.framebuffer.depth_format == Pica::Regs::DepthFormat::D24S8; | ||
| 681 | state.stencil.test_func = PicaToGL::CompareFunc(regs.output_merger.stencil_test.func); | ||
| 682 | state.stencil.test_ref = regs.output_merger.stencil_test.reference_value; | ||
| 683 | state.stencil.test_mask = regs.output_merger.stencil_test.input_mask; | ||
| 684 | state.stencil.write_mask = regs.output_merger.stencil_test.write_mask; | ||
| 685 | state.stencil.action_stencil_fail = PicaToGL::StencilOp(regs.output_merger.stencil_test.action_stencil_fail); | ||
| 686 | state.stencil.action_depth_fail = PicaToGL::StencilOp(regs.output_merger.stencil_test.action_depth_fail); | ||
| 687 | state.stencil.action_depth_pass = PicaToGL::StencilOp(regs.output_merger.stencil_test.action_depth_pass); | ||
| 679 | } | 688 | } |
| 680 | 689 | ||
| 681 | void RasterizerOpenGL::SyncDepthTest() { | 690 | void RasterizerOpenGL::SyncDepthTest() { |
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index 871324014..ba47ce8b8 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp | |||
| @@ -26,6 +26,9 @@ OpenGLState::OpenGLState() { | |||
| 26 | stencil.test_ref = 0; | 26 | stencil.test_ref = 0; |
| 27 | stencil.test_mask = -1; | 27 | stencil.test_mask = -1; |
| 28 | stencil.write_mask = -1; | 28 | stencil.write_mask = -1; |
| 29 | stencil.action_depth_fail = GL_KEEP; | ||
| 30 | stencil.action_depth_pass = GL_KEEP; | ||
| 31 | stencil.action_stencil_fail = GL_KEEP; | ||
| 29 | 32 | ||
| 30 | blend.enabled = false; | 33 | blend.enabled = false; |
| 31 | blend.src_rgb_func = GL_ONE; | 34 | blend.src_rgb_func = GL_ONE; |
| @@ -105,6 +108,12 @@ void OpenGLState::Apply() { | |||
| 105 | glStencilFunc(stencil.test_func, stencil.test_ref, stencil.test_mask); | 108 | glStencilFunc(stencil.test_func, stencil.test_ref, stencil.test_mask); |
| 106 | } | 109 | } |
| 107 | 110 | ||
| 111 | if (stencil.action_depth_fail != cur_state.stencil.action_depth_fail || | ||
| 112 | stencil.action_depth_pass != cur_state.stencil.action_depth_pass || | ||
| 113 | stencil.action_stencil_fail != cur_state.stencil.action_stencil_fail) { | ||
| 114 | glStencilOp(stencil.action_stencil_fail, stencil.action_depth_fail, stencil.action_depth_pass); | ||
| 115 | } | ||
| 116 | |||
| 108 | // Stencil mask | 117 | // Stencil mask |
| 109 | if (stencil.write_mask != cur_state.stencil.write_mask) { | 118 | if (stencil.write_mask != cur_state.stencil.write_mask) { |
| 110 | glStencilMask(stencil.write_mask); | 119 | glStencilMask(stencil.write_mask); |
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index 3e2379021..81e7e0877 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h | |||
| @@ -32,6 +32,9 @@ public: | |||
| 32 | GLint test_ref; // GL_STENCIL_REF | 32 | GLint test_ref; // GL_STENCIL_REF |
| 33 | GLuint test_mask; // GL_STENCIL_VALUE_MASK | 33 | GLuint test_mask; // GL_STENCIL_VALUE_MASK |
| 34 | GLuint write_mask; // GL_STENCIL_WRITEMASK | 34 | GLuint write_mask; // GL_STENCIL_WRITEMASK |
| 35 | GLenum action_stencil_fail; // GL_STENCIL_FAIL | ||
| 36 | GLenum action_depth_fail; // GL_STENCIL_PASS_DEPTH_FAIL | ||
| 37 | GLenum action_depth_pass; // GL_STENCIL_PASS_DEPTH_PASS | ||
| 35 | } stencil; | 38 | } stencil; |
| 36 | 39 | ||
| 37 | struct { | 40 | struct { |
diff --git a/src/video_core/renderer_opengl/pica_to_gl.h b/src/video_core/renderer_opengl/pica_to_gl.h index 3b562da86..a8f84a411 100644 --- a/src/video_core/renderer_opengl/pica_to_gl.h +++ b/src/video_core/renderer_opengl/pica_to_gl.h | |||
| @@ -152,6 +152,27 @@ inline GLenum CompareFunc(Pica::Regs::CompareFunc func) { | |||
| 152 | return compare_func_table[(unsigned)func]; | 152 | return compare_func_table[(unsigned)func]; |
| 153 | } | 153 | } |
| 154 | 154 | ||
| 155 | inline GLenum StencilOp(Pica::Regs::StencilAction action) { | ||
| 156 | static const GLenum stencil_op_table[] = { | ||
| 157 | GL_KEEP, // StencilAction::Keep | ||
| 158 | GL_KEEP, | ||
| 159 | GL_REPLACE, // StencilAction::Replace | ||
| 160 | GL_INCR, // StencilAction::Increment | ||
| 161 | GL_DECR, // StencilAction::Decrement | ||
| 162 | GL_INVERT // StencilAction::Invert | ||
| 163 | }; | ||
| 164 | |||
| 165 | // Range check table for input | ||
| 166 | if ((unsigned)action >= ARRAY_SIZE(stencil_op_table)) { | ||
| 167 | LOG_CRITICAL(Render_OpenGL, "Unknown stencil op %d", action); | ||
| 168 | UNREACHABLE(); | ||
| 169 | |||
| 170 | return GL_KEEP; | ||
| 171 | } | ||
| 172 | |||
| 173 | return stencil_op_table[(unsigned)action]; | ||
| 174 | } | ||
| 175 | |||
| 155 | inline std::array<GLfloat, 4> ColorRGBA8(const u8* bytes) { | 176 | inline std::array<GLfloat, 4> ColorRGBA8(const u8* bytes) { |
| 156 | return { { bytes[0] / 255.0f, | 177 | return { { bytes[0] / 255.0f, |
| 157 | bytes[1] / 255.0f, | 178 | bytes[1] / 255.0f, |