21 #include "../../SDL_internal.h"
23 #if SDL_VIDEO_DRIVER_WINRT
33 #include <windows.graphics.display.h>
34 #include <windows.system.display.h>
37 using namespace Windows::ApplicationModel::Core;
38 using namespace Windows::Foundation;
39 using namespace Windows::Graphics::Display;
40 using namespace Windows::UI::Core;
41 using namespace Windows::UI::ViewManagement;
45 static const GUID IID_IDisplayRequest = { 0xe5732044, 0xf49f, 0x4b60, { 0x8d, 0xd4, 0x5e, 0x7e, 0x3a, 0x63, 0x2a, 0xc0 } };
46 static const GUID IID_IDXGIFactory2 = { 0x50c83a1c, 0xe072, 0x4c48, { 0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0 } };
53 #include "../SDL_sysvideo.h"
54 #include "../SDL_pixels_c.h"
55 #include "../../events/SDL_events_c.h"
56 #include "../../render/SDL_sysrender.h"
59 #include "../../core/windows/SDL_windows.h"
62 #include "../../core/winrt/SDL_winrtapp_direct3d.h"
63 #include "../../core/winrt/SDL_winrtapp_xaml.h"
74 static int WINRT_VideoInit(
_THIS);
75 static int WINRT_InitModes(
_THIS);
77 static void WINRT_VideoQuit(
_THIS);
89 static ABI::Windows::System::Display::IDisplayRequest * WINRT_CreateDisplayRequest(
_THIS);
90 extern void WINRT_SuspendScreenSaver(
_THIS);
100 WINRT_Available(
void)
141 device->VideoInit = WINRT_VideoInit;
142 device->VideoQuit = WINRT_VideoQuit;
143 device->CreateSDLWindow = WINRT_CreateWindow;
144 device->SetWindowSize = WINRT_SetWindowSize;
145 device->SetWindowFullscreen = WINRT_SetWindowFullscreen;
146 device->DestroyWindow = WINRT_DestroyWindow;
147 device->SetDisplayMode = WINRT_SetDisplayMode;
149 device->GetWindowWMInfo = WINRT_GetWindowWMInfo;
150 device->SuspendScreenSaver = WINRT_SuspendScreenSaver;
152 #if NTDDI_VERSION >= NTDDI_WIN10
153 device->HasScreenKeyboardSupport = WINRT_HasScreenKeyboardSupport;
154 device->ShowScreenKeyboard = WINRT_ShowScreenKeyboard;
155 device->HideScreenKeyboard = WINRT_HideScreenKeyboard;
156 device->IsScreenKeyboardShown = WINRT_IsScreenKeyboardShown;
159 #ifdef SDL_VIDEO_OPENGL_EGL
160 device->GL_LoadLibrary = WINRT_GLES_LoadLibrary;
161 device->GL_GetProcAddress = WINRT_GLES_GetProcAddress;
162 device->GL_UnloadLibrary = WINRT_GLES_UnloadLibrary;
163 device->GL_CreateContext = WINRT_GLES_CreateContext;
164 device->GL_MakeCurrent = WINRT_GLES_MakeCurrent;
165 device->GL_SetSwapInterval = WINRT_GLES_SetSwapInterval;
166 device->GL_GetSwapInterval = WINRT_GLES_GetSwapInterval;
167 device->GL_SwapWindow = WINRT_GLES_SwapWindow;
168 device->GL_DeleteContext = WINRT_GLES_DeleteContext;
170 device->free = WINRT_DeleteDevice;
175 #define WINRTVID_DRIVER_NAME "winrt"
177 WINRTVID_DRIVER_NAME,
"SDL WinRT video driver",
178 WINRT_Available, WINRT_CreateDevice
182 WINRT_VideoInit(
_THIS)
185 if (WINRT_InitModes(
_this) < 0) {
190 WINRT_InitGameBar(
_this);
199 Uint32 D3D11_DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat);
202 WINRT_DXGIModeToSDLDisplayMode(
const DXGI_MODE_DESC * dxgiMode,
SDL_DisplayMode * sdlMode)
205 sdlMode->
w = dxgiMode->Width;
206 sdlMode->
h = dxgiMode->Height;
207 sdlMode->
refresh_rate = dxgiMode->RefreshRate.Numerator / dxgiMode->RefreshRate.Denominator;
208 sdlMode->
format = D3D11_DXGIFormatToSDLPixelFormat(dxgiMode->Format);
212 WINRT_AddDisplaysForOutput (
_THIS, IDXGIAdapter1 * dxgiAdapter1,
int outputIndex)
215 IDXGIOutput * dxgiOutput =
NULL;
216 DXGI_OUTPUT_DESC dxgiOutputDesc;
218 char * displayName =
NULL;
220 DXGI_MODE_DESC * dxgiModes =
NULL;
221 int functionResult = -1;
222 DXGI_MODE_DESC modeToMatch, closestMatch;
226 hr = dxgiAdapter1->EnumOutputs(outputIndex, &dxgiOutput);
228 if (hr != DXGI_ERROR_NOT_FOUND) {
234 hr = dxgiOutput->GetDesc(&dxgiOutputDesc);
241 modeToMatch.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
242 modeToMatch.Width = (dxgiOutputDesc.DesktopCoordinates.right - dxgiOutputDesc.DesktopCoordinates.left);
243 modeToMatch.Height = (dxgiOutputDesc.DesktopCoordinates.bottom - dxgiOutputDesc.DesktopCoordinates.top);
244 hr = dxgiOutput->FindClosestMatchingMode(&modeToMatch, &closestMatch,
NULL);
245 if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) {
256 display.name =
"Windows Simulator / Terminal Services Display";
257 mode.w = (dxgiOutputDesc.DesktopCoordinates.right - dxgiOutputDesc.DesktopCoordinates.left);
258 mode.h = (dxgiOutputDesc.DesktopCoordinates.bottom - dxgiOutputDesc.DesktopCoordinates.top);
259 mode.format = DXGI_FORMAT_B8G8R8A8_UNORM;
260 mode.refresh_rate = 0;
272 WINRT_DXGIModeToSDLDisplayMode(&closestMatch, &
display.desktop_mode);
275 hr = dxgiOutput->GetDisplayModeList(DXGI_FORMAT_B8G8R8A8_UNORM, 0, &numModes,
NULL);
277 if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) {
284 dxgiModes = (DXGI_MODE_DESC *)
SDL_calloc(numModes,
sizeof(DXGI_MODE_DESC));
290 hr = dxgiOutput->GetDisplayModeList(DXGI_FORMAT_B8G8R8A8_UNORM, 0, &numModes, dxgiModes);
296 for (
UINT i = 0;
i < numModes; ++
i) {
298 WINRT_DXGIModeToSDLDisplayMode(&dxgiModes[
i], &sdlMode);
313 dxgiOutput->Release();
318 return functionResult;
322 WINRT_AddDisplaysForAdapter (
_THIS, IDXGIFactory2 * dxgiFactory2,
int adapterIndex)
325 IDXGIAdapter1 * dxgiAdapter1;
327 hr = dxgiFactory2->EnumAdapters1(adapterIndex, &dxgiAdapter1);
329 if (hr != DXGI_ERROR_NOT_FOUND) {
335 for (
int outputIndex = 0; ; ++outputIndex) {
336 if (WINRT_AddDisplaysForOutput(
_this, dxgiAdapter1, outputIndex) < 0) {
352 if (adapterIndex == 0 && outputIndex == 0) {
355 #if SDL_WINRT_USE_APPLICATIONVIEW
356 ApplicationView ^ appView = ApplicationView::GetForCurrentView();
358 CoreWindow ^ coreWin = CoreWindow::GetForCurrentThread();
361 display.name =
"DXGI Display-detection Workaround";
370 #if (NTDDI_VERSION >= NTDDI_WIN10) || (SDL_WINRT_USE_APPLICATIONVIEW && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
371 mode.w = WINRT_DIPS_TO_PHYSICAL_PIXELS(appView->VisibleBounds.Width);
372 mode.h = WINRT_DIPS_TO_PHYSICAL_PIXELS(appView->VisibleBounds.Height);
377 mode.w = WINRT_DIPS_TO_PHYSICAL_PIXELS(coreWin->Bounds.Width);
378 mode.h = WINRT_DIPS_TO_PHYSICAL_PIXELS(coreWin->Bounds.Height);
381 mode.format = DXGI_FORMAT_B8G8R8A8_UNORM;
382 mode.refresh_rate = 0;
388 return SDL_SetError(
"Failed to apply DXGI Display-detection workaround");
396 dxgiAdapter1->Release();
401 WINRT_InitModes(
_THIS)
410 IDXGIFactory2 * dxgiFactory2 =
NULL;
412 hr = CreateDXGIFactory1(IID_IDXGIFactory2, (
void **)&dxgiFactory2);
418 for (
int adapterIndex = 0; ; ++adapterIndex) {
419 if (WINRT_AddDisplaysForAdapter(
_this, dxgiFactory2, adapterIndex) < 0) {
434 WINRT_VideoQuit(
_THIS)
441 WINRT_QuitGameBar(
_this);
445 static const Uint32 WINRT_DetectableFlags =
457 bool is_fullscreen =
false;
461 is_fullscreen =
data->appView->IsFullScreen;
463 #elif (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) || (NTDDI_VERSION == NTDDI_WIN8)
464 is_fullscreen =
true;
467 if (
data->coreWindow.Get()) {
470 int w = WINRT_DIPS_TO_PHYSICAL_PIXELS(
data->coreWindow->Bounds.Width);
471 int h = WINRT_DIPS_TO_PHYSICAL_PIXELS(
data->coreWindow->Bounds.Height);
473 #if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) || (NTDDI_VERSION > NTDDI_WIN8)
477 const DisplayOrientations currentOrientation = WINRT_DISPLAY_PROPERTY(CurrentOrientation);
478 switch (currentOrientation) {
479 #if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
480 case DisplayOrientations::Landscape:
481 case DisplayOrientations::LandscapeFlipped:
483 case DisplayOrientations::Portrait:
484 case DisplayOrientations::PortraitFlipped:
501 if (
data->coreWindow->Visible) {
507 #if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) && (NTDDI_VERSION < NTDDI_WINBLUE)
511 if (
data->coreWindow->Visible &&
data->coreWindow->Bounds.Contains(
data->coreWindow->PointerPosition)) {
524 mask &= WINRT_DetectableFlags;
535 WINRT_IsCoreWindowActive(CoreWindow ^ coreWindow)
545 if (coreWindow->CustomProperties->HasKey(
"SDLHelperWindowActivationState")) {
546 CoreWindowActivationState activationState = \
547 safe_cast<CoreWindowActivationState>(coreWindow->CustomProperties->Lookup(
"SDLHelperWindowActivationState"));
548 return (activationState != CoreWindowActivationState::Deactivated);
585 data->coreWindow = CoreWindow::GetForCurrentThread();
586 #if SDL_WINRT_USE_APPLICATIONVIEW
587 data->appView = ApplicationView::GetForCurrentView();
594 #if SDL_VIDEO_OPENGL_EGL
608 if (SDL_EGL_ChooseConfig(
_this) != 0) {
618 Microsoft::WRL::ComPtr<IUnknown> cpp_winrtEglWindow = video_data->
winrtEglWindow;
619 data->egl_surface = ((eglCreateWindowSurface_Old_Function)
_this->egl_data->eglCreateWindowSurface)(
620 _this->egl_data->egl_display,
621 _this->egl_data->egl_config,
622 cpp_winrtEglWindow,
NULL);
624 return SDL_EGL_SetError(
"unable to create EGL native-window surface",
"eglCreateWindowSurface");
626 }
else if (
data->coreWindow.Get() !=
nullptr) {
630 IInspectable * coreWindowAsIInspectable = reinterpret_cast<IInspectable *>(
data->coreWindow.Get());
631 data->egl_surface =
_this->egl_data->eglCreateWindowSurface(
632 _this->egl_data->egl_display,
633 _this->egl_data->egl_config,
634 coreWindowAsIInspectable,
637 return SDL_EGL_SetError(
"unable to create EGL native-window surface",
"eglCreateWindowSurface");
640 return SDL_SetError(
"No supported means to create an EGL window surface are available");
650 #if SDL_VIDEO_OPENGL_EGL
651 if (
data->egl_surface) {
669 window->x = WINRT_DIPS_TO_PHYSICAL_PIXELS(
data->coreWindow->Bounds.Left);
670 window->y = WINRT_DIPS_TO_PHYSICAL_PIXELS(
data->coreWindow->Bounds.Top);
671 #if NTDDI_VERSION < NTDDI_WIN10
673 window->w = WINRT_DIPS_TO_PHYSICAL_PIXELS(
data->coreWindow->Bounds.Width);
674 window->h = WINRT_DIPS_TO_PHYSICAL_PIXELS(
data->coreWindow->Bounds.Height);
679 bool didSetSize =
false;
681 const Windows::Foundation::Size
size(WINRT_PHYSICAL_PIXELS_TO_DIPS(
window->w),
682 WINRT_PHYSICAL_PIXELS_TO_DIPS(
window->h));
683 didSetSize =
data->appView->TryResizeView(
size);
689 window->w = WINRT_DIPS_TO_PHYSICAL_PIXELS(
data->coreWindow->Bounds.Width);
690 window->h = WINRT_DIPS_TO_PHYSICAL_PIXELS(
data->coreWindow->Bounds.Height);
700 bool isWindowActive = WINRT_IsCoreWindowActive(
data->coreWindow.Get());
701 if (isWindowActive) {
718 #if NTDDI_VERSION >= NTDDI_WIN10
720 const Windows::Foundation::Size
size(WINRT_PHYSICAL_PIXELS_TO_DIPS(
window->w),
721 WINRT_PHYSICAL_PIXELS_TO_DIPS(
window->h));
729 #if NTDDI_VERSION >= NTDDI_WIN10
731 bool isWindowActive = WINRT_IsCoreWindowActive(
data->coreWindow.Get());
732 if (isWindowActive) {
734 if (!
data->appView->IsFullScreenMode) {
735 data->appView->TryEnterFullScreenMode();
738 if (
data->appView->IsFullScreenMode) {
739 data->appView->ExitFullScreenMode();
771 info->
info.winrt.
window = reinterpret_cast<IInspectable *>(
data->coreWindow.Get());
781 static ABI::Windows::System::Display::IDisplayRequest *
782 WINRT_CreateDisplayRequest(
_THIS)
785 wchar_t *wClassName = L
"Windows.System.Display.DisplayRequest";
787 IActivationFactory *pActivationFactory =
NULL;
788 IInspectable * pDisplayRequestRaw =
nullptr;
789 ABI::Windows::System::Display::IDisplayRequest * pDisplayRequest =
nullptr;
792 hr = ::WindowsCreateString(wClassName, (UINT32)wcslen(wClassName), &hClassName);
797 hr = Windows::Foundation::GetActivationFactory(hClassName, &pActivationFactory);
802 hr = pActivationFactory->ActivateInstance(&pDisplayRequestRaw);
807 hr = pDisplayRequestRaw->QueryInterface(IID_IDisplayRequest, (
void **) &pDisplayRequest);
813 if (pDisplayRequestRaw) {
814 pDisplayRequestRaw->Release();
816 if (pActivationFactory) {
817 pActivationFactory->Release();
820 ::WindowsDeleteString(hClassName);
823 return pDisplayRequest;
827 WINRT_SuspendScreenSaver(
_THIS)
831 ABI::Windows::System::Display::IDisplayRequest *
displayRequest = (ABI::Windows::System::Display::IDisplayRequest *) driverdata->
displayRequest;