21#include "../../SDL_internal.h"
23#if SDL_VIDEO_DRIVER_WINRT
33#include <windows.graphics.display.h>
34#include <windows.system.display.h>
37using namespace Windows::ApplicationModel::Core;
38using namespace Windows::Foundation;
39using namespace Windows::Graphics::Display;
40using namespace Windows::UI::Core;
41using namespace Windows::UI::ViewManagement;
45static const GUID IID_IDisplayRequest = { 0xe5732044, 0xf49f, 0x4b60, { 0x8d, 0xd4, 0x5e, 0x7e, 0x3a, 0x63, 0x2a, 0xc0 } };
46static 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"
74static int WINRT_VideoInit(
_THIS);
75static int WINRT_InitModes(
_THIS);
77static void WINRT_VideoQuit(
_THIS);
89static ABI::Windows::System::Display::IDisplayRequest * WINRT_CreateDisplayRequest(
_THIS);
90extern void WINRT_SuspendScreenSaver(
_THIS);
120WINRT_CreateDevice(
int devindex)
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
182WINRT_VideoInit(
_THIS)
185 if (WINRT_InitModes(
_this) < 0) {
190 WINRT_InitGameBar(
_this);
199Uint32 D3D11_DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat);
202WINRT_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);
212WINRT_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;
271 display.
name = displayName;
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;
322WINRT_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();
401WINRT_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) {
434WINRT_VideoQuit(
_THIS)
441 WINRT_QuitGameBar(
_this);
445static 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;
535WINRT_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());
781static ABI::Windows::System::Display::IDisplayRequest *
782WINRT_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;
827WINRT_SuspendScreenSaver(
_THIS)
831 ABI::Windows::System::Display::IDisplayRequest * displayRequest = (ABI::Windows::System::Display::IDisplayRequest *) driverdata->
displayRequest;
833 displayRequest->RequestActive();
835 displayRequest->RequestRelease();
#define SDL_OutOfMemory()
void SDL_SetKeyboardFocus(SDL_Window *window)
void SDL_SetMouseFocus(SDL_Window *window)
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLenum GLuint GLenum GLsizei const GLchar * buf
GLfloat GLfloat GLfloat GLfloat h
GLubyte GLubyte GLubyte GLubyte w
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
VideoBootStrap WINRT_bootstrap
int SDL_AddVideoDisplay(const SDL_VideoDisplay *display)
SDL_bool SDL_AddDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode *mode)
#define SDL_MINOR_VERSION
#define SDL_MAJOR_VERSION
static SDL_VideoDevice * _this
@ SDL_WINDOW_FULLSCREEN_DESKTOP
#define WIN_StringToUTF8(S)
int WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr)
SDL_bool WINRT_XAMLWasEnabled
void WINRT_InitTouch(_THIS)
void WINRT_PumpEvents(_THIS)
void WINRT_QuitMouse(_THIS)
void WINRT_InitMouse(_THIS)
Uint32 WINRT_DetectWindowFlags(SDL_Window *window)
#define SDL_WINRT_USE_APPLICATIONVIEW
SDL_Window * WINRT_GlobalSDLWindow
void WINRT_UpdateWindowFlags(SDL_Window *window, Uint32 mask)
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
EGLSurface EGLNativeWindowType * window
static SDL_AudioDeviceID device
The structure that defines a display mode.
union SDL_SysWMinfo::@17 info
IUnknown * winrtEglWindow
IUnknown * displayRequest
SDL_bool suspend_screensaver
SDL_DisplayMode desktop_mode
SDL_DisplayMode current_mode
The type used to identify a window.