2 Simple DirectMedia Layer
3 Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
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.
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:
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.
21 #include "../../SDL_internal.h"
23 #if SDL_VIDEO_DRIVER_WINDOWS
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"
33 #include "SDL_windowsvideo.h"
34 #include "SDL_windowsframebuffer.h"
35 #include "SDL_windowsshape.h"
37 /* Initialization/Query functions */
38 static int WIN_VideoInit(_THIS);
39 static void WIN_VideoQuit(_THIS);
42 SDL_bool g_WindowsEnableMessageLoop = SDL_TRUE;
43 SDL_bool g_WindowFrameUsableWhileCursorHidden = SDL_TRUE;
45 static void UpdateWindowsEnableMessageLoop(void *userdata, const char *name, const char *oldValue, const char *newValue)
47 if (newValue && *newValue == '0') {
48 g_WindowsEnableMessageLoop = SDL_FALSE;
50 g_WindowsEnableMessageLoop = SDL_TRUE;
54 static void UpdateWindowFrameUsableWhileCursorHidden(void *userdata, const char *name, const char *oldValue, const char *newValue)
56 if (newValue && *newValue == '0') {
57 g_WindowFrameUsableWhileCursorHidden = SDL_FALSE;
59 g_WindowFrameUsableWhileCursorHidden = SDL_TRUE;
64 /* Windows driver bootstrap functions */
73 WIN_DeleteDevice(SDL_VideoDevice * device)
75 SDL_VideoData *data = (SDL_VideoData *) device->driverdata;
79 SDL_UnloadObject(data->userDLL);
81 if (data->shcoreDLL) {
82 SDL_UnloadObject(data->shcoreDLL);
85 SDL_free(device->driverdata);
89 static SDL_VideoDevice *
90 WIN_CreateDevice(int devindex)
92 SDL_VideoDevice *device;
95 SDL_RegisterApp(NULL, 0, NULL);
97 /* Initialize all variables that we clean on shutdown */
98 device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
100 data = (struct SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
109 device->driverdata = data;
111 data->userDLL = SDL_LoadObject("USER32.DLL");
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");
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");
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;
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;
158 device->shape_driver.CreateShaper = Win32_CreateShaper;
159 device->shape_driver.SetWindowShape = Win32_SetWindowShape;
160 device->shape_driver.ResizeWindowShape = Win32_ResizeWindowShape;
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;
184 device->StartTextInput = WIN_StartTextInput;
185 device->StopTextInput = WIN_StopTextInput;
186 device->SetTextInputRect = WIN_SetTextInputRect;
188 device->SetClipboardText = WIN_SetClipboardText;
189 device->GetClipboardText = WIN_GetClipboardText;
190 device->HasClipboardText = WIN_HasClipboardText;
192 device->free = WIN_DeleteDevice;
198 VideoBootStrap WINDOWS_bootstrap = {
199 "windows", "SDL Windows video driver", WIN_Available, WIN_CreateDevice
205 if (WIN_InitModes(_this) < 0) {
209 WIN_InitKeyboard(_this);
210 WIN_InitMouse(_this);
212 SDL_AddHintCallback(SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP, UpdateWindowsEnableMessageLoop, NULL);
213 SDL_AddHintCallback(SDL_HINT_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN, UpdateWindowFrameUsableWhileCursorHidden, NULL);
221 WIN_QuitModes(_this);
222 WIN_QuitKeyboard(_this);
223 WIN_QuitMouse(_this);
227 #define D3D_DEBUG_INFO
231 D3D_LoadDLL(void **pD3DDLL, IDirect3D9 **pDirect3D9Interface)
233 *pD3DDLL = SDL_LoadObject("D3D9.DLL");
235 typedef IDirect3D9 *(WINAPI *Direct3DCreate9_t) (UINT SDKVersion);
236 Direct3DCreate9_t Direct3DCreate9Func;
239 typedef HRESULT (WINAPI *Direct3DCreate9Ex_t)(UINT SDKVersion, IDirect3D9Ex **ppD3D);
240 Direct3DCreate9Ex_t Direct3DCreate9ExFunc;
242 Direct3DCreate9ExFunc = (Direct3DCreate9Ex_t)SDL_LoadFunction(*pD3DDLL, "Direct3DCreate9Ex");
243 if (Direct3DCreate9ExFunc) {
244 IDirect3D9Ex *pDirect3D9ExInterface;
245 HRESULT hr = Direct3DCreate9ExFunc(D3D_SDK_VERSION, &pDirect3D9ExInterface);
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);
255 #endif /* USE_D3D9EX */
257 Direct3DCreate9Func = (Direct3DCreate9_t)SDL_LoadFunction(*pD3DDLL, "Direct3DCreate9");
258 if (Direct3DCreate9Func) {
259 *pDirect3D9Interface = Direct3DCreate9Func(D3D_SDK_VERSION);
260 if (*pDirect3D9Interface) {
265 SDL_UnloadObject(*pD3DDLL);
268 *pDirect3D9Interface = NULL;
274 SDL_Direct3D9GetAdapterIndex(int displayIndex)
278 if (!D3D_LoadDLL(&pD3DDLL, &pD3D)) {
279 SDL_SetError("Unable to create Direct3D interface");
280 return D3DADAPTER_DEFAULT;
282 SDL_DisplayData *pData = (SDL_DisplayData *)SDL_GetDisplayDriverData(displayIndex);
283 int adapterIndex = D3DADAPTER_DEFAULT;
286 SDL_SetError("Invalid display index");
287 adapterIndex = -1; /* make sure we return something invalid */
289 char *displayName = WIN_StringToUTF8(pData->DeviceName);
290 unsigned int count = IDirect3D9_GetAdapterCount(pD3D);
292 for (i=0; i<count; i++) {
293 D3DADAPTER_IDENTIFIER9 id;
294 IDirect3D9_GetAdapterIdentifier(pD3D, i, 0, &id);
296 if (SDL_strcmp(id.DeviceName, displayName) == 0) {
301 SDL_free(displayName);
304 /* free up the D3D stuff we inited */
305 IDirect3D9_Release(pD3D);
306 SDL_UnloadObject(pD3DDLL);
318 DXGI_LoadDLL(void **pDXGIDLL, IDXGIFactory **pDXGIFactory)
320 *pDXGIDLL = SDL_LoadObject("DXGI.DLL");
322 HRESULT (WINAPI *CreateDXGI)(REFIID riid, void **ppFactory);
325 (HRESULT (WINAPI *) (REFIID, void**)) SDL_LoadFunction(*pDXGIDLL,
326 "CreateDXGIFactory");
328 GUID dxgiGUID = {0x7b7166ec,0x21c7,0x44ae,{0xb2,0x1a,0xc9,0xae,0x32,0x1a,0xe3,0x69}};
329 if (!SUCCEEDED(CreateDXGI(&dxgiGUID, (void**)pDXGIFactory))) {
330 *pDXGIFactory = NULL;
333 if (!*pDXGIFactory) {
334 SDL_UnloadObject(*pDXGIDLL);
341 *pDXGIFactory = NULL;
349 SDL_DXGIGetOutputInfo(int displayIndex, int *adapterIndex, int *outputIndex)
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");
357 SDL_DisplayData *pData = (SDL_DisplayData *)SDL_GetDisplayDriverData(displayIndex);
360 int nAdapter, nOutput;
361 IDXGIFactory *pDXGIFactory;
362 IDXGIAdapter *pDXGIAdapter;
363 IDXGIOutput* pDXGIOutput;
366 SDL_InvalidParamError("adapterIndex");
371 SDL_InvalidParamError("outputIndex");
379 SDL_SetError("Invalid display index");
383 if (!DXGI_LoadDLL(&pDXGIDLL, &pDXGIFactory)) {
384 SDL_SetError("Unable to create DXGI interface");
388 displayName = WIN_StringToUTF8(pData->DeviceName);
390 while (*adapterIndex == -1 && SUCCEEDED(IDXGIFactory_EnumAdapters(pDXGIFactory, nAdapter, &pDXGIAdapter))) {
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;
400 SDL_free(outputName);
402 IDXGIOutput_Release(pDXGIOutput);
405 IDXGIAdapter_Release(pDXGIAdapter);
408 SDL_free(displayName);
410 /* free up the DXGI factory */
411 IDXGIFactory_Release(pDXGIFactory);
412 SDL_UnloadObject(pDXGIDLL);
414 if (*adapterIndex == -1) {
422 #endif /* SDL_VIDEO_DRIVER_WINDOWS */
424 /* vim: set ts=4 sw=4 expandtab: */