mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-08 23:25:40 +12:00
Additionally made the surface cache search hit for any address that lies in the surface. This should allow multiple races to be done in Mario Kart and fixes the intro video.
147 lines
No EOL
4.8 KiB
C++
147 lines
No EOL
4.8 KiB
C++
#pragma once
|
|
#include "PICA/regs.hpp"
|
|
#include "boost/icl/interval.hpp"
|
|
#include "helpers.hpp"
|
|
#include "opengl.hpp"
|
|
|
|
template <typename T>
|
|
using Interval = boost::icl::right_open_interval<T>;
|
|
|
|
struct ColourBuffer {
|
|
u32 location;
|
|
PICA::ColorFmt format;
|
|
OpenGL::uvec2 size;
|
|
bool valid;
|
|
|
|
// Range of VRAM taken up by buffer
|
|
Interval<u32> range;
|
|
// OpenGL resources allocated to buffer
|
|
OpenGL::Texture texture;
|
|
OpenGL::Framebuffer fbo;
|
|
|
|
ColourBuffer() : valid(false) {}
|
|
|
|
ColourBuffer(u32 loc, PICA::ColorFmt format, u32 x, u32 y, bool valid = true)
|
|
: location(loc), format(format), size({x, y}), valid(valid) {
|
|
|
|
u64 endLoc = (u64)loc + sizeInBytes();
|
|
// Check if start and end are valid here
|
|
range = Interval<u32>(loc, (u32)endLoc);
|
|
}
|
|
|
|
void allocate() {
|
|
// 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.
|
|
// If this becomes a bottleneck, we can fix it semi-easily
|
|
auto prevTexture = OpenGL::getTex2D();
|
|
texture.create(size.x(), size.y(), GL_RGBA8);
|
|
texture.bind();
|
|
texture.setMinFilter(OpenGL::Linear);
|
|
texture.setMagFilter(OpenGL::Linear);
|
|
glBindTexture(GL_TEXTURE_2D, prevTexture);
|
|
|
|
//Helpers::panic("Creating FBO: %d, %d\n", size.x(), size.y());
|
|
|
|
fbo.createWithDrawTexture(texture);
|
|
fbo.bind(OpenGL::DrawAndReadFramebuffer);
|
|
|
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
|
Helpers::panic("Incomplete framebuffer");
|
|
|
|
// TODO: This should not clear the framebuffer contents. It should load them from VRAM.
|
|
GLint oldViewport[4];
|
|
glGetIntegerv(GL_VIEWPORT, oldViewport);
|
|
OpenGL::setViewport(size.x(), size.y());
|
|
OpenGL::setClearColor(0.0, 0.0, 0.0, 1.0);
|
|
OpenGL::clearColor();
|
|
OpenGL::setViewport(oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]);
|
|
}
|
|
|
|
void free() {
|
|
valid = false;
|
|
|
|
if (texture.exists() || fbo.exists()){
|
|
texture.free();
|
|
fbo.free();
|
|
}
|
|
}
|
|
|
|
bool matches(ColourBuffer& other) {
|
|
return location == other.location && format == other.format &&
|
|
size.x() == other.size.x() && size.y() == other.size.y();
|
|
}
|
|
|
|
size_t sizeInBytes() {
|
|
return (size_t)size.x() * (size_t)size.y() * PICA::sizePerPixel(format);
|
|
}
|
|
};
|
|
|
|
struct DepthBuffer {
|
|
u32 location;
|
|
PICA::DepthFmt format;
|
|
OpenGL::uvec2 size; // Implicitly set to the size of the framebuffer
|
|
bool valid;
|
|
|
|
// Range of VRAM taken up by buffer
|
|
Interval<u32> range;
|
|
// OpenGL texture used for storing depth/stencil
|
|
OpenGL::Texture texture;
|
|
|
|
DepthBuffer() : valid(false) {}
|
|
|
|
DepthBuffer(u32 loc, PICA::DepthFmt format, u32 x, u32 y, bool valid = true) :
|
|
location(loc), format(format), size({x, y}), valid(valid) {
|
|
|
|
u64 endLoc = (u64)loc + sizeInBytes();
|
|
// Check if start and end are valid here
|
|
range = Interval<u32>(loc, (u32)endLoc);
|
|
}
|
|
|
|
void allocate() {
|
|
// 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.
|
|
// If this becomes a bottleneck, we can fix it semi-easily
|
|
auto prevTexture = OpenGL::getTex2D();
|
|
|
|
// Internal formats for the texture based on format
|
|
static constexpr std::array<GLenum, 4> internalFormats = {
|
|
GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT24, GL_DEPTH24_STENCIL8
|
|
};
|
|
|
|
// Format of the texture
|
|
static constexpr std::array<GLenum, 4> formats = {
|
|
GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL
|
|
};
|
|
|
|
static constexpr std::array<GLenum, 4> types = {
|
|
GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT_24_8
|
|
};
|
|
|
|
auto internalFormat = internalFormats[(int)format];
|
|
auto fmt = formats[(int)format];
|
|
auto type = types[(int)format];
|
|
|
|
texture.createDSTexture(size.x(), size.y(), internalFormat, fmt, nullptr, type, GL_TEXTURE_2D);
|
|
texture.bind();
|
|
texture.setMinFilter(OpenGL::Nearest);
|
|
texture.setMagFilter(OpenGL::Nearest);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, prevTexture);
|
|
}
|
|
|
|
void free() {
|
|
if(texture.exists()){
|
|
texture.free();
|
|
}
|
|
valid = false;
|
|
}
|
|
|
|
bool matches(DepthBuffer& other) {
|
|
return location == other.location && format == other.format &&
|
|
size.x() == other.size.x() && size.y() == other.size.y();
|
|
}
|
|
|
|
size_t sizeInBytes() {
|
|
return (size_t)size.x() * (size_t)size.y() * PICA::sizePerPixel(format);
|
|
}
|
|
}; |