aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJesse Talavera-Greenberg <jesse@jesse.tg>2023-09-15 09:31:05 -0400
committerGitHub <noreply@github.com>2023-09-15 15:31:05 +0200
commitdb963aa002cdf943c86d19f8abd3f4fd40be38ec (patch)
treebded72c0147f3749d3f346266ed4b1321e3b2979 /src
parent1aaf22d181e55abb8ad27be89ebae106b1c1cfcf (diff)
Make the NDS teardown more robust (#1798)
* Make cleanup a little more robust to mitigate undefined behavior - Add some null checks before cleaning up the GPU3D renderer - Make sure that all deleted objects are null - Move cleanup logic out of an assert call - Note that deleting a null pointer is a no-op, so there's no need to check for null beforehand - Use RAII for GLCompositor instead of Init/DeInit methods * Replace a DeInit call that I missed * Make ARMJIT_Memory less likely to generate errors - Set FastMem7/9Start to nullptr at the end - Only close and unmap the file if it's initialized * Make Renderer3D manage its resources with RAII * Don't try to deallocate frontend resources that aren't loaded * Make ARMJIT_Memory::DeInit more robust on the Switch * Reset MemoryFile on Windows to INVALID_HANDLE_VALUE, not nullptr - There is a difference * Don't explicitly store a Valid state in GLCompositor or the 3D renderers - Instead, create them with static methods while making the actual constructors private * Make initialization of OpenGL resources fail if OpenGL isn't loaded * assert that OpenGL is loaded instead of returning failure
Diffstat (limited to 'src')
-rw-r--r--src/ARMJIT.cpp1
-rw-r--r--src/ARMJIT_Memory.cpp49
-rw-r--r--src/DSi.cpp12
-rw-r--r--src/DSi_Camera.cpp3
-rw-r--r--src/GPU.cpp28
-rw-r--r--src/GPU3D.h7
-rw-r--r--src/GPU3D_OpenGL.cpp204
-rw-r--r--src/GPU3D_OpenGL.h61
-rw-r--r--src/GPU3D_Soft.cpp11
-rw-r--r--src/GPU3D_Soft.h6
-rw-r--r--src/GPU_OpenGL.cpp61
-rw-r--r--src/GPU_OpenGL.h15
-rw-r--r--src/NDS.cpp6
-rw-r--r--src/OpenGLSupport.cpp22
-rw-r--r--src/SPI.cpp1
-rw-r--r--src/SPU.cpp6
-rw-r--r--src/frontend/qt_sdl/AudioInOut.cpp9
-rw-r--r--src/frontend/qt_sdl/LocalMP.cpp21
18 files changed, 313 insertions, 210 deletions
diff --git a/src/ARMJIT.cpp b/src/ARMJIT.cpp
index 7a4cdc6..77bb50d 100644
--- a/src/ARMJIT.cpp
+++ b/src/ARMJIT.cpp
@@ -330,6 +330,7 @@ void DeInit()
ARMJIT_Memory::DeInit();
delete JITCompiler;
+ JITCompiler = nullptr;
}
void Reset()
diff --git a/src/ARMJIT_Memory.cpp b/src/ARMJIT_Memory.cpp
index 8e6a9f6..25652cb 100644
--- a/src/ARMJIT_Memory.cpp
+++ b/src/ARMJIT_Memory.cpp
@@ -308,7 +308,7 @@ HANDLE MemoryFile;
LPVOID ExceptionHandlerHandle;
#else
u8* MemoryBase;
-int MemoryFile;
+int MemoryFile = -1;
#endif
bool MapIntoRange(u32 addr, u32 num, u32 offset, u32 size)
@@ -811,25 +811,58 @@ void DeInit()
{
#if defined(__SWITCH__)
virtmemLock();
- virtmemRemoveReservation(FastMem9Reservation);
- virtmemRemoveReservation(FastMem7Reservation);
+ if (FastMem9Reservation)
+ virtmemRemoveReservation(FastMem9Reservation);
+
+ if (FastMem7Reservation)
+ virtmemRemoveReservation(FastMem7Reservation);
+
+ FastMem9Reservation = nullptr;
+ FastMem7Reservation = nullptr;
virtmemUnlock();
svcUnmapProcessCodeMemory(envGetOwnProcessHandle(), (u64)MemoryBaseCodeMem, (u64)MemoryBase, MemoryTotalSize);
free(MemoryBase);
+ MemoryBase = nullptr;
#elif defined(_WIN32)
- assert(UnmapViewOfFile(MemoryBase));
- CloseHandle(MemoryFile);
+ if (MemoryBase)
+ {
+ bool viewUnmapped = UnmapViewOfFile(MemoryBase);
+ assert(viewUnmapped);
+ MemoryBase = nullptr;
+ FastMem9Start = nullptr;
+ FastMem7Start = nullptr;
+ }
+
+ if (MemoryFile)
+ {
+ CloseHandle(MemoryFile);
+ MemoryFile = INVALID_HANDLE_VALUE;
+ }
- RemoveVectoredExceptionHandler(ExceptionHandlerHandle);
+ if (ExceptionHandlerHandle)
+ {
+ RemoveVectoredExceptionHandler(ExceptionHandlerHandle);
+ ExceptionHandlerHandle = nullptr;
+ }
#else
sigaction(SIGSEGV, &OldSaSegv, nullptr);
#ifdef __APPLE__
sigaction(SIGBUS, &OldSaBus, nullptr);
#endif
+ if (MemoryBase)
+ {
+ munmap(MemoryBase, MemoryTotalSize);
+ MemoryBase = nullptr;
+ FastMem9Start = nullptr;
+ FastMem7Start = nullptr;
+ }
- munmap(MemoryBase, MemoryTotalSize);
- close(MemoryFile);
+ if (MemoryFile >= 0)
+ {
+ close(MemoryFile);
+ MemoryFile = -1;
+ }
#if defined(__ANDROID__)
if (Libandroid)
diff --git a/src/DSi.cpp b/src/DSi.cpp
index dc066a7..5dd8ac9 100644
--- a/src/DSi.cpp
+++ b/src/DSi.cpp
@@ -128,6 +128,10 @@ void DeInit()
delete[] NWRAM_A;
delete[] NWRAM_B;
delete[] NWRAM_C;
+
+ NWRAM_A = nullptr;
+ NWRAM_B = nullptr;
+ NWRAM_C = nullptr;
#endif
DSi_I2C::DeInit();
@@ -135,10 +139,16 @@ void DeInit()
DSi_AES::DeInit();
DSi_DSP::DeInit();
- for (int i = 0; i < 8; i++) delete NDMAs[i];
+ for (int i = 0; i < 8; i++)
+ {
+ delete NDMAs[i];
+ NDMAs[i] = nullptr;
+ }
delete SDMMC;
+ SDMMC = nullptr;
delete SDIO;
+ SDIO = nullptr;
}
void Reset()
diff --git a/src/DSi_Camera.cpp b/src/DSi_Camera.cpp
index 9f45a6a..c5fa29d 100644
--- a/src/DSi_Camera.cpp
+++ b/src/DSi_Camera.cpp
@@ -63,6 +63,9 @@ void DeInit()
{
delete Camera0;
delete Camera1;
+
+ Camera0 = nullptr;
+ Camera1 = nullptr;
}
void Reset()
diff --git a/src/GPU.cpp b/src/GPU.cpp
index f51748b..077fc8b 100644
--- a/src/GPU.cpp
+++ b/src/GPU.cpp
@@ -171,6 +171,11 @@ void DeInit()
if (Framebuffer[0][1]) delete[] Framebuffer[0][1];
if (Framebuffer[1][0]) delete[] Framebuffer[1][0];
if (Framebuffer[1][1]) delete[] Framebuffer[1][1];
+
+ Framebuffer[0][0] = nullptr;
+ Framebuffer[0][1] = nullptr;
+ Framebuffer[1][0] = nullptr;
+ Framebuffer[1][1] = nullptr;
}
void ResetVRAMCache()
@@ -388,20 +393,18 @@ void InitRenderer(int renderer)
#ifdef OGLRENDERER_ENABLED
if (renderer == 1)
{
- CurGLCompositor = std::make_unique<GLCompositor>();
- // Create opengl rendrerer
- if (!CurGLCompositor->Init())
+ CurGLCompositor = GLCompositor::New();
+ // Create opengl renderer
+ if (!CurGLCompositor)
{
// Fallback on software renderer
renderer = 0;
GPU3D::CurrentRenderer = std::make_unique<GPU3D::SoftRenderer>();
- GPU3D::CurrentRenderer->Init();
}
- GPU3D::CurrentRenderer = std::make_unique<GPU3D::GLRenderer>();
- if (!GPU3D::CurrentRenderer->Init())
+ GPU3D::CurrentRenderer = GPU3D::GLRenderer::New();
+ if (!GPU3D::CurrentRenderer)
{
// Fallback on software renderer
- CurGLCompositor->DeInit();
CurGLCompositor.reset();
renderer = 0;
GPU3D::CurrentRenderer = std::make_unique<GPU3D::SoftRenderer>();
@@ -411,7 +414,6 @@ void InitRenderer(int renderer)
#endif
{
GPU3D::CurrentRenderer = std::make_unique<GPU3D::SoftRenderer>();
- GPU3D::CurrentRenderer->Init();
}
Renderer = renderer;
@@ -419,12 +421,12 @@ void InitRenderer(int renderer)
void DeInitRenderer()
{
- GPU3D::CurrentRenderer->DeInit();
+ // Delete the 3D renderer, if it exists
+ GPU3D::CurrentRenderer.reset();
+
#ifdef OGLRENDERER_ENABLED
- if (Renderer == 1)
- {
- CurGLCompositor->DeInit();
- }
+ // Delete the compositor, if one exists
+ CurGLCompositor.reset();
#endif
}
diff --git a/src/GPU3D.h b/src/GPU3D.h
index 4a7bfdc..44d422a 100644
--- a/src/GPU3D.h
+++ b/src/GPU3D.h
@@ -137,14 +137,11 @@ void Write32(u32 addr, u32 val);
class Renderer3D
{
public:
- Renderer3D(bool Accelerated);
- virtual ~Renderer3D() {};
+ virtual ~Renderer3D() = default;
Renderer3D(const Renderer3D&) = delete;
Renderer3D& operator=(const Renderer3D&) = delete;
- virtual bool Init() = 0;
- virtual void DeInit() = 0;
virtual void Reset() = 0;
// This "Accelerated" flag currently communicates if the framebuffer should
@@ -159,6 +156,8 @@ public:
virtual void RenderFrame() = 0;
virtual void RestartFrame() {};
virtual u32* GetLine(int line) = 0;
+protected:
+ Renderer3D(bool Accelerated);
};
extern int Renderer;
diff --git a/src/GPU3D_OpenGL.cpp b/src/GPU3D_OpenGL.cpp
index ebabd51..9648be3 100644
--- a/src/GPU3D_OpenGL.cpp
+++ b/src/GPU3D_OpenGL.cpp
@@ -18,6 +18,7 @@
#include "GPU3D_OpenGL.h"
+#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "NDS.h"
@@ -96,14 +97,20 @@ void SetupDefaultTexParams(GLuint tex)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
-GLRenderer::GLRenderer()
- : Renderer3D(true)
+GLRenderer::GLRenderer() noexcept : Renderer3D(true)
{
+ // GLRenderer::New() will be used to actually initialize the renderer;
+ // The various glDelete* functions silently ignore invalid IDs,
+ // so we can just let the destructor clean up a half-initialized renderer.
}
-bool GLRenderer::Init()
+std::unique_ptr<GLRenderer> GLRenderer::New() noexcept
{
- GLint uni_id;
+ assert(glEnable != 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());
glEnable(GL_DEPTH_TEST);
glEnable(GL_STENCIL_TEST);
@@ -112,86 +119,93 @@ bool GLRenderer::Init()
glClearDepth(1.0);
- if (!OpenGL::BuildShaderProgram(kClearVS, kClearFS, ClearShaderPlain, "ClearShader"))
- return false;
+ if (!OpenGL::BuildShaderProgram(kClearVS, kClearFS, result->ClearShaderPlain, "ClearShader"))
+ return nullptr;
- glBindAttribLocation(ClearShaderPlain[2], 0, "vPosition");
- glBindFragDataLocation(ClearShaderPlain[2], 0, "oColor");
- glBindFragDataLocation(ClearShaderPlain[2], 1, "oAttr");
+ glBindAttribLocation(result->ClearShaderPlain[2], 0, "vPosition");
+ glBindFragDataLocation(result->ClearShaderPlain[2], 0, "oColor");
+ glBindFragDataLocation(result->ClearShaderPlain[2], 1, "oAttr");
- if (!OpenGL::LinkShaderProgram(ClearShaderPlain))
- return false;
+ if (!OpenGL::LinkShaderProgram(result->ClearShaderPlain))
+ return nullptr;
- ClearUniformLoc[0] = glGetUniformLocation(ClearShaderPlain[2], "uColor");
- ClearUniformLoc[1] = glGetUniformLocation(ClearShaderPlain[2], "uDepth");
- ClearUniformLoc[2] = glGetUniformLocation(ClearShaderPlain[2], "uOpaquePolyID");
- ClearUniformLoc[3] = glGetUniformLocation(ClearShaderPlain[2], "uFogFlag");
-
- memset(RenderShader, 0, sizeof(RenderShader));
-
- if (!BuildRenderShader(0,
- kRenderVS_Z, kRenderFS_ZO)) return false;
- if (!BuildRenderShader(RenderFlag_WBuffer,
- kRenderVS_W, kRenderFS_WO)) return false;
- if (!BuildRenderShader(RenderFlag_Edge,
- kRenderVS_Z, kRenderFS_ZE)) return false;
- if (!BuildRenderShader(RenderFlag_Edge | RenderFlag_WBuffer,
- kRenderVS_W, kRenderFS_WE)) return false;
- if (!BuildRenderShader(RenderFlag_Trans,
- kRenderVS_Z, kRenderFS_ZT)) return false;
- if (!BuildRenderShader(RenderFlag_Trans | RenderFlag_WBuffer,
- kRenderVS_W, kRenderFS_WT)) return false;
- if (!BuildRenderShader(RenderFlag_ShadowMask,
- kRenderVS_Z, kRenderFS_ZSM)) return false;
- if (!BuildRenderShader(RenderFlag_ShadowMask | RenderFlag_WBuffer,
- kRenderVS_W, kRenderFS_WSM)) return false;
-
-
- if (!OpenGL::BuildShaderProgram(kFinalPassVS, kFinalPassEdgeFS, FinalPassEdgeShader, "FinalPassEdgeShader"))
- return false;
- if (!OpenGL::BuildShaderProgram(kFinalPassVS, kFinalPassFogFS, FinalPassFogShader, "FinalPassFogShader"))
- return false;
+ result->ClearUniformLoc[0] = glGetUniformLocation(result->ClearShaderPlain[2], "uColor");
+ result->ClearUniformLoc[1] = glGetUniformLocation(result->ClearShaderPlain[2], "uDepth");
+ result->ClearUniformLoc[2] = glGetUniformLocation(result->ClearShaderPlain[2], "uOpaquePolyID");
+ result->ClearUniformLoc[3] = glGetUniformLocation(result->ClearShaderPlain[2], "uFogFlag");
- glBindAttribLocation(FinalPassEdgeShader[2], 0, "vPosition");
- glBindFragDataLocation(FinalPassEdgeShader[2], 0, "oColor");
+ memset(result->RenderShader, 0, sizeof(RenderShader));
- if (!OpenGL::LinkShaderProgram(FinalPassEdgeShader))
- return false;
+ if (!result->BuildRenderShader(0, kRenderVS_Z, kRenderFS_ZO))
+ return nullptr;
+
+ if (!result->BuildRenderShader(RenderFlag_WBuffer, kRenderVS_W, kRenderFS_WO))
+ return nullptr;
+
+ if (!result->BuildRenderShader(RenderFlag_Edge, kRenderVS_Z, kRenderFS_ZE))
+ return nullptr;
+
+ if (!result->BuildRenderShader(RenderFlag_Edge | RenderFlag_WBuffer, kRenderVS_W, kRenderFS_WE))
+ return nullptr;
+
+ if (!result->BuildRenderShader(RenderFlag_Trans, kRenderVS_Z, kRenderFS_ZT))
+ return nullptr;
+
+ if (!result->BuildRenderShader(RenderFlag_Trans | RenderFlag_WBuffer, kRenderVS_W, kRenderFS_WT))
+ return nullptr;
+
+ if (!result->BuildRenderShader(RenderFlag_ShadowMask, kRenderVS_Z, kRenderFS_ZSM))
+ return nullptr;
+
+ if (!result->BuildRenderShader(RenderFlag_ShadowMask | RenderFlag_WBuffer, kRenderVS_W, kRenderFS_WSM))
+ return nullptr;
- uni_id = glGetUniformBlockIndex(FinalPassEdgeShader[2], "uConfig");
- glUniformBlockBinding(FinalPassEdgeShader[2], uni_id, 0);
+ if (!OpenGL::BuildShaderProgram(kFinalPassVS, kFinalPassEdgeFS, result->FinalPassEdgeShader, "FinalPassEdgeShader"))
+ return nullptr;
- glUseProgram(FinalPassEdgeShader[2]);
+ if (!OpenGL::BuildShaderProgram(kFinalPassVS, kFinalPassFogFS, result->FinalPassFogShader, "FinalPassFogShader"))
+ return nullptr;
- uni_id = glGetUniformLocation(FinalPassEdgeShader[2], "DepthBuffer");
+ glBindAttribLocation(result->FinalPassEdgeShader[2], 0, "vPosition");
+ glBindFragDataLocation(result->FinalPassEdgeShader[2], 0, "oColor");
+
+ if (!OpenGL::LinkShaderProgram(result->FinalPassEdgeShader))
+ return nullptr;
+
+ GLint uni_id = glGetUniformBlockIndex(result->FinalPassEdgeShader[2], "uConfig");
+ glUniformBlockBinding(result->FinalPassEdgeShader[2], uni_id, 0);
+
+ glUseProgram(result->FinalPassEdgeShader[2]);
+
+ uni_id = glGetUniformLocation(result->FinalPassEdgeShader[2], "DepthBuffer");
glUniform1i(uni_id, 0);
- uni_id = glGetUniformLocation(FinalPassEdgeShader[2], "AttrBuffer");
+ uni_id = glGetUniformLocation(result->FinalPassEdgeShader[2], "AttrBuffer");
glUniform1i(uni_id, 1);
- glBindAttribLocation(FinalPassFogShader[2], 0, "vPosition");
- glBindFragDataLocation(FinalPassFogShader[2], 0, "oColor");
+ glBindAttribLocation(result->FinalPassFogShader[2], 0, "vPosition");
+ glBindFragDataLocation(result->FinalPassFogShader[2], 0, "oColor");
- if (!OpenGL::LinkShaderProgram(FinalPassFogShader))
- return false;
+ if (!OpenGL::LinkShaderProgram(result->FinalPassFogShader))
+ return nullptr;
- uni_id = glGetUniformBlockIndex(FinalPassFogShader[2], "uConfig");
- glUniformBlockBinding(FinalPassFogShader[2], uni_id, 0);
+ uni_id = glGetUniformBlockIndex(result->FinalPassFogShader[2], "uConfig");
+ glUniformBlockBinding(result->FinalPassFogShader[2], uni_id, 0);
- glUseProgram(FinalPassFogShader[2]);
+ glUseProgram(result->FinalPassFogShader[2]);
- uni_id = glGetUniformLocation(FinalPassFogShader[2], "DepthBuffer");
+ uni_id = glGetUniformLocation(result->FinalPassFogShader[2], "DepthBuffer");
glUniform1i(uni_id, 0);
- uni_id = glGetUniformLocation(FinalPassFogShader[2], "AttrBuffer");
+ uni_id = glGetUniformLocation(result->FinalPassFogShader[2], "AttrBuffer");
glUniform1i(uni_id, 1);
- memset(&ShaderConfig, 0, sizeof(ShaderConfig));
+ memset(&result->ShaderConfig, 0, sizeof(ShaderConfig));
- glGenBuffers(1, &ShaderConfigUBO);
- glBindBuffer(GL_UNIFORM_BUFFER, ShaderConfigUBO);
- static_assert((sizeof(ShaderConfig) & 15) == 0, "");
- glBufferData(GL_UNIFORM_BUFFER, sizeof(ShaderConfig), &ShaderConfig, GL_STATIC_DRAW);
- glBindBufferBase(GL_UNIFORM_BUFFER, 0, ShaderConfigUBO);
+ glGenBuffers(1, &result->ShaderConfigUBO);
+ glBindBuffer(GL_UNIFORM_BUFFER, result->ShaderConfigUBO);
+ static_assert((sizeof(ShaderConfig) & 15) == 0);
+ glBufferData(GL_UNIFORM_BUFFER, sizeof(ShaderConfig), &result->ShaderConfig, GL_STATIC_DRAW);
+ glBindBufferBase(GL_UNIFORM_BUFFER, 0, result->ShaderConfigUBO);
float clearvtx[6*2] =
@@ -205,22 +219,22 @@ bool GLRenderer::Init()
1.0, 1.0
};
- glGenBuffers(1, &ClearVertexBufferID);
- glBindBuffer(GL_ARRAY_BUFFER, ClearVertexBufferID);
+ glGenBuffers(1, &result->ClearVertexBufferID);
+ glBindBuffer(GL_ARRAY_BUFFER, result->ClearVertexBufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(clearvtx), clearvtx, GL_STATIC_DRAW);
- glGenVertexArrays(1, &ClearVertexArrayID);
- glBindVertexArray(ClearVertexArrayID);
+ glGenVertexArrays(1, &result->ClearVertexArrayID);
+ glBindVertexArray(result->ClearVertexArrayID);
glEnableVertexAttribArray(0); // position
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)(0));
- glGenBuffers(1, &VertexBufferID);
- glBindBuffer(GL_ARRAY_BUFFER, VertexBufferID);
- glBufferData(GL_ARRAY_BUFFER, sizeof(VertexBuffer), NULL, GL_DYNAMIC_DRAW);
+ glGenBuffers(1, &result->VertexBufferID);
+ glBindBuffer(GL_ARRAY_BUFFER, result->VertexBufferID);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(VertexBuffer), nullptr, GL_DYNAMIC_DRAW);
- glGenVertexArrays(1, &VertexArrayID);
- glBindVertexArray(VertexArrayID);
+ glGenVertexArrays(1, &result->VertexArrayID);
+ glBindVertexArray(result->VertexArrayID);
glEnableVertexAttribArray(0); // position
glVertexAttribIPointer(0, 4, GL_UNSIGNED_SHORT, 7*4, (void*)(0));
glEnableVertexAttribArray(1); // color
@@ -230,43 +244,43 @@ bool GLRenderer::Init()
glEnableVertexAttribArray(3); // attrib
glVertexAttribIPointer(3, 3, GL_UNSIGNED_INT, 7*4, (void*)(4*4));
- glGenBuffers(1, &IndexBufferID);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferID);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(IndexBuffer), NULL, GL_DYNAMIC_DRAW);
+ glGenBuffers(1, &result->IndexBufferID);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, result->IndexBufferID);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(IndexBuffer), nullptr, GL_DYNAMIC_DRAW);
- glGenFramebuffers(4, &FramebufferID[0]);
- glBindFramebuffer(GL_FRAMEBUFFER, FramebufferID[0]);
+ glGenFramebuffers(4, &result->FramebufferID[0]);
+ glBindFramebuffer(GL_FRAMEBUFFER, result->FramebufferID[0]);
- glGenTextures(8, &FramebufferTex[0]);
- FrontBuffer = 0;
+ glGenTextures(8, &result->FramebufferTex[0]);
+ result->FrontBuffer = 0;
// color buffers
- SetupDefaultTexParams(FramebufferTex[0]);
- SetupDefaultTexParams(FramebufferTex[1]);
+ SetupDefaultTexParams(result->FramebufferTex[0]);
+ SetupDefaultTexParams(result->FramebufferTex[1]);
// depth/stencil buffer
- SetupDefaultTexParams(FramebufferTex[4]);
- SetupDefaultTexParams(FramebufferTex[6]);
+ SetupDefaultTexParams(result->FramebufferTex[4]);
+ SetupDefaultTexParams(result->FramebufferTex[6]);
// attribute buffer
// R: opaque polyID (for edgemarking)
// G: edge flag
// B: fog flag
- SetupDefaultTexParams(FramebufferTex[5]);
- SetupDefaultTexParams(FramebufferTex[7]);
+ SetupDefaultTexParams(result->FramebufferTex[5]);
+ SetupDefaultTexParams(result->FramebufferTex[7]);
// downscale framebuffer for display capture (always 256x192)
- SetupDefaultTexParams(FramebufferTex[3]);
+ SetupDefaultTexParams(result->FramebufferTex[3]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 192, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glEnable(GL_BLEND);
glBlendEquationSeparate(GL_FUNC_ADD, GL_MAX);
- glGenBuffers(1, &PixelbufferID);
+ glGenBuffers(1, &result->PixelbufferID);
glActiveTexture(GL_TEXTURE0);
- glGenTextures(1, &TexMemID);
- glBindTexture(GL_TEXTURE_2D, TexMemID);
+ glGenTextures(1, &result->TexMemID);
+ glBindTexture(GL_TEXTURE_2D, result->TexMemID);
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);
@@ -274,8 +288,8 @@ bool GLRenderer::Init()
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, 1024, 512, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, NULL);
glActiveTexture(GL_TEXTURE1);
- glGenTextures(1, &TexPalMemID);
- glBindTexture(GL_TEXTURE_2D, TexPalMemID);
+ glGenTextures(1, &result->TexPalMemID);
+ glBindTexture(GL_TEXTURE_2D, result->TexPalMemID);
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);
@@ -284,11 +298,13 @@ bool GLRenderer::Init()
glBindFramebuffer(GL_FRAMEBUFFER, 0);
- return true;
+ return result;
}
-void GLRenderer::DeInit()
+GLRenderer::~GLRenderer()
{
+ assert(glDeleteTextures != nullptr);
+
glDeleteTextures(1, &TexMemID);
glDeleteTextures(1, &TexPalMemID);
diff --git a/src/GPU3D_OpenGL.h b/src/GPU3D_OpenGL.h
index a9dd62c..597f13e 100644
--- a/src/GPU3D_OpenGL.h
+++ b/src/GPU3D_OpenGL.h
@@ -28,10 +28,7 @@ namespace GPU3D
class GLRenderer : public Renderer3D
{
public:
- GLRenderer();
- virtual ~GLRenderer() override {};
- virtual bool Init() override;
- virtual void DeInit() override;
+ virtual ~GLRenderer() override;
virtual void Reset() override;
virtual void SetRenderSettings(GPU::RenderSettings& settings) override;
@@ -42,7 +39,11 @@ public:
void SetupAccelFrame();
void PrepareCaptureFrame();
+
+ static std::unique_ptr<GLRenderer> New() noexcept;
private:
+ // Used by New()
+ GLRenderer() noexcept;
// GL version requirements
// * texelFetch: 3.0 (GLSL 1.30) (3.2/1.50 for MS)
@@ -62,7 +63,7 @@ private:
u32 RenderKey;
};
- RendererPolygon PolygonList[2048];
+ RendererPolygon PolygonList[2048] {};
bool BuildRenderShader(u32 flags, const char* vs, const char* fs);
void UseRenderShader(u32 flags);
@@ -83,13 +84,13 @@ private:
};
- GLuint ClearShaderPlain[3];
+ GLuint ClearShaderPlain[3] {};
- GLuint RenderShader[16][3];
+ GLuint RenderShader[16][3] {};
GLuint CurShaderID = -1;
- GLuint FinalPassEdgeShader[3];
- GLuint FinalPassFogShader[3];
+ GLuint FinalPassEdgeShader[3] {};
+ GLuint FinalPassFogShader[3] {};
// std140 compliant structure
struct
@@ -104,13 +105,13 @@ private:
u32 uFogOffset; // int 304 / 1
u32 uFogShift; // int 305 / 1
u32 _pad1[2]; // int 306 / 2
- } ShaderConfig;
+ } ShaderConfig {};
- GLuint ShaderConfigUBO;
- int NumFinalPolys, NumOpaqueFinalPolys;
+ GLuint ShaderConfigUBO {};
+ int NumFinalPolys {}, NumOpaqueFinalPolys {};
- GLuint ClearVertexBufferID, ClearVertexArrayID;
- GLint ClearUniformLoc[4];
+ GLuint ClearVertexBufferID = 0, ClearVertexArrayID {};
+ GLint ClearUniformLoc[4] {};
// vertex buffer
// * XYZW: 4x16bit
@@ -124,28 +125,28 @@ private:
// * bit8: front-facing (?)
// * bit9: W-buffering (?)
- GLuint VertexBufferID;
- u32 VertexBuffer[10240 * 7];
- u32 NumVertices;
+ GLuint VertexBufferID {};
+ u32 VertexBuffer[10240 * 7] {};
+ u32 NumVertices {};
- GLuint VertexArrayID;
- GLuint IndexBufferID;
- u16 IndexBuffer[2048 * 40];
- u32 NumIndices, NumEdgeIndices;
+ GLuint VertexArrayID {};
+ GLuint IndexBufferID {};
+ u16 IndexBuffer[2048 * 40] {};
+ u32 NumIndices {}, NumEdgeIndices {};
const u32 EdgeIndicesOffset = 2048 * 30;
- GLuint TexMemID;
- GLuint TexPalMemID;
+ GLuint TexMemID {};
+ GLuint TexPalMemID {};
- int ScaleFactor;
- bool BetterPolygons;
- int ScreenW, ScreenH;
+ int ScaleFactor {};
+ bool BetterPolygons {};
+ int ScreenW {}, ScreenH {};
- GLuint FramebufferTex[8];
- int FrontBuffer;
- GLuint FramebufferID[4], PixelbufferID;
- u32 Framebuffer[256*192];
+ GLuint FramebufferTex[8] {};
+ int FrontBuffer {};
+ GLuint FramebufferID[4] {}, PixelbufferID {};
+ u32 Framebuffer[256*192] {};
};
diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp
index 98514ab..f7078b5 100644
--- a/src/GPU3D_Soft.cpp
+++ b/src/GPU3D_Soft.cpp
@@ -71,14 +71,9 @@ void SoftRenderer::SetupRenderThread()
}
-SoftRenderer::SoftRenderer()
+SoftRenderer::SoftRenderer() noexcept
: Renderer3D(false)
{
-
-}
-
-bool SoftRenderer::Init()
-{
Sema_RenderStart = Platform::Semaphore_Create();
Sema_RenderDone = Platform::Semaphore_Create();
Sema_ScanlineCount = Platform::Semaphore_Create();
@@ -86,11 +81,9 @@ bool SoftRenderer::Init()
Threaded = false;
RenderThreadRunning = false;
RenderThreadRendering = false;
-
- return true;
}
-void SoftRenderer::DeInit()
+SoftRenderer::~SoftRenderer()
{
StopRenderThread();
diff --git a/src/GPU3D_Soft.h b/src/GPU3D_Soft.h
index 0c6ca43..948832f 100644
--- a/src/GPU3D_Soft.h
+++ b/src/GPU3D_Soft.h
@@ -28,10 +28,8 @@ namespace GPU3D
class SoftRenderer : public Renderer3D
{
public:
- SoftRenderer();
- virtual ~SoftRenderer() override {};
- virtual bool Init() override;
- virtual void DeInit() override;
+ SoftRenderer() noexcept;
+ virtual ~SoftRenderer() override;
virtual void Reset() override;
virtual void SetRenderSettings(GPU::RenderSettings& settings) override;
diff --git a/src/GPU_OpenGL.cpp b/src/GPU_OpenGL.cpp
index 837d224..47e04d2 100644
--- a/src/GPU_OpenGL.cpp
+++ b/src/GPU_OpenGL.cpp
@@ -18,6 +18,7 @@
#include "GPU_OpenGL.h"
+#include <assert.h>
#include <cstdio>
#include <cstring>
@@ -32,33 +33,36 @@ namespace GPU
using namespace OpenGL;
-bool GLCompositor::Init()
+std::unique_ptr<GLCompositor> GLCompositor::New() noexcept
{
- if (!OpenGL::BuildShaderProgram(kCompositorVS, kCompositorFS_Nearest, CompShader[0], "CompositorShader"))
- //if (!OpenGL::BuildShaderProgram(kCompositorVS, kCompositorFS_Linear, CompShader[0], "CompositorShader"))
- //if (!OpenGL::BuildShaderProgram(kCompositorVS_xBRZ, kCompositorFS_xBRZ, CompShader[0], "CompositorShader"))
- return false;
+ assert(glBindAttribLocation != nullptr);
- for (int i = 0; i < 1; i++)
- {
- GLint uni_id;
+ std::array<GLuint, 3> CompShader {};
+ if (!OpenGL::BuildShaderProgram(kCompositorVS, kCompositorFS_Nearest, &CompShader[0], "CompositorShader"))
+ return nullptr;
- glBindAttribLocation(CompShader[i][2], 0, "vPosition");
- glBindAttribLocation(CompShader[i][2], 1, "vTexcoord");
- glBindFragDataLocation(CompShader[i][2], 0, "oColor");
+ glBindAttribLocation(CompShader[2], 0, "vPosition");
+ glBindAttribLocation(CompShader[2], 1, "vTexcoord");
+ glBindFragDataLocation(CompShader[2], 0, "oColor");
- if (!OpenGL::LinkShaderProgram(CompShader[i]))
- return false;
+ if (!OpenGL::LinkShaderProgram(CompShader.data()))
+ // OpenGL::LinkShaderProgram already deletes the shader program object
+ // if linking the shaders together failed.
+ return nullptr;
- CompScaleLoc[i] = glGetUniformLocation(CompShader[i][2], "u3DScale");
- Comp3DXPosLoc[i] = glGetUniformLocation(CompShader[i][2], "u3DXPos");
+ return std::unique_ptr<GLCompositor>(new GLCompositor(CompShader));
+}
- glUseProgram(CompShader[i][2]);
- uni_id = glGetUniformLocation(CompShader[i][2], "ScreenTex");
- glUniform1i(uni_id, 0);
- uni_id = glGetUniformLocation(CompShader[i][2], "_3DTex");
- glUniform1i(uni_id, 1);
- }
+GLCompositor::GLCompositor(std::array<GLuint, 3> compShader) noexcept : CompShader(compShader)
+{
+ CompScaleLoc = glGetUniformLocation(CompShader[2], "u3DScale");
+ Comp3DXPosLoc = glGetUniformLocation(CompShader[2], "u3DXPos");
+
+ glUseProgram(CompShader[2]);
+ GLuint screenTextureUniform = glGetUniformLocation(CompShader[2], "ScreenTex");
+ glUniform1i(screenTextureUniform, 0);
+ GLuint _3dTextureUniform = glGetUniformLocation(CompShader[2], "_3DTex");
+ glUniform1i(_3dTextureUniform, 1);
// all this mess is to prevent bleeding
#define SETVERTEX(i, x, y, offset) \
@@ -119,12 +123,12 @@ bool GLCompositor::Init()
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
- return true;
}
-void GLCompositor::DeInit()
+GLCompositor::~GLCompositor()
{
+ assert(glDeleteFramebuffers != nullptr);
+
glDeleteFramebuffers(2, CompScreenOutputFB);
glDeleteTextures(1, &CompScreenInputTex);
glDeleteTextures(2, CompScreenOutputTex);
@@ -132,8 +136,7 @@ void GLCompositor::DeInit()
glDeleteVertexArrays(1, &CompVertexArrayID);
glDeleteBuffers(1, &CompVertexBufferID);
- for (int i = 0; i < 1; i++)
- OpenGL::DeleteShaderProgram(CompShader[i]);
+ OpenGL::DeleteShaderProgram(CompShader.data());
}
void GLCompositor::Reset()
@@ -197,11 +200,11 @@ void GLCompositor::RenderFrame()
glClear(GL_COLOR_BUFFER_BIT);
// TODO: select more shaders (filtering, etc)
- OpenGL::UseShaderProgram(CompShader[0]);
- glUniform1ui(CompScaleLoc[0], Scale);
+ OpenGL::UseShaderProgram(CompShader.data());
+ glUniform1ui(CompScaleLoc, Scale);
// TODO: support setting this midframe, if ever needed
- glUniform1i(Comp3DXPosLoc[0], ((int)GPU3D::RenderXPos << 23) >> 23);
+ glUniform1i(Comp3DXPosLoc, ((int)GPU3D::RenderXPos << 23) >> 23);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, CompScreenInputTex);
diff --git a/src/GPU_OpenGL.h b/src/GPU_OpenGL.h
index d27ae20..90c17ae 100644
--- a/src/GPU_OpenGL.h
+++ b/src/GPU_OpenGL.h
@@ -20,6 +20,9 @@
#include "OpenGLSupport.h"
+#include <array>
+#include <memory>
+
namespace GPU
{
@@ -28,12 +31,11 @@ struct RenderSettings;
class GLCompositor
{
public:
- GLCompositor() = default;
+ static std::unique_ptr<GLCompositor> New() noexcept;
GLCompositor(const GLCompositor&) = delete;
GLCompositor& operator=(const GLCompositor&) = delete;
+ ~GLCompositor();
- bool Init();
- void DeInit();
void Reset();
void SetRenderSettings(RenderSettings& settings);
@@ -42,13 +44,14 @@ public:
void RenderFrame();
void BindOutputTexture(int buf);
private:
+ GLCompositor(std::array<GLuint, 3> CompShader) noexcept;
int Scale;
int ScreenH, ScreenW;
- GLuint CompShader[1][3];
- GLuint CompScaleLoc[1];
- GLuint Comp3DXPosLoc[1];
+ std::array<GLuint, 3> CompShader;
+ GLuint CompScaleLoc;
+ GLuint Comp3DXPosLoc;
GLuint CompVertexBufferID;
GLuint CompVertexArrayID;
diff --git a/src/NDS.cpp b/src/NDS.cpp
index 2f1759f..1e7321d 100644
--- a/src/NDS.cpp
+++ b/src/NDS.cpp
@@ -226,10 +226,16 @@ void DeInit()
#endif
delete ARM9;
+ ARM9 = nullptr;
+
delete ARM7;
+ ARM7 = nullptr;
for (int i = 0; i < 8; i++)
+ {
delete DMAs[i];
+ DMAs[i] = nullptr;
+ }
NDSCart::DeInit();
GBACart::DeInit();
diff --git a/src/OpenGLSupport.cpp b/src/OpenGLSupport.cpp
index 958930d..f1914fc 100644
--- a/src/OpenGLSupport.cpp
+++ b/src/OpenGLSupport.cpp
@@ -29,6 +29,12 @@ bool BuildShaderProgram(const char* vs, const char* fs, GLuint* ids, const char*
int len;
int res;
+ if (!glCreateShader)
+ {
+ Log(LogLevel::Error, "OpenGL: Cannot build shader program, OpenGL hasn't been loaded\n");
+ return false;
+ }
+
ids[0] = glCreateShader(GL_VERTEX_SHADER);
len = strlen(vs);
glShaderSource(ids[0], 1, &vs, &len);
@@ -87,6 +93,12 @@ bool LinkShaderProgram(GLuint* ids)
{
int res;
+ if (!glLinkProgram)
+ {
+ Log(LogLevel::Error, "OpenGL: Cannot link shader program, OpenGL hasn't been loaded\n");
+ return false;
+ }
+
glLinkProgram(ids[2]);
glDetachShader(ids[2], ids[0]);
@@ -115,12 +127,18 @@ bool LinkShaderProgram(GLuint* ids)
void DeleteShaderProgram(GLuint* ids)
{
- glDeleteProgram(ids[2]);
+ if (glDeleteProgram)
+ { // If OpenGL isn't loaded, then there's no shader program to delete
+ glDeleteProgram(ids[2]);
+ }
}
void UseShaderProgram(GLuint* ids)
{
- glUseProgram(ids[2]);
+ if (glUseProgram)
+ { // If OpenGL isn't loaded, then there's no shader program to use
+ glUseProgram(ids[2]);
+ }
}
}
diff --git a/src/SPI.cpp b/src/SPI.cpp
index bbfacbf..3c44964 100644
--- a/src/SPI.cpp
+++ b/src/SPI.cpp
@@ -91,6 +91,7 @@ bool Init()
void DeInit()
{
if (Firmware) delete[] Firmware;
+ Firmware = nullptr;
}
u32 FixFirmwareLength(u32 originalLength)
diff --git a/src/SPU.cpp b/src/SPU.cpp
index 734590e..e83a0c7 100644
--- a/src/SPU.cpp
+++ b/src/SPU.cpp
@@ -135,12 +135,18 @@ bool Init()
void DeInit()
{
for (int i = 0; i < 16; i++)
+ {
delete Channels[i];
+ Channels[i] = nullptr;
+ }
delete Capture[0];
delete Capture[1];
+ Capture[0] = nullptr;
+ Capture[1] = nullptr;
Platform::Mutex_Free(AudioLock);
+ AudioLock = nullptr;
}
void Reset()
diff --git a/src/frontend/qt_sdl/AudioInOut.cpp b/src/frontend/qt_sdl/AudioInOut.cpp
index d44e92d..48e8a86 100644
--- a/src/frontend/qt_sdl/AudioInOut.cpp
+++ b/src/frontend/qt_sdl/AudioInOut.cpp
@@ -334,12 +334,17 @@ void Init()
void DeInit()
{
if (audioDevice) SDL_CloseAudioDevice(audioDevice);
+ audioDevice = 0;
MicClose();
- SDL_DestroyCond(audioSync);
- SDL_DestroyMutex(audioSyncLock);
+ if (audioSync) SDL_DestroyCond(audioSync);
+ audioSync = nullptr;
+
+ if (audioSyncLock) SDL_DestroyMutex(audioSyncLock);
+ audioSyncLock = nullptr;
if (micWavBuffer) delete[] micWavBuffer;
+ micWavBuffer = nullptr;
}
void AudioSync()
diff --git a/src/frontend/qt_sdl/LocalMP.cpp b/src/frontend/qt_sdl/LocalMP.cpp
index 31801b7..870ea8b 100644
--- a/src/frontend/qt_sdl/LocalMP.cpp
+++ b/src/frontend/qt_sdl/LocalMP.cpp
@@ -297,16 +297,21 @@ bool Init()
void DeInit()
{
- MPQueue->lock();
- MPQueueHeader* header = (MPQueueHeader*)MPQueue->data();
- header->ConnectedBitmask &= ~(1 << InstanceID);
- header->InstanceBitmask &= ~(1 << InstanceID);
- header->NumInstances--;
- MPQueue->unlock();
+ if (MPQueue)
+ {
+ MPQueue->lock();
+ MPQueueHeader* header = (MPQueueHeader*)MPQueue->data();
+ header->ConnectedBitmask &= ~(1 << InstanceID);
+ header->InstanceBitmask &= ~(1 << InstanceID);
+ header->NumInstances--;
+ MPQueue->unlock();
- SemPoolDeinit();
+ SemPoolDeinit();
+
+ MPQueue->detach();
+ }
- MPQueue->detach();
+ MPQueue = nullptr;
delete MPQueue;
}