Atlas - SDL_windowsvideo.c
Home / ext / SDL2 / src / video / windows Lines: 1 | Size: 14423 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2018 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "../../SDL_internal.h" 22 23#if SDL_VIDEO_DRIVER_WINDOWS 24 25#include "SDL_main.h" 26#include "SDL_video.h" 27#include "SDL_hints.h" 28#include "SDL_mouse.h" 29#include "SDL_system.h" 30#include "../SDL_sysvideo.h" 31#include "../SDL_pixels_c.h" 32 33#include "SDL_windowsvideo.h" 34#include "SDL_windowsframebuffer.h" 35#include "SDL_windowsshape.h" 36#include "SDL_windowsvulkan.h" 37 38/* Initialization/Query functions */ 39static int WIN_VideoInit(_THIS); 40static void WIN_VideoQuit(_THIS); 41 42/* Hints */ 43SDL_bool g_WindowsEnableMessageLoop = SDL_TRUE; 44SDL_bool g_WindowFrameUsableWhileCursorHidden = SDL_TRUE; 45 46static void SDLCALL 47UpdateWindowsEnableMessageLoop(void *userdata, const char *name, const char *oldValue, const char *newValue) 48{ 49 if (newValue && *newValue == '0') { 50 g_WindowsEnableMessageLoop = SDL_FALSE; 51 } else { 52 g_WindowsEnableMessageLoop = SDL_TRUE; 53 } 54} 55 56static void SDLCALL 57UpdateWindowFrameUsableWhileCursorHidden(void *userdata, const char *name, const char *oldValue, const char *newValue) 58{ 59 if (newValue && *newValue == '0') { 60 g_WindowFrameUsableWhileCursorHidden = SDL_FALSE; 61 } else { 62 g_WindowFrameUsableWhileCursorHidden = SDL_TRUE; 63 } 64} 65 66 67/* Windows driver bootstrap functions */ 68 69static int 70WIN_Available(void) 71{ 72 return (1); 73} 74 75static void 76WIN_DeleteDevice(SDL_VideoDevice * device) 77{ 78 SDL_VideoData *data = (SDL_VideoData *) device->driverdata; 79 80 SDL_UnregisterApp(); 81 if (data->userDLL) { 82 SDL_UnloadObject(data->userDLL); 83 } 84 if (data->shcoreDLL) { 85 SDL_UnloadObject(data->shcoreDLL); 86 } 87 88 SDL_free(device->driverdata); 89 SDL_free(device); 90} 91 92static SDL_VideoDevice * 93WIN_CreateDevice(int devindex) 94{ 95 SDL_VideoDevice *device; 96 SDL_VideoData *data; 97 98 SDL_RegisterApp(NULL, 0, NULL); 99 100 /* Initialize all variables that we clean on shutdown */ 101 device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice)); 102 if (device) { 103 data = (struct SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData)); 104 } else { 105 data = NULL; 106 } 107 if (!data) { 108 SDL_free(device); 109 SDL_OutOfMemory(); 110 return NULL; 111 } 112 device->driverdata = data; 113 114 data->userDLL = SDL_LoadObject("USER32.DLL"); 115 if (data->userDLL) { 116 data->CloseTouchInputHandle = (BOOL (WINAPI *)(HTOUCHINPUT)) SDL_LoadFunction(data->userDLL, "CloseTouchInputHandle"); 117 data->GetTouchInputInfo = (BOOL (WINAPI *)(HTOUCHINPUT, UINT, PTOUCHINPUT, int)) SDL_LoadFunction(data->userDLL, "GetTouchInputInfo"); 118 data->RegisterTouchWindow = (BOOL (WINAPI *)(HWND, ULONG)) SDL_LoadFunction(data->userDLL, "RegisterTouchWindow"); 119 } else { 120 SDL_ClearError(); 121 } 122 123 data->shcoreDLL = SDL_LoadObject("SHCORE.DLL"); 124 if (data->shcoreDLL) { 125 data->GetDpiForMonitor = (HRESULT (WINAPI *)(HMONITOR, MONITOR_DPI_TYPE, UINT *, UINT *)) SDL_LoadFunction(data->shcoreDLL, "GetDpiForMonitor"); 126 } else { 127 SDL_ClearError(); 128 } 129 130 /* Set the function pointers */ 131 device->VideoInit = WIN_VideoInit; 132 device->VideoQuit = WIN_VideoQuit; 133 device->GetDisplayBounds = WIN_GetDisplayBounds; 134 device->GetDisplayUsableBounds = WIN_GetDisplayUsableBounds; 135 device->GetDisplayDPI = WIN_GetDisplayDPI; 136 device->GetDisplayModes = WIN_GetDisplayModes; 137 device->SetDisplayMode = WIN_SetDisplayMode; 138 device->PumpEvents = WIN_PumpEvents; 139 140 device->CreateSDLWindow = WIN_CreateWindow; 141 device->CreateSDLWindowFrom = WIN_CreateWindowFrom; 142 device->SetWindowTitle = WIN_SetWindowTitle; 143 device->SetWindowIcon = WIN_SetWindowIcon; 144 device->SetWindowPosition = WIN_SetWindowPosition; 145 device->SetWindowSize = WIN_SetWindowSize; 146 device->GetWindowBordersSize = WIN_GetWindowBordersSize; 147 device->SetWindowOpacity = WIN_SetWindowOpacity; 148 device->ShowWindow = WIN_ShowWindow; 149 device->HideWindow = WIN_HideWindow; 150 device->RaiseWindow = WIN_RaiseWindow; 151 device->MaximizeWindow = WIN_MaximizeWindow; 152 device->MinimizeWindow = WIN_MinimizeWindow; 153 device->RestoreWindow = WIN_RestoreWindow; 154 device->SetWindowBordered = WIN_SetWindowBordered; 155 device->SetWindowResizable = WIN_SetWindowResizable; 156 device->SetWindowFullscreen = WIN_SetWindowFullscreen; 157 device->SetWindowGammaRamp = WIN_SetWindowGammaRamp; 158 device->GetWindowGammaRamp = WIN_GetWindowGammaRamp; 159 device->SetWindowGrab = WIN_SetWindowGrab; 160 device->DestroyWindow = WIN_DestroyWindow; 161 device->GetWindowWMInfo = WIN_GetWindowWMInfo; 162 device->CreateWindowFramebuffer = WIN_CreateWindowFramebuffer; 163 device->UpdateWindowFramebuffer = WIN_UpdateWindowFramebuffer; 164 device->DestroyWindowFramebuffer = WIN_DestroyWindowFramebuffer; 165 device->OnWindowEnter = WIN_OnWindowEnter; 166 device->SetWindowHitTest = WIN_SetWindowHitTest; 167 device->AcceptDragAndDrop = WIN_AcceptDragAndDrop; 168 169 device->shape_driver.CreateShaper = Win32_CreateShaper; 170 device->shape_driver.SetWindowShape = Win32_SetWindowShape; 171 device->shape_driver.ResizeWindowShape = Win32_ResizeWindowShape; 172 173#if SDL_VIDEO_OPENGL_WGL 174 device->GL_LoadLibrary = WIN_GL_LoadLibrary; 175 device->GL_GetProcAddress = WIN_GL_GetProcAddress; 176 device->GL_UnloadLibrary = WIN_GL_UnloadLibrary; 177 device->GL_CreateContext = WIN_GL_CreateContext; 178 device->GL_MakeCurrent = WIN_GL_MakeCurrent; 179 device->GL_SetSwapInterval = WIN_GL_SetSwapInterval; 180 device->GL_GetSwapInterval = WIN_GL_GetSwapInterval; 181 device->GL_SwapWindow = WIN_GL_SwapWindow; 182 device->GL_DeleteContext = WIN_GL_DeleteContext; 183#elif SDL_VIDEO_OPENGL_EGL 184 /* Use EGL based functions */ 185 device->GL_LoadLibrary = WIN_GLES_LoadLibrary; 186 device->GL_GetProcAddress = WIN_GLES_GetProcAddress; 187 device->GL_UnloadLibrary = WIN_GLES_UnloadLibrary; 188 device->GL_CreateContext = WIN_GLES_CreateContext; 189 device->GL_MakeCurrent = WIN_GLES_MakeCurrent; 190 device->GL_SetSwapInterval = WIN_GLES_SetSwapInterval; 191 device->GL_GetSwapInterval = WIN_GLES_GetSwapInterval; 192 device->GL_SwapWindow = WIN_GLES_SwapWindow; 193 device->GL_DeleteContext = WIN_GLES_DeleteContext; 194#endif 195#if SDL_VIDEO_VULKAN 196 device->Vulkan_LoadLibrary = WIN_Vulkan_LoadLibrary; 197 device->Vulkan_UnloadLibrary = WIN_Vulkan_UnloadLibrary; 198 device->Vulkan_GetInstanceExtensions = WIN_Vulkan_GetInstanceExtensions; 199 device->Vulkan_CreateSurface = WIN_Vulkan_CreateSurface; 200#endif 201 202 device->StartTextInput = WIN_StartTextInput; 203 device->StopTextInput = WIN_StopTextInput; 204 device->SetTextInputRect = WIN_SetTextInputRect; 205 206 device->SetClipboardText = WIN_SetClipboardText; 207 device->GetClipboardText = WIN_GetClipboardText; 208 device->HasClipboardText = WIN_HasClipboardText; 209 210 device->free = WIN_DeleteDevice; 211 212 return device; 213} 214 215 216VideoBootStrap WINDOWS_bootstrap = { 217 "windows", "SDL Windows video driver", WIN_Available, WIN_CreateDevice 218}; 219 220int 221WIN_VideoInit(_THIS) 222{ 223 if (WIN_InitModes(_this) < 0) { 224 return -1; 225 } 226 227 WIN_InitKeyboard(_this); 228 WIN_InitMouse(_this); 229 230 SDL_AddHintCallback(SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP, UpdateWindowsEnableMessageLoop, NULL); 231 SDL_AddHintCallback(SDL_HINT_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN, UpdateWindowFrameUsableWhileCursorHidden, NULL); 232 233 return 0; 234} 235 236void 237WIN_VideoQuit(_THIS) 238{ 239 WIN_QuitModes(_this); 240 WIN_QuitKeyboard(_this); 241 WIN_QuitMouse(_this); 242} 243 244 245#define D3D_DEBUG_INFO 246#include <d3d9.h> 247 248SDL_bool 249D3D_LoadDLL(void **pD3DDLL, IDirect3D9 **pDirect3D9Interface) 250{ 251 *pD3DDLL = SDL_LoadObject("D3D9.DLL"); 252 if (*pD3DDLL) { 253 typedef IDirect3D9 *(WINAPI *Direct3DCreate9_t) (UINT SDKVersion); 254 Direct3DCreate9_t Direct3DCreate9Func; 255 256#ifdef USE_D3D9EX 257 typedef HRESULT (WINAPI *Direct3DCreate9Ex_t)(UINT SDKVersion, IDirect3D9Ex **ppD3D); 258 Direct3DCreate9Ex_t Direct3DCreate9ExFunc; 259 260 Direct3DCreate9ExFunc = (Direct3DCreate9Ex_t)SDL_LoadFunction(*pD3DDLL, "Direct3DCreate9Ex"); 261 if (Direct3DCreate9ExFunc) { 262 IDirect3D9Ex *pDirect3D9ExInterface; 263 HRESULT hr = Direct3DCreate9ExFunc(D3D_SDK_VERSION, &pDirect3D9ExInterface); 264 if (SUCCEEDED(hr)) { 265 const GUID IDirect3D9_GUID = { 0x81bdcbca, 0x64d4, 0x426d, { 0xae, 0x8d, 0xad, 0x1, 0x47, 0xf4, 0x27, 0x5c } }; 266 hr = IDirect3D9Ex_QueryInterface(pDirect3D9ExInterface, &IDirect3D9_GUID, (void**)pDirect3D9Interface); 267 IDirect3D9Ex_Release(pDirect3D9ExInterface); 268 if (SUCCEEDED(hr)) { 269 return SDL_TRUE; 270 } 271 } 272 } 273#endif /* USE_D3D9EX */ 274 275 Direct3DCreate9Func = (Direct3DCreate9_t)SDL_LoadFunction(*pD3DDLL, "Direct3DCreate9"); 276 if (Direct3DCreate9Func) { 277 *pDirect3D9Interface = Direct3DCreate9Func(D3D_SDK_VERSION); 278 if (*pDirect3D9Interface) { 279 return SDL_TRUE; 280 } 281 } 282 283 SDL_UnloadObject(*pD3DDLL); 284 *pD3DDLL = NULL; 285 } 286 *pDirect3D9Interface = NULL; 287 return SDL_FALSE; 288} 289 290 291int 292SDL_Direct3D9GetAdapterIndex(int displayIndex) 293{ 294 void *pD3DDLL; 295 IDirect3D9 *pD3D; 296 if (!D3D_LoadDLL(&pD3DDLL, &pD3D)) { 297 SDL_SetError("Unable to create Direct3D interface"); 298 return D3DADAPTER_DEFAULT; 299 } else { 300 SDL_DisplayData *pData = (SDL_DisplayData *)SDL_GetDisplayDriverData(displayIndex); 301 int adapterIndex = D3DADAPTER_DEFAULT; 302 303 if (!pData) { 304 SDL_SetError("Invalid display index"); 305 adapterIndex = -1; /* make sure we return something invalid */ 306 } else { 307 char *displayName = WIN_StringToUTF8(pData->DeviceName); 308 unsigned int count = IDirect3D9_GetAdapterCount(pD3D); 309 unsigned int i; 310 for (i=0; i<count; i++) { 311 D3DADAPTER_IDENTIFIER9 id; 312 IDirect3D9_GetAdapterIdentifier(pD3D, i, 0, &id); 313 314 if (SDL_strcmp(id.DeviceName, displayName) == 0) { 315 adapterIndex = i; 316 break; 317 } 318 } 319 SDL_free(displayName); 320 } 321 322 /* free up the D3D stuff we inited */ 323 IDirect3D9_Release(pD3D); 324 SDL_UnloadObject(pD3DDLL); 325 326 return adapterIndex; 327 } 328} 329 330#if HAVE_DXGI_H 331#define CINTERFACE 332#define COBJMACROS 333#include <dxgi.h> 334 335static SDL_bool 336DXGI_LoadDLL(void **pDXGIDLL, IDXGIFactory **pDXGIFactory) 337{ 338 *pDXGIDLL = SDL_LoadObject("DXGI.DLL"); 339 if (*pDXGIDLL) { 340 HRESULT (WINAPI *CreateDXGI)(REFIID riid, void **ppFactory); 341 342 CreateDXGI = 343 (HRESULT (WINAPI *) (REFIID, void**)) SDL_LoadFunction(*pDXGIDLL, 344 "CreateDXGIFactory"); 345 if (CreateDXGI) { 346 GUID dxgiGUID = {0x7b7166ec,0x21c7,0x44ae,{0xb2,0x1a,0xc9,0xae,0x32,0x1a,0xe3,0x69}}; 347 if (!SUCCEEDED(CreateDXGI(&dxgiGUID, (void**)pDXGIFactory))) { 348 *pDXGIFactory = NULL; 349 } 350 } 351 if (!*pDXGIFactory) { 352 SDL_UnloadObject(*pDXGIDLL); 353 *pDXGIDLL = NULL; 354 return SDL_FALSE; 355 } 356 357 return SDL_TRUE; 358 } else { 359 *pDXGIFactory = NULL; 360 return SDL_FALSE; 361 } 362} 363#endif 364 365 366SDL_bool 367SDL_DXGIGetOutputInfo(int displayIndex, int *adapterIndex, int *outputIndex) 368{ 369#if !HAVE_DXGI_H 370 if (adapterIndex) *adapterIndex = -1; 371 if (outputIndex) *outputIndex = -1; 372 SDL_SetError("SDL was compiled without DXGI support due to missing dxgi.h header"); 373 return SDL_FALSE; 374#else 375 SDL_DisplayData *pData = (SDL_DisplayData *)SDL_GetDisplayDriverData(displayIndex); 376 void *pDXGIDLL; 377 char *displayName; 378 int nAdapter, nOutput; 379 IDXGIFactory *pDXGIFactory; 380 IDXGIAdapter *pDXGIAdapter; 381 IDXGIOutput* pDXGIOutput; 382 383 if (!adapterIndex) { 384 SDL_InvalidParamError("adapterIndex"); 385 return SDL_FALSE; 386 } 387 388 if (!outputIndex) { 389 SDL_InvalidParamError("outputIndex"); 390 return SDL_FALSE; 391 } 392 393 *adapterIndex = -1; 394 *outputIndex = -1; 395 396 if (!pData) { 397 SDL_SetError("Invalid display index"); 398 return SDL_FALSE; 399 } 400 401 if (!DXGI_LoadDLL(&pDXGIDLL, &pDXGIFactory)) { 402 SDL_SetError("Unable to create DXGI interface"); 403 return SDL_FALSE; 404 } 405 406 displayName = WIN_StringToUTF8(pData->DeviceName); 407 nAdapter = 0; 408 while (*adapterIndex == -1 && SUCCEEDED(IDXGIFactory_EnumAdapters(pDXGIFactory, nAdapter, &pDXGIAdapter))) { 409 nOutput = 0; 410 while (*adapterIndex == -1 && SUCCEEDED(IDXGIAdapter_EnumOutputs(pDXGIAdapter, nOutput, &pDXGIOutput))) { 411 DXGI_OUTPUT_DESC outputDesc; 412 if (SUCCEEDED(IDXGIOutput_GetDesc(pDXGIOutput, &outputDesc))) { 413 char *outputName = WIN_StringToUTF8(outputDesc.DeviceName); 414 if (SDL_strcmp(outputName, displayName) == 0) { 415 *adapterIndex = nAdapter; 416 *outputIndex = nOutput; 417 } 418 SDL_free(outputName); 419 } 420 IDXGIOutput_Release(pDXGIOutput); 421 nOutput++; 422 } 423 IDXGIAdapter_Release(pDXGIAdapter); 424 nAdapter++; 425 } 426 SDL_free(displayName); 427 428 /* free up the DXGI factory */ 429 IDXGIFactory_Release(pDXGIFactory); 430 SDL_UnloadObject(pDXGIDLL); 431 432 if (*adapterIndex == -1) { 433 return SDL_FALSE; 434 } else { 435 return SDL_TRUE; 436 } 437#endif 438} 439 440#endif /* SDL_VIDEO_DRIVER_WINDOWS */ 441 442/* vim: set ts=4 sw=4 expandtab: */ 443[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.