src/video/windows/SDL_windowsvideo.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 02 Jan 2016 10:10:34 -0800
changeset 9998 f67cf37e9cd4
parent 9813 0652406e46c6
child 10019 36f7e8084508
permissions -rw-r--r--
Updated copyright to 2016
     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: */