src/video/windows/SDL_windowsvideo.c
author Sam Lantinga
Fri, 27 Jan 2017 06:05:50 -0800
changeset 10856 486aa38c6a88
parent 10737 3406a0f8b041
child 11219 f94279990934
permissions -rw-r--r--
Added Thrustmaster Wheel FFB entry to the list of wheels
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2017 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->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
   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
   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 
   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
   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
   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
   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: */