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