diff options
author | Jesse Talavera-Greenberg <jesse@jesse.tg> | 2023-11-29 09:23:11 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-29 15:23:11 +0100 |
commit | 7caddf9615875e54b725bd7df266361c46d47b6f (patch) | |
tree | 966698578db1f764715ff4ee5e8ee4c787cbeb10 /src/GPU_OpenGL.cpp | |
parent | e973236203292637eb7bd009a4cfbd6fd785181f (diff) |
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`
Diffstat (limited to 'src/GPU_OpenGL.cpp')
-rw-r--r-- | src/GPU_OpenGL.cpp | 110 |
1 files changed, 85 insertions, 25 deletions
diff --git a/src/GPU_OpenGL.cpp b/src/GPU_OpenGL.cpp index 2db3810..2e2857c 100644 --- a/src/GPU_OpenGL.cpp +++ b/src/GPU_OpenGL.cpp @@ -33,13 +33,13 @@ namespace melonDS using namespace OpenGL; -std::unique_ptr<GLCompositor> GLCompositor::New(melonDS::GPU& gpu) noexcept +std::optional<GLCompositor> GLCompositor::New() noexcept { assert(glBindAttribLocation != nullptr); std::array<GLuint, 3> CompShader {}; if (!OpenGL::BuildShaderProgram(kCompositorVS, kCompositorFS_Nearest, &CompShader[0], "CompositorShader")) - return nullptr; + return std::nullopt; glBindAttribLocation(CompShader[2], 0, "vPosition"); glBindAttribLocation(CompShader[2], 1, "vTexcoord"); @@ -48,12 +48,12 @@ std::unique_ptr<GLCompositor> GLCompositor::New(melonDS::GPU& gpu) noexcept if (!OpenGL::LinkShaderProgram(CompShader.data())) // OpenGL::LinkShaderProgram already deletes the shader program object // if linking the shaders together failed. - return nullptr; + return std::nullopt; - return std::unique_ptr<GLCompositor>(new GLCompositor(CompShader, gpu)); + return { GLCompositor(CompShader) }; } -GLCompositor::GLCompositor(std::array<GLuint, 3> compShader, melonDS::GPU& gpu) noexcept : CompShader(compShader), GPU(gpu) +GLCompositor::GLCompositor(std::array<GLuint, 3> compShader) noexcept : CompShader(compShader) { CompScaleLoc = glGetUniformLocation(CompShader[2], "u3DScale"); Comp3DXPosLoc = glGetUniformLocation(CompShader[2], "u3DXPos"); @@ -92,7 +92,7 @@ GLCompositor::GLCompositor(std::array<GLuint, 3> compShader, melonDS::GPU& gpu) glGenBuffers(1, &CompVertexBufferID); glBindBuffer(GL_ARRAY_BUFFER, CompVertexBufferID); - glBufferData(GL_ARRAY_BUFFER, sizeof(CompVertices), CompVertices, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, sizeof(CompVertices), &CompVertices[0], GL_STATIC_DRAW); glGenVertexArrays(1, &CompVertexArrayID); glBindVertexArray(CompVertexArrayID); @@ -101,7 +101,7 @@ GLCompositor::GLCompositor(std::array<GLuint, 3> compShader, melonDS::GPU& gpu) glEnableVertexAttribArray(1); // texcoord glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(CompVertex), (void*)(offsetof(CompVertex, Texcoord))); - glGenFramebuffers(2, CompScreenOutputFB); + glGenFramebuffers(CompScreenOutputFB.size(), &CompScreenOutputFB[0]); glGenTextures(1, &CompScreenInputTex); glActiveTexture(GL_TEXTURE0); @@ -112,10 +112,10 @@ GLCompositor::GLCompositor(std::array<GLuint, 3> compShader, melonDS::GPU& gpu) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 256*3 + 1, 192*2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, NULL); - glGenTextures(2, CompScreenOutputTex); - for (int i = 0; i < 2; i++) + glGenTextures(CompScreenOutputTex.size(), &CompScreenOutputTex[0]); + for (GLuint i : CompScreenOutputTex) { - glBindTexture(GL_TEXTURE_2D, CompScreenOutputTex[i]); + glBindTexture(GL_TEXTURE_2D, i); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -129,9 +129,9 @@ GLCompositor::~GLCompositor() { assert(glDeleteFramebuffers != nullptr); - glDeleteFramebuffers(2, CompScreenOutputFB); + glDeleteFramebuffers(CompScreenOutputFB.size(), &CompScreenOutputFB[0]); glDeleteTextures(1, &CompScreenInputTex); - glDeleteTextures(2, CompScreenOutputTex); + glDeleteTextures(CompScreenOutputTex.size(), &CompScreenOutputTex[0]); glDeleteVertexArrays(1, &CompVertexArrayID); glDeleteBuffers(1, &CompVertexBufferID); @@ -139,14 +139,75 @@ GLCompositor::~GLCompositor() OpenGL::DeleteShaderProgram(CompShader.data()); } -void GLCompositor::Reset() + +GLCompositor::GLCompositor(GLCompositor&& other) noexcept : + Scale(other.Scale), + ScreenH(other.ScreenH), + ScreenW(other.ScreenW), + CompScaleLoc(other.CompScaleLoc), + Comp3DXPosLoc(other.Comp3DXPosLoc), + CompVertices(other.CompVertices), + CompShader(other.CompShader), + CompVertexBufferID(other.CompVertexBufferID), + CompVertexArrayID(other.CompVertexArrayID), + CompScreenInputTex(other.CompScreenInputTex), + CompScreenOutputTex(other.CompScreenOutputTex), + CompScreenOutputFB(other.CompScreenOutputFB) { + other.CompScreenOutputFB = {}; + other.CompScreenInputTex = {}; + other.CompScreenOutputTex = {}; + other.CompVertexArrayID = {}; + other.CompVertexBufferID = {}; + other.CompShader = {}; +} + +GLCompositor& GLCompositor::operator=(GLCompositor&& other) noexcept +{ + if (this != &other) + { + Scale = other.Scale; + ScreenH = other.ScreenH; + ScreenW = other.ScreenW; + CompScaleLoc = other.CompScaleLoc; + Comp3DXPosLoc = other.Comp3DXPosLoc; + CompVertices = other.CompVertices; + + // Clean up these resources before overwriting them + OpenGL::DeleteShaderProgram(CompShader.data()); + CompShader = other.CompShader; + + glDeleteBuffers(1, &CompVertexBufferID); + CompVertexBufferID = other.CompVertexBufferID; + + glDeleteVertexArrays(1, &CompVertexArrayID); + CompVertexArrayID = other.CompVertexArrayID; + + glDeleteTextures(1, &CompScreenInputTex); + CompScreenInputTex = other.CompScreenInputTex; + + glDeleteTextures(CompScreenOutputTex.size(), &CompScreenOutputTex[0]); + CompScreenOutputTex = other.CompScreenOutputTex; + + glDeleteFramebuffers(CompScreenOutputFB.size(), &CompScreenOutputFB[0]); + CompScreenOutputFB = other.CompScreenOutputFB; + + other.CompScreenOutputFB = {}; + other.CompScreenInputTex = {}; + other.CompScreenOutputTex = {}; + other.CompVertexArrayID = {}; + other.CompVertexBufferID = {}; + other.CompShader = {}; + } + + return *this; } -void GLCompositor::SetRenderSettings(const RenderSettings& settings) noexcept +void GLCompositor::SetScaleFactor(int scale) noexcept { - int scale = settings.GL_ScaleFactor; + if (scale == Scale) + return; Scale = scale; ScreenW = 256 * scale; @@ -170,13 +231,12 @@ void GLCompositor::SetRenderSettings(const RenderSettings& settings) noexcept glBindFramebuffer(GL_FRAMEBUFFER, 0); } -void GLCompositor::Stop() +void GLCompositor::Stop(const GPU& gpu) noexcept { for (int i = 0; i < 2; i++) { - int frontbuf = GPU.FrontBuffer; glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, CompScreenOutputFB[frontbuf]); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, CompScreenOutputFB[gpu.FrontBuffer]); glClear(GL_COLOR_BUFFER_BIT); } @@ -184,9 +244,9 @@ void GLCompositor::Stop() glBindFramebuffer(GL_FRAMEBUFFER, 0); } -void GLCompositor::RenderFrame() +void GLCompositor::RenderFrame(const GPU& gpu, GLRenderer& renderer) noexcept { - int frontbuf = GPU.FrontBuffer; + int frontbuf = gpu.FrontBuffer; glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, CompScreenOutputFB[frontbuf]); @@ -204,21 +264,21 @@ void GLCompositor::RenderFrame() glUniform1ui(CompScaleLoc, Scale); // TODO: support setting this midframe, if ever needed - glUniform1i(Comp3DXPosLoc, ((int)GPU.GPU3D.GetRenderXPos() << 23) >> 23); + glUniform1i(Comp3DXPosLoc, ((int)gpu.GPU3D.GetRenderXPos() << 23) >> 23); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, CompScreenInputTex); - if (GPU.Framebuffer[frontbuf][0] && GPU.Framebuffer[frontbuf][1]) + if (gpu.Framebuffer[frontbuf][0] && gpu.Framebuffer[frontbuf][1]) { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256*3 + 1, 192, GL_RGBA_INTEGER, - GL_UNSIGNED_BYTE, GPU.Framebuffer[frontbuf][0]); + GL_UNSIGNED_BYTE, gpu.Framebuffer[frontbuf][0].get()); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192, 256*3 + 1, 192, GL_RGBA_INTEGER, - GL_UNSIGNED_BYTE, GPU.Framebuffer[frontbuf][1]); + GL_UNSIGNED_BYTE, gpu.Framebuffer[frontbuf][1].get()); } glActiveTexture(GL_TEXTURE1); - reinterpret_cast<GLRenderer*>(GPU.GPU3D.GetCurrentRenderer())->SetupAccelFrame(); + renderer.SetupAccelFrame(); glBindBuffer(GL_ARRAY_BUFFER, CompVertexBufferID); glBindVertexArray(CompVertexArrayID); |