From adb78bf838ef50b71e7880a44a8375bd92fae10d Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Fri, 28 Jul 2023 01:35:49 +0300 Subject: [PATCH] [GL] More state stuff --- include/renderer_gl/gl_state.hpp | 44 ++++++++++++++++++++++++++++ include/renderer_gl/opengl.hpp | 2 ++ src/core/renderer_gl/gl_state.cpp | 12 ++++++++ src/core/renderer_gl/renderer_gl.cpp | 16 +++++----- 4 files changed, 67 insertions(+), 7 deletions(-) diff --git a/include/renderer_gl/gl_state.hpp b/include/renderer_gl/gl_state.hpp index 78e8a386..a6c8d1f9 100644 --- a/include/renderer_gl/gl_state.hpp +++ b/include/renderer_gl/gl_state.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include "helpers.hpp" #include "opengl.hpp" // GL state manager object for use in the OpenGL GPU renderer and potentially other things in the future (such as a potential ImGui GUI) @@ -18,10 +19,16 @@ // backend-agnostic as possible struct GLStateManager { + // We only support 6 clipping planes in our state manager because that's the minimum for GL_MAX_CLIP_PLANES + // And nobody needs more than 6 clip planes anyways + static constexpr GLint clipPlaneCount = 6; + bool blendEnabled; + bool logicOpEnabled; bool depthEnabled; bool scissorEnabled; bool stencilEnabled; + u32 enabledClipPlanes; // Bitfield of enabled clip planes // Colour/depth masks bool redMask, greenMask, blueMask, alphaMask; @@ -35,6 +42,7 @@ struct GLStateManager { void reset(); void resetBlend(); + void resetClipping(); void resetColourMask(); void resetDepth(); void resetVAO(); @@ -99,6 +107,42 @@ struct GLStateManager { } } + void enableLogicOp() { + if (!logicOpEnabled) { + logicOpEnabled = true; + OpenGL::enableLogicOp(); + } + } + + void disableLogicOp() { + if (logicOpEnabled) { + logicOpEnabled = false; + OpenGL::disableLogicOp(); + } + } + + void enableClipPlane(GLuint index) { + if (index >= clipPlaneCount) [[unlikely]] { + Helpers::panic("Enabled invalid clipping plane %d\n", index); + } + + if ((enabledClipPlanes & (1 << index)) == 0) { + enabledClipPlanes |= 1 << index; // Enable relevant bit in clipping plane bitfield + OpenGL::enableClipPlane(index); // Enable plane + } + } + + void disableClipPlane(GLuint index) { + if (index >= clipPlaneCount) [[unlikely]] { + Helpers::panic("Disabled invalid clipping plane %d\n", index); + } + + if ((enabledClipPlanes & (1 << index)) != 0) { + enabledClipPlanes ^= 1 << index; // Disable relevant bit in bitfield by flipping it + OpenGL::disableClipPlane(index); // Disable plane + } + } + void bindVAO(GLuint handle) { if (boundVAO != handle) { boundVAO = handle; diff --git a/include/renderer_gl/opengl.hpp b/include/renderer_gl/opengl.hpp index c1ceb4c7..8a52b1d6 100644 --- a/include/renderer_gl/opengl.hpp +++ b/include/renderer_gl/opengl.hpp @@ -519,6 +519,8 @@ namespace OpenGL { 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); } diff --git a/src/core/renderer_gl/gl_state.cpp b/src/core/renderer_gl/gl_state.cpp index e965f944..6d073128 100644 --- a/src/core/renderer_gl/gl_state.cpp +++ b/src/core/renderer_gl/gl_state.cpp @@ -2,7 +2,18 @@ void GLStateManager::resetBlend() { blendEnabled = false; + logicOpEnabled = false; + OpenGL::disableBlend(); + OpenGL::disableLogicOp(); +} + +void GLStateManager::resetClipping() { + // Disable all (supported) clip planes + enabledClipPlanes = 0; + for (int i = 0; i < clipPlaneCount; i++) { + OpenGL::disableClipPlane(i); + } } void GLStateManager::resetColourMask() { @@ -48,6 +59,7 @@ void GLStateManager::resetProgram() { void GLStateManager::reset() { resetBlend(); + resetClipping(); resetColourMask(); resetDepth(); diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index e41dd2bd..ddbffd98 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -185,10 +185,12 @@ void RendererGL::setupBlending() { if (!blendingEnabled) { // Logic ops are enabled const u32 logicOp = getBits<0, 4>(regs[PICA::InternalRegs::LogicOp]); glLogicOp(logicOps[logicOp]); - glEnable(GL_COLOR_LOGIC_OP); + + // If logic ops are enabled we don't need to disable blending because they override it + gl.enableLogicOp(); } else { gl.enableBlend(); - glDisable(GL_COLOR_LOGIC_OP); + gl.disableLogicOp(); // Get blending equations const u32 blendControl = regs[PICA::InternalRegs::BlendFunc]; @@ -359,9 +361,9 @@ void RendererGL::drawVertices(PICA::PrimType primType, std::span v gl.bindVAO(vao); gl.useProgram(triangleProgram); - OpenGL::enableClipPlane(0); // Clipping plane 0 is always enabled + gl.enableClipPlane(0); // Clipping plane 0 is always enabled if (regs[PICA::InternalRegs::ClipEnable] & 1) { - OpenGL::enableClipPlane(1); + gl.enableClipPlane(1); } setupBlending(); @@ -563,7 +565,7 @@ void RendererGL::displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u screenFramebuffer.bind(OpenGL::DrawFramebuffer); gl.disableBlend(); - glDisable(GL_COLOR_LOGIC_OP); + gl.disableLogicOp(); gl.disableDepth(); gl.disableScissor(); gl.disableStencil(); @@ -571,8 +573,8 @@ void RendererGL::displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u gl.useProgram(displayProgram); gl.bindVAO(dummyVAO); - OpenGL::disableClipPlane(0); - OpenGL::disableClipPlane(1); + gl.disableClipPlane(0); + gl.disableClipPlane(1); // Hack: Detect whether we are writing to the top or bottom screen by checking output gap and drawing to the proper part of the output texture // We consider output gap == 320 to mean bottom, and anything else to mean top