Clean up the 3D renderer for enhanced flexibility (#1895)

* Give `GPU2D::Unit` a virtual destructor

- Undefined behavior avoided!

* Add an `array2d` alias

* Move various parts of `GPU2D::SoftRenderer` to `constexpr`

- `SoftRenderer::MosaicTable` is now initialized at compile-time
- Most of the `SoftRenderer::Color*` functions are now `constexpr`
- The aforementioned functions are used with a constant value in at least one place, so they'll be at least partially computed at compile-time

* Generalize `GLRenderer::PrepareCaptureFrame`

- Declare it in the base `Renderer3D` class, but make it empty

* Remove unneeded `virtual` specifiers

* Store `Framebuffer`'s memory in `unique_ptr`s

- Reduce the risk of leaks this way

* Clean up how `GLCompositor` is initialized

- Return it as an `std::optional` instead of a `std::unique_ptr`
- Make `GLCompositor` movable
- Replace `GLCompositor`'s plain arrays with `std::array` to simplify moving

* Pass `GPU` to `GLCompositor`'s important functions instead of passing it to the constructor

* Move `GLCompositor` to be a field within `GLRenderer`

- Some methods were moved up and made `virtual`

* Fix some linker errors

* Set the renderer in the frontend

* Remove unneeded `virtual` specifiers

* Remove `RenderSettings` in favor of just exposing the relevant member variables

* Update the frontend to accommodate the core changes

* Add `constexpr` and `const` to places in the interpolator

* Qualify references to `size_t`

* Construct the `optional` directly instead of using `make_optional`

- It makes the Linux build choke
- I think it's because `GLCompositor`'s constructor is `private`
This commit is contained in:
Jesse Talavera-Greenberg
2023-11-29 09:23:11 -05:00
committed by GitHub
parent e973236203
commit 7caddf9615
15 changed files with 366 additions and 334 deletions

View File

@ -97,7 +97,10 @@ void SetupDefaultTexParams(GLuint tex)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
GLRenderer::GLRenderer(melonDS::GPU& gpu) noexcept : Renderer3D(true), GPU(gpu)
GLRenderer::GLRenderer(GLCompositor&& compositor, melonDS::GPU& gpu) noexcept :
Renderer3D(true),
GPU(gpu),
CurGLCompositor(std::move(compositor))
{
// GLRenderer::New() will be used to actually initialize the renderer;
// The various glDelete* functions silently ignore invalid IDs,
@ -108,9 +111,14 @@ std::unique_ptr<GLRenderer> GLRenderer::New(melonDS::GPU& gpu) noexcept
{
assert(glEnable != nullptr);
std::optional<GLCompositor> compositor = GLCompositor::New();
if (!compositor)
return nullptr;
// Will be returned if the initialization succeeds,
// or cleaned up via RAII if it fails.
std::unique_ptr<GLRenderer> result = std::unique_ptr<GLRenderer>(new GLRenderer(gpu));
std::unique_ptr<GLRenderer> result = std::unique_ptr<GLRenderer>(new GLRenderer(std::move(*compositor), gpu));
compositor = std::nullopt;
glEnable(GL_DEPTH_TEST);
glEnable(GL_STENCIL_TEST);
@ -327,14 +335,29 @@ GLRenderer::~GLRenderer()
void GLRenderer::Reset()
{
// This is where the compositor's Reset() method would be called,
// except there's no such method right now.
}
void GLRenderer::SetRenderSettings(const RenderSettings& settings) noexcept
void GLRenderer::SetBetterPolygons(bool betterpolygons) noexcept
{
int scale = settings.GL_ScaleFactor;
SetRenderSettings(betterpolygons, ScaleFactor);
}
void GLRenderer::SetScaleFactor(int scale) noexcept
{
SetRenderSettings(BetterPolygons, scale);
}
void GLRenderer::SetRenderSettings(bool betterpolygons, int scale) noexcept
{
if (betterpolygons == BetterPolygons && scale == ScaleFactor)
return;
CurGLCompositor.SetScaleFactor(scale);
ScaleFactor = scale;
BetterPolygons = settings.GL_BetterPolygons;
BetterPolygons = betterpolygons;
ScreenW = 256 * scale;
ScreenH = 192 * scale;
@ -1302,6 +1325,11 @@ void GLRenderer::RenderFrame()
FrontBuffer = FrontBuffer ? 0 : 1;
}
void GLRenderer::Stop()
{
CurGLCompositor.Stop(GPU);
}
void GLRenderer::PrepareCaptureFrame()
{
// TODO: make sure this picks the right buffer when doing antialiasing
@ -1317,6 +1345,11 @@ void GLRenderer::PrepareCaptureFrame()
glReadPixels(0, 0, 256, 192, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
}
void GLRenderer::Blit()
{
CurGLCompositor.RenderFrame(GPU, *this);
}
u32* GLRenderer::GetLine(int line)
{
int stride = 256;