diff --git a/include/renderer_gl/gl_state.hpp b/include/renderer_gl/gl_state.hpp index a6c8d1f9..98f589e0 100644 --- a/include/renderer_gl/gl_state.hpp +++ b/include/renderer_gl/gl_state.hpp @@ -34,11 +34,13 @@ struct GLStateManager { bool redMask, greenMask, blueMask, alphaMask; bool depthMask; + GLuint stencilMask; GLuint boundVAO; GLuint boundVBO; GLuint currentProgram; GLenum depthFunc; + GLenum logicOp; void reset(); void resetBlend(); @@ -121,6 +123,13 @@ struct GLStateManager { } } + void setLogicOp(GLenum op) { + if (logicOp != op) { + logicOp = op; + OpenGL::setLogicOp(op); + } + } + void enableClipPlane(GLuint index) { if (index >= clipPlaneCount) [[unlikely]] { Helpers::panic("Enabled invalid clipping plane %d\n", index); @@ -143,6 +152,13 @@ struct GLStateManager { } } + void setStencilMask(GLuint mask) { + if (stencilMask != mask) { + stencilMask = mask; + OpenGL::setStencilMask(mask); + } + } + void bindVAO(GLuint handle) { if (boundVAO != handle) { boundVAO = handle; diff --git a/include/renderer_gl/opengl.hpp b/include/renderer_gl/opengl.hpp index 8a52b1d6..e129f6b6 100644 --- a/include/renderer_gl/opengl.hpp +++ b/include/renderer_gl/opengl.hpp @@ -497,42 +497,45 @@ namespace OpenGL { }; static void setClearColor(float val) { glClearColor(val, val, val, val); } - static void setClearColor(float r, float g, float b, float a) { glClearColor(r, g, b, a); } - static void setClearDepth(float depth) { glClearDepthf(depth); } - static void setClearStencil(GLint stencil) { glClearStencil(stencil); } - static void clearColor() { glClear(GL_COLOR_BUFFER_BIT); } - static void clearDepth() { glClear(GL_DEPTH_BUFFER_BIT); } - static void clearStencil() { glClear(GL_STENCIL_BUFFER_BIT); } - static void clearColorAndDepth() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } - static void clearColorAndStencil() { glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } - static void clearDepthAndStencil() { glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } - static void clearAll() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } + static void setClearColor(float r, float g, float b, float a) { glClearColor(r, g, b, a); } + static void setClearDepth(float depth) { glClearDepthf(depth); } + static void setClearStencil(GLint stencil) { glClearStencil(stencil); } + static void clearColor() { glClear(GL_COLOR_BUFFER_BIT); } + static void clearDepth() { glClear(GL_DEPTH_BUFFER_BIT); } + static void clearStencil() { glClear(GL_STENCIL_BUFFER_BIT); } + static void clearColorAndDepth() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } + static void clearColorAndStencil() { glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } + static void clearDepthAndStencil() { glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } + static void clearAll() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } - static void setViewport(GLsizei width, GLsizei height) { glViewport(0, 0, width, height); } - static void setViewport(GLsizei x, GLsizei y, GLsizei width, GLsizei height) { glViewport(x, y, width, height); } - static void setScissor(GLsizei width, GLsizei height) { glScissor(0, 0, width, height); } - static void setScissor(GLsizei x, GLsizei y, GLsizei width, GLsizei height) { glScissor(x, y, width, height); } - static void setStencilMask(GLuint mask) { glStencilMask(mask); } + static void setViewport(GLsizei width, GLsizei height) { glViewport(0, 0, width, height); } + static void setViewport(GLsizei x, GLsizei y, GLsizei width, GLsizei height) { glViewport(x, y, width, height); } + static void setScissor(GLsizei width, GLsizei height) { glScissor(0, 0, width, height); } + static void setScissor(GLsizei x, GLsizei y, GLsizei width, GLsizei height) { glScissor(x, y, width, height); } + static void setStencilMask(GLuint mask) { glStencilMask(mask); } - static void bindScreenFramebuffer() { glBindFramebuffer(GL_FRAMEBUFFER, 0); } - static void enableScissor() { glEnable(GL_SCISSOR_TEST); } - static void disableScissor() { glDisable(GL_SCISSOR_TEST); } - static void enableBlend() { glEnable(GL_BLEND); } - static void disableBlend() { glDisable(GL_BLEND); } + static void bindScreenFramebuffer() { glBindFramebuffer(GL_FRAMEBUFFER, 0); } + static void enableScissor() { glEnable(GL_SCISSOR_TEST); } + static void disableScissor() { glDisable(GL_SCISSOR_TEST); } + static void enableBlend() { glEnable(GL_BLEND); } + static void disableBlend() { glDisable(GL_BLEND); } static void enableLogicOp() { glEnable(GL_COLOR_LOGIC_OP); } static void disableLogicOp() { glDisable(GL_COLOR_LOGIC_OP); } - static void enableDepth() { glEnable(GL_DEPTH_TEST); } - static void disableDepth() { glDisable(GL_DEPTH_TEST); } - static void enableStencil() { glEnable(GL_STENCIL_TEST); } - static void disableStencil() { glDisable(GL_STENCIL_TEST); } + static void enableDepth() { glEnable(GL_DEPTH_TEST); } + static void disableDepth() { glDisable(GL_DEPTH_TEST); } + static void enableStencil() { glEnable(GL_STENCIL_TEST); } + static void disableStencil() { glDisable(GL_STENCIL_TEST); } - static void enableClipPlane(GLuint index) { glEnable(GL_CLIP_DISTANCE0 + index); } + static void enableClipPlane(GLuint index) { glEnable(GL_CLIP_DISTANCE0 + index); } static void disableClipPlane(GLuint index) { glDisable(GL_CLIP_DISTANCE0 + index); } - static void setDepthFunc(DepthFunc func) { glDepthFunc(static_cast(func)); } + static void setDepthFunc(DepthFunc func) { glDepthFunc(static_cast(func)); } static void setColourMask(GLboolean r, GLboolean g, GLboolean b, GLboolean a) { glColorMask(r, g, b, a); } static void setDepthMask(GLboolean mask) { glDepthMask(mask); } + // TODO: Add a proper enum for this + static void setLogicOp(GLenum op) { glLogicOp(op); } + enum Primitives { Triangle = GL_TRIANGLES, Triangles = Triangle, diff --git a/src/core/renderer_gl/gl_state.cpp b/src/core/renderer_gl/gl_state.cpp index 6d073128..4a512f44 100644 --- a/src/core/renderer_gl/gl_state.cpp +++ b/src/core/renderer_gl/gl_state.cpp @@ -3,9 +3,11 @@ void GLStateManager::resetBlend() { blendEnabled = false; logicOpEnabled = false; + logicOp = GL_COPY; OpenGL::disableBlend(); OpenGL::disableLogicOp(); + OpenGL::setLogicOp(GL_COPY); } void GLStateManager::resetClipping() { @@ -39,7 +41,10 @@ void GLStateManager::resetScissor() { void GLStateManager::resetStencil() { stencilEnabled = false; + stencilMask = 0xff; + OpenGL::disableStencil(); + OpenGL::setStencilMask(0xff); } void GLStateManager::resetVAO() { diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index ddbffd98..f140893d 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -184,7 +184,7 @@ void RendererGL::setupBlending() { if (!blendingEnabled) { // Logic ops are enabled const u32 logicOp = getBits<0, 4>(regs[PICA::InternalRegs::LogicOp]); - glLogicOp(logicOps[logicOp]); + gl.setLogicOp(logicOps[logicOp]); // If logic ops are enabled we don't need to disable blending because they override it gl.enableLogicOp(); @@ -243,7 +243,7 @@ void RendererGL::setupStencilTest(bool stencilEnable) { const u32 stencilBufferMask = stencilWrite ? getBits<8, 8>(stencilConfig) : 0; glStencilFunc(stencilFuncs[stencilFunc], reference, stencilRefMask); - glStencilMask(stencilBufferMask); + gl.setStencilMask(stencilBufferMask); static constexpr std::array stencilOps = { GL_KEEP, @@ -489,7 +489,7 @@ void RendererGL::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 co if (format == DepthFmt::Depth24Stencil8) { const u8 stencil = (value >> 24); - OpenGL::setStencilMask(0xff); + gl.setStencilMask(0xff); OpenGL::setClearStencil(stencil); OpenGL::clearDepthAndStencil(); } else {