sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

SDL_windowsvideo.c (14642B)


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