mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Error handling cleanup, with some Claude help
This commit is contained in:
1 parent
6272eca2e7
commit
ced24079cb
3 files changed
+102
-52
No files matched your search
@@ -8,6 +8,7 @@
|
||||
#include "Common/System/NativeApp.h"
|
||||
#include "Common/System/System.h"
|
||||
#include "Common/System/Display.h"
|
||||
#include "Common/StringUtils.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/ConfigValues.h"
|
||||
#include "Core/System.h"
|
||||
@@ -32,7 +33,7 @@ static bool g_XDisplayOpen = false;
|
||||
static EGLNativeWindowType g_Window = (EGLNativeWindowType)nullptr;
|
||||
static bool useEGLSwap = false;
|
||||
|
||||
int CheckEGLErrors(const char *file, int line) {
|
||||
int CheckEGLErrors(const char *file, int line, std::string *errorMessage) {
|
||||
EGLenum error;
|
||||
const char *errortext = "unknown";
|
||||
error = eglGetError();
|
||||
@@ -54,27 +55,25 @@ int CheckEGLErrors(const char *file, int line) {
|
||||
case EGL_BAD_NATIVE_WINDOW: errortext = "EGL_BAD_NATIVE_WINDOW"; break;
|
||||
default: errortext = "unknown"; break;
|
||||
}
|
||||
fprintf( stderr, "ERROR: EGL Error %s detected in file %s at line %d (0x%X)\n", errortext, file, line, error );
|
||||
if (errorMessage) {
|
||||
*errorMessage += StringFromFormat("EGL Error %s detected in file %s at line %d (0x%X)\n", errortext, file, line, error);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define EGL_ERROR(str, check) { \
|
||||
if (check) CheckEGLErrors( __FILE__, __LINE__ ); \
|
||||
fprintf(stderr, "EGL ERROR: " str "\n"); \
|
||||
return 1; \
|
||||
}
|
||||
|
||||
static bool EGL_OpenInit() {
|
||||
// NOTE: Not using the EGL_ERROR macro here since it always does "return 1",
|
||||
// which means "success" for this bool-returning function.
|
||||
static bool EGL_OpenInit(std::string *errorMessage) {
|
||||
if ((g_eglDisplay = eglGetDisplay(g_Display)) == EGL_NO_DISPLAY) {
|
||||
CheckEGLErrors(__FILE__, __LINE__);
|
||||
fprintf(stderr, "EGL ERROR: Unable to create EGL display.\n");
|
||||
CheckEGLErrors(__FILE__, __LINE__, errorMessage);
|
||||
if (errorMessage) {
|
||||
*errorMessage += "Unable to create EGL display.\n";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (eglInitialize(g_eglDisplay, NULL, NULL) != EGL_TRUE) {
|
||||
CheckEGLErrors(__FILE__, __LINE__);
|
||||
fprintf(stderr, "EGL ERROR: Unable to initialize EGL display.\n");
|
||||
CheckEGLErrors(__FILE__, __LINE__, errorMessage);
|
||||
if (errorMessage) {
|
||||
*errorMessage += "Unable to initialize EGL display.\n";
|
||||
}
|
||||
eglTerminate(g_eglDisplay);
|
||||
g_eglDisplay = EGL_NO_DISPLAY;
|
||||
return false;
|
||||
@@ -83,15 +82,19 @@ static bool EGL_OpenInit() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int8_t EGL_Open(SDL_Window *window) {
|
||||
static int8_t EGL_Open(SDL_Window *window, std::string *errorMessage) {
|
||||
#if defined(USING_FBDEV)
|
||||
g_Display = (EGLNativeDisplayType)nullptr;
|
||||
g_Window = (EGLNativeWindowType)nullptr;
|
||||
#elif defined(__APPLE__)
|
||||
g_Display = (EGLNativeDisplayType)XOpenDisplay(nullptr);
|
||||
g_XDisplayOpen = g_Display != nullptr;
|
||||
if (!g_XDisplayOpen)
|
||||
EGL_ERROR("Unable to get display!", false);
|
||||
if (!g_XDisplayOpen) {
|
||||
if (errorMessage) {
|
||||
*errorMessage += "Unable to get display!\n";
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
g_Window = (EGLNativeWindowType)nullptr;
|
||||
#else
|
||||
// Get the SDL window native handle
|
||||
@@ -107,26 +110,36 @@ static int8_t EGL_Open(SDL_Window *window) {
|
||||
g_Display = (EGLNativeDisplayType)waylandDisplay;
|
||||
g_Window = (EGLNativeWindowType)waylandEGLWindow;
|
||||
} else {
|
||||
fprintf(stderr, "ERROR: Unable to retrieve native window properties\n");
|
||||
if (errorMessage) {
|
||||
*errorMessage += "Unable to retrieve native window properties, falling back to X11.\n";
|
||||
}
|
||||
g_Display = (EGLNativeDisplayType)XOpenDisplay(nullptr);
|
||||
g_XDisplayOpen = g_Display != nullptr;
|
||||
if (!g_XDisplayOpen)
|
||||
EGL_ERROR("Unable to get display!", false);
|
||||
if (!g_XDisplayOpen) {
|
||||
if (errorMessage) {
|
||||
*errorMessage += "Unable to get display!\n";
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
g_Window = (EGLNativeWindowType)nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (!EGL_OpenInit()) {
|
||||
if (!EGL_OpenInit(errorMessage)) {
|
||||
g_Display = (EGLNativeDisplayType)XOpenDisplay(nullptr);
|
||||
g_XDisplayOpen = g_Display != nullptr;
|
||||
if (!g_XDisplayOpen)
|
||||
EGL_ERROR("Unable to get display!", false);
|
||||
if (!g_XDisplayOpen) {
|
||||
if (errorMessage) {
|
||||
*errorMessage += "Unable to get display!\n";
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
g_Window = (EGLNativeWindowType)nullptr;
|
||||
}
|
||||
|
||||
#endif
|
||||
if (g_eglDisplay == EGL_NO_DISPLAY)
|
||||
EGL_OpenInit();
|
||||
EGL_OpenInit(errorMessage);
|
||||
return g_eglDisplay == EGL_NO_DISPLAY ? 1 : 0;
|
||||
}
|
||||
|
||||
@@ -134,18 +147,26 @@ static int8_t EGL_Open(SDL_Window *window) {
|
||||
#define EGL_OPENGL_ES3_BIT_KHR (1 << 6)
|
||||
#endif
|
||||
|
||||
EGLConfig EGL_FindConfig(int *contextVersion) {
|
||||
EGLConfig EGL_FindConfig(int *contextVersion, std::string *errorMessage) {
|
||||
std::vector<EGLConfig> configs;
|
||||
EGLint numConfigs = 0;
|
||||
|
||||
EGLBoolean result = eglGetConfigs(g_eglDisplay, nullptr, 0, &numConfigs);
|
||||
if (result != EGL_TRUE || numConfigs == 0) {
|
||||
CheckEGLErrors(__FILE__, __LINE__, errorMessage);
|
||||
if (errorMessage) {
|
||||
*errorMessage += "eglGetConfigs failed to return any configs.\n";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
configs.resize(numConfigs);
|
||||
result = eglGetConfigs(g_eglDisplay, &configs[0], numConfigs, &numConfigs);
|
||||
if (result != EGL_TRUE || numConfigs == 0) {
|
||||
CheckEGLErrors(__FILE__, __LINE__, errorMessage);
|
||||
if (errorMessage) {
|
||||
*errorMessage += "eglGetConfigs failed to return any configs.\n";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -228,11 +249,13 @@ EGLConfig EGL_FindConfig(int *contextVersion) {
|
||||
return best;
|
||||
}
|
||||
|
||||
int8_t EGL_Init(SDL_Window *window) {
|
||||
int8_t EGL_Init(SDL_Window *window, std::string *errorMessage) {
|
||||
int contextVersion = 0;
|
||||
EGLConfig eglConfig = EGL_FindConfig(&contextVersion);
|
||||
EGLConfig eglConfig = EGL_FindConfig(&contextVersion, errorMessage);
|
||||
if (!eglConfig) {
|
||||
EGL_ERROR("Unable to find a usable EGL config.", true);
|
||||
if (errorMessage) {
|
||||
*errorMessage += "Unable to find a usable EGL config.\n";
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -246,18 +269,27 @@ int8_t EGL_Init(SDL_Window *window) {
|
||||
|
||||
g_eglContext = eglCreateContext(g_eglDisplay, eglConfig, nullptr, contextAttributes);
|
||||
if (g_eglContext == EGL_NO_CONTEXT) {
|
||||
EGL_ERROR("Unable to create GLES context!", true);
|
||||
CheckEGLErrors(__FILE__, __LINE__, errorMessage);
|
||||
if (errorMessage) {
|
||||
*errorMessage += "Unable to create GLES context!\n";
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_eglSurface = eglCreateWindowSurface(g_eglDisplay, eglConfig, g_Window, nullptr);
|
||||
if (g_eglSurface == EGL_NO_SURFACE) {
|
||||
EGL_ERROR("Unable to create EGL surface!", true);
|
||||
CheckEGLErrors(__FILE__, __LINE__, errorMessage);
|
||||
if (errorMessage) {
|
||||
*errorMessage += "Unable to create EGL surface!\n";
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (eglMakeCurrent(g_eglDisplay, g_eglSurface, g_eglSurface, g_eglContext) != EGL_TRUE) {
|
||||
EGL_ERROR("Unable to make GLES context current.", true);
|
||||
CheckEGLErrors(__FILE__, __LINE__, errorMessage);
|
||||
if (errorMessage) {
|
||||
*errorMessage += "Unable to make GLES context current.\n";
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -290,7 +322,7 @@ void EGL_Close() {
|
||||
|
||||
#endif // USING_EGL
|
||||
|
||||
SDL_Window *CreateSDLGLWindowAndContext(int x, int y, int w, int h, int mode, int forceGLVersion, SDL_GLContext *glContextOut) {
|
||||
SDL_Window *CreateSDLGLWindowAndContext(int x, int y, int w, int h, int mode, int forceGLVersion, SDL_GLContext *glContextOut, std::string *errorMessage) {
|
||||
// We start hidden because we have to try several windows.
|
||||
// On Mac, full screen animates so each attempt is slow.
|
||||
mode |= SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN;
|
||||
@@ -333,7 +365,9 @@ SDL_Window *CreateSDLGLWindowAndContext(int x, int y, int w, int h, int mode, in
|
||||
window = SDL_CreateWindow("PPSSPP", w, h, (SDL_WindowFlags)mode);
|
||||
if (!window) {
|
||||
// Definitely don't shutdown here: we'll keep trying more GL versions.
|
||||
fprintf(stderr, "SDL_CreateWindow failed for GL %d.%d: %s\n", ver.major, ver.minor, SDL_GetError());
|
||||
if (errorMessage) {
|
||||
*errorMessage += StringFromFormat("SDL_CreateWindow failed for GL %d.%d: %s\n", ver.major, ver.minor, SDL_GetError());
|
||||
}
|
||||
// Skip the DestroyWindow.
|
||||
continue;
|
||||
}
|
||||
@@ -360,14 +394,18 @@ SDL_Window *CreateSDLGLWindowAndContext(int x, int y, int w, int h, int mode, in
|
||||
|
||||
window = SDL_CreateWindow("PPSSPP", w, h, (SDL_WindowFlags)mode);
|
||||
if (window == nullptr) {
|
||||
fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError());
|
||||
if (errorMessage) {
|
||||
*errorMessage += StringFromFormat("SDL_CreateWindow failed: %s\n", SDL_GetError());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
glContext = SDL_GL_CreateContext(window);
|
||||
if (!glContext) {
|
||||
// OK, now we really have tried everything. We give up.
|
||||
fprintf(stderr, "SDL_GL_CreateContext failed: %s\n", SDL_GetError());
|
||||
if (errorMessage) {
|
||||
*errorMessage += StringFromFormat("SDL_GL_CreateContext failed: %s\n", SDL_GetError());
|
||||
}
|
||||
SDL_DestroyWindow(window);
|
||||
return nullptr;
|
||||
}
|
||||
@@ -379,10 +417,12 @@ SDL_Window *CreateSDLGLWindowAndContext(int x, int y, int w, int h, int mode, in
|
||||
}
|
||||
|
||||
#ifdef USING_EGL
|
||||
if (EGL_Open(window) != 0) {
|
||||
fprintf(stderr, "EGL_Open() failed\n");
|
||||
} else if (EGL_Init(window) != 0) {
|
||||
fprintf(stderr, "EGL_Init() failed\n");
|
||||
// EGL is optional here - if it fails, we just keep using the regular SDL/GLX swap set up above.
|
||||
std::string eglError;
|
||||
if (EGL_Open(window, &eglError) != 0) {
|
||||
WARN_LOG(Log::G3D, "EGL_Open() failed: %s", eglError.c_str());
|
||||
} else if (EGL_Init(window, &eglError) != 0) {
|
||||
WARN_LOG(Log::G3D, "EGL_Init() failed: %s", eglError.c_str());
|
||||
} else {
|
||||
useEGLSwap = true;
|
||||
}
|
||||
@@ -397,7 +437,9 @@ SDL_Window *CreateSDLGLWindowAndContext(int x, int y, int w, int h, int mode, in
|
||||
GLenum glew_err = glewInit();
|
||||
// glx is not required, igore.
|
||||
if (glew_err != GLEW_OK && glew_err != GLEW_ERROR_NO_GLX_DISPLAY) {
|
||||
fprintf(stderr, "Failed to initialize glew!\n");
|
||||
if (errorMessage) {
|
||||
*errorMessage += StringFromFormat("Failed to initialize glew: %s\n", (const char *)glewGetErrorString(glew_err));
|
||||
}
|
||||
SDL_GL_DestroyContext(glContext);
|
||||
SDL_DestroyWindow(window);
|
||||
return nullptr;
|
||||
@@ -407,9 +449,11 @@ SDL_Window *CreateSDLGLWindowAndContext(int x, int y, int w, int h, int mode, in
|
||||
glGetError();
|
||||
|
||||
if (GLEW_VERSION_2_0) {
|
||||
fprintf(stderr, "OpenGL 2.0 or higher.\n");
|
||||
INFO_LOG(Log::G3D, "OpenGL 2.0 or higher.");
|
||||
} else {
|
||||
fprintf(stderr, "Sorry, this program requires OpenGL 2.0.\n");
|
||||
if (errorMessage) {
|
||||
*errorMessage += "Sorry, this program requires OpenGL 2.0.\n";
|
||||
}
|
||||
SDL_GL_DestroyContext(glContext);
|
||||
SDL_DestroyWindow(window);
|
||||
return nullptr;
|
||||
|
||||
@@ -46,4 +46,4 @@ private:
|
||||
GLRenderManager *renderManager_ = nullptr;
|
||||
};
|
||||
|
||||
SDL_Window *CreateSDLGLWindowAndContext(int x, int y, int w, int h, int mode, int forceGLVersion, SDL_GLContext *glContextOut);
|
||||
SDL_Window *CreateSDLGLWindowAndContext(int x, int y, int w, int h, int mode, int forceGLVersion, SDL_GLContext *glContextOut, std::string *errorMessage);
|
||||
+14
-8
@@ -1748,7 +1748,7 @@ void UpdateSDLCursor() {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool DetermineVulkanWindowSystem(SDL_Window *window, WindowSystem *windowSystem, void **data1, void **data2) {
|
||||
bool DetermineVulkanWindowSystem(SDL_Window *window, WindowSystem *windowSystem, void **data1, void **data2, std::string *errorMessage) {
|
||||
_dbg_assert_(window);
|
||||
SDL_PropertiesID windowProps = SDL_GetWindowProperties(window);
|
||||
void *x11Display = SDL_GetPointerProperty(windowProps, SDL_PROP_WINDOW_X11_DISPLAY_POINTER, nullptr);
|
||||
@@ -1794,7 +1794,9 @@ bool DetermineVulkanWindowSystem(SDL_Window *window, WindowSystem *windowSystem,
|
||||
}
|
||||
#endif
|
||||
#endif // VK_USE_PLATFORM_METAL_EXT
|
||||
fprintf(stderr, "Unable to determine Vulkan window system from SDL3 window properties\n");
|
||||
if (errorMessage) {
|
||||
*errorMessage = "Unable to determine Vulkan window system from SDL3 window properties";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2067,25 +2069,29 @@ int main(int argc, char *argv[]) {
|
||||
GraphicsContext *ctx = nullptr;
|
||||
if (backend == GPUBackend::OPENGL) {
|
||||
SDL_GLContext glContext = nullptr;
|
||||
window = CreateSDLGLWindowAndContext(x, y, w, h, mode, cmdLineOptions.force_gl_version, &glContext);
|
||||
window = CreateSDLGLWindowAndContext(x, y, w, h, mode, cmdLineOptions.force_gl_version, &glContext, errorMessage);
|
||||
|
||||
data1 = (void *)window;
|
||||
data2 = (void *)glContext;
|
||||
|
||||
ctx = new SDLGLGraphicsContext();
|
||||
} else {
|
||||
mode |= SDL_WINDOW_VULKAN | SDL_WINDOW_HIDDEN;
|
||||
window = SDL_CreateWindow("Initializing graphics...", w, h, (SDL_WindowFlags)mode);
|
||||
// Use a local copy of mode: this flag combination is Vulkan-specific, and if we fall back to
|
||||
// OpenGL below, we don't want SDL_WINDOW_VULKAN to stick around and get OR'd in there too.
|
||||
Uint32 vulkanMode = mode | SDL_WINDOW_VULKAN | SDL_WINDOW_HIDDEN;
|
||||
window = SDL_CreateWindow("Initializing graphics...", w, h, (SDL_WindowFlags)vulkanMode);
|
||||
if (!window) {
|
||||
fprintf(stderr, "Error creating SDL window: %s\n", SDL_GetError());
|
||||
exit(1);
|
||||
if (errorMessage) {
|
||||
*errorMessage = StringFromFormat("Error creating SDL window: %s", SDL_GetError());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (x != SDL_WINDOWPOS_UNDEFINED && y != SDL_WINDOWPOS_UNDEFINED) {
|
||||
SDL_SetWindowPosition(window, x, y);
|
||||
}
|
||||
|
||||
// Overwrite the surface init params with what we need for Vulkan..
|
||||
if (!DetermineVulkanWindowSystem(window, &windowSystem, &data1, &data2)) {
|
||||
if (!DetermineVulkanWindowSystem(window, &windowSystem, &data1, &data2, errorMessage)) {
|
||||
return false;
|
||||
}
|
||||
// NOTE : This should match the lines below in the Vulkan case.
|
||||
|
||||
Reference in new issue
Block a user