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