mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-06-08 03:51:39 +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 {
|
struct GLStateManager {
|
||||||
bool blendEnabled;
|
bool blendEnabled;
|
||||||
bool depthEnabled;
|
bool depthEnabled;
|
||||||
|
bool scissorEnabled;
|
||||||
|
|
||||||
|
GLuint boundVAO;
|
||||||
|
GLuint boundVBO;
|
||||||
|
GLuint currentProgram;
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
void resetBlend();
|
void resetBlend();
|
||||||
void resetDepth();
|
void resetDepth();
|
||||||
|
void resetVAO();
|
||||||
|
void resetVBO();
|
||||||
|
void resetProgram();
|
||||||
|
void resetScissor();
|
||||||
|
|
||||||
void enableDepth() {
|
void enableDepth() {
|
||||||
if (!depthEnabled) {
|
if (!depthEnabled) {
|
||||||
|
@ -52,6 +61,45 @@ struct GLStateManager {
|
||||||
OpenGL::disableBlend();
|
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!");
|
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()) {
|
if (triangleProgram.exists()) {
|
||||||
const auto oldProgram = OpenGL::getProgram();
|
const auto oldProgram = OpenGL::getProgram();
|
||||||
|
|
||||||
triangleProgram.use();
|
gl.useProgram(triangleProgram);
|
||||||
oldAlphaControl = 0; // Default alpha control to 0
|
oldAlphaControl = 0; // Default alpha control to 0
|
||||||
oldTexUnitConfig = 0; // Default tex unit config to 0
|
oldTexUnitConfig = 0; // Default tex unit config to 0
|
||||||
|
|
||||||
|
@ -606,7 +606,7 @@ void Renderer::reset() {
|
||||||
glUniform1f(depthOffsetLoc, oldDepthOffset);
|
glUniform1f(depthOffsetLoc, oldDepthOffset);
|
||||||
glUniform1i(depthmapEnableLoc, oldDepthmapEnable);
|
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 vert(vertexShader, OpenGL::Vertex);
|
||||||
OpenGL::Shader frag(fragmentShader, OpenGL::Fragment);
|
OpenGL::Shader frag(fragmentShader, OpenGL::Fragment);
|
||||||
triangleProgram.create({ vert, frag });
|
triangleProgram.create({ vert, frag });
|
||||||
triangleProgram.use();
|
gl.useProgram(triangleProgram);
|
||||||
|
|
||||||
alphaControlLoc = OpenGL::uniformLocation(triangleProgram, "u_alphaControl");
|
alphaControlLoc = OpenGL::uniformLocation(triangleProgram, "u_alphaControl");
|
||||||
texUnitConfigLoc = OpenGL::uniformLocation(triangleProgram, "u_textureConfig");
|
texUnitConfigLoc = OpenGL::uniformLocation(triangleProgram, "u_textureConfig");
|
||||||
|
@ -642,13 +642,13 @@ void Renderer::initGraphicsContext() {
|
||||||
OpenGL::Shader fragDisplay(displayFragmentShader, OpenGL::Fragment);
|
OpenGL::Shader fragDisplay(displayFragmentShader, OpenGL::Fragment);
|
||||||
displayProgram.create({ vertDisplay, fragDisplay });
|
displayProgram.create({ vertDisplay, fragDisplay });
|
||||||
|
|
||||||
displayProgram.use();
|
gl.useProgram(displayProgram);
|
||||||
glUniform1i(OpenGL::uniformLocation(displayProgram, "u_texture"), 0); // Init sampler object
|
glUniform1i(OpenGL::uniformLocation(displayProgram, "u_texture"), 0); // Init sampler object
|
||||||
|
|
||||||
vbo.createFixedSize(sizeof(Vertex) * vertexBufferSize, GL_STREAM_DRAW);
|
vbo.createFixedSize(sizeof(Vertex) * vertexBufferSize, GL_STREAM_DRAW);
|
||||||
vbo.bind();
|
gl.bindVBO(vbo);
|
||||||
vao.create();
|
vao.create();
|
||||||
vao.bind();
|
gl.bindVAO(vao);
|
||||||
|
|
||||||
// Position (x, y, z, w) attributes
|
// Position (x, y, z, w) attributes
|
||||||
vao.setAttributeFloat<float>(0, 4, sizeof(Vertex), offsetof(Vertex, s.positions));
|
vao.setAttributeFloat<float>(0, 4, sizeof(Vertex), offsetof(Vertex, s.positions));
|
||||||
|
@ -725,9 +725,9 @@ void Renderer::setupBlending() {
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!blendingEnabled) {
|
if (!blendingEnabled) {
|
||||||
OpenGL::disableBlend();
|
gl.disableBlend();
|
||||||
} else {
|
} else {
|
||||||
OpenGL::enableBlend();
|
gl.enableBlend();
|
||||||
|
|
||||||
// Get blending equations
|
// Get blending equations
|
||||||
const u32 blendControl = regs[PICA::InternalRegs::BlendFunc];
|
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
|
// 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"
|
// 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
|
// And not actually perform the very expensive driver call for it
|
||||||
OpenGL::disableScissor();
|
gl.disableScissor();
|
||||||
|
|
||||||
vbo.bind();
|
gl.bindVBO(vbo);
|
||||||
vao.bind();
|
gl.bindVAO(vao);
|
||||||
triangleProgram.use();
|
gl.useProgram(triangleProgram);
|
||||||
|
|
||||||
// Adjust alpha test if necessary
|
// Adjust alpha test if necessary
|
||||||
const u32 alphaControl = regs[PICA::InternalRegs::AlphaTestConfig];
|
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
|
// 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
|
// Because it attaches a depth texture to the aforementioned colour buffer
|
||||||
if (depthEnable) {
|
if (depthEnable) {
|
||||||
OpenGL::enableDepth();
|
gl.enableDepth();
|
||||||
glDepthFunc(depthModes[depthFunc]);
|
glDepthFunc(depthModes[depthFunc]);
|
||||||
glDepthMask(depthWriteEnable ? GL_TRUE : GL_FALSE);
|
glDepthMask(depthWriteEnable ? GL_TRUE : GL_FALSE);
|
||||||
bindDepthBuffer();
|
bindDepthBuffer();
|
||||||
} else {
|
} else {
|
||||||
if (depthWriteEnable) {
|
if (depthWriteEnable) {
|
||||||
OpenGL::enableDepth();
|
gl.enableDepth();
|
||||||
glDepthFunc(GL_ALWAYS);
|
glDepthFunc(GL_ALWAYS);
|
||||||
glDepthMask(GL_TRUE);
|
glDepthMask(GL_TRUE);
|
||||||
bindDepthBuffer();
|
bindDepthBuffer();
|
||||||
} else {
|
} else {
|
||||||
OpenGL::disableDepth();
|
gl.disableDepth();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -947,7 +947,7 @@ constexpr u32 topScreenBuffer = 0x1f000000;
|
||||||
constexpr u32 bottomScreenBuffer = 0x1f05dc00;
|
constexpr u32 bottomScreenBuffer = 0x1f05dc00;
|
||||||
|
|
||||||
void Renderer::display() {
|
void Renderer::display() {
|
||||||
OpenGL::disableScissor();
|
gl.disableScissor();
|
||||||
|
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
screenFramebuffer.bind(OpenGL::ReadFramebuffer);
|
screenFramebuffer.bind(OpenGL::ReadFramebuffer);
|
||||||
|
@ -1038,12 +1038,14 @@ void Renderer::displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32
|
||||||
tex.bind();
|
tex.bind();
|
||||||
screenFramebuffer.bind(OpenGL::DrawFramebuffer);
|
screenFramebuffer.bind(OpenGL::DrawFramebuffer);
|
||||||
|
|
||||||
OpenGL::disableBlend();
|
gl.disableBlend();
|
||||||
OpenGL::disableDepth();
|
gl.disableDepth();
|
||||||
OpenGL::disableScissor();
|
gl.disableScissor();
|
||||||
|
gl.useProgram(displayProgram);
|
||||||
|
gl.bindVAO(dummyVAO);
|
||||||
|
|
||||||
OpenGL::disableClipPlane(0);
|
OpenGL::disableClipPlane(0);
|
||||||
OpenGL::disableClipPlane(1);
|
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
|
// 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
|
// 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
|
OpenGL::setViewport(0, 240, 400, 240); // Top screen viewport
|
||||||
}
|
}
|
||||||
|
|
||||||
dummyVAO.bind();
|
|
||||||
OpenGL::draw(OpenGL::TriangleStrip, 4); // Actually draw our 3DS screen
|
OpenGL::draw(OpenGL::TriangleStrip, 4); // Actually draw our 3DS screen
|
||||||
}
|
}
|
|
@ -10,7 +10,33 @@ void GLStateManager::resetDepth() {
|
||||||
OpenGL::disableDepth();
|
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() {
|
void GLStateManager::reset() {
|
||||||
resetBlend();
|
resetBlend();
|
||||||
resetDepth();
|
resetDepth();
|
||||||
|
|
||||||
|
resetVAO();
|
||||||
|
resetVBO();
|
||||||
|
resetProgram();
|
||||||
|
resetScissor();
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue