From 88bfab066c54b3bfe33450a8bcd3bedf67ca7f4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 5 Aug 2026 16:37:57 +0200 Subject: [PATCH] Add size hints for Vulkan surface size, using SDL window size, in case it can't be determined by the driver --- Common/GPU/GraphicsContext.h | 7 ++-- Common/GPU/OpenGL/OpenGLGraphicsContext.cpp | 2 +- Common/GPU/OpenGL/OpenGLGraphicsContext.h | 4 +- Common/GPU/Vulkan/VulkanContext.cpp | 38 +++++++++++++---- Common/GPU/Vulkan/VulkanContext.h | 5 ++- Common/GPU/Vulkan/VulkanGraphicsContext.cpp | 12 +++--- Common/GPU/Vulkan/VulkanGraphicsContext.h | 4 +- Common/System/Display.cpp | 2 +- Core/EmuThread.cpp | 2 +- Qt/QtMain.cpp | 2 +- Qt/QtMain.h | 3 +- SDL/SDLGLGraphicsContext.cpp | 2 +- SDL/SDLGLGraphicsContext.h | 4 +- SDL/SDLMain.cpp | 6 ++- UI/NativeApp.cpp | 2 +- UI/UIAtlas.cpp | 46 ++++++++++----------- UWP/PPSSPP_UWPMain.h | 1 - Windows/GPU/D3D11Context.cpp | 2 +- Windows/GPU/D3D11Context.h | 4 +- Windows/GPU/WindowsGLContext.cpp | 5 +-- Windows/GPU/WindowsGLContext.h | 3 +- android/jni/app-android.cpp | 6 +-- headless/SDLHeadlessGLGraphicsContext.cpp | 2 +- headless/SDLHeadlessGLGraphicsContext.h | 4 +- ios/ViewController.mm | 2 +- ios/ViewControllerMetal.mm | 2 +- libretro/LibretroGraphicsContext.h | 2 +- 27 files changed, 96 insertions(+), 78 deletions(-) diff --git a/Common/GPU/GraphicsContext.h b/Common/GPU/GraphicsContext.h index a4b2667a41..0e26f1438c 100644 --- a/Common/GPU/GraphicsContext.h +++ b/Common/GPU/GraphicsContext.h @@ -28,7 +28,9 @@ public: virtual void ShutdownAPI() {} // These should be called on the render thread if NeedsRenderThread. - virtual bool InitSurface(WindowSystem winsys, void *data1, void *data2, std::string *errorMessage) { return true; } + // widthHint/heightHint are optional hints for the initial surface size, used by backends/window systems + // that can't otherwise determine it (0 if unknown - most implementations ignore these). + virtual bool InitSurface(WindowSystem winsys, void *data1, void *data2, int widthHint, int heightHint, std::string *errorMessage) { return true; } virtual void ShutdownSurface() {} // Used during window resize on desktop ONLY. Must be called from the window thread, @@ -36,7 +38,7 @@ public: virtual void Pause() {} virtual void Resume() {} - virtual void Resize() = 0; + virtual void Resize(int widthHint, int heightHint) {} virtual void NotifyWindowRestored() {} // Needs casting to the appropriate type, unfortunately. Should find a better solution.. @@ -68,6 +70,5 @@ class NullGraphicsContext : public GraphicsContext { public: NullGraphicsContext() {} Draw::DrawContext *GetDrawContext() override { return nullptr; } - void Resize() override {} bool NeedsSeparateEmuThread() const override { return false; } }; diff --git a/Common/GPU/OpenGL/OpenGLGraphicsContext.cpp b/Common/GPU/OpenGL/OpenGLGraphicsContext.cpp index 796255d0b9..f73a802d45 100644 --- a/Common/GPU/OpenGL/OpenGLGraphicsContext.cpp +++ b/Common/GPU/OpenGL/OpenGLGraphicsContext.cpp @@ -15,7 +15,7 @@ OpenGLGraphicsContext::OpenGLGraphicsContext() { g_display.rot_matrix.setIdentity(); } -bool OpenGLGraphicsContext::InitSurface(WindowSystem winsys, void *data1, void *data2, std::string *errorMessage) { +bool OpenGLGraphicsContext::InitSurface(WindowSystem winsys, void *data1, void *data2, int widthHint, int heightHint, std::string *errorMessage) { CheckGLExtensions(); INFO_LOG(Log::G3D, "OpenGLGraphicsContext::InitSurface"); draw_ = Draw::T3DCreateGLContext(false); // Can't fail diff --git a/Common/GPU/OpenGL/OpenGLGraphicsContext.h b/Common/GPU/OpenGL/OpenGLGraphicsContext.h index 88ba27f5f3..9ea8ff5db0 100644 --- a/Common/GPU/OpenGL/OpenGLGraphicsContext.h +++ b/Common/GPU/OpenGL/OpenGLGraphicsContext.h @@ -13,10 +13,10 @@ public: bool NeedsSeparateEmuThread() const override { return true; } - bool InitSurface(WindowSystem winsys, void *data1, void *data2, std::string *error_message) override; + bool InitSurface(WindowSystem winsys, void *data1, void *data2, int widthHint, int heightHint, std::string *error_message) override; void ShutdownSurface() override; - void Resize() override {} + void Resize(int widthHint, int heightHint) override {} Draw::DrawContext *GetDrawContext() override { return draw_; diff --git a/Common/GPU/Vulkan/VulkanContext.cpp b/Common/GPU/Vulkan/VulkanContext.cpp index 05d21c94d0..5311c070ac 100644 --- a/Common/GPU/Vulkan/VulkanContext.cpp +++ b/Common/GPU/Vulkan/VulkanContext.cpp @@ -64,6 +64,23 @@ std::string VulkanVendorString(uint32_t vendorId) { } } +const char *WindowSystemToString(WindowSystem winsys) { + switch (winsys) { + case WINDOWSYSTEM_UNINITIALIZED: return "UNINITIALIZED"; + case WINDOWSYSTEM_WIN32: return "WIN32"; + case WINDOWSYSTEM_ANDROID: return "ANDROID"; + case WINDOWSYSTEM_METAL_EXT: return "METAL_EXT"; + case WINDOWSYSTEM_XLIB: return "XLIB"; + case WINDOWSYSTEM_XCB: return "XCB"; + case WINDOWSYSTEM_WAYLAND: return "WAYLAND"; + case WINDOWSYSTEM_DISPLAY: return "DISPLAY"; + case WINDOWSYSTEM_SDL: return "SDL"; + case WINDOWSYSTEM_NONE: return "NONE"; + default: + return "UNKNOWN"; + } +} + const char *VulkanPresentModeToString(VkPresentModeKHR presentMode) { switch (presentMode) { case VK_PRESENT_MODE_IMMEDIATE_KHR: return "IMMEDIATE"; @@ -953,10 +970,10 @@ void VulkanContext::SetDebugNameImpl(uint64_t handle, VkObjectType type, const c VkResult VulkanContext::InitSurface(WindowSystem winsys, void *data1, void *data2) { winsys_ = winsys; if (winsysData1_ != data1 && winsysData1_ != 0) { - WARN_LOG(Log::G3D, "winsysData1 changed from %p to %p", winsysData1_, data1); + WARN_LOG(Log::G3D, "%s: winsysData1 changed from %p to %p", WindowSystemToString(winsys_), winsysData1_, data1); } if (winsysData2_ != data2 && winsysData2_ != 0) { - WARN_LOG(Log::G3D, "winsysData2 changed from %p to %p", winsysData2_, data2); + WARN_LOG(Log::G3D, "%s: winsysData2 changed from %p to %p", WindowSystemToString(winsys_), winsysData2_, data2); } winsysData1_ = data1; winsysData2_ = data2; @@ -970,7 +987,7 @@ VkResult VulkanContext::ReinitSurface() { surface_ = VK_NULL_HANDLE; } - INFO_LOG(Log::G3D, "Creating Vulkan surface for window (data1=%p data2=%p)", winsysData1_, winsysData2_); + INFO_LOG(Log::G3D, "Creating Vulkan surface for window (winsys=%s data1=%p data2=%p)", WindowSystemToString(winsys_), winsysData1_, winsysData2_); VkResult retval = VK_SUCCESS; @@ -1370,7 +1387,7 @@ static std::string surface_transforms_to_string(VkSurfaceTransformFlagsKHR trans return str; } -bool VulkanContext::InitSwapchain(VkPresentModeKHR desiredPresentMode) { +bool VulkanContext::InitSwapchain(VkPresentModeKHR desiredPresentMode, int widthHint, int heightHint) { _assert_(physical_device_ >= 0 && physical_device_ < (int)physical_devices_.size()); if (!surface_) { ERROR_LOG(Log::G3D, "VK: No surface, can't create swapchain"); @@ -1396,14 +1413,21 @@ bool VulkanContext::InitSwapchain(VkPresentModeKHR desiredPresentMode) { return true; } - VkExtent2D currentExtent{ surfCapabilities_.currentExtent }; + VkExtent2D currentExtent = surfCapabilities_.currentExtent; - INFO_LOG(Log::G3D, "surfCapabilities_.current: %dx%d", currentExtent.width, currentExtent.height); + if (currentExtent.width == 0xFFFFFFFF || currentExtent.height == 0xFFFFFFFF) { + // If the surface size is undefined, using the hints. + currentExtent.width = widthHint; + currentExtent.height = heightHint; + INFO_LOG(Log::G3D, "Couldn't query surface size. Using hints from window: %dx%d", currentExtent.width, currentExtent.height); + } else { + INFO_LOG(Log::G3D, "surfCapabilities_.current: %dx%d", currentExtent.width, currentExtent.height); + } swapChainExtent_.width = clamp(currentExtent.width, surfCapabilities_.minImageExtent.width, surfCapabilities_.maxImageExtent.width); swapChainExtent_.height = clamp(currentExtent.height, surfCapabilities_.minImageExtent.height, surfCapabilities_.maxImageExtent.height); - INFO_LOG(Log::G3D, "surfCapabilities_.current after clamp: %dx%d min: %dx%d max: %dx%d computed: %dx%d cbdraw", + INFO_LOG(Log::G3D, "surfCapabilities_.current: %dx%d min: %dx%d max: %dx%d after clamp: %dx%d", currentExtent.width, currentExtent.height, surfCapabilities_.minImageExtent.width, surfCapabilities_.minImageExtent.height, surfCapabilities_.maxImageExtent.width, surfCapabilities_.maxImageExtent.height, diff --git a/Common/GPU/Vulkan/VulkanContext.h b/Common/GPU/Vulkan/VulkanContext.h index 822e5cf7fb..2ed9d13b02 100644 --- a/Common/GPU/Vulkan/VulkanContext.h +++ b/Common/GPU/Vulkan/VulkanContext.h @@ -190,12 +190,13 @@ public: VulkanDeleteList &Delete() { return globalDeleteList_; } // The parameters are whatever the chosen window system wants. - // The extents will be automatically determined. + // The extents will be automatically determined. widthHint/heightHint are optional hints for the + // initial surface size (0 if unknown), used by window systems that can't otherwise determine it. VkResult InitSurface(WindowSystem winsys, void *data1, void *data2); VkResult ReinitSurface(); // If the present mode is not available, will fall back to the first available (which is almost always FIFO). - bool InitSwapchain(VkPresentModeKHR desiredPresentMode); + bool InitSwapchain(VkPresentModeKHR desiredPresentMode, int widthHint, int heightHint); void DestroySwapchain(); void DestroySurface(); diff --git a/Common/GPU/Vulkan/VulkanGraphicsContext.cpp b/Common/GPU/Vulkan/VulkanGraphicsContext.cpp index b1ace7a65f..e613d5d09d 100644 --- a/Common/GPU/Vulkan/VulkanGraphicsContext.cpp +++ b/Common/GPU/Vulkan/VulkanGraphicsContext.cpp @@ -118,7 +118,7 @@ bool VulkanGraphicsContext::InitAPI(void *wnd, std::string *deviceName, std::str return true; } -bool VulkanGraphicsContext::InitSurface(WindowSystem winsys, void *data1, void *data2, std::string *errorMessage) { +bool VulkanGraphicsContext::InitSurface(WindowSystem winsys, void *data1, void *data2, int widthHint, int heightHint, std::string *errorMessage) { vulkan_->InitSurface(winsys, data1, data2); bool useMultiThreading = g_Config.bRenderMultiThreading; @@ -136,7 +136,7 @@ bool VulkanGraphicsContext::InitSurface(WindowSystem winsys, void *data1, void * : VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT); #endif - if (!vulkan_->InitSwapchain(presentMode)) { + if (!vulkan_->InitSwapchain(presentMode, widthHint, heightHint)) { *errorMessage = vulkan_->InitError(); return false; } @@ -180,7 +180,7 @@ void VulkanGraphicsContext::ShutdownAPI() { finalize_glslang(); } -void VulkanGraphicsContext::Resize() { +void VulkanGraphicsContext::Resize(int widthHint, int heightHint) { draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight()); VkPresentModeKHR presentMode = ConfigPresentModeToVulkan(draw_); @@ -190,16 +190,16 @@ void VulkanGraphicsContext::Resize() { : VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT); #endif - vulkan_->InitSwapchain(presentMode); + vulkan_->InitSwapchain(presentMode, widthHint, heightHint); draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, vulkan_->GetBackbufferWidth(), vulkan_->GetBackbufferHeight()); } void VulkanGraphicsContext::Poll() { // Check for existing swapchain to avoid issues during shutdown. if (vulkan_->IsSwapchainInited() && renderManager_->NeedsSwapchainRecreate()) { - Resize(); + Resize(0, 0); } else if (vulkan_->IsSwapchainInited() && windowRestored_) { - Resize(); + Resize(0, 0); windowRestored_ = false; } } diff --git a/Common/GPU/Vulkan/VulkanGraphicsContext.h b/Common/GPU/Vulkan/VulkanGraphicsContext.h index 35450cd116..331ea8e689 100644 --- a/Common/GPU/Vulkan/VulkanGraphicsContext.h +++ b/Common/GPU/Vulkan/VulkanGraphicsContext.h @@ -27,10 +27,10 @@ class VulkanGraphicsContext : public GraphicsContext { public: VulkanGraphicsContext() : draw_(nullptr) {} bool InitAPI(void *wnd, std::string *deviceName, std::string *errorMessage) override; - bool InitSurface(WindowSystem winsys, void *data1, void *data2, std::string *errorMessage) override; + bool InitSurface(WindowSystem winsys, void *data1, void *data2, int widthHint, int heightHint, std::string *errorMessage) override; void ShutdownSurface() override; void ShutdownAPI() override; - void Resize() override; + void Resize(int widthHint, int heightHint) override; void Poll() override; void NotifyWindowRestored() override { diff --git a/Common/System/Display.cpp b/Common/System/Display.cpp index d80f0a6175..01a4ebe319 100644 --- a/Common/System/Display.cpp +++ b/Common/System/Display.cpp @@ -71,7 +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); + INFO_LOG(Log::G3D, "recalculate: %dx%d, new_scale: %fx%f, custom:%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/Core/EmuThread.cpp b/Core/EmuThread.cpp index 01c82f80ca..960fb41f09 100644 --- a/Core/EmuThread.cpp +++ b/Core/EmuThread.cpp @@ -129,7 +129,7 @@ bool RunMainLoop(GraphicsContext *graphicsContext, Application *application, std bool MainThreadFunc(GraphicsContext *graphicsContext, Application *application, const WindowDesc &windowDesc, std::function frame) { // This is now the render thread, and will spawn the emu thread below. std::string error_string; - bool success = graphicsContext->InitSurface(windowDesc.winsys, windowDesc.data1, windowDesc.data2, &error_string); + bool success = graphicsContext->InitSurface(windowDesc.winsys, windowDesc.data1, windowDesc.data2, 0, 0, &error_string); if (!success) { return false; } diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index 2717fe5992..4f0e2963a5 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -873,7 +873,7 @@ void MainUI::initializeGL() { graphicsContext = new QtGLGraphicsContext(); std::string errorMessage; graphicsContext->InitAPI(nullptr, nullptr, &errorMessage); - graphicsContext->InitSurface(WINDOWSYSTEM_NONE, nullptr, nullptr, &errorMessage); + graphicsContext->InitSurface(WINDOWSYSTEM_NONE, nullptr, nullptr, 0, 0, &errorMessage); INFO_LOG(Log::System, "Using thread, starting emu thread"); emuThread_ = EmuThread_Start(graphicsContext, new NativeApplication(), [this](GraphicsContext *graphicsContext){ NativeFrame(graphicsContext); diff --git a/Qt/QtMain.h b/Qt/QtMain.h index a728c127e5..96ffbfd811 100644 --- a/Qt/QtMain.h +++ b/Qt/QtMain.h @@ -54,7 +54,7 @@ public: return true; } - bool InitSurface(WindowSystem winsys, void *data1, void *data2, std::string *errorMessage) override { + bool InitSurface(WindowSystem winsys, void *data1, void *data2, int widthHint, int heightHint, std::string *errorMessage) override { // Not used in this context. draw_ = Draw::T3DCreateGLContext(false); renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); @@ -71,7 +71,6 @@ public: draw_ = nullptr; renderManager_ = nullptr; } - void Resize() override {} Draw::DrawContext *GetDrawContext() override { return draw_; diff --git a/SDL/SDLGLGraphicsContext.cpp b/SDL/SDLGLGraphicsContext.cpp index 16dbac2e65..a7cef1495a 100644 --- a/SDL/SDLGLGraphicsContext.cpp +++ b/SDL/SDLGLGraphicsContext.cpp @@ -463,7 +463,7 @@ SDL_Window *CreateSDLGLWindowAndContext(int x, int y, int w, int h, int mode, in return window; } -bool SDLGLGraphicsContext::InitSurface(WindowSystem winsys, void *data1, void *data2, std::string *error_message) { +bool SDLGLGraphicsContext::InitSurface(WindowSystem winsys, void *data1, void *data2, int widthHint, int heightHint, std::string *error_message) { SDL_Window *window = (SDL_Window *)data1; SDL_GLContext glContext = (SDL_GLContext)data2; if (!window || !glContext) { diff --git a/SDL/SDLGLGraphicsContext.h b/SDL/SDLGLGraphicsContext.h index 061ffdc653..6a875a3099 100644 --- a/SDL/SDLGLGraphicsContext.h +++ b/SDL/SDLGLGraphicsContext.h @@ -16,13 +16,11 @@ public: // Returns 0 on success. // data1 should be the SDL_Window pointer, data2 is the SDL_WindowFlags. - bool InitSurface(WindowSystem winsys, void *data1, void *data2, std::string *error_message) override; + bool InitSurface(WindowSystem winsys, void *data1, void *data2, int widthHint, int heightHint, std::string *error_message) override; void ShutdownSurface() override; bool NeedsSeparateEmuThread() const override { return true; } - void Resize() override {} - Draw::DrawContext *GetDrawContext() override { return draw_; } diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index 4fc1998704..4b793fef13 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -2058,6 +2058,7 @@ int main(int argc, char *argv[]) { fallbackGPUBackend = (int)GPUBackend::OPENGL; break; } + int initialPixelWidth = 0, initialPixelHeight = 0; SDL_Window *window = nullptr; auto initializeBackend = [&](GPUBackend backend, GraphicsContext **graphicsContext, std::string *errorMessage) -> bool { @@ -2103,7 +2104,9 @@ int main(int argc, char *argv[]) { return false; } - if (!ctx->InitSurface(windowSystem, data1, data2, errorMessage)) { + SDL_GetWindowSizeInPixels(window, &initialPixelWidth, &initialPixelHeight); + + if (!ctx->InitSurface(windowSystem, data1, data2, initialPixelWidth, initialPixelHeight, errorMessage)) { fprintf(stderr, "Surface creation failed: %s\n", errorMessage->c_str()); return false; } @@ -2142,7 +2145,6 @@ int main(int argc, char *argv[]) { // Initialize g_display synchronously before starting the EmuThread below, since it renders // immediately without waiting for us to process an initial SDL resize/scale event - // otherwise the first frames can render with dp_xres/dp_yres still at their defaults. - int initialPixelWidth = 0, initialPixelHeight = 0; SDL_GetWindowSizeInPixels(window, &initialPixelWidth, &initialPixelHeight); Native_UpdateScreenScale(initialPixelWidth, initialPixelHeight, UIScaleFactorToMultiplier(g_Config.iUIScaleFactor)); diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index c1ae9917d1..b6b0a7c395 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1149,7 +1149,7 @@ void NativeFrame(GraphicsContext *graphicsContext) { #endif } - graphicsContext->Resize(); + graphicsContext->Resize(g_display.pixel_xres, g_display.pixel_yres); g_screenManager->resized(); // TODO: Move this to the GraphicsContext objects for each backend. diff --git a/UI/UIAtlas.cpp b/UI/UIAtlas.cpp index c2ca1142d5..ad980eb9ac 100644 --- a/UI/UIAtlas.cpp +++ b/UI/UIAtlas.cpp @@ -264,13 +264,13 @@ static bool RasterizeSVG(std::string_view filename, float dpiScale, int maxTextu while (shape) { if (!IsImageID(imageIDs, imageCount, shape->id)) { // Not an image we care about, hide it. - DEBUG_LOG(Log::G3D, "Ignoring shape %s", shape->id); + DEBUG_LOG(Log::UI, "Ignoring shape %s", shape->id); shape->flags &= ~NSVG_FLAGS_VISIBLE; } else { if (usedShapes.find(shape->id) != usedShapes.end()) { - DEBUG_LOG(Log::G3D, "Duplicate shape ID in SVG, merging bboxes: %s", shape->id); + VERBOSE_LOG(Log::UI, "Duplicate shape ID in SVG, merging bboxes: %s", shape->id); } else { - DEBUG_LOG(Log::G3D, "Found shape: %s (%0.2f %0.2f %0.2f %0.2f)", shape->id, shape->bounds[0], shape->bounds[1], shape->bounds[2], shape->bounds[3]); + VERBOSE_LOG(Log::UI, "Found shape: %s (%0.2f %0.2f %0.2f %0.2f)", shape->id, shape->bounds[0], shape->bounds[1], shape->bounds[2], shape->bounds[3]); } usedShapes[shape->id].Merge(shape); } @@ -288,14 +288,14 @@ static bool RasterizeSVG(std::string_view filename, float dpiScale, int maxTextu int maxSide = (int)(std::max(image->width, image->height) * scale); if (maxTextureSize > 0 && maxSide > maxTextureSize) { float newScale = (float)maxTextureSize / (float)maxSide; - INFO_LOG(Log::G3D, "Reducing SVG scale from %0.2f to %0.2f to fit in max texture size", scale, newScale); + INFO_LOG(Log::UI, "Reducing SVG scale from %0.2f to %0.2f to fit in max texture size", scale, newScale); scale = newScale; } int svgWidth = image->width * scale; int svgHeight = image->height * scale; - INFO_LOG(Log::G3D, "Rasterizing SVG: %d x %d at scale %0.2f", svgWidth, svgHeight, scale); + INFO_LOG(Log::UI, "Rasterizing SVG: %d x %d at scale %0.2f", svgWidth, svgHeight, scale); char *svgImg = new char[svgWidth * svgHeight * 4]; memset(svgImg, 0, svgWidth * svgHeight * 4); @@ -311,7 +311,7 @@ static bool RasterizeSVG(std::string_view filename, float dpiScale, int maxTextu Image &img = (*images)[index]; if (!img.IsEmpty()) { - WARN_LOG(Log::G3D, "%.*s: Skipping image '%.*s' (%d), already loaded from SVG", STR_VIEW(filename), STR_VIEW(imageIDs[index].id), index); + WARN_LOG(Log::UI, "%.*s: Skipping image '%.*s' (%d), already loaded from SVG", STR_VIEW(filename), STR_VIEW(imageIDs[index].id), index); continue; } @@ -322,7 +322,7 @@ static bool RasterizeSVG(std::string_view filename, float dpiScale, int maxTextu int w = maxX - minX; int h = maxY - minY; if (w <= 0 || h <= 0) { - ERROR_LOG(Log::G3D, "Invalid size for %s: %dx%d", shapeId.c_str(), w, h); + ERROR_LOG(Log::UI, "Invalid size for %s: %dx%d", shapeId.c_str(), w, h); continue; } img.resize(w, h); @@ -341,7 +341,7 @@ static bool RasterizeSVG(std::string_view filename, float dpiScale, int maxTextu if (SAVE_DEBUG_IMAGES) { std::string name = std::string("../buttons_") + PNGNameFromID(shapeId); - WARN_LOG(Log::G3D, "Writing debug image %s", name.c_str()); + WARN_LOG(Log::UI, "Writing debug image %s", name.c_str()); pngSave(Path(name), img.data(), img.width(), img.height(), 4); } @@ -351,7 +351,7 @@ static bool RasterizeSVG(std::string_view filename, float dpiScale, int maxTextu shapeCount = (int)usedShapes.size(); if (SAVE_DEBUG_ATLAS) { - WARN_LOG(Log::G3D, "Writing debug image buttons_rasterized.png"); + WARN_LOG(Log::UI, "Writing debug image buttons_rasterized.png"); pngSave(Path("../buttons_rasterized.png"), svgImg, svgWidth, svgHeight, 4); } delete[] svgImg; @@ -360,7 +360,7 @@ static bool RasterizeSVG(std::string_view filename, float dpiScale, int maxTextu nsvgDelete(image); } - INFO_LOG(Log::G3D, " - Rasterized %d images in the svg image in %0.2f ms", shapeCount, svgStart.ElapsedMs()); + INFO_LOG(Log::UI, " - Rasterized %d images in the svg image in %0.2f ms", shapeCount, svgStart.ElapsedMs()); return true; } @@ -399,7 +399,7 @@ static bool GenerateUIAtlasImage(Atlas *atlas, float dpiScale, Image *dest, int // Here we could exclude some images from the drop shadow, if desired. if (!images[i].IsEmpty()) { if (imageIDs[i].addShadow) { - // DEBUG_LOG(Log::G3D, "Adding drop shadow to %.*s", STR_VIEW(imageIDs[i].id)); + // DEBUG_LOG(Log::UI, "Adding drop shadow to %.*s", STR_VIEW(imageIDs[i].id)); AddDropShadow(images[i], 3, 0.66f); } else { // Make sure there are transparent pixels to filter from. @@ -409,7 +409,7 @@ static bool GenerateUIAtlasImage(Atlas *atlas, float dpiScale, Image *dest, int } }, 0, (int)images.size(), 2, TaskPriority::HIGH); - INFO_LOG(Log::G3D, " - Drop-shadowed images in %0.2f ms", shadowStart.ElapsedMs()); + INFO_LOG(Log::UI, " - Drop-shadowed images in %0.2f ms", shadowStart.ElapsedMs()); Instant pngStart = Instant::Now(); @@ -423,7 +423,7 @@ static bool GenerateUIAtlasImage(Atlas *atlas, float dpiScale, Image *dest, int if (!img.IsEmpty()) { // Was already loaded from SVG. - DEBUG_LOG(Log::G3D, "Skipping image '%.*s' (%d), already loaded from SVG", STR_VIEW(imageIDs[i].id), i); + VERBOSE_LOG(Log::UI, "Skipping image '%.*s' (%d), already loaded from SVG", STR_VIEW(imageIDs[i].id), i); continue; } @@ -440,14 +440,14 @@ static bool GenerateUIAtlasImage(Atlas *atlas, float dpiScale, Image *dest, int name.append(pngName); bool success = img.LoadPNG(name.c_str()); if (!success) { - ERROR_LOG(Log::G3D, "%.*s is missing. Not present in SVG files and no suitable PNG found (%s)", STR_VIEW(imageIDs[i].id), name.c_str()); + ERROR_LOG(Log::UI, "%.*s is missing. Not present in SVG files and no suitable PNG found (%s)", STR_VIEW(imageIDs[i].id), name.c_str()); } else { pngsLoaded++; img.ConvertToPremultipliedAlpha(); } } } - INFO_LOG(Log::G3D, " - Loaded %d png images in %.2f ms", pngsLoaded, pngStart.ElapsedMs()); + INFO_LOG(Log::UI, " - Loaded %d png images in %.2f ms", pngsLoaded, pngStart.ElapsedMs()); Instant addStart = Instant::Now(); int area = 0; @@ -456,17 +456,17 @@ static bool GenerateUIAtlasImage(Atlas *atlas, float dpiScale, Image *dest, int area += images[i].width() * images[i].height(); } - INFO_LOG(Log::G3D, " - Added %zu images to bucket in %.2f ms", bucket.data.size(), addStart.ElapsedMs()); + INFO_LOG(Log::UI, " - Added %zu images to bucket in %.2f ms", bucket.data.size(), addStart.ElapsedMs()); int imageWidth = RoundToNextPowerOf2((int)sqrtf(area)); Instant bucketStart = Instant::Now(); bucket.Pack2(imageWidth); - INFO_LOG(Log::G3D, " - Packed in %.2f ms (image size: %dx%d)", bucketStart.ElapsedMs(), bucket.w, bucket.h); + INFO_LOG(Log::UI, " - Packed in %.2f ms (image size: %dx%d)", bucketStart.ElapsedMs(), bucket.w, bucket.h); Instant resolveStart = Instant::Now(); std::vector results = bucket.Resolve(dest); - INFO_LOG(Log::G3D, " - Resolved %zu images in %.2f ms (final image size: %dx%d)", results.size(), resolveStart.ElapsedMs(), dest->width(), dest->height()); + INFO_LOG(Log::UI, " - Resolved %zu images in %.2f ms (final image size: %dx%d)", results.size(), resolveStart.ElapsedMs(), dest->width(), dest->height()); _dbg_assert_(!results.empty()); // Fill out the atlas structure. @@ -483,10 +483,10 @@ static bool GenerateUIAtlasImage(Atlas *atlas, float dpiScale, Image *dest, int // For debug, write out the atlas. if (SAVE_DEBUG_ATLAS) { - WARN_LOG(Log::G3D, "Writing debug image ui_atlas_gen.png"); + WARN_LOG(Log::UI, "Writing debug image ui_atlas_gen.png"); dest->SavePNG("../ui_atlas_gen.png"); } - INFO_LOG(Log::G3D, "UI atlas generated in %.2f ms, size %dx%d with %zu images", svgStart.ElapsedMs(), dest->width(), dest->height(), genAtlasImages.size()); + INFO_LOG(Log::UI, "UI atlas generated in %.2f ms, size %dx%d with %zu images", svgStart.ElapsedMs(), dest->width(), dest->height(), genAtlasImages.size()); return true; } @@ -496,12 +496,12 @@ static float g_cachedDpiScale = 0.0f; // The caller must cache the Atlas. Draw::Texture *GenerateUIAtlas(Draw::DrawContext *draw, Atlas *atlas, float dpiScale, bool invalidate) { if (g_cachedUIAtlasImage.IsEmpty() || dpiScale != g_cachedDpiScale || invalidate) { - INFO_LOG(Log::G3D, "Regenerating atlas (empty: %s). Dpi scale (changed: %s): %0.2f (invalidate=%d)", + INFO_LOG(Log::UI, "Regenerating atlas (empty: %s). Dpi scale (changed: %s): %0.2f (invalidate=%d)", g_cachedUIAtlasImage.IsEmpty() ? "true" : "false", dpiScale != g_cachedDpiScale ? "true" : "false", dpiScale, invalidate); g_cachedUIAtlasImage.clear(); if (!GenerateUIAtlasImage(atlas, dpiScale, &g_cachedUIAtlasImage, draw->GetDeviceCaps().maxTextureSize, g_uiImageIDs, ARRAY_SIZE(g_uiImageIDs))) { - ERROR_LOG(Log::G3D, "Failed to generate UI atlas!"); + ERROR_LOG(Log::UI, "Failed to generate UI atlas!"); return nullptr; } } @@ -526,7 +526,7 @@ static void LoadAtlasMetadata(Atlas &metadata, const char *filename) { const uint8_t *atlas_data = g_VFS.ReadFile(filename, &atlas_data_size); bool load_success = atlas_data != nullptr && metadata.LoadMeta(atlas_data, atlas_data_size); if (!load_success) { - ERROR_LOG(Log::G3D, "Failed to load %s - graphics may be broken", filename); + ERROR_LOG(Log::UI, "Failed to load %s - graphics may be broken", filename); // Stumble along with broken visuals instead of dying... } delete[] atlas_data; diff --git a/UWP/PPSSPP_UWPMain.h b/UWP/PPSSPP_UWPMain.h index 0c824f8e7e..c7311943c8 100644 --- a/UWP/PPSSPP_UWPMain.h +++ b/UWP/PPSSPP_UWPMain.h @@ -20,7 +20,6 @@ public: UWPGraphicsContext(std::shared_ptr resources); void ShutdownAPI() override; - void Resize() override {} Draw::DrawContext * GetDrawContext() override { return draw_; } diff --git a/Windows/GPU/D3D11Context.cpp b/Windows/GPU/D3D11Context.cpp index 465fba5d82..0f9ec5f2e5 100644 --- a/Windows/GPU/D3D11Context.cpp +++ b/Windows/GPU/D3D11Context.cpp @@ -163,7 +163,7 @@ bool D3D11Context::InitAPI(void *wnd, std::string *deviceName, std::string *erro return true; } -bool D3D11Context::InitSurface(WindowSystem winsys, void *data1, void *data2, std::string *error_message) { +bool D3D11Context::InitSurface(WindowSystem winsys, void *data1, void *data2, int widthHint, int heightHint, std::string *error_message) { _dbg_assert_(winsys == WINDOWSYSTEM_WIN32); HINSTANCE hInst = (HINSTANCE)data1; HWND wnd = (HWND)data2; diff --git a/Windows/GPU/D3D11Context.h b/Windows/GPU/D3D11Context.h index f41a69d278..43b98fd768 100644 --- a/Windows/GPU/D3D11Context.h +++ b/Windows/GPU/D3D11Context.h @@ -31,12 +31,10 @@ class DrawContext; class D3D11Context : public GraphicsContext { public: bool InitAPI(void *wnd, std::string *deviceName, std::string *errorMessage) override; - bool InitSurface(WindowSystem winsys, void *data1, void *data2, std::string *errorMessage) override; + bool InitSurface(WindowSystem winsys, void *data1, void *data2, int widthHint, int heightHint, std::string *errorMessage) override; void ShutdownSurface() override; void ShutdownAPI() override; - void Resize() override; - Draw::DrawContext *GetDrawContext() override { return draw_; } private: diff --git a/Windows/GPU/WindowsGLContext.cpp b/Windows/GPU/WindowsGLContext.cpp index 357878b69a..a52864c7c4 100644 --- a/Windows/GPU/WindowsGLContext.cpp +++ b/Windows/GPU/WindowsGLContext.cpp @@ -181,7 +181,7 @@ void WindowsGLContext::ShutdownAPI() { glslang::FinalizeProcess(); } -bool WindowsGLContext::InitSurface(WindowSystem winsys, void *data1, void *data2, std::string *error_message) { +bool WindowsGLContext::InitSurface(WindowSystem winsys, void *data1, void *data2, int widthHint, int heightHint, std::string *error_message) { HINSTANCE hInst = (HINSTANCE)data1; HWND window = (HWND)data2; @@ -478,9 +478,6 @@ void WindowsGLContext::ShutdownSurface() { ReleaseGLContext(); } -void WindowsGLContext::Resize() { -} - void WindowsGLContext::ThreadStart() { renderManager_->ThreadStart(draw_); } diff --git a/Windows/GPU/WindowsGLContext.h b/Windows/GPU/WindowsGLContext.h index 47aaa3d8b9..82a3d2b527 100644 --- a/Windows/GPU/WindowsGLContext.h +++ b/Windows/GPU/WindowsGLContext.h @@ -19,7 +19,7 @@ public: bool InitAPI(void *wnd, std::string *deviceName, std::string *errorMessage) override; void ShutdownAPI() override; - bool InitSurface(WindowSystem winsys, void *data1, void *data2, std::string *errorMessage) override; + bool InitSurface(WindowSystem winsys, void *data1, void *data2, int widthHint, int heightHint, std::string *errorMessage) override; void ShutdownSurface() override; void Poll() override; @@ -28,7 +28,6 @@ public: // not the rendering thread or CPU thread. void Pause() override; void Resume() override; - void Resize() override; // If these are used, they are called from the render thread. If NeedsRenderThread is false, they are not called. void ThreadStart() override; diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index d622134f9c..6c431b54f3 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -949,7 +949,7 @@ extern "C" jboolean Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * e std::string errorMessage; if (!renderer_inited) { INFO_LOG(Log::G3D, "NativeApp.displayInit() first time"); - if (!graphicsContext->InitSurface(WINDOWSYSTEM_ANDROID, nullptr, nullptr, &errorMessage)) { + if (!graphicsContext->InitSurface(WINDOWSYSTEM_ANDROID, nullptr, nullptr, 0, 0, &errorMessage)) { System_Toast("Graphics initialization failed. Quitting."); return false; } @@ -976,7 +976,7 @@ extern "C" jboolean Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * e INFO_LOG(Log::G3D, "Shut down both threads. Now let's bring it up again!"); - if (!graphicsContext->InitSurface(WINDOWSYSTEM_ANDROID, nullptr, nullptr, &errorMessage)) { + if (!graphicsContext->InitSurface(WINDOWSYSTEM_ANDROID, nullptr, nullptr, 0, 0, &errorMessage)) { System_Toast(("Graphics initialization failed: Quitting: " + errorMessage).c_str()); return false; } @@ -1694,7 +1694,7 @@ static void VulkanEmuThread(ANativeWindow *wnd, GraphicsContext *graphicsContext display_xres, display_yres, desiredBackbufferSizeX, desiredBackbufferSizeY); std::string errorMessage; - if (!graphicsContext->InitSurface(WINDOWSYSTEM_ANDROID, wnd, nullptr, &errorMessage)) { + if (!graphicsContext->InitSurface(WINDOWSYSTEM_ANDROID, wnd, nullptr, 0, 0, &errorMessage)) { // On Android, if we get here, really no point in continuing. // The UI is supposed to render on any device both on OpenGL and Vulkan. If either of those don't work // on a device, we blacklist it. Hopefully we should have already failed in InitAPI anyway and reverted to GL back then. diff --git a/headless/SDLHeadlessGLGraphicsContext.cpp b/headless/SDLHeadlessGLGraphicsContext.cpp index 40e5aab5d2..05117dbe34 100644 --- a/headless/SDLHeadlessGLGraphicsContext.cpp +++ b/headless/SDLHeadlessGLGraphicsContext.cpp @@ -73,7 +73,7 @@ void SDLHeadlessGLGraphicsContext::ShutdownSurface() { glContext_ = nullptr; } -bool SDLHeadlessGLGraphicsContext::InitSurface(WindowSystem winsys, void *data1, void *data2, std::string *errorMessage) { +bool SDLHeadlessGLGraphicsContext::InitSurface(WindowSystem winsys, void *data1, void *data2, int widthHint, int heightHint, std::string *errorMessage) { // Not used in this context. return true; } diff --git a/headless/SDLHeadlessGLGraphicsContext.h b/headless/SDLHeadlessGLGraphicsContext.h index 95345c3fc9..ef9e6144a0 100644 --- a/headless/SDLHeadlessGLGraphicsContext.h +++ b/headless/SDLHeadlessGLGraphicsContext.h @@ -31,7 +31,7 @@ public: ~SDLHeadlessGLGraphicsContext() { delete draw_; } bool InitAPI(void *wnd, std::string *deviceNameSetting, std::string *errorMessage) override; - bool InitSurface(WindowSystem winsys, void *data1, void *data2, std::string *errorMessage) override; + bool InitSurface(WindowSystem winsys, void *data1, void *data2, int widthHint, int heightHint, std::string *errorMessage) override; void ShutdownSurface() override; @@ -53,7 +53,7 @@ public: renderManager_->ThreadEnd(); } - void Resize() override {} + void Resize(int widthHint, int heightHint) override {} // Call from emu thread void NotifyEmuThreadExit() override { diff --git a/ios/ViewController.mm b/ios/ViewController.mm index 6383d9c08d..f9ecc6e639 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -147,7 +147,7 @@ PPSSPPBaseViewController *sharedViewController; ERROR_LOG(Log::G3D, "InitAPI failed: %s", errorMessage.c_str()); } - if (!graphicsContext->InitSurface(WINDOWSYSTEM_NONE, nullptr, nullptr, &errorMessage)) { + if (!graphicsContext->InitSurface(WINDOWSYSTEM_NONE, nullptr, nullptr, 0, 0, &errorMessage)) { ERROR_LOG(Log::G3D, "InitSurface failed: %s", errorMessage.c_str()); } diff --git a/ios/ViewControllerMetal.mm b/ios/ViewControllerMetal.mm index 62645f52d2..0a75c4f6b7 100644 --- a/ios/ViewControllerMetal.mm +++ b/ios/ViewControllerMetal.mm @@ -69,7 +69,7 @@ static void VulkanRenderLoop(GraphicsContext *graphicsContext, CAMetalLayer *met //WARN_LOG(G3D, "runVulkanRenderLoop. desiredBackbufferSizeX=%d desiredBackbufferSizeY=%d", // desiredBackbufferSizeX, desiredBackbufferSizeY); std::string errorMessage; - if (!graphicsContext->InitSurface(WINDOWSYSTEM_METAL_EXT, (__bridge void *)metalLayer, nullptr, &errorMessage)) { + if (!graphicsContext->InitSurface(WINDOWSYSTEM_METAL_EXT, (__bridge void *)metalLayer, nullptr, 0, 0, &errorMessage)) { // On Android, if we get here, really no point in continuing. // The UI is supposed to render on any device both on OpenGL and Vulkan. If either of those don't work // on a device, we blacklist it. Hopefully we should have already failed in InitAPI anyway and reverted to GL back then. diff --git a/libretro/LibretroGraphicsContext.h b/libretro/LibretroGraphicsContext.h index 5e0bc2ac4c..0979b6e378 100644 --- a/libretro/LibretroGraphicsContext.h +++ b/libretro/LibretroGraphicsContext.h @@ -29,7 +29,7 @@ public: DestroyDrawContext(); } virtual void SwapBuffers() = 0; - void Resize() override {} + void Resize(int widthHint, int heightHint) override {} virtual void GotBackbuffer(); virtual void LostBackbuffer();