SDL_windowsvideo.c (13374B)
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org> 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 37/* Initialization/Query functions */ 38static int WIN_VideoInit(_THIS); 39static void WIN_VideoQuit(_THIS); 40 41/* Hints */ 42SDL_bool g_WindowsEnableMessageLoop = SDL_TRUE; 43SDL_bool g_WindowFrameUsableWhileCursorHidden = SDL_TRUE; 44 45static void UpdateWindowsEnableMessageLoop(void *userdata, const char *name, const char *oldValue, const char *newValue) 46{ 47 if (newValue && *newValue == '0') { 48 g_WindowsEnableMessageLoop = SDL_FALSE; 49 } else { 50 g_WindowsEnableMessageLoop = SDL_TRUE; 51 } 52} 53 54static void UpdateWindowFrameUsableWhileCursorHidden(void *userdata, const char *name, const char *oldValue, const char *newValue) 55{ 56 if (newValue && *newValue == '0') { 57 g_WindowFrameUsableWhileCursorHidden = SDL_FALSE; 58 } else { 59 g_WindowFrameUsableWhileCursorHidden = SDL_TRUE; 60 } 61} 62 63 64/* Windows driver bootstrap functions */ 65 66static int 67WIN_Available(void) 68{ 69 return (1); 70} 71 72static void 73WIN_DeleteDevice(SDL_VideoDevice * device) 74{ 75 SDL_VideoData *data = (SDL_VideoData *) device->driverdata; 76 77 SDL_UnregisterApp(); 78 if (data->userDLL) { 79 SDL_UnloadObject(data->userDLL); 80 } 81 82 SDL_free(device->driverdata); 83 SDL_free(device); 84} 85 86static SDL_VideoDevice * 87WIN_CreateDevice(int devindex) 88{ 89 SDL_VideoDevice *device; 90 SDL_VideoData *data; 91 92 SDL_RegisterApp(NULL, 0, NULL); 93 94 /* Initialize all variables that we clean on shutdown */ 95 device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice)); 96 if (device) { 97 data = (struct SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData)); 98 } else { 99 data = NULL; 100 } 101 if (!data) { 102 SDL_free(device); 103 SDL_OutOfMemory(); 104 return NULL; 105 } 106 device->driverdata = data; 107 108 data->userDLL = SDL_LoadObject("USER32.DLL"); 109 if (data->userDLL) { 110 data->CloseTouchInputHandle = (BOOL (WINAPI *)(HTOUCHINPUT)) SDL_LoadFunction(data->userDLL, "CloseTouchInputHandle"); 111 data->GetTouchInputInfo = (BOOL (WINAPI *)(HTOUCHINPUT, UINT, PTOUCHINPUT, int)) SDL_LoadFunction(data->userDLL, "GetTouchInputInfo"); 112 data->RegisterTouchWindow = (BOOL (WINAPI *)(HWND, ULONG)) SDL_LoadFunction(data->userDLL, "RegisterTouchWindow"); 113 } 114 115 /* Set the function pointers */ 116 device->VideoInit = WIN_VideoInit; 117 device->VideoQuit = WIN_VideoQuit; 118 device->GetDisplayBounds = WIN_GetDisplayBounds; 119 device->GetDisplayModes = WIN_GetDisplayModes; 120 device->SetDisplayMode = WIN_SetDisplayMode; 121 device->PumpEvents = WIN_PumpEvents; 122 123#undef CreateWindow 124 device->CreateWindow = WIN_CreateWindow; 125 device->CreateWindowFrom = WIN_CreateWindowFrom; 126 device->SetWindowTitle = WIN_SetWindowTitle; 127 device->SetWindowIcon = WIN_SetWindowIcon; 128 device->SetWindowPosition = WIN_SetWindowPosition; 129 device->SetWindowSize = WIN_SetWindowSize; 130 device->ShowWindow = WIN_ShowWindow; 131 device->HideWindow = WIN_HideWindow; 132 device->RaiseWindow = WIN_RaiseWindow; 133 device->MaximizeWindow = WIN_MaximizeWindow; 134 device->MinimizeWindow = WIN_MinimizeWindow; 135 device->RestoreWindow = WIN_RestoreWindow; 136 device->SetWindowBordered = WIN_SetWindowBordered; 137 device->SetWindowFullscreen = WIN_SetWindowFullscreen; 138 device->SetWindowGammaRamp = WIN_SetWindowGammaRamp; 139 device->GetWindowGammaRamp = WIN_GetWindowGammaRamp; 140 device->SetWindowGrab = WIN_SetWindowGrab; 141 device->DestroyWindow = WIN_DestroyWindow; 142 device->GetWindowWMInfo = WIN_GetWindowWMInfo; 143 device->CreateWindowFramebuffer = WIN_CreateWindowFramebuffer; 144 device->UpdateWindowFramebuffer = WIN_UpdateWindowFramebuffer; 145 device->DestroyWindowFramebuffer = WIN_DestroyWindowFramebuffer; 146 device->OnWindowEnter = WIN_OnWindowEnter; 147 device->SetWindowHitTest = WIN_SetWindowHitTest; 148 149 device->shape_driver.CreateShaper = Win32_CreateShaper; 150 device->shape_driver.SetWindowShape = Win32_SetWindowShape; 151 device->shape_driver.ResizeWindowShape = Win32_ResizeWindowShape; 152 153#if SDL_VIDEO_OPENGL_WGL 154 device->GL_LoadLibrary = WIN_GL_LoadLibrary; 155 device->GL_GetProcAddress = WIN_GL_GetProcAddress; 156 device->GL_UnloadLibrary = WIN_GL_UnloadLibrary; 157 device->GL_CreateContext = WIN_GL_CreateContext; 158 device->GL_MakeCurrent = WIN_GL_MakeCurrent; 159 device->GL_SetSwapInterval = WIN_GL_SetSwapInterval; 160 device->GL_GetSwapInterval = WIN_GL_GetSwapInterval; 161 device->GL_SwapWindow = WIN_GL_SwapWindow; 162 device->GL_DeleteContext = WIN_GL_DeleteContext; 163#elif SDL_VIDEO_OPENGL_EGL 164 /* Use EGL based functions */ 165 device->GL_LoadLibrary = WIN_GLES_LoadLibrary; 166 device->GL_GetProcAddress = WIN_GLES_GetProcAddress; 167 device->GL_UnloadLibrary = WIN_GLES_UnloadLibrary; 168 device->GL_CreateContext = WIN_GLES_CreateContext; 169 device->GL_MakeCurrent = WIN_GLES_MakeCurrent; 170 device->GL_SetSwapInterval = WIN_GLES_SetSwapInterval; 171 device->GL_GetSwapInterval = WIN_GLES_GetSwapInterval; 172 device->GL_SwapWindow = WIN_GLES_SwapWindow; 173 device->GL_DeleteContext = WIN_GLES_DeleteContext; 174#endif 175 device->StartTextInput = WIN_StartTextInput; 176 device->StopTextInput = WIN_StopTextInput; 177 device->SetTextInputRect = WIN_SetTextInputRect; 178 179 device->SetClipboardText = WIN_SetClipboardText; 180 device->GetClipboardText = WIN_GetClipboardText; 181 device->HasClipboardText = WIN_HasClipboardText; 182 183 device->free = WIN_DeleteDevice; 184 185 return device; 186} 187 188 189VideoBootStrap WINDOWS_bootstrap = { 190 "windows", "SDL Windows video driver", WIN_Available, WIN_CreateDevice 191}; 192 193int 194WIN_VideoInit(_THIS) 195{ 196 if (WIN_InitModes(_this) < 0) { 197 return -1; 198 } 199 200 WIN_InitKeyboard(_this); 201 WIN_InitMouse(_this); 202 203 SDL_AddHintCallback(SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP, UpdateWindowsEnableMessageLoop, NULL); 204 SDL_AddHintCallback(SDL_HINT_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN, UpdateWindowFrameUsableWhileCursorHidden, NULL); 205 206 return 0; 207} 208 209void 210WIN_VideoQuit(_THIS) 211{ 212 WIN_QuitModes(_this); 213 WIN_QuitKeyboard(_this); 214 WIN_QuitMouse(_this); 215} 216 217 218#define D3D_DEBUG_INFO 219#include <d3d9.h> 220 221SDL_bool 222D3D_LoadDLL(void **pD3DDLL, IDirect3D9 **pDirect3D9Interface) 223{ 224 *pD3DDLL = SDL_LoadObject("D3D9.DLL"); 225 if (*pD3DDLL) { 226 typedef IDirect3D9 *(WINAPI *Direct3DCreate9_t) (UINT SDKVersion); 227 Direct3DCreate9_t Direct3DCreate9Func; 228 229#ifdef USE_D3D9EX 230 typedef HRESULT (WINAPI *Direct3DCreate9Ex_t)(UINT SDKVersion, IDirect3D9Ex **ppD3D); 231 Direct3DCreate9Ex_t Direct3DCreate9ExFunc; 232 233 Direct3DCreate9ExFunc = (Direct3DCreate9Ex_t)SDL_LoadFunction(*pD3DDLL, "Direct3DCreate9Ex"); 234 if (Direct3DCreate9ExFunc) { 235 IDirect3D9Ex *pDirect3D9ExInterface; 236 HRESULT hr = Direct3DCreate9ExFunc(D3D_SDK_VERSION, &pDirect3D9ExInterface); 237 if (SUCCEEDED(hr)) { 238 const GUID IDirect3D9_GUID = { 0x81bdcbca, 0x64d4, 0x426d, { 0xae, 0x8d, 0xad, 0x1, 0x47, 0xf4, 0x27, 0x5c } }; 239 hr = IDirect3D9Ex_QueryInterface(pDirect3D9ExInterface, &IDirect3D9_GUID, (void**)pDirect3D9Interface); 240 IDirect3D9Ex_Release(pDirect3D9ExInterface); 241 if (SUCCEEDED(hr)) { 242 return SDL_TRUE; 243 } 244 } 245 } 246#endif /* USE_D3D9EX */ 247 248 Direct3DCreate9Func = (Direct3DCreate9_t)SDL_LoadFunction(*pD3DDLL, "Direct3DCreate9"); 249 if (Direct3DCreate9Func) { 250 *pDirect3D9Interface = Direct3DCreate9Func(D3D_SDK_VERSION); 251 if (*pDirect3D9Interface) { 252 return SDL_TRUE; 253 } 254 } 255 256 SDL_UnloadObject(*pD3DDLL); 257 *pD3DDLL = NULL; 258 } 259 *pDirect3D9Interface = NULL; 260 return SDL_FALSE; 261} 262 263 264int 265SDL_Direct3D9GetAdapterIndex(int displayIndex) 266{ 267 void *pD3DDLL; 268 IDirect3D9 *pD3D; 269 if (!D3D_LoadDLL(&pD3DDLL, &pD3D)) { 270 SDL_SetError("Unable to create Direct3D interface"); 271 return D3DADAPTER_DEFAULT; 272 } else { 273 SDL_DisplayData *pData = (SDL_DisplayData *)SDL_GetDisplayDriverData(displayIndex); 274 int adapterIndex = D3DADAPTER_DEFAULT; 275 276 if (!pData) { 277 SDL_SetError("Invalid display index"); 278 adapterIndex = -1; /* make sure we return something invalid */ 279 } else { 280 char *displayName = WIN_StringToUTF8(pData->DeviceName); 281 unsigned int count = IDirect3D9_GetAdapterCount(pD3D); 282 unsigned int i; 283 for (i=0; i<count; i++) { 284 D3DADAPTER_IDENTIFIER9 id; 285 IDirect3D9_GetAdapterIdentifier(pD3D, i, 0, &id); 286 287 if (SDL_strcmp(id.DeviceName, displayName) == 0) { 288 adapterIndex = i; 289 break; 290 } 291 } 292 SDL_free(displayName); 293 } 294 295 /* free up the D3D stuff we inited */ 296 IDirect3D9_Release(pD3D); 297 SDL_UnloadObject(pD3DDLL); 298 299 return adapterIndex; 300 } 301} 302 303#if HAVE_DXGI_H 304#define CINTERFACE 305#define COBJMACROS 306#include <dxgi.h> 307 308static SDL_bool 309DXGI_LoadDLL(void **pDXGIDLL, IDXGIFactory **pDXGIFactory) 310{ 311 *pDXGIDLL = SDL_LoadObject("DXGI.DLL"); 312 if (*pDXGIDLL) { 313 HRESULT (WINAPI *CreateDXGI)(REFIID riid, void **ppFactory); 314 315 CreateDXGI = 316 (HRESULT (WINAPI *) (REFIID, void**)) SDL_LoadFunction(*pDXGIDLL, 317 "CreateDXGIFactory"); 318 if (CreateDXGI) { 319 GUID dxgiGUID = {0x7b7166ec,0x21c7,0x44ae,{0xb2,0x1a,0xc9,0xae,0x32,0x1a,0xe3,0x69}}; 320 if (!SUCCEEDED(CreateDXGI(&dxgiGUID, (void**)pDXGIFactory))) { 321 *pDXGIFactory = NULL; 322 } 323 } 324 if (!*pDXGIFactory) { 325 SDL_UnloadObject(*pDXGIDLL); 326 *pDXGIDLL = NULL; 327 return SDL_FALSE; 328 } 329 330 return SDL_TRUE; 331 } else { 332 *pDXGIFactory = NULL; 333 return SDL_FALSE; 334 } 335} 336#endif 337 338 339SDL_bool 340SDL_DXGIGetOutputInfo(int displayIndex, int *adapterIndex, int *outputIndex) 341{ 342#if !HAVE_DXGI_H 343 if (adapterIndex) *adapterIndex = -1; 344 if (outputIndex) *outputIndex = -1; 345 SDL_SetError("SDL was compiled without DXGI support due to missing dxgi.h header"); 346 return SDL_FALSE; 347#else 348 SDL_DisplayData *pData = (SDL_DisplayData *)SDL_GetDisplayDriverData(displayIndex); 349 void *pDXGIDLL; 350 char *displayName; 351 int nAdapter, nOutput; 352 IDXGIFactory *pDXGIFactory; 353 IDXGIAdapter *pDXGIAdapter; 354 IDXGIOutput* pDXGIOutput; 355 356 if (!adapterIndex) { 357 SDL_InvalidParamError("adapterIndex"); 358 return SDL_FALSE; 359 } 360 361 if (!outputIndex) { 362 SDL_InvalidParamError("outputIndex"); 363 return SDL_FALSE; 364 } 365 366 *adapterIndex = -1; 367 *outputIndex = -1; 368 369 if (!pData) { 370 SDL_SetError("Invalid display index"); 371 return SDL_FALSE; 372 } 373 374 if (!DXGI_LoadDLL(&pDXGIDLL, &pDXGIFactory)) { 375 SDL_SetError("Unable to create DXGI interface"); 376 return SDL_FALSE; 377 } 378 379 displayName = WIN_StringToUTF8(pData->DeviceName); 380 nAdapter = 0; 381 while (*adapterIndex == -1 && SUCCEEDED(IDXGIFactory_EnumAdapters(pDXGIFactory, nAdapter, &pDXGIAdapter))) { 382 nOutput = 0; 383 while (*adapterIndex == -1 && SUCCEEDED(IDXGIAdapter_EnumOutputs(pDXGIAdapter, nOutput, &pDXGIOutput))) { 384 DXGI_OUTPUT_DESC outputDesc; 385 if (SUCCEEDED(IDXGIOutput_GetDesc(pDXGIOutput, &outputDesc))) { 386 char *outputName = WIN_StringToUTF8(outputDesc.DeviceName); 387 if (SDL_strcmp(outputName, displayName) == 0) { 388 *adapterIndex = nAdapter; 389 *outputIndex = nOutput; 390 } 391 SDL_free(outputName); 392 } 393 IDXGIOutput_Release(pDXGIOutput); 394 nOutput++; 395 } 396 IDXGIAdapter_Release(pDXGIAdapter); 397 nAdapter++; 398 } 399 SDL_free(displayName); 400 401 /* free up the DXGI factory */ 402 IDXGIFactory_Release(pDXGIFactory); 403 SDL_UnloadObject(pDXGIDLL); 404 405 if (*adapterIndex == -1) { 406 return SDL_FALSE; 407 } else { 408 return SDL_TRUE; 409 } 410#endif 411} 412 413#endif /* SDL_VIDEO_DRIVER_WINDOWS */ 414 415/* vim: set ts=4 sw=4 expandtab: */