diff --git a/.vscode/launch-example-wsl.json b/.vscode/launch-example-wsl.json new file mode 100644 index 0000000000..e7559b0393 --- /dev/null +++ b/.vscode/launch-example-wsl.json @@ -0,0 +1,37 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "(gdb) Launch PPSSPPSDL (WSL)", + "type": "cppdbg", + "request": "launch", + "program": "/home/hrydg/ppsspp/build/PPSSPPSDL", + "osx": { + "program": "${workspaceFolder}/build/PPSSPPSDL.app/Contents/MacOS/PPSSPPSDL" + }, + "linux": { + "program": "/home/hrydg/ppsspp/build/PPSSPPSDL" + }, + "args": [], + "stopAtEntry": false, + "cwd": "/home/hrydg/ppsspp", + "sourceFileMap": { + "/home/hrydg/ppsspp": "${workspaceFolder}" + }, + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "pipeTransport": { + "pipeProgram": "wsl.exe", + "pipeArgs": [ + "-d", + "Ubuntu", + "--" + ], + "pipeCwd": "C:/", + "quoteArgs": false, + "debuggerPath": "/usr/bin/gdb" + } + } + ] +} \ No newline at end of file diff --git a/.vscode/launch-example.json b/.vscode/launch-example.json new file mode 100644 index 0000000000..878ad9851c --- /dev/null +++ b/.vscode/launch-example.json @@ -0,0 +1,24 @@ +{ + "comment": "Copy this to launch.json if you want to, or edit as desired first", + "version": "0.2.0", + "configurations": [ + { + "name": "(lldb) Launch", + "type": "cppdbg", + "request": "launch", + "program": "", + "osx": { + "program": "${workspaceFolder}/build/PPSSPPSDL.app/Contents/MacOS/PPSSPPSDL" + }, + "linux": { + "program": "${workspaceRoot}/build/PPSSPPSDL" + }, + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "lldb" + } + ] +} \ No newline at end of file diff --git a/Common/System/Display.cpp b/Common/System/Display.cpp index 096595e360..d80f0a6175 100644 --- a/Common/System/Display.cpp +++ b/Common/System/Display.cpp @@ -3,6 +3,7 @@ #include "Common/System/Display.h" #include "Common/Math/math_util.h" #include "Common/GPU/MiscTypes.h" +#include "Common/Log.h" DisplayProperties g_display; @@ -70,6 +71,7 @@ DisplayProperties::DisplayProperties() { } bool DisplayProperties::Recalculate(int new_pixel_xres, int new_pixel_yres, float new_scale_x, float new_scale_y, float customScale) { + INFO_LOG(Log::G3D, "recalculate: %dx%d, %f, %f, %f", new_pixel_xres, new_pixel_yres, new_scale_x, new_scale_y, customScale); bool px_changed = false; if (new_pixel_xres > 0 && pixel_xres != new_pixel_xres) { pixel_xres = new_pixel_xres; diff --git a/Common/UI/Screen.cpp b/Common/UI/Screen.cpp index 903be8a968..3b0ca9ab43 100644 --- a/Common/UI/Screen.cpp +++ b/Common/UI/Screen.cpp @@ -255,7 +255,7 @@ void ScreenManager::deviceRestored(Draw::DrawContext *draw) { } void ScreenManager::resized() { - INFO_LOG(Log::UI, "ScreenManager::resized(dp: %dx%d)", g_display.dp_xres, g_display.dp_yres); + INFO_LOG(Log::UI, "ScreenManager::resized(g_display.dp_xres/dp_yres: %dx%d)", g_display.dp_xres, g_display.dp_yres); // Have to notify the whole stack, otherwise there will be problems when going back // to non-top screens. for (auto &layer : stack_) { diff --git a/SDL/SDLGLGraphicsContext.cpp b/SDL/SDLGLGraphicsContext.cpp index da4ca4e2c1..e0bed058ac 100644 --- a/SDL/SDLGLGraphicsContext.cpp +++ b/SDL/SDLGLGraphicsContext.cpp @@ -286,6 +286,8 @@ void EGL_Close() { #endif // USING_EGL + + // TODO: All this stuff doesn't really belong here. bool SDLGLGraphicsContext::InitSurface(WindowSystem winsys, void *data1, void *data2, std::string *error_message) { SDL_Window *window = *(SDL_Window **)data1; @@ -448,10 +450,6 @@ bool SDLGLGraphicsContext::InitSurface(WindowSystem winsys, void *data1, void *d }); window_ = window; - - // HACK: Ensure that the swap interval is set after context creation (needed for kmsdrm) - SDL_GL_SetSwapInterval(1); - return true; } diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index 4e7267958b..c4f0167ed0 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -96,8 +96,6 @@ static float g_ForcedDPI = 0.0f; // if this is 0.0f, use g_DesktopDPI static float g_RefreshRate = 60.f; static int g_sampleRate = 44100; -static bool g_rebootEmuThread = false; - static SDL_AudioSpec g_retFmt; static int g_audioFramesPerBuffer = 0; @@ -1334,6 +1332,7 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta #if !defined(MOBILE_DEVICE) case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: { + INFO_LOG(Log::UI, "SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: %d x %d", event.window.data1, event.window.data2); int new_width = event.window.data1; int new_height = event.window.data2; @@ -1342,6 +1341,7 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta Uint64 window_flags = SDL_GetWindowFlags(window); bool fullscreen = (window_flags & SDL_WINDOW_FULLSCREEN) != 0; + // !!! This is the wrong thread! // This one calls NativeResized if the size changed. Native_UpdateScreenScale(new_width, new_height, UIScaleFactorToMultiplier(g_Config.iUIScaleFactor)); @@ -1408,7 +1408,9 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta #endif case SDL_EVENT_KEY_DOWN: { - if (event.key.repeat > 0) { break;} + if (event.key.repeat > 0) { + break; + } int k = event.key.key; KeyInput key; key.flags = KeyInputFlags::DOWN; @@ -1420,15 +1422,7 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta key.deviceId = DEVICE_ID_KEYBOARD; NativeKey(key); -#ifdef _DEBUG - if (k == SDLK_F7) { - fprintf(stderr, "f7 pressed - rebooting emuthread\n"); - g_rebootEmuThread = true; - } -#endif - // Convenience subset of what - // "Enable standard shortcut keys" - // does on Windows. + // Convenience subset of what "Enable standard shortcut keys" does on Windows. if (g_Config.bSystemControls) { bool ctrl = bool(event.key.mod & SDL_KMOD_CTRL); if (ctrl && (k == SDLK_W)) @@ -1539,6 +1533,7 @@ static void ProcessSDLEvent(SDL_Window *window, const SDL_Event &event, InputSta switch (event.button.button) { case SDL_BUTTON_LEFT: { + INFO_LOG(Log::UI, "SDL_EVENT_MOUSE_BUTTON_DOWN: %f x %f", event.button.x, event.button.y); // We have to juggle around 3 kinds of "DPI spaces" if a logical DPI is // provided (through --dpi, it is equal to system DPI if unspecified): // - SDL gives us motion events in "system DPI" points @@ -1749,6 +1744,7 @@ void UpdateSDLCursor() { } bool DetermineVulkanWindowSystem(SDL_Window *window, WindowSystem *windowSystem, void **data1, void **data2) { + _dbg_assert_(window); SDL_PropertiesID windowProps = SDL_GetWindowProperties(window); void *x11Display = SDL_GetPointerProperty(windowProps, SDL_PROP_WINDOW_X11_DISPLAY_POINTER, nullptr); if (x11Display != nullptr) { @@ -2039,82 +2035,93 @@ int main(int argc, char *argv[]) { SDL_Window *window = nullptr; // Switch away from Vulkan if not available. - if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN && !vulkanMayBeAvailable) { - g_Config.iGPUBackend = (int)GPUBackend::OPENGL; + int fallbackGPUBackend = -1; + switch ((GPUBackend)g_Config.iGPUBackend) { + case GPUBackend::VULKAN: + if (!vulkanMayBeAvailable) { + fprintf(stderr, "Vulkan is not available, switching to OpenGL.\n"); + g_Config.iGPUBackend = (int)GPUBackend::OPENGL; + } else { + fallbackGPUBackend = (int)GPUBackend::OPENGL; + } + break; + case GPUBackend::OPENGL: + fallbackGPUBackend = (int)GPUBackend::VULKAN; + break; + default: + fprintf(stderr, "Unknown GPU backend %d, switching to Vulkan.\n", g_Config.iGPUBackend); + g_Config.iGPUBackend = (int)GPUBackend::VULKAN; + fallbackGPUBackend = (int)GPUBackend::OPENGL; + break; } - window = SDL_CreateWindow("Initializing graphics...", w, h, (SDL_WindowFlags)mode); + auto initializeBackend = [&](GPUBackend backend, GraphicsContext **graphicsContext, std::string *errorMessage) -> bool { + // Surface init params. + WindowSystem windowSystem = WINDOWSYSTEM_NONE; + void *data1 = &window; + void *data2 = (void *)(uintptr_t)mode; + if (backend == GPUBackend::OPENGL) { + mode |= SDL_WINDOW_OPENGL; + window = SDL_CreateWindow("Initializing graphics...", w, h, (SDL_WindowFlags)mode); + if (!window) { + fprintf(stderr, "Error creating SDL window: %s\n", SDL_GetError()); + exit(1); + } - // Surface init params. These are set up for OpenGL by default. - WindowSystem windowSystem = WINDOWSYSTEM_NONE; - void *data1 = &window; - void *data2 = nullptr; + SDLGLGraphicsContext *glctx = new SDLGLGraphicsContext(cmdLineOptions.force_gl_version); + *graphicsContext = glctx; - std::string error_message; - if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL) { - SDLGLGraphicsContext *glctx = new SDLGLGraphicsContext(cmdLineOptions.force_gl_version); - if (!window) { - fprintf(stderr, "Error creating SDL window: %s\n", SDL_GetError()); - exit(1); - } - if (x != SDL_WINDOWPOS_UNDEFINED && y != SDL_WINDOWPOS_UNDEFINED) { - SDL_SetWindowPosition(window, x, y); - } - - glctx->InitAPI(nullptr, nullptr, &error_message); - if (!glctx->InitSurface(WINDOWSYSTEM_NONE, &window, (void *)(uintptr_t)mode, &error_message)) { - // Let's try the fallback once per process run. - fprintf(stderr, "GL init error '%s' - falling back to Vulkan\n", error_message.c_str()); - g_Config.iGPUBackend = (int)GPUBackend::VULKAN; - SetGPUBackend((GPUBackend)g_Config.iGPUBackend); - delete glctx; + glctx->InitAPI(nullptr, nullptr, errorMessage); + if (!glctx->InitSurface(windowSystem, data1, data2, errorMessage)) { + fprintf(stderr, "OpenGL surface creation failed: %s\n", errorMessage->c_str()); + return false; + } + } else { + mode |= SDL_WINDOW_VULKAN; + window = SDL_CreateWindow("Initializing graphics...", w, h, (SDL_WindowFlags)mode); + if (!window) { + fprintf(stderr, "Error creating SDL window: %s\n", SDL_GetError()); + exit(1); + } // Overwrite the surface init params with what we need for Vulkan.. if (!DetermineVulkanWindowSystem(window, &windowSystem, &data1, &data2)) { - return 1; + return false; } - // NOTE : This should match the lines below in the Vulkan case. VulkanGraphicsContext *vkctx = new VulkanGraphicsContext(); - vkctx->InitAPI(nullptr, &g_Config.sVulkanDevice, &error_message); + if (!vkctx->InitAPI(nullptr, &g_Config.sVulkanDevice, errorMessage)) { + fprintf(stderr, "Vulkan initialization failed: %s\n", errorMessage->c_str()); + return false; + } + if (!vkctx->InitSurface(windowSystem, data1, data2, errorMessage)) { + fprintf(stderr, "Vulkan surface creation failed: %s\n", errorMessage->c_str()); + return false; + } + *graphicsContext = vkctx; + } + return true; + }; - if (!vkctx->InitSurface(windowSystem, data1, data2, &error_message)) { - fprintf(stderr, "Vulkan fallback failed: %s\n", error_message.c_str()); + std::string error_message; + if (!initializeBackend((GPUBackend)g_Config.iGPUBackend, &graphicsContext, &error_message)) { + fprintf(stderr, "Failed to initialize graphics backend: %s\n", error_message.c_str()); + if (fallbackGPUBackend != -1) { + fprintf(stderr, "Attempting to fall back to %s...\n", fallbackGPUBackend == (int)GPUBackend::OPENGL ? "OpenGL" : "Vulkan"); + g_Config.iGPUBackend = fallbackGPUBackend; + error_message.clear(); + if (!initializeBackend((GPUBackend)g_Config.iGPUBackend, &graphicsContext, &error_message)) { + fprintf(stderr, "Fallback failed: %s\n", error_message.c_str()); return 1; } - graphicsContext = vkctx; } else { - graphicsContext = glctx; - } -#if !PPSSPP_PLATFORM(SWITCH) - } else if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN) { - // Overwrite the surface init params with what we need for Vulkan.. - if (!DetermineVulkanWindowSystem(window, &windowSystem, &data1, &data2)) { + fprintf(stderr, "No fallback GPU backend available. Exiting.\n"); return 1; } + } - VulkanGraphicsContext *vkctx = new VulkanGraphicsContext(); - vkctx->InitAPI(nullptr, &g_Config.sVulkanDevice, &error_message); - if (!vkctx->InitSurface(windowSystem, data1, data2, &error_message)) { - // Let's try the fallback once per process run. - - fprintf(stderr, "Vulkan init error '%s' - falling back to GL\n", error_message.c_str()); - g_Config.iGPUBackend = (int)GPUBackend::OPENGL; - SetGPUBackend((GPUBackend)g_Config.iGPUBackend); - delete vkctx; - - // NOTE : This should match the three lines above in the OpenGL case. - SDLGLGraphicsContext *glctx = new SDLGLGraphicsContext(cmdLineOptions.force_gl_version); - glctx->InitAPI(nullptr, nullptr, &error_message); - if (!glctx->InitSurface(windowSystem, data1, data2, &error_message)) { - fprintf(stderr, "GL fallback failed: %s\n", error_message.c_str()); - return 1; - } - graphicsContext = glctx; - } else { - graphicsContext = vkctx; - } -#endif + if (x != SDL_WINDOWPOS_UNDEFINED && y != SDL_WINDOWPOS_UNDEFINED) { + SDL_SetWindowPosition(window, x, y); } UpdateScreenDPI(window); @@ -2175,6 +2182,7 @@ int main(int argc, char *argv[]) { EnableFZ(); // We use the emuthread both for OpenGL and Vulkan, but in OpenGL mode we also render from the main thread. + _dbg_assert_(graphicsContext); std::thread emuThread = EmuThread_Start(graphicsContext, new NativeApplication(), nullptr); InputStateTracker inputTracker{}; @@ -2251,24 +2259,6 @@ int main(int argc, char *argv[]) { UpdateWindowState(window); } } - - if (g_rebootEmuThread) { - fprintf(stderr, "rebooting emu thread"); - g_rebootEmuThread = false; - EmuThread_Join(graphicsContext, emuThread); - graphicsContext->ShutdownSurface(); - - fprintf(stderr, "OK, shutdown complete. starting up graphics again.\n"); - - if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL) { - SDLGLGraphicsContext *ctx = (SDLGLGraphicsContext *)graphicsContext; - if (!ctx->InitSurface(windowSystem,data1, data2, &error_message)) { - fprintf(stderr, "Failed to reinit graphics.\n"); - } - } - - emuThread = EmuThread_Start(graphicsContext, new NativeApplication(), nullptr); - } } EmuThread_Join(graphicsContext, emuThread);