mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-11 08:39:48 +12:00
More OpenGL state management stuff
This commit is contained in:
parent
e01f0ea4d0
commit
139c8759c9
3 changed files with 96 additions and 21 deletions
|
@ -20,10 +20,19 @@
|
|||
struct GLStateManager {
|
||||
bool blendEnabled;
|
||||
bool depthEnabled;
|
||||
bool scissorEnabled;
|
||||
|
||||
GLuint boundVAO;
|
||||
GLuint boundVBO;
|
||||
GLuint currentProgram;
|
||||
|
||||
void reset();
|
||||
void resetBlend();
|
||||
void resetDepth();
|
||||
void resetVAO();
|
||||
void resetVBO();
|
||||
void resetProgram();
|
||||
void resetScissor();
|
||||
|
||||
void enableDepth() {
|
||||
if (!depthEnabled) {
|
||||
|
@ -52,6 +61,45 @@ struct GLStateManager {
|
|||
OpenGL::disableBlend();
|
||||
}
|
||||
}
|
||||
|
||||
void enableScissor() {
|
||||
if (!scissorEnabled) {
|
||||
scissorEnabled = true;
|
||||
OpenGL::enableScissor();
|
||||
}
|
||||
}
|
||||
|
||||
void disableScissor() {
|
||||
if (scissorEnabled) {
|
||||
scissorEnabled = false;
|
||||
OpenGL::disableScissor();
|
||||
}
|
||||
}
|
||||
|
||||
void bindVAO(GLuint handle) {
|
||||
if (boundVAO != handle) {
|
||||
boundVAO = handle;
|
||||
glBindVertexArray(handle);
|
||||
}
|
||||
}
|
||||
|
||||
void bindVBO(GLuint handle) {
|
||||
if (boundVBO != handle) {
|
||||
boundVBO = handle;
|
||||
glBindBuffer(GL_ARRAY_BUFFER, handle);
|
||||
}
|
||||
}
|
||||
|
||||
void useProgram(GLuint handle) {
|
||||
if (currentProgram != handle) {
|
||||
currentProgram = handle;
|
||||
glUseProgram(handle);
|
||||
}
|
||||
}
|
||||
|
||||
void bindVAO(const OpenGL::VertexArray& vao) { bindVAO(vao.handle()); }
|
||||
void bindVBO(const OpenGL::VertexBuffer& vbo) { bindVBO(vbo.handle()); }
|
||||
void useProgram(const OpenGL::Program& program) { useProgram(program.handle()); }
|
||||
};
|
||||
|
||||
static_assert(std::is_trivially_constructible<GLStateManager>(), "OpenGL State Manager class is not trivially constructible!");
|
||||
|
|
|
@ -592,7 +592,7 @@ void Renderer::reset() {
|
|||
if (triangleProgram.exists()) {
|
||||
const auto oldProgram = OpenGL::getProgram();
|
||||
|
||||
triangleProgram.use();
|
||||
gl.useProgram(triangleProgram);
|
||||
oldAlphaControl = 0; // Default alpha control to 0
|
||||
oldTexUnitConfig = 0; // Default tex unit config to 0
|
||||
|
||||
|
@ -606,7 +606,7 @@ void Renderer::reset() {
|
|||
glUniform1f(depthOffsetLoc, oldDepthOffset);
|
||||
glUniform1i(depthmapEnableLoc, oldDepthmapEnable);
|
||||
|
||||
glUseProgram(oldProgram); // Switch to old GL program
|
||||
gl.useProgram(oldProgram); // Switch to old GL program
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -614,7 +614,7 @@ void Renderer::initGraphicsContext() {
|
|||
OpenGL::Shader vert(vertexShader, OpenGL::Vertex);
|
||||
OpenGL::Shader frag(fragmentShader, OpenGL::Fragment);
|
||||
triangleProgram.create({ vert, frag });
|
||||
triangleProgram.use();
|
||||
gl.useProgram(triangleProgram);
|
||||
|
||||
alphaControlLoc = OpenGL::uniformLocation(triangleProgram, "u_alphaControl");
|
||||
texUnitConfigLoc = OpenGL::uniformLocation(triangleProgram, "u_textureConfig");
|
||||
|
@ -642,13 +642,13 @@ void Renderer::initGraphicsContext() {
|
|||
OpenGL::Shader fragDisplay(displayFragmentShader, OpenGL::Fragment);
|
||||
displayProgram.create({ vertDisplay, fragDisplay });
|
||||
|
||||
displayProgram.use();
|
||||
gl.useProgram(displayProgram);
|
||||
glUniform1i(OpenGL::uniformLocation(displayProgram, "u_texture"), 0); // Init sampler object
|
||||
|
||||
vbo.createFixedSize(sizeof(Vertex) * vertexBufferSize, GL_STREAM_DRAW);
|
||||
vbo.bind();
|
||||
gl.bindVBO(vbo);
|
||||
vao.create();
|
||||
vao.bind();
|
||||
gl.bindVAO(vao);
|
||||
|
||||
// Position (x, y, z, w) attributes
|
||||
vao.setAttributeFloat<float>(0, 4, sizeof(Vertex), offsetof(Vertex, s.positions));
|
||||
|
@ -725,9 +725,9 @@ void Renderer::setupBlending() {
|
|||
};
|
||||
|
||||
if (!blendingEnabled) {
|
||||
OpenGL::disableBlend();
|
||||
gl.disableBlend();
|
||||
} else {
|
||||
OpenGL::enableBlend();
|
||||
gl.enableBlend();
|
||||
|
||||
// Get blending equations
|
||||
const u32 blendControl = regs[PICA::InternalRegs::BlendFunc];
|
||||
|
@ -852,11 +852,11 @@ void Renderer::drawVertices(PICA::PrimType primType, std::span<const Vertex> ver
|
|||
// TODO: We should implement a GL state tracker that tracks settings like scissor, blending, bound program, etc
|
||||
// This way if we attempt to eg do multiple glEnable(GL_BLEND) calls in a row, it will say "Oh blending is already enabled"
|
||||
// And not actually perform the very expensive driver call for it
|
||||
OpenGL::disableScissor();
|
||||
gl.disableScissor();
|
||||
|
||||
vbo.bind();
|
||||
vao.bind();
|
||||
triangleProgram.use();
|
||||
gl.bindVBO(vbo);
|
||||
gl.bindVAO(vao);
|
||||
gl.useProgram(triangleProgram);
|
||||
|
||||
// Adjust alpha test if necessary
|
||||
const u32 alphaControl = regs[PICA::InternalRegs::AlphaTestConfig];
|
||||
|
@ -924,18 +924,18 @@ void Renderer::drawVertices(PICA::PrimType primType, std::span<const Vertex> ver
|
|||
// Note: The code below must execute after we've bound the colour buffer & its framebuffer
|
||||
// Because it attaches a depth texture to the aforementioned colour buffer
|
||||
if (depthEnable) {
|
||||
OpenGL::enableDepth();
|
||||
gl.enableDepth();
|
||||
glDepthFunc(depthModes[depthFunc]);
|
||||
glDepthMask(depthWriteEnable ? GL_TRUE : GL_FALSE);
|
||||
bindDepthBuffer();
|
||||
} else {
|
||||
if (depthWriteEnable) {
|
||||
OpenGL::enableDepth();
|
||||
gl.enableDepth();
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
glDepthMask(GL_TRUE);
|
||||
bindDepthBuffer();
|
||||
} else {
|
||||
OpenGL::disableDepth();
|
||||
gl.disableDepth();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -947,7 +947,7 @@ constexpr u32 topScreenBuffer = 0x1f000000;
|
|||
constexpr u32 bottomScreenBuffer = 0x1f05dc00;
|
||||
|
||||
void Renderer::display() {
|
||||
OpenGL::disableScissor();
|
||||
gl.disableScissor();
|
||||
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
screenFramebuffer.bind(OpenGL::ReadFramebuffer);
|
||||
|
@ -1038,12 +1038,14 @@ void Renderer::displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32
|
|||
tex.bind();
|
||||
screenFramebuffer.bind(OpenGL::DrawFramebuffer);
|
||||
|
||||
OpenGL::disableBlend();
|
||||
OpenGL::disableDepth();
|
||||
OpenGL::disableScissor();
|
||||
gl.disableBlend();
|
||||
gl.disableDepth();
|
||||
gl.disableScissor();
|
||||
gl.useProgram(displayProgram);
|
||||
gl.bindVAO(dummyVAO);
|
||||
|
||||
OpenGL::disableClipPlane(0);
|
||||
OpenGL::disableClipPlane(1);
|
||||
displayProgram.use();
|
||||
|
||||
// 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
|
||||
|
@ -1053,6 +1055,5 @@ void Renderer::displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32
|
|||
OpenGL::setViewport(0, 240, 400, 240); // Top screen viewport
|
||||
}
|
||||
|
||||
dummyVAO.bind();
|
||||
OpenGL::draw(OpenGL::TriangleStrip, 4); // Actually draw our 3DS screen
|
||||
}
|
|
@ -10,7 +10,33 @@ void GLStateManager::resetDepth() {
|
|||
OpenGL::disableDepth();
|
||||
}
|
||||
|
||||
void GLStateManager::resetScissor() {
|
||||
scissorEnabled = false;
|
||||
OpenGL::disableScissor();
|
||||
OpenGL::setScissor(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void GLStateManager::resetVAO() {
|
||||
boundVAO = 0;
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void GLStateManager::resetVBO() {
|
||||
boundVBO = 0;
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
void GLStateManager::resetProgram() {
|
||||
currentProgram = 0;
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
void GLStateManager::reset() {
|
||||
resetBlend();
|
||||
resetDepth();
|
||||
|
||||
resetVAO();
|
||||
resetVBO();
|
||||
resetProgram();
|
||||
resetScissor();
|
||||
}
|
Loading…
Add table
Reference in a new issue