Add clear colour to GL state manager

This commit is contained in:
wheremyfoodat 2023-08-12 17:02:00 +03:00
parent 4107a84c0d
commit 0f5c41cd69
4 changed files with 138 additions and 128 deletions

View file

@ -34,6 +34,8 @@ struct GLStateManager {
bool redMask, greenMask, blueMask, alphaMask; bool redMask, greenMask, blueMask, alphaMask;
bool depthMask; bool depthMask;
float clearRed, clearBlue, clearGreen, clearAlpha;
GLuint stencilMask; GLuint stencilMask;
GLuint boundVAO; GLuint boundVAO;
GLuint boundVBO; GLuint boundVBO;
@ -44,6 +46,7 @@ struct GLStateManager {
void reset(); void reset();
void resetBlend(); void resetBlend();
void resetClearing();
void resetClipping(); void resetClipping();
void resetColourMask(); void resetColourMask();
void resetDepth(); void resetDepth();
@ -209,6 +212,17 @@ struct GLStateManager {
} }
} }
void setClearColour(float r, float g, float b, float a) {
if (clearRed != r || clearGreen != g || clearBlue != b || clearAlpha != a) {
clearRed = r;
clearGreen = g;
clearBlue = b;
clearAlpha = a;
OpenGL::setClearColor(r, g, b, a);
}
}
void setDepthFunc(OpenGL::DepthFunc func) { setDepthFunc(static_cast<GLenum>(func)); } void setDepthFunc(OpenGL::DepthFunc func) { setDepthFunc(static_cast<GLenum>(func)); }
}; };

View file

@ -20,46 +20,20 @@ struct ColourBuffer {
OpenGL::Texture texture; OpenGL::Texture texture;
OpenGL::Framebuffer fbo; OpenGL::Framebuffer fbo;
GLenum internalFormat;
GLenum fmt;
GLenum type;
ColourBuffer() : valid(false) {} ColourBuffer() : valid(false) {}
ColourBuffer(u32 loc, PICA::ColorFmt format, u32 x, u32 y, bool valid = true) ColourBuffer(u32 loc, PICA::ColorFmt format, u32 x, u32 y, bool valid = true) : location(loc), format(format), size({x, y}), valid(valid) {
: location(loc), format(format), size({x, y}), valid(valid) {
u64 endLoc = (u64)loc + sizeInBytes(); u64 endLoc = (u64)loc + sizeInBytes();
// Check if start and end are valid here // Check if start and end are valid here
range = Interval<u32>(loc, (u32)endLoc); range = Interval<u32>(loc, (u32)endLoc);
} }
void allocate() { void allocate() {
// Internal formats for the texture based on format
static constexpr std::array<GLenum, 5> internalFormats = {
GL_RGBA8, GL_RGB8, GL_RGB5_A1, GL_RGB565, GL_RGBA4
};
// Format of the texture
static constexpr std::array<GLenum, 5> formats = {
GL_RGBA, GL_BGR, GL_RGBA, GL_RGB, GL_RGBA,
};
static constexpr std::array<GLenum, 5> types = {
GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_5_5_1,
GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_4_4_4_4,
};
internalFormat = internalFormats[(int)format];
fmt = formats[(int)format];
type = types[(int)format];
// Create texture for the FBO, setting up filters and the like // Create texture for the FBO, setting up filters and the like
// Reading back the current texture is slow, but allocate calls should be few and far between. // Reading back the current texture is slow, but allocate calls should be few and far between.
// If this becomes a bottleneck, we can fix it semi-easily // If this becomes a bottleneck, we can fix it semi-easily
auto prevTexture = OpenGL::getTex2D(); auto prevTexture = OpenGL::getTex2D();
texture.create(size.x(), size.y(), internalFormat); texture.create(size.x(), size.y(), GL_RGBA8);
texture.bind(); texture.bind();
texture.setMinFilter(OpenGL::Linear); texture.setMinFilter(OpenGL::Linear);
texture.setMagFilter(OpenGL::Linear); texture.setMagFilter(OpenGL::Linear);
@ -73,16 +47,22 @@ struct ColourBuffer {
fbo.createWithDrawTexture(texture); fbo.createWithDrawTexture(texture);
fbo.bind(OpenGL::DrawAndReadFramebuffer); fbo.bind(OpenGL::DrawAndReadFramebuffer);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
Helpers::panic("Incomplete framebuffer"); Helpers::panic("Incomplete framebuffer");
}
// TODO: This should not clear the framebuffer contents. It should load them from VRAM. // TODO: This should not clear the framebuffer contents. It should load them from VRAM.
GLint oldViewport[4]; GLint oldViewport[4];
GLfloat oldClearColour[4];
glGetIntegerv(GL_VIEWPORT, oldViewport); glGetIntegerv(GL_VIEWPORT, oldViewport);
glGetFloatv(GL_COLOR_CLEAR_VALUE, oldClearColour);
OpenGL::setViewport(size.x(), size.y()); OpenGL::setViewport(size.x(), size.y());
OpenGL::setClearColor(0.0, 0.0, 0.0, 1.0); OpenGL::setClearColor(0.0, 0.0, 0.0, 1.0);
OpenGL::clearColor(); OpenGL::clearColor();
OpenGL::setViewport(oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]); OpenGL::setViewport(oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]);
OpenGL::setClearColor(oldClearColour[0], oldClearColour[1], oldClearColour[2], oldClearColour[3]);
} }
void free() { void free() {
@ -104,8 +84,7 @@ struct ColourBuffer {
} }
bool matches(ColourBuffer& other) { bool matches(ColourBuffer& other) {
return location == other.location && format == other.format && return location == other.location && format == other.format && size.x() == other.size.x() && size.y() == other.size.y();
size.x() == other.size.x() && size.y() == other.size.y();
} }
size_t sizeInBytes() { size_t sizeInBytes() {
@ -127,9 +106,7 @@ struct DepthBuffer {
DepthBuffer() : valid(false) {} DepthBuffer() : valid(false) {}
DepthBuffer(u32 loc, PICA::DepthFmt format, u32 x, u32 y, bool valid = true) : DepthBuffer(u32 loc, PICA::DepthFmt format, u32 x, u32 y, bool valid = true) : location(loc), format(format), size({x, y}), valid(valid) {
location(loc), format(format), size({x, y}), valid(valid) {
u64 endLoc = (u64)loc + sizeInBytes(); u64 endLoc = (u64)loc + sizeInBytes();
// Check if start and end are valid here // Check if start and end are valid here
range = Interval<u32>(loc, (u32)endLoc); range = Interval<u32>(loc, (u32)endLoc);
@ -143,16 +120,25 @@ struct DepthBuffer {
// Internal formats for the texture based on format // Internal formats for the texture based on format
static constexpr std::array<GLenum, 4> internalFormats = { static constexpr std::array<GLenum, 4> internalFormats = {
GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT24, GL_DEPTH24_STENCIL8 GL_DEPTH_COMPONENT16,
GL_DEPTH_COMPONENT24,
GL_DEPTH_COMPONENT24,
GL_DEPTH24_STENCIL8,
}; };
// Format of the texture // Format of the texture
static constexpr std::array<GLenum, 4> formats = { static constexpr std::array<GLenum, 4> formats = {
GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL GL_DEPTH_COMPONENT,
GL_DEPTH_COMPONENT,
GL_DEPTH_COMPONENT,
GL_DEPTH_STENCIL,
}; };
static constexpr std::array<GLenum, 4> types = { static constexpr std::array<GLenum, 4> types = {
GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT_24_8 GL_UNSIGNED_SHORT,
GL_UNSIGNED_INT,
GL_UNSIGNED_INT,
GL_UNSIGNED_INT_24_8,
}; };
auto internalFormat = internalFormats[(int)format]; auto internalFormat = internalFormats[(int)format];
@ -165,12 +151,12 @@ struct DepthBuffer {
texture.setMagFilter(OpenGL::Nearest); texture.setMagFilter(OpenGL::Nearest);
glBindTexture(GL_TEXTURE_2D, prevTexture); glBindTexture(GL_TEXTURE_2D, prevTexture);
fbo.createWithDrawTexture(texture, fmt == GL_DEPTH_STENCIL ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT); fbo.createWithDrawTexture(texture, fmt == GL_DEPTH_STENCIL ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
Helpers::panic("Incomplete framebuffer"); Helpers::panic("Incomplete framebuffer");
} }
}
void free() { void free() {
valid = false; valid = false;
@ -180,8 +166,7 @@ struct DepthBuffer {
} }
bool matches(DepthBuffer& other) { bool matches(DepthBuffer& other) {
return location == other.location && format == other.format && return location == other.location && format == other.format && size.x() == other.size.x() && size.y() == other.size.y();
size.x() == other.size.x() && size.y() == other.size.y();
} }
size_t sizeInBytes() { size_t sizeInBytes() {

View file

@ -10,6 +10,15 @@ void GLStateManager::resetBlend() {
OpenGL::setLogicOp(GL_COPY); OpenGL::setLogicOp(GL_COPY);
} }
void GLStateManager::resetClearing() {
clearRed = 0.f;
clearBlue = 0.f;
clearGreen = 0.f;
clearAlpha = 1.f;
OpenGL::setClearColor(clearRed, clearBlue, clearGreen, clearAlpha);
}
void GLStateManager::resetClipping() { void GLStateManager::resetClipping() {
// Disable all (supported) clip planes // Disable all (supported) clip planes
enabledClipPlanes = 0; enabledClipPlanes = 0;
@ -64,6 +73,7 @@ void GLStateManager::resetProgram() {
void GLStateManager::reset() { void GLStateManager::reset() {
resetBlend(); resetBlend();
resetClearing();
resetClipping(); resetClipping();
resetColourMask(); resetColourMask();
resetDepth(); resetDepth();

View file

@ -141,7 +141,7 @@ void RendererGL::initGraphicsContext(SDL_Window* window) {
GLint oldViewport[4]; GLint oldViewport[4];
glGetIntegerv(GL_VIEWPORT, oldViewport); glGetIntegerv(GL_VIEWPORT, oldViewport);
OpenGL::setViewport(screenTextureWidth, screenTextureHeight); OpenGL::setViewport(screenTextureWidth, screenTextureHeight);
OpenGL::setClearColor(0.0, 0.0, 0.0, 1.0); gl.setClearColour(0.0, 0.0, 0.0, 1.0);
OpenGL::clearColor(); OpenGL::clearColor();
OpenGL::setViewport(oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]); OpenGL::setViewport(oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]);
@ -473,7 +473,7 @@ void RendererGL::display() {
auto bottomScreen = colourBufferCache.findFromAddress(bottomScreenAddr); auto bottomScreen = colourBufferCache.findFromAddress(bottomScreenAddr);
screenFramebuffer.bind(OpenGL::DrawFramebuffer); screenFramebuffer.bind(OpenGL::DrawFramebuffer);
OpenGL::setClearColor(0.f); gl.setClearColour(0.f, 0.f, 0.f, 1.f);
OpenGL::clearColor(); OpenGL::clearColor();
if (topScreen) { if (topScreen) {
@ -504,8 +504,9 @@ void RendererGL::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 co
const float b = getBits<8, 8>(value) / 255.0f; const float b = getBits<8, 8>(value) / 255.0f;
const float a = (value & 0xff) / 255.0f; const float a = (value & 0xff) / 255.0f;
color->get().fbo.bind(OpenGL::DrawFramebuffer); color->get().fbo.bind(OpenGL::DrawFramebuffer);
gl.setColourMask(true, true, true, true); gl.setColourMask(true, true, true, true);
OpenGL::setClearColor(r, g, b, a); gl.setClearColour(r, g, b, a);
OpenGL::clearColor(); OpenGL::clearColor();
return; return;
} }