mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Merge pull request #22033 from hrydgard/sdl-headless-vulkan
Headless SDL: Add support for Vulkan rendering
This commit is contained in:
12 files changed
+197
-98
No files matched your search
+12
-2
@@ -1049,6 +1049,7 @@ else()
|
||||
SDL/SDLJoystick.h
|
||||
SDL/SDLJoystick.cpp
|
||||
SDL/SDLMain.cpp
|
||||
SDL/SDLUtil.cpp
|
||||
SDL/SDLGLGraphicsContext.cpp
|
||||
)
|
||||
if(SDL_TTF_LIB_TARGET)
|
||||
@@ -1329,13 +1330,22 @@ if(HEADLESS)
|
||||
headless/Headless.cpp
|
||||
headless/Compare.cpp
|
||||
headless/Compare.h
|
||||
headless/SDLHeadlessGLGraphicsContext.cpp
|
||||
headless/SDLHeadlessGLGraphicsContext.h
|
||||
)
|
||||
if(SDL_LIB_TARGET)
|
||||
list(APPEND HeadlessSource
|
||||
headless/SDLHeadlessGLGraphicsContext.cpp
|
||||
headless/SDLHeadlessGLGraphicsContext.h
|
||||
# TODO: Break these out into a library instead of cross linking like this.
|
||||
SDL/SDLUtil.cpp
|
||||
SDL/SDLUtil.h
|
||||
)
|
||||
endif()
|
||||
if(APPLE)
|
||||
list(APPEND HeadlessSource
|
||||
Common/Render/Text/draw_text_cocoa.mm
|
||||
Common/Render/Text/draw_text_cocoa.h
|
||||
SDL/SDLCocoaMetalLayer.h
|
||||
SDL/SDLCocoaMetalLayer.mm
|
||||
)
|
||||
set_source_files_properties(Common/Render/Text/draw_text_cocoa.mm
|
||||
PROPERTIES COMPILE_FLAGS -fobjc-arc)
|
||||
|
||||
@@ -91,6 +91,23 @@ const char *VulkanImageLayoutToString(VkImageLayout imageLayout) {
|
||||
}
|
||||
}
|
||||
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
VulkanContext::VulkanContext() {
|
||||
// Do nothing here.
|
||||
}
|
||||
@@ -970,9 +987,9 @@ 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;
|
||||
VkResult retval = VK_SUCCESS;
|
||||
|
||||
switch (winsys_) {
|
||||
#ifdef _WIN32
|
||||
@@ -1233,7 +1250,7 @@ VkResult VulkanContext::ReinitSurface() {
|
||||
#endif
|
||||
|
||||
default:
|
||||
_assert_msg_(false, "Vulkan support for chosen window system not implemented");
|
||||
_assert_msg_(false, "Vulkan support for chosen window system (%s) not implemented", WindowSystemToString(winsys_));
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
|
||||
|
||||
+7
-61
@@ -67,6 +67,7 @@ SDLJoystick *joystick = NULL;
|
||||
#include "Core/Config.h"
|
||||
#include "Core/ConfigValues.h"
|
||||
#include "SDLGLGraphicsContext.h"
|
||||
#include "SDLUtil.h"
|
||||
|
||||
#include <SDL3/SDL_vulkan.h>
|
||||
|
||||
@@ -1726,58 +1727,6 @@ void UpdateSDLCursor() {
|
||||
#endif
|
||||
}
|
||||
|
||||
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);
|
||||
if (x11Display != nullptr) {
|
||||
intptr_t x11Window = (intptr_t)SDL_GetNumberProperty(windowProps, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0);
|
||||
#if defined(VK_USE_PLATFORM_XLIB_KHR)
|
||||
*windowSystem = WINDOWSYSTEM_XLIB;
|
||||
*data1 = x11Display;
|
||||
*data2 = (void *)x11Window;
|
||||
#elif defined(VK_USE_PLATFORM_XCB_KHR)
|
||||
*windowSystem = WINDOWSYSTEM_XCB;
|
||||
*data1 = (void *)XGetXCBConnection((Display *)x11Display);
|
||||
*data2 = (void *)x11Window;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
|
||||
void *waylandDisplay = SDL_GetPointerProperty(windowProps, SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER, nullptr);
|
||||
void *waylandSurface = SDL_GetPointerProperty(windowProps, SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, nullptr);
|
||||
if (waylandDisplay != nullptr && waylandSurface != nullptr) {
|
||||
*windowSystem = WINDOWSYSTEM_WAYLAND;
|
||||
*data1 = waylandDisplay;
|
||||
*data2 = waylandSurface;
|
||||
return true;
|
||||
}
|
||||
#elif defined(VK_USE_PLATFORM_METAL_EXT)
|
||||
#if PPSSPP_PLATFORM(MAC)
|
||||
void *cocoaWindow = SDL_GetPointerProperty(windowProps, SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, nullptr);
|
||||
if (cocoaWindow != nullptr) {
|
||||
*windowSystem = WINDOWSYSTEM_METAL_EXT;
|
||||
*data1 = makeWindowMetalCompatible(cocoaWindow);
|
||||
*data2 = nullptr;
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
// This path is currently not used as we do not use SDL on iOS, but it is here for completeness.
|
||||
void *uikitWindow = SDL_GetPointerProperty(windowProps, SDL_PROP_WINDOW_UIKIT_WINDOW_POINTER, nullptr);
|
||||
if (uikitWindow != nullptr) {
|
||||
*windowSystem = WINDOWSYSTEM_METAL_EXT;
|
||||
*data1 = makeWindowMetalCompatible(uikitWindow);
|
||||
*data2 = nullptr;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#endif // VK_USE_PLATFORM_METAL_EXT
|
||||
if (errorMessage) {
|
||||
*errorMessage = "Unable to determine Vulkan window system from SDL3 window properties";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#undef main
|
||||
#endif
|
||||
@@ -2007,19 +1956,16 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
SDL_Window *window = nullptr;
|
||||
WindowDesc windowDesc;
|
||||
auto initializeBackend = [&](GPUBackend backend, GraphicsContext **graphicsContext, std::string *errorMessage) -> bool {
|
||||
// Surface init params.
|
||||
WindowSystem windowSystem = WINDOWSYSTEM_NONE;
|
||||
void *data1 = nullptr;
|
||||
void *data2 = nullptr;
|
||||
|
||||
GraphicsContext *ctx = nullptr;
|
||||
if (backend == GPUBackend::OPENGL) {
|
||||
SDL_GLContext glContext = nullptr;
|
||||
window = CreateSDLGLWindowAndContext(x, y, w, h, mode, cmdLineOptions.force_gl_version, &glContext, errorMessage);
|
||||
|
||||
data1 = (void *)window;
|
||||
data2 = (void *)glContext;
|
||||
windowDesc.winsys = WINDOWSYSTEM_SDL;
|
||||
windowDesc.data1 = (void *)window;
|
||||
windowDesc.data2 = (void *)glContext;
|
||||
|
||||
ctx = new SDLGLGraphicsContext();
|
||||
} else {
|
||||
@@ -2038,7 +1984,7 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
// Overwrite the surface init params with what we need for Vulkan..
|
||||
if (!DetermineVulkanWindowSystem(window, &windowSystem, &data1, &data2, errorMessage)) {
|
||||
if (!DetermineVulkanWindowSystem(window, &windowDesc, errorMessage)) {
|
||||
return false;
|
||||
}
|
||||
// NOTE : This should match the lines below in the Vulkan case.
|
||||
@@ -2061,7 +2007,7 @@ int main(int argc, char *argv[]) {
|
||||
});
|
||||
}
|
||||
|
||||
if (!ctx->InitSurface(windowSystem, data1, data2, errorMessage)) {
|
||||
if (!ctx->InitSurface(windowDesc.winsys, windowDesc.data1, windowDesc.data2, errorMessage)) {
|
||||
fprintf(stderr, "Surface creation failed: %s\n", errorMessage->c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include "ppsspp_config.h"
|
||||
|
||||
#if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS)
|
||||
#include "SDL/SDLCocoaMetalLayer.h"
|
||||
#endif
|
||||
|
||||
#include "Common/GPU/MiscTypes.h"
|
||||
#include "Common/GPU/Vulkan/VulkanLoader.h"
|
||||
#include "Common/GPU/Vulkan/VulkanContext.h"
|
||||
#include "Common/GPU/GraphicsContext.h"
|
||||
|
||||
#include "SDL/SDLUtil.h"
|
||||
|
||||
bool DetermineVulkanWindowSystem(SDL_Window *window, WindowDesc *desc, std::string *errorMessage) {
|
||||
_dbg_assert_(window);
|
||||
SDL_PropertiesID windowProps = SDL_GetWindowProperties(window);
|
||||
void *x11Display = SDL_GetPointerProperty(windowProps, SDL_PROP_WINDOW_X11_DISPLAY_POINTER, nullptr);
|
||||
if (x11Display != nullptr) {
|
||||
intptr_t x11Window = (intptr_t)SDL_GetNumberProperty(windowProps, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0);
|
||||
#if defined(VK_USE_PLATFORM_XLIB_KHR)
|
||||
desc->winsys = WINDOWSYSTEM_XLIB;
|
||||
desc->data1 = x11Display;
|
||||
desc->data2 = (void *)x11Window;
|
||||
#elif defined(VK_USE_PLATFORM_XCB_KHR)
|
||||
desc->winsys = WINDOWSYSTEM_XCB;
|
||||
desc->data1 = (void *)XGetXCBConnection((Display *)x11Display);
|
||||
desc->data2 = (void *)x11Window;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
|
||||
void *waylandDisplay = SDL_GetPointerProperty(windowProps, SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER, nullptr);
|
||||
void *waylandSurface = SDL_GetPointerProperty(windowProps, SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, nullptr);
|
||||
if (waylandDisplay != nullptr && waylandSurface != nullptr) {
|
||||
desc->winsys = WINDOWSYSTEM_WAYLAND;
|
||||
desc->data1 = waylandDisplay;
|
||||
desc->data2 = waylandSurface;
|
||||
return true;
|
||||
}
|
||||
#elif defined(VK_USE_PLATFORM_METAL_EXT)
|
||||
#if PPSSPP_PLATFORM(MAC)
|
||||
void *cocoaWindow = SDL_GetPointerProperty(windowProps, SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, nullptr);
|
||||
if (cocoaWindow != nullptr) {
|
||||
desc->winsys = WINDOWSYSTEM_METAL_EXT;
|
||||
desc->data1 = makeWindowMetalCompatible(cocoaWindow);
|
||||
desc->data2 = nullptr;
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
// This path is currently not used as we do not use SDL on iOS, but it is here for completeness.
|
||||
void *uikitWindow = SDL_GetPointerProperty(windowProps, SDL_PROP_WINDOW_UIKIT_WINDOW_POINTER, nullptr);
|
||||
if (uikitWindow != nullptr) {
|
||||
desc->winsys = WINDOWSYSTEM_METAL_EXT;
|
||||
desc->data1 = makeWindowMetalCompatible(uikitWindow);
|
||||
desc->data2 = nullptr;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#endif // VK_USE_PLATFORM_METAL_EXT
|
||||
if (errorMessage) {
|
||||
*errorMessage = "Unable to determine Vulkan window system from SDL3 window properties";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include "Common/GPU/MiscTypes.h"
|
||||
#include <string>
|
||||
|
||||
struct WindowDesc;
|
||||
|
||||
bool DetermineVulkanWindowSystem(SDL_Window *window, WindowDesc *desc, std::string *errorMessage);
|
||||
+15
-7
@@ -228,7 +228,15 @@ void System_SendDebugScreenshot(const uint8_t *data, int width, int height) {
|
||||
static GraphicsContext *CreateGraphicsContext(GPUCore gpuCore, std::string **deviceSetting) {
|
||||
#ifdef SDL
|
||||
*deviceSetting = nullptr;
|
||||
return new SDLHeadlessGLGraphicsContext();
|
||||
switch (gpuCore) {
|
||||
case GPUCORE_GLES:
|
||||
return new SDLHeadlessGLGraphicsContext();
|
||||
case GPUCORE_VULKAN:
|
||||
*deviceSetting = &g_Config.sVulkanDevice;
|
||||
return new VulkanGraphicsContext();
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
#elif PPSSPP_PLATFORM(WINDOWS) && !PPSSPP_PLATFORM(UWP)
|
||||
switch (gpuCore) {
|
||||
#if PPSSPP_API(ANY_GL)
|
||||
@@ -244,8 +252,7 @@ static GraphicsContext *CreateGraphicsContext(GPUCore gpuCore, std::string **dev
|
||||
return new VulkanGraphicsContext();
|
||||
case GPUCORE_SOFTWARE:
|
||||
default:
|
||||
_assert_(false);
|
||||
break;
|
||||
return nullptr;
|
||||
}
|
||||
#elif PPSSPP_ARCH(LOONGARCH64)
|
||||
// The loongarch64 cross-compilation toolchain has no SDL3 packages available (see the
|
||||
@@ -260,8 +267,8 @@ static GraphicsContext *CreateGraphicsContext(GPUCore gpuCore, std::string **dev
|
||||
return nullptr;
|
||||
#else
|
||||
#error The Headless build is not supported on this platform. Please use SDL (Mac/Linux) or Windows (non-UWP).
|
||||
#endif
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct AutoTestOptions {
|
||||
@@ -675,6 +682,7 @@ int main(int argc, const char* argv[]) {
|
||||
// Time to set up graphics
|
||||
GraphicsContext *graphicsContext = nullptr;
|
||||
std::string *deviceSetting = nullptr;
|
||||
void *window = nullptr;
|
||||
WindowDesc windowDesc;
|
||||
if (g_Config.bSoftwareRendering) {
|
||||
// For software rendering, we just create a dummy graphics context (to share as much code as possible).
|
||||
@@ -686,7 +694,7 @@ int main(int argc, const char* argv[]) {
|
||||
return 1;
|
||||
#else
|
||||
// TODO: Will we need a larger window for higher resolutions? Well, not if we use buffered rendering.
|
||||
windowDesc = CreateHiddenWindow(480, 272, cmdLineOptions.gpuBackend.value());
|
||||
window = CreateHiddenWindow(480, 272, cmdLineOptions.gpuBackend.value(), &windowDesc);
|
||||
if (!windowDesc.Valid()) {
|
||||
fprintf(stderr, "Failed to create a window for graphics context");
|
||||
return 1;
|
||||
@@ -811,8 +819,8 @@ int main(int argc, const char* argv[]) {
|
||||
#if PPSSPP_PLATFORM(ANDROID) || PPSSPP_ARCH(LOONGARCH64)
|
||||
// ... see above
|
||||
#else
|
||||
if (windowDesc.Valid()) {
|
||||
DestroyHiddenWindow(windowDesc);
|
||||
if (window) {
|
||||
DestroyHiddenWindow(window, windowDesc);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -338,6 +338,14 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\SDL\SDLUtil.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Windows\CaptureDevice.cpp" />
|
||||
<ClCompile Include="..\Windows\GPU\D3D11Context.cpp" />
|
||||
<ClCompile Include="..\Windows\GPU\WindowsGLContext.cpp">
|
||||
@@ -399,8 +407,23 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\Common\GPU\Vulkan\VulkanGraphicsContext.h" />
|
||||
<ClInclude Include="..\SDL\SDLUtil.h">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Compare.h" />
|
||||
<ClInclude Include="SDLHeadlessGLGraphicsContext.h" />
|
||||
<ClInclude Include="SDLHeadlessGLGraphicsContext.h">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="WindowsHeadlessHost.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
<ClCompile Include="..\Common\GPU\Vulkan\VulkanGraphicsContext.cpp">
|
||||
<Filter>Windows</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\SDL\SDLUtil.cpp">
|
||||
<Filter>Other Platforms</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\test.py" />
|
||||
@@ -41,6 +44,9 @@
|
||||
<ClInclude Include="..\Common\GPU\Vulkan\VulkanGraphicsContext.h">
|
||||
<Filter>Windows</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\SDL\SDLUtil.h">
|
||||
<Filter>Other Platforms</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Windows">
|
||||
|
||||
@@ -34,10 +34,11 @@
|
||||
#include "Core/Config.h"
|
||||
#include "Core/System.h"
|
||||
#include "GPU/GPUState.h"
|
||||
#include "SDL/SDLUtil.h"
|
||||
|
||||
const bool WINDOW_VISIBLE = false;
|
||||
|
||||
WindowDesc CreateHiddenWindow(int w, int h, GPUBackend backend) {
|
||||
void *CreateHiddenWindow(int w, int h, GPUBackend backend, WindowDesc *desc) {
|
||||
Uint32 flags = SDL_WINDOW_BORDERLESS;
|
||||
if (backend == GPUBackend::OPENGL) {
|
||||
flags |= SDL_WINDOW_OPENGL;
|
||||
@@ -47,20 +48,33 @@ WindowDesc CreateHiddenWindow(int w, int h, GPUBackend backend) {
|
||||
if (!WINDOW_VISIBLE) {
|
||||
flags |= SDL_WINDOW_HIDDEN;
|
||||
}
|
||||
WindowDesc desc;
|
||||
desc.data2 = SDL_CreateWindow("PPSSPPHeadless", w, h, flags);
|
||||
desc.winsys = WindowSystem::WINDOWSYSTEM_SDL;
|
||||
if (!desc.data2) {
|
||||
|
||||
SDL_Window *window = SDL_CreateWindow("PPSSPPHeadless", w, h, flags);
|
||||
if (!window) {
|
||||
const char *err = SDL_GetError();
|
||||
printf("Failed to create offscreen window: %s\n", err ? err : "(unknown error)");
|
||||
return {};
|
||||
fprintf(stderr, "Failed to create offscreen window: %s\n", err ? err : "(unknown error)");
|
||||
return nullptr;
|
||||
}
|
||||
return desc;
|
||||
|
||||
if (backend == GPUBackend::VULKAN) {
|
||||
// Overwrite the surface init params with what we need for Vulkan..
|
||||
std::string errorMessage;
|
||||
if (!DetermineVulkanWindowSystem(window, desc, &errorMessage)) {
|
||||
fprintf(stderr, "Failed to determine Vulkan window system: %s\n", errorMessage.c_str());
|
||||
SDL_DestroyWindow(window);
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
desc->winsys = WindowSystem::WINDOWSYSTEM_SDL;
|
||||
// For OpenGL, we just need the SDL_Window pointer.
|
||||
desc->data2 = window;
|
||||
}
|
||||
return window;
|
||||
}
|
||||
|
||||
void DestroyHiddenWindow(WindowDesc window) {
|
||||
if (window.data2) {
|
||||
SDL_DestroyWindow(static_cast<SDL_Window *>(window.data2));
|
||||
void DestroyHiddenWindow(void *window, WindowDesc desc) {
|
||||
if (window) {
|
||||
SDL_DestroyWindow(static_cast<SDL_Window *>(window));
|
||||
SDL_Quit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ private:
|
||||
SDL_GLContext glContext_;
|
||||
};
|
||||
|
||||
WindowDesc CreateHiddenWindow(int w, int h, GPUBackend backend);
|
||||
void DestroyHiddenWindow(WindowDesc window);
|
||||
void *CreateHiddenWindow(int w, int h, GPUBackend backend, WindowDesc *desc);
|
||||
void DestroyHiddenWindow(void *window, WindowDesc desc);
|
||||
|
||||
#endif
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
const bool WINDOW_VISIBLE = false;
|
||||
|
||||
WindowDesc CreateHiddenWindow(int w, int h, GPUBackend backend) {
|
||||
void *CreateHiddenWindow(int w, int h, GPUBackend backend, WindowDesc *desc) {
|
||||
static WNDCLASSEX wndClass = {
|
||||
sizeof(WNDCLASSEX),
|
||||
CS_HREDRAW | CS_VREDRAW | CS_OWNDC,
|
||||
@@ -47,15 +47,15 @@ WindowDesc CreateHiddenWindow(int w, int h, GPUBackend backend) {
|
||||
ShowWindow(wnd, TRUE);
|
||||
SetFocus(wnd);
|
||||
}
|
||||
WindowDesc desc;
|
||||
desc.data1 = GetModuleHandle(NULL);
|
||||
desc.data2 = wnd;
|
||||
desc.winsys = WindowSystem::WINDOWSYSTEM_WIN32;
|
||||
return desc;
|
||||
desc->data1 = GetModuleHandle(NULL); // easy way to get the HINSTANCE.
|
||||
desc->data2 = wnd;
|
||||
desc->winsys = WindowSystem::WINDOWSYSTEM_WIN32;
|
||||
return static_cast<void *>(wnd);
|
||||
}
|
||||
|
||||
void DestroyHiddenWindow(WindowDesc window) {
|
||||
if (window.data2) {
|
||||
DestroyWindow(static_cast<HWND>(window.data2));
|
||||
void DestroyHiddenWindow(void *window, WindowDesc desc) {
|
||||
if (window) {
|
||||
DestroyWindow(static_cast<HWND>(window));
|
||||
UnregisterClass(L"PPSSPPHeadless", static_cast<HINSTANCE>(desc.data1));
|
||||
}
|
||||
}
|
||||
@@ -22,5 +22,5 @@
|
||||
struct WindowDesc;
|
||||
|
||||
// Same API as for SDL
|
||||
WindowDesc CreateHiddenWindow(int w, int h, GPUBackend backend);
|
||||
void DestroyHiddenWindow(WindowDesc window);
|
||||
void *CreateHiddenWindow(int w, int h, GPUBackend backend, WindowDesc *desc);
|
||||
void DestroyHiddenWindow(void *window, WindowDesc desc);
|
||||
Reference in new issue
Block a user