[GL] More state stuff

This commit is contained in:
wheremyfoodat 2023-07-28 01:35:49 +03:00
parent 64fa970468
commit adb78bf838
4 changed files with 67 additions and 7 deletions

View file

@ -1,6 +1,7 @@
#pragma once
#include <type_traits>
#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;

View file

@ -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); }

View file

@ -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();

View file

@ -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<const Vertex> 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