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