diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index ab6ed0302b..b6827f143e 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -1623,7 +1623,8 @@ void GLGSRender::InitDrawBuffers() void GLGSRender::Enable(u32 cmd, u32 enable) { - switch (cmd) { + switch (cmd) + { case NV4097_SET_DITHER_ENABLE: enable ? glEnable(GL_DITHER) : glDisable(GL_DITHER); break; @@ -1696,6 +1697,10 @@ void GLGSRender::Enable(u32 cmd, u32 enable) enable ? glEnable(GL_DEPTH_BOUNDS_TEST_EXT) : glDisable(GL_DEPTH_BOUNDS_TEST_EXT); break; + case NV4097_SET_TWO_SIDED_STENCIL_TEST_ENABLE: + enable ? glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT) : glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT); + break; + case NV4097_SET_USER_CLIP_PLANE_CONTROL: const u32 clip_plane_0 = enable & 0xf; const u32 clip_plane_1 = (enable >> 4) & 0xf; @@ -1791,9 +1796,9 @@ void GLGSRender::PointSize(float size) checkForGlError("glPointSize"); } -void GLGSRender::LogicOp(u32 opcdoe) +void GLGSRender::LogicOp(u32 opcode) { - glLogicOp(opcdoe); + glLogicOp(opcode); checkForGlError("glLogicOp"); } @@ -1809,6 +1814,12 @@ void GLGSRender::LineStipple(u16 factor, u16 pattern) checkForGlError("glLineStipple"); } +void GLGSRender::PolygonStipple(u32 pattern) +{ + glPolygonStipple((const GLubyte*)pattern); + checkForGlError("glPolygonStipple"); +} + void GLGSRender::PrimitiveRestartIndex(u32 index) { glPrimitiveRestartIndex(index); @@ -1895,6 +1906,39 @@ void GLGSRender::Scissor(u16 x, u16 y, u16 width, u16 height) checkForGlError("glScissor"); } +void GLGSRender::StencilOp(u32 fail, u32 zfail, u32 zpass) +{ + glStencilOp(fail, zfail, zpass); + checkForGlError("glStencilOp"); +} + +void GLGSRender::StencilMask(u32 mask) +{ + glStencilMask(mask); + checkForGlError("glStencilMask"); +} + +void GLGSRender::StencilFunc(u32 func, u32 ref, u32 mask) +{ + glStencilFunc(func, ref, mask); + checkForGlError("glStencilFunc"); +} + +void GLGSRender::StencilOpSeparate(u32 mode, u32 fail, u32 zfail, u32 zpass) +{ + mode ? glStencilOpSeparate(GL_FRONT, fail, zfail, zpass) : glStencilOpSeparate(GL_BACK, fail, zfail, zpass); +} + +void GLGSRender::StencilMaskSeparate(u32 mode, u32 mask) +{ + mode ? glStencilMaskSeparate(GL_FRONT, mask) : glStencilMaskSeparate(GL_BACK, mask); +} + +void GLGSRender::StencilFuncSeparate(u32 mode, u32 func, u32 ref, u32 mask) +{ + mode ? glStencilFuncSeparate(GL_FRONT, func, ref, mask) : glStencilFuncSeparate(GL_BACK, func, ref, mask); +} + void GLGSRender::ExecCMD() { if (!LoadProgram()) @@ -1906,77 +1950,12 @@ void GLGSRender::ExecCMD() InitDrawBuffers(); - if (m_set_two_sided_stencil_test_enable) - { - if (m_set_stencil_fail && m_set_stencil_zfail && m_set_stencil_zpass) - { - glStencilOpSeparate(GL_FRONT, m_stencil_fail, m_stencil_zfail, m_stencil_zpass); - checkForGlError("glStencilOpSeparate"); - } - - if (m_set_stencil_mask) - { - glStencilMaskSeparate(GL_FRONT, m_stencil_mask); - checkForGlError("glStencilMaskSeparate"); - } - - if (m_set_stencil_func && m_set_stencil_func_ref && m_set_stencil_func_mask) - { - glStencilFuncSeparate(GL_FRONT, m_stencil_func, m_stencil_func_ref, m_stencil_func_mask); - checkForGlError("glStencilFuncSeparate"); - } - - if (m_set_back_stencil_fail && m_set_back_stencil_zfail && m_set_back_stencil_zpass) - { - glStencilOpSeparate(GL_BACK, m_back_stencil_fail, m_back_stencil_zfail, m_back_stencil_zpass); - checkForGlError("glStencilOpSeparate(GL_BACK)"); - } - - if (m_set_back_stencil_mask) - { - glStencilMaskSeparate(GL_BACK, m_back_stencil_mask); - checkForGlError("glStencilMaskSeparate(GL_BACK)"); - } - - if (m_set_back_stencil_func && m_set_back_stencil_func_ref && m_set_back_stencil_func_mask) - { - glStencilFuncSeparate(GL_BACK, m_back_stencil_func, m_back_stencil_func_ref, m_back_stencil_func_mask); - checkForGlError("glStencilFuncSeparate(GL_BACK)"); - } - } - else - { - if (m_set_stencil_fail && m_set_stencil_zfail && m_set_stencil_zpass) - { - glStencilOp(m_stencil_fail, m_stencil_zfail, m_stencil_zpass); - checkForGlError("glStencilOp"); - } - - if (m_set_stencil_mask) - { - glStencilMask(m_stencil_mask); - checkForGlError("glStencilMask"); - } - - if (m_set_stencil_func && m_set_stencil_func_ref && m_set_stencil_func_mask) - { - glStencilFunc(m_stencil_func, m_stencil_func_ref, m_stencil_func_mask); - checkForGlError("glStencilFunc"); - } - } - - if (m_set_polygon_stipple) - { - glPolygonStipple((const GLubyte*)m_polygon_stipple_pattern); - checkForGlError("glPolygonStipple"); - } - if (m_indexed_array.m_count && m_draw_array_count) { LOG_WARNING(RSX, "m_indexed_array.m_count && draw_array_count"); } - for (u32 i=0; i < m_textures_count; ++i) + for (u32 i = 0; i < m_textures_count; ++i) { if (!m_textures[i].IsEnabled()) continue; @@ -2055,12 +2034,6 @@ void GLGSRender::ExecCMD() void GLGSRender::Flip() { - if (m_set_scissor_horizontal && m_set_scissor_vertical) - { - glScissor(0, 0, RSXThread::m_width, RSXThread::m_height); - checkForGlError("glScissor"); - } - static u8* src_buffer = nullptr; static u32 width = 0; static u32 height = 0; @@ -2161,13 +2134,6 @@ void GLGSRender::Flip() m_frame->Flip(m_context); - // Restore scissor - if (m_set_scissor_horizontal && m_set_scissor_vertical) - { - glScissor(m_scissor_x, m_scissor_y, m_scissor_w, m_scissor_h); - checkForGlError("glScissor"); - } - } u32 LinearToSwizzleAddress(u32 x, u32 y, u32 z, u32 log2_width, u32 log2_height, u32 log2_depth) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index dbaa1135ea..7ab9f406d1 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -201,9 +201,10 @@ protected: virtual void DepthMask(u32 flag); virtual void PolygonMode(u32 face, u32 mode); virtual void PointSize(float size); - virtual void LogicOp(u32 opcdoe); + virtual void LogicOp(u32 opcode); virtual void LineWidth(float width); virtual void LineStipple(u16 factor, u16 pattern); + virtual void PolygonStipple(u32 pattern); virtual void PrimitiveRestartIndex(u32 index); virtual void CullFace(u32 mode); virtual void FrontFace(u32 mode); @@ -218,5 +219,11 @@ protected: virtual void ShadeModel(u32 mode); virtual void DepthBoundsEXT(float min, float max); virtual void Scissor(u16 x, u16 y, u16 width, u16 height); + virtual void StencilOp(u32 fail, u32 zfail, u32 zpass); + virtual void StencilMask(u32 mask); + virtual void StencilFunc(u32 func, u32 ref, u32 mask); + virtual void StencilOpSeparate(u32 mode, u32 fail, u32 zfail, u32 zpass); + virtual void StencilMaskSeparate(u32 mode, u32 mask); + virtual void StencilFuncSeparate(u32 mode, u32 func, u32 ref, u32 mask); virtual void Flip(); }; diff --git a/rpcs3/Emu/RSX/Null/NullGSRender.h b/rpcs3/Emu/RSX/Null/NullGSRender.h index de2167a8b7..53786c3b8e 100644 --- a/rpcs3/Emu/RSX/Null/NullGSRender.h +++ b/rpcs3/Emu/RSX/Null/NullGSRender.h @@ -26,9 +26,10 @@ private: virtual void DepthMask(u32 flag) {} virtual void PolygonMode(u32 face, u32 mode) {} virtual void PointSize(float size) {} - virtual void LogicOp(u32 opcdoe) {} + virtual void LogicOp(u32 opcode) {} virtual void LineWidth(float width) {} virtual void LineStipple(u16 factor, u16 pattern) {} + virtual void PolygonStipple(u32 pattern) {} virtual void PrimitiveRestartIndex(u32 index) {} virtual void CullFace(u32 mode) {} virtual void FrontFace(u32 mode) {} @@ -43,6 +44,12 @@ private: virtual void ShadeModel(u32 mode) {} virtual void DepthBoundsEXT(float min, float max) {} virtual void Scissor(u16 x, u16 y, u16 width, u16 height) {} + virtual void StencilOp(u32 fail, u32 zfail, u32 zpass) {} + virtual void StencilMask(u32 mask) {} + virtual void StencilFunc(u32 func, u32 ref, u32 mask) {} + virtual void StencilOpSeparate(u32 mode, u32 fail, u32 zfail, u32 zpass) {} + virtual void StencilMaskSeparate(u32 mode, u32 mask) {} + virtual void StencilFuncSeparate(u32 mode, u32 func, u32 ref, u32 mask) {} virtual void Flip() {} virtual void Close() {} }; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index e57931d415..660781eb51 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -1270,7 +1270,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_TWO_SIDED_STENCIL_TEST_ENABLE: { - m_set_two_sided_stencil_test_enable = ARGS(0) ? true : false; + const u32 value = ARGS(0); + Enable(cmd, ARGS(0)); } break; @@ -1283,84 +1284,85 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_STENCIL_MASK: { + const u32 value = ARGS(0); m_set_stencil_mask = true; - m_stencil_mask = ARGS(0); + StencilMask(value); } break; case NV4097_SET_STENCIL_FUNC: { - m_set_stencil_func = true; - m_stencil_func = ARGS(0); - - if (count >= 2) + if (count == 3) { - m_set_stencil_func_ref = true; + m_set_stencil_func = true; + m_stencil_func = ARGS(0); m_stencil_func_ref = ARGS(1); - - if (count >= 3) - { - m_set_stencil_func_mask = true; - m_stencil_func_mask = ARGS(2); - } + m_stencil_func_mask = ARGS(2); + StencilFunc(m_stencil_func, m_stencil_func_ref, m_stencil_func_mask); } } break; case NV4097_SET_STENCIL_FUNC_REF: { - m_set_stencil_func_ref = true; m_stencil_func_ref = ARGS(0); + + if (m_set_stencil_func) + { + StencilFunc(m_stencil_func, m_stencil_func_ref, m_stencil_func_mask); + } } break; case NV4097_SET_STENCIL_FUNC_MASK: { - m_set_stencil_func_mask = true; m_stencil_func_mask = ARGS(0); + + if (m_set_stencil_func) + { + StencilFunc(m_stencil_func, m_stencil_func_ref, m_stencil_func_mask); + } } break; case NV4097_SET_STENCIL_OP_FAIL: { - m_set_stencil_fail = true; - m_stencil_fail = ARGS(0); - - if (count >= 2) + if (count == 3) { - m_set_stencil_zfail = true; + m_set_stencil_op_fail = true; + m_stencil_fail = ARGS(0); m_stencil_zfail = ARGS(1); - - if (count >= 3) - { - m_set_stencil_zpass = true; - m_stencil_zpass = ARGS(2); - } + m_stencil_zpass = ARGS(2); + StencilOp(m_stencil_fail, m_stencil_zfail, m_stencil_zpass); } } break; case NV4097_SET_BACK_STENCIL_MASK: { - m_set_back_stencil_mask = true; m_back_stencil_mask = ARGS(0); + + StencilMaskSeparate(0, m_back_stencil_mask); // GL_BACK + + if (m_set_stencil_mask) + { + StencilMaskSeparate(1, m_stencil_mask); // GL_FRONT + } } break; case NV4097_SET_BACK_STENCIL_FUNC: { - m_set_back_stencil_func = true; - m_back_stencil_func = ARGS(0); - - if (count >= 2) + if (count == 3) { - m_set_back_stencil_func_ref = true; + m_set_back_stencil_func = true; + m_back_stencil_func = ARGS(0); m_back_stencil_func_ref = ARGS(1); - - if (count >= 3) + m_back_stencil_func_mask = ARGS(2); + StencilFuncSeparate(0, m_back_stencil_func, m_back_stencil_func_ref, m_back_stencil_func_mask); // GL_BACK + if (m_set_stencil_func) { - m_set_back_stencil_func_mask = true; - m_back_stencil_func_mask = ARGS(2); + StencilFuncSeparate(1, m_stencil_func, m_stencil_func_ref, m_stencil_func_mask); // GL_FRONT } } } @@ -1368,34 +1370,52 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_BACK_STENCIL_FUNC_REF: { - m_set_back_stencil_func_ref = true; m_back_stencil_func_ref = ARGS(0); + + if (m_set_back_stencil_func) + { + StencilFuncSeparate(0, m_back_stencil_func, m_back_stencil_func_ref, m_back_stencil_func_mask); // GL_BACK + + if (m_set_stencil_func) + { + StencilFuncSeparate(1, m_stencil_func, m_stencil_func_ref, m_stencil_func_mask); // GL_FRONT + } + } + } break; case NV4097_SET_BACK_STENCIL_FUNC_MASK: { - m_set_back_stencil_func_mask = true; m_back_stencil_func_mask = ARGS(0); + + if (m_set_back_stencil_func) + { + StencilFuncSeparate(0, m_back_stencil_func, m_back_stencil_func_ref, m_back_stencil_func_mask); // GL_BACK + + if (m_set_stencil_func) + { + StencilFuncSeparate(1, m_stencil_func, m_stencil_func_ref, m_stencil_func_mask); // GL_FRONT + } + } } break; case NV4097_SET_BACK_STENCIL_OP_FAIL: { - m_set_stencil_fail = true; - m_stencil_fail = ARGS(0); - - if (count >= 2) + if (count == 3) { - m_set_back_stencil_zfail = true; + m_back_stencil_fail = ARGS(0); m_back_stencil_zfail = ARGS(1); + m_back_stencil_zpass = ARGS(2); + StencilOpSeparate(0, m_back_stencil_fail, m_back_stencil_zfail, m_back_stencil_zpass); // GL_BACK - if (count >= 3) + if (m_set_stencil_op_fail) { - m_set_back_stencil_zpass = true; - m_back_stencil_zpass = ARGS(2); + StencilOpSeparate(1, m_stencil_fail, m_stencil_zfail, m_stencil_zpass); // GL_FRONT } } + } break; @@ -1764,9 +1784,11 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_POLYGON_STIPPLE_PATTERN: { + u32 pattern[32]; for (u32 i = 0; i < 32; i++) { - m_polygon_stipple_pattern[i] = ARGS(i); + pattern[i] = ARGS(i); + PolygonStipple(pattern[i]); } } break; diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index ed74dbf027..618573d21a 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -307,6 +307,7 @@ public: u32 m_back_stencil_zfail; bool m_set_back_stencil_zpass; u32 m_back_stencil_zpass; + bool m_set_stencil_op_fail; // Line width bool m_set_line_width; @@ -578,6 +579,7 @@ protected: m_set_back_stencil_fail = false; m_set_back_stencil_zfail = false; m_set_back_stencil_zpass = false; + m_set_stencil_op_fail = false; m_set_point_sprite_control = false; m_set_point_size = false; m_set_line_width = false; @@ -643,9 +645,10 @@ protected: virtual void DepthMask(u32 flag) = 0; virtual void PolygonMode(u32 face, u32 mode) = 0; virtual void PointSize(float size) = 0; - virtual void LogicOp(u32 opcdoe) = 0; + virtual void LogicOp(u32 opcode) = 0; virtual void LineWidth(float width) = 0; virtual void LineStipple(u16 factor, u16 pattern) = 0; + virtual void PolygonStipple(u32 pattern) = 0; virtual void PrimitiveRestartIndex(u32 index) = 0; virtual void CullFace(u32 mode) = 0; virtual void FrontFace(u32 mode) = 0; @@ -660,6 +663,12 @@ protected: virtual void ShadeModel(u32 mode) = 0; virtual void DepthBoundsEXT(float min, float max) = 0; virtual void Scissor(u16 x, u16 y, u16 width, u16 height) = 0; + virtual void StencilOp(u32 fail, u32 zfail, u32 zpass) = 0; + virtual void StencilMask(u32 mask) = 0; + virtual void StencilFunc(u32 func, u32 ref, u32 mask) = 0; + virtual void StencilOpSeparate(u32 mode, u32 fail, u32 zfail, u32 zpass) = 0; + virtual void StencilMaskSeparate(u32 mode, u32 mask) = 0; + virtual void StencilFuncSeparate(u32 mode, u32 func, u32 ref, u32 mask) = 0; virtual void Flip() = 0; void LoadVertexData(u32 first, u32 count)