#include "SDL3/SDL_error.h" #include "materialsystem/igamewindow.h" #include "tier0/lib.h" #include "tier0/platform.h" #include "tier1/interface.h" #include "tier1/utlvector.h" #define SDL_MAIN_HANDLED #include "SDL3/SDL.h" #include "SDL3/SDL_init.h" #include "SDL3/SDL_video.h" #include "SDL3/SDL_vulkan.h" #include "SDL3/SDL_events.h" class CSDLGameWindow: public IGameWindow { public: virtual void Init() override; virtual void Shutdown() override; virtual void Frame( float fDelta ) override; virtual uint32_t GetRenderWidth() override; virtual uint32_t GetRenderHeight() override; virtual bool BRenderSizeUpdated() override; virtual void SetOutputImage( IImage *pImage ) override; virtual IImage *GetOutputImage() override; virtual void *CreateVulkanSurface( void *pInstance ) override; virtual void DestroyVulkanSurface( void *pInstance ) override; SDL_WindowID WindowID(); bool m_bWindowSizeUpdated; uint32_t m_uRenderWidth; uint32_t m_uRenderHeight; private: VkSurfaceKHR m_hSurface; SDL_Window *m_pWindow; IImage *m_pOutputImage; }; void CSDLGameWindow::Init() { m_pWindow = SDL_CreateWindow("funnygame", 1280, 720, SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE); if (!m_pWindow) Plat_FatalErrorFunc("SDL_CreateWindow: %s\n", SDL_GetError()); m_uRenderWidth = 1280; m_uRenderWidth = 720; } void CSDLGameWindow::Shutdown() { } void CSDLGameWindow::Frame( float fDelta ) { } uint32_t CSDLGameWindow::GetRenderWidth() { return m_uRenderWidth; } uint32_t CSDLGameWindow::GetRenderHeight() { return m_uRenderHeight; } bool CSDLGameWindow::BRenderSizeUpdated() { return m_bWindowSizeUpdated; } void CSDLGameWindow::SetOutputImage( IImage *pImage ) { m_pOutputImage = pImage; } IImage *CSDLGameWindow::GetOutputImage() { return m_pOutputImage; } void *CSDLGameWindow::CreateVulkanSurface( void *pInstance ) { SDL_Vulkan_CreateSurface(m_pWindow, (VkInstance)pInstance, NULL, (VkSurfaceKHR*)&m_hSurface); return (void*)m_hSurface; } void CSDLGameWindow::DestroyVulkanSurface( void *pInstance ) { SDL_Vulkan_DestroySurface((VkInstance)pInstance, (VkSurfaceKHR)m_hSurface, NULL); } SDL_WindowID CSDLGameWindow::WindowID() { return SDL_GetWindowID(m_pWindow); } class CSDLGameWindowManager: public IGameWindowManager { public: virtual void Init() override; virtual void Frame( float fDelta ) override; virtual void Shutdown() override; virtual IGameWindow *CreateWindow() override; virtual void DestroyWindow( IGameWindow* pWindow ) override; virtual int GetVulkanInstanceExtensionCount() override; virtual const char **GetVulkanInstanceExtensions() override; private: CUtlVector m_pWindows; }; IGameWindowManager *GameWindowManager() { static CSDLGameWindowManager mgr; return &mgr; } EXPOSE_INTERFACE_FN(GameWindowManager, IGameWindowManager, GAME_WINDOW_MANAGER_INTERFACE_VERSION) void CSDLGameWindowManager::Init() { if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_GAMEPAD)) Plat_FatalErrorFunc("SDL_Init: %s\n", SDL_GetError()); } void CSDLGameWindowManager::Frame( float fDelta ) { SDL_Event event; CSDLGameWindow *pWindow; pWindow = NULL; for (auto a: m_pWindows) { a->m_bWindowSizeUpdated = false; } while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: for (auto a: m_pWindows) { if (a->WindowID() != event.window.windowID) break; pWindow = a; break; } pWindow->m_bWindowSizeUpdated = true; pWindow->m_uRenderWidth = event.window.data1; pWindow->m_uRenderHeight = event.window.data2; break; case SDL_EVENT_QUIT: Plat_Exit(0); break; default: break; } } } void CSDLGameWindowManager::Shutdown() { } IGameWindow *CSDLGameWindowManager::CreateWindow() { CSDLGameWindow *pWindow = new CSDLGameWindow; m_pWindows.AppendTail(pWindow); return pWindow; } void CSDLGameWindowManager::DestroyWindow( IGameWindow* pWindow ) { delete (CSDLGameWindow*)pWindow; } int CSDLGameWindowManager::GetVulkanInstanceExtensionCount() { uint32_t nCount; SDL_Vulkan_GetInstanceExtensions(&nCount); return nCount; } const char **CSDLGameWindowManager::GetVulkanInstanceExtensions() { uint32_t nCount; return (const char **)SDL_Vulkan_GetInstanceExtensions(&nCount); }