src/video/windows/SDL_windowsvideo.c
author EXL <exlmotodev@gmail.com>
Tue, 12 Nov 2019 17:24:37 -0500
changeset 13238 007002587d5d
parent 13166 fe327ab07b2e
permissions -rw-r--r--
haiku: Rename BE_* entities to HAIKU_*
In favor Bugzilla #2349.
Update copyright years to 2019.

Partially fixes Bugzilla #4442.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2019 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 #include "SDL_windowsvulkan.h"
    37 
    38 /* Initialization/Query functions */
    39 static int WIN_VideoInit(_THIS);
    40 static void WIN_VideoQuit(_THIS);
    41 
    42 /* Hints */
    43 SDL_bool g_WindowsEnableMessageLoop = SDL_TRUE;
    44 SDL_bool g_WindowFrameUsableWhileCursorHidden = SDL_TRUE;
    45 
    46 static void SDLCALL
    47 UpdateWindowsEnableMessageLoop(void *userdata, const char *name, const char *oldValue, const char *newValue)
    48 {
    49     if (newValue && *newValue == '0') {
    50         g_WindowsEnableMessageLoop = SDL_FALSE;
    51     } else {
    52         g_WindowsEnableMessageLoop = SDL_TRUE;
    53     }
    54 }
    55 
    56 static void SDLCALL
    57 UpdateWindowFrameUsableWhileCursorHidden(void *userdata, const char *name, const char *oldValue, const char *newValue)
    58 {
    59     if (newValue && *newValue == '0') {
    60         g_WindowFrameUsableWhileCursorHidden = SDL_FALSE;
    61     } else {
    62         g_WindowFrameUsableWhileCursorHidden = SDL_TRUE;
    63     }
    64 }
    65 
    66 static void WIN_SuspendScreenSaver(_THIS)
    67 {
    68     if (_this->suspend_screensaver) {
    69         SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
    70     } else {
    71         SetThreadExecutionState(ES_CONTINUOUS);
    72     }
    73 }
    74 
    75 
    76 /* Windows driver bootstrap functions */
    77 
    78 static int
    79 WIN_Available(void)
    80 {
    81     return (1);
    82 }
    83 
    84 static void
    85 WIN_DeleteDevice(SDL_VideoDevice * device)
    86 {
    87     SDL_VideoData *data = (SDL_VideoData *) device->driverdata;
    88 
    89     SDL_UnregisterApp();
    90     if (data->userDLL) {
    91         SDL_UnloadObject(data->userDLL);
    92     }
    93     if (data->shcoreDLL) {
    94         SDL_UnloadObject(data->shcoreDLL);
    95     }
    96 
    97     SDL_free(device->driverdata);
    98     SDL_free(device);
    99 }
   100 
   101 static SDL_VideoDevice *
   102 WIN_CreateDevice(int devindex)
   103 {
   104     SDL_VideoDevice *device;
   105     SDL_VideoData *data;
   106 
   107     SDL_RegisterApp(NULL, 0, NULL);
   108 
   109     /* Initialize all variables that we clean on shutdown */
   110     device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
   111     if (device) {
   112         data = (struct SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
   113     } else {
   114         data = NULL;
   115     }
   116     if (!data) {
   117         SDL_free(device);
   118         SDL_OutOfMemory();
   119         return NULL;
   120     }
   121     device->driverdata = data;
   122 
   123     data->userDLL = SDL_LoadObject("USER32.DLL");
   124     if (data->userDLL) {
   125         data->CloseTouchInputHandle = (BOOL (WINAPI *)(HTOUCHINPUT)) SDL_LoadFunction(data->userDLL, "CloseTouchInputHandle");
   126         data->GetTouchInputInfo = (BOOL (WINAPI *)(HTOUCHINPUT, UINT, PTOUCHINPUT, int)) SDL_LoadFunction(data->userDLL, "GetTouchInputInfo");
   127         data->RegisterTouchWindow = (BOOL (WINAPI *)(HWND, ULONG)) SDL_LoadFunction(data->userDLL, "RegisterTouchWindow");
   128     } else {
   129         SDL_ClearError();
   130     }
   131 
   132     data->shcoreDLL = SDL_LoadObject("SHCORE.DLL");
   133     if (data->shcoreDLL) {
   134         data->GetDpiForMonitor = (HRESULT (WINAPI *)(HMONITOR, MONITOR_DPI_TYPE, UINT *, UINT *)) SDL_LoadFunction(data->shcoreDLL, "GetDpiForMonitor");
   135     } else {
   136         SDL_ClearError();
   137     }
   138 
   139     /* Set the function pointers */
   140     device->VideoInit = WIN_VideoInit;
   141     device->VideoQuit = WIN_VideoQuit;
   142     device->GetDisplayBounds = WIN_GetDisplayBounds;
   143     device->GetDisplayUsableBounds = WIN_GetDisplayUsableBounds;
   144     device->GetDisplayDPI = WIN_GetDisplayDPI;
   145     device->GetDisplayModes = WIN_GetDisplayModes;
   146     device->SetDisplayMode = WIN_SetDisplayMode;
   147     device->PumpEvents = WIN_PumpEvents;
   148     device->SuspendScreenSaver = WIN_SuspendScreenSaver;
   149 
   150     device->CreateSDLWindow = WIN_CreateWindow;
   151     device->CreateSDLWindowFrom = WIN_CreateWindowFrom;
   152     device->SetWindowTitle = WIN_SetWindowTitle;
   153     device->SetWindowIcon = WIN_SetWindowIcon;
   154     device->SetWindowPosition = WIN_SetWindowPosition;
   155     device->SetWindowSize = WIN_SetWindowSize;
   156     device->GetWindowBordersSize = WIN_GetWindowBordersSize;
   157     device->SetWindowOpacity = WIN_SetWindowOpacity;
   158     device->ShowWindow = WIN_ShowWindow;
   159     device->HideWindow = WIN_HideWindow;
   160     device->RaiseWindow = WIN_RaiseWindow;
   161     device->MaximizeWindow = WIN_MaximizeWindow;
   162     device->MinimizeWindow = WIN_MinimizeWindow;
   163     device->RestoreWindow = WIN_RestoreWindow;
   164     device->SetWindowBordered = WIN_SetWindowBordered;
   165     device->SetWindowResizable = WIN_SetWindowResizable;
   166     device->SetWindowFullscreen = WIN_SetWindowFullscreen;
   167     device->SetWindowGammaRamp = WIN_SetWindowGammaRamp;
   168     device->GetWindowGammaRamp = WIN_GetWindowGammaRamp;
   169     device->SetWindowGrab = WIN_SetWindowGrab;
   170     device->DestroyWindow = WIN_DestroyWindow;
   171     device->GetWindowWMInfo = WIN_GetWindowWMInfo;
   172     device->CreateWindowFramebuffer = WIN_CreateWindowFramebuffer;
   173     device->UpdateWindowFramebuffer = WIN_UpdateWindowFramebuffer;
   174     device->DestroyWindowFramebuffer = WIN_DestroyWindowFramebuffer;
   175     device->OnWindowEnter = WIN_OnWindowEnter;
   176     device->SetWindowHitTest = WIN_SetWindowHitTest;
   177     device->AcceptDragAndDrop = WIN_AcceptDragAndDrop;
   178 
   179     device->shape_driver.CreateShaper = Win32_CreateShaper;
   180     device->shape_driver.SetWindowShape = Win32_SetWindowShape;
   181     device->shape_driver.ResizeWindowShape = Win32_ResizeWindowShape;
   182 
   183 #if SDL_VIDEO_OPENGL_WGL
   184     device->GL_LoadLibrary = WIN_GL_LoadLibrary;
   185     device->GL_GetProcAddress = WIN_GL_GetProcAddress;
   186     device->GL_UnloadLibrary = WIN_GL_UnloadLibrary;
   187     device->GL_CreateContext = WIN_GL_CreateContext;
   188     device->GL_MakeCurrent = WIN_GL_MakeCurrent;
   189     device->GL_SetSwapInterval = WIN_GL_SetSwapInterval;
   190     device->GL_GetSwapInterval = WIN_GL_GetSwapInterval;
   191     device->GL_SwapWindow = WIN_GL_SwapWindow;
   192     device->GL_DeleteContext = WIN_GL_DeleteContext;
   193 #elif SDL_VIDEO_OPENGL_EGL        
   194     /* Use EGL based functions */
   195     device->GL_LoadLibrary = WIN_GLES_LoadLibrary;
   196     device->GL_GetProcAddress = WIN_GLES_GetProcAddress;
   197     device->GL_UnloadLibrary = WIN_GLES_UnloadLibrary;
   198     device->GL_CreateContext = WIN_GLES_CreateContext;
   199     device->GL_MakeCurrent = WIN_GLES_MakeCurrent;
   200     device->GL_SetSwapInterval = WIN_GLES_SetSwapInterval;
   201     device->GL_GetSwapInterval = WIN_GLES_GetSwapInterval;
   202     device->GL_SwapWindow = WIN_GLES_SwapWindow;
   203     device->GL_DeleteContext = WIN_GLES_DeleteContext;
   204 #endif
   205 #if SDL_VIDEO_VULKAN
   206     device->Vulkan_LoadLibrary = WIN_Vulkan_LoadLibrary;
   207     device->Vulkan_UnloadLibrary = WIN_Vulkan_UnloadLibrary;
   208     device->Vulkan_GetInstanceExtensions = WIN_Vulkan_GetInstanceExtensions;
   209     device->Vulkan_CreateSurface = WIN_Vulkan_CreateSurface;
   210 #endif
   211 
   212     device->StartTextInput = WIN_StartTextInput;
   213     device->StopTextInput = WIN_StopTextInput;
   214     device->SetTextInputRect = WIN_SetTextInputRect;
   215 
   216     device->SetClipboardText = WIN_SetClipboardText;
   217     device->GetClipboardText = WIN_GetClipboardText;
   218     device->HasClipboardText = WIN_HasClipboardText;
   219 
   220     device->free = WIN_DeleteDevice;
   221 
   222     return device;
   223 }
   224 
   225 
   226 VideoBootStrap WINDOWS_bootstrap = {
   227     "windows", "SDL Windows video driver", WIN_Available, WIN_CreateDevice
   228 };
   229 
   230 int
   231 WIN_VideoInit(_THIS)
   232 {
   233     if (WIN_InitModes(_this) < 0) {
   234         return -1;
   235     }
   236 
   237     WIN_InitKeyboard(_this);
   238     WIN_InitMouse(_this);
   239 
   240     SDL_AddHintCallback(SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP, UpdateWindowsEnableMessageLoop, NULL);
   241     SDL_AddHintCallback(SDL_HINT_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN, UpdateWindowFrameUsableWhileCursorHidden, NULL);
   242 
   243     return 0;
   244 }
   245 
   246 void
   247 WIN_VideoQuit(_THIS)
   248 {
   249     WIN_QuitModes(_this);
   250     WIN_QuitKeyboard(_this);
   251     WIN_QuitMouse(_this);
   252 }
   253 
   254 
   255 #define D3D_DEBUG_INFO
   256 #include <d3d9.h>
   257 
   258 SDL_bool 
   259 D3D_LoadDLL(void **pD3DDLL, IDirect3D9 **pDirect3D9Interface)
   260 {
   261     *pD3DDLL = SDL_LoadObject("D3D9.DLL");
   262     if (*pD3DDLL) {
   263         typedef IDirect3D9 *(WINAPI *Direct3DCreate9_t) (UINT SDKVersion);
   264         Direct3DCreate9_t Direct3DCreate9Func;
   265 
   266 #ifdef USE_D3D9EX
   267         typedef HRESULT (WINAPI *Direct3DCreate9Ex_t)(UINT SDKVersion, IDirect3D9Ex **ppD3D);
   268         Direct3DCreate9Ex_t Direct3DCreate9ExFunc;
   269 
   270         Direct3DCreate9ExFunc = (Direct3DCreate9Ex_t)SDL_LoadFunction(*pD3DDLL, "Direct3DCreate9Ex");
   271         if (Direct3DCreate9ExFunc) {
   272             IDirect3D9Ex *pDirect3D9ExInterface;
   273             HRESULT hr = Direct3DCreate9ExFunc(D3D_SDK_VERSION, &pDirect3D9ExInterface);
   274             if (SUCCEEDED(hr)) {
   275                 const GUID IDirect3D9_GUID = { 0x81bdcbca, 0x64d4, 0x426d, { 0xae, 0x8d, 0xad, 0x1, 0x47, 0xf4, 0x27, 0x5c } };
   276                 hr = IDirect3D9Ex_QueryInterface(pDirect3D9ExInterface, &IDirect3D9_GUID, (void**)pDirect3D9Interface);
   277                 IDirect3D9Ex_Release(pDirect3D9ExInterface);
   278                 if (SUCCEEDED(hr)) {
   279                     return SDL_TRUE;
   280                 }
   281             }
   282         }
   283 #endif /* USE_D3D9EX */
   284 
   285         Direct3DCreate9Func = (Direct3DCreate9_t)SDL_LoadFunction(*pD3DDLL, "Direct3DCreate9");
   286         if (Direct3DCreate9Func) {
   287             *pDirect3D9Interface = Direct3DCreate9Func(D3D_SDK_VERSION);
   288             if (*pDirect3D9Interface) {
   289                 return SDL_TRUE;
   290             }
   291         }
   292 
   293         SDL_UnloadObject(*pD3DDLL);
   294         *pD3DDLL = NULL;
   295     }
   296     *pDirect3D9Interface = NULL;
   297     return SDL_FALSE;
   298 }
   299 
   300 
   301 int
   302 SDL_Direct3D9GetAdapterIndex(int displayIndex)
   303 {
   304     void *pD3DDLL;
   305     IDirect3D9 *pD3D;
   306     if (!D3D_LoadDLL(&pD3DDLL, &pD3D)) {
   307         SDL_SetError("Unable to create Direct3D interface");
   308         return D3DADAPTER_DEFAULT;
   309     } else {
   310         SDL_DisplayData *pData = (SDL_DisplayData *)SDL_GetDisplayDriverData(displayIndex);
   311         int adapterIndex = D3DADAPTER_DEFAULT;
   312 
   313         if (!pData) {
   314             SDL_SetError("Invalid display index");
   315             adapterIndex = -1; /* make sure we return something invalid */
   316         } else {
   317             char *displayName = WIN_StringToUTF8(pData->DeviceName);
   318             unsigned int count = IDirect3D9_GetAdapterCount(pD3D);
   319             unsigned int i;
   320             for (i=0; i<count; i++) {
   321                 D3DADAPTER_IDENTIFIER9 id;
   322                 IDirect3D9_GetAdapterIdentifier(pD3D, i, 0, &id);
   323 
   324                 if (SDL_strcmp(id.DeviceName, displayName) == 0) {
   325                     adapterIndex = i;
   326                     break;
   327                 }
   328             }
   329             SDL_free(displayName);
   330         }
   331 
   332         /* free up the D3D stuff we inited */
   333         IDirect3D9_Release(pD3D);
   334         SDL_UnloadObject(pD3DDLL);
   335 
   336         return adapterIndex;
   337     }
   338 }
   339 
   340 #if HAVE_DXGI_H
   341 #define CINTERFACE
   342 #define COBJMACROS
   343 #include <dxgi.h>
   344 
   345 static SDL_bool
   346 DXGI_LoadDLL(void **pDXGIDLL, IDXGIFactory **pDXGIFactory)
   347 {
   348     *pDXGIDLL = SDL_LoadObject("DXGI.DLL");
   349     if (*pDXGIDLL) {
   350         HRESULT (WINAPI *CreateDXGI)(REFIID riid, void **ppFactory);
   351 
   352         CreateDXGI =
   353             (HRESULT (WINAPI *) (REFIID, void**)) SDL_LoadFunction(*pDXGIDLL,
   354             "CreateDXGIFactory");
   355         if (CreateDXGI) {
   356             GUID dxgiGUID = {0x7b7166ec,0x21c7,0x44ae,{0xb2,0x1a,0xc9,0xae,0x32,0x1a,0xe3,0x69}};
   357             if (!SUCCEEDED(CreateDXGI(&dxgiGUID, (void**)pDXGIFactory))) {
   358                 *pDXGIFactory = NULL;
   359             }
   360         }
   361         if (!*pDXGIFactory) {
   362             SDL_UnloadObject(*pDXGIDLL);
   363             *pDXGIDLL = NULL;
   364             return SDL_FALSE;
   365         }
   366 
   367         return SDL_TRUE;
   368     } else {
   369         *pDXGIFactory = NULL;
   370         return SDL_FALSE;
   371     }
   372 }
   373 #endif
   374 
   375 
   376 SDL_bool
   377 SDL_DXGIGetOutputInfo(int displayIndex, int *adapterIndex, int *outputIndex)
   378 {
   379 #if !HAVE_DXGI_H
   380     if (adapterIndex) *adapterIndex = -1;
   381     if (outputIndex) *outputIndex = -1;
   382     SDL_SetError("SDL was compiled without DXGI support due to missing dxgi.h header");
   383     return SDL_FALSE;
   384 #else
   385     SDL_DisplayData *pData = (SDL_DisplayData *)SDL_GetDisplayDriverData(displayIndex);
   386     void *pDXGIDLL;
   387     char *displayName;
   388     int nAdapter, nOutput;
   389     IDXGIFactory *pDXGIFactory = NULL;
   390     IDXGIAdapter *pDXGIAdapter;
   391     IDXGIOutput* pDXGIOutput;
   392 
   393     if (!adapterIndex) {
   394         SDL_InvalidParamError("adapterIndex");
   395         return SDL_FALSE;
   396     }
   397 
   398     if (!outputIndex) {
   399         SDL_InvalidParamError("outputIndex");
   400         return SDL_FALSE;
   401     }
   402 
   403     *adapterIndex = -1;
   404     *outputIndex = -1;
   405 
   406     if (!pData) {
   407         SDL_SetError("Invalid display index");
   408         return SDL_FALSE;
   409     }
   410 
   411     if (!DXGI_LoadDLL(&pDXGIDLL, &pDXGIFactory)) {
   412         SDL_SetError("Unable to create DXGI interface");
   413         return SDL_FALSE;
   414     }
   415 
   416     displayName = WIN_StringToUTF8(pData->DeviceName);
   417     nAdapter = 0;
   418     while (*adapterIndex == -1 && SUCCEEDED(IDXGIFactory_EnumAdapters(pDXGIFactory, nAdapter, &pDXGIAdapter))) {
   419         nOutput = 0;
   420         while (*adapterIndex == -1 && SUCCEEDED(IDXGIAdapter_EnumOutputs(pDXGIAdapter, nOutput, &pDXGIOutput))) {
   421             DXGI_OUTPUT_DESC outputDesc;
   422             if (SUCCEEDED(IDXGIOutput_GetDesc(pDXGIOutput, &outputDesc))) {
   423                 char *outputName = WIN_StringToUTF8(outputDesc.DeviceName);
   424                 if (SDL_strcmp(outputName, displayName) == 0) {
   425                     *adapterIndex = nAdapter;
   426                     *outputIndex = nOutput;
   427                 }
   428                 SDL_free(outputName);
   429             }
   430             IDXGIOutput_Release(pDXGIOutput);
   431             nOutput++;
   432         }
   433         IDXGIAdapter_Release(pDXGIAdapter);
   434         nAdapter++;
   435     }
   436     SDL_free(displayName);
   437 
   438     /* free up the DXGI factory */
   439     IDXGIFactory_Release(pDXGIFactory);
   440     SDL_UnloadObject(pDXGIDLL);
   441 
   442     if (*adapterIndex == -1) {
   443         return SDL_FALSE;
   444     } else {
   445         return SDL_TRUE;
   446     }
   447 #endif
   448 }
   449 
   450 #endif /* SDL_VIDEO_DRIVER_WINDOWS */
   451 
   452 /* vim: set ts=4 sw=4 expandtab: */