WinRT: experimental and preliminary support for XAML-based overlays on Windows 8/RT
authorDavid Ludwig <dludwig@pobox.com>
Tue, 27 Aug 2013 21:21:09 -0400
changeset 8505a76a3842c9eb
parent 8504 3205689d1fff
child 8506 dc013502fd78
WinRT: experimental and preliminary support for XAML-based overlays on Windows 8/RT

The XAML support here is still rudimentary. Bugs do exist. You've been warned.

XAML support in Windows Phone 8 is not yet available (in SDL/WinRT).
VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj
VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj.filters
include/SDL_system.h
src/core/winrt/SDL_winrtapp.cpp
src/core/winrt/SDL_winrtxaml.cpp
src/render/direct3d11/SDL_render_d3d11.cpp
src/video/winrt/SDL_winrtevents.cpp
src/video/winrt/SDL_winrtevents_c.h
src/video/winrt/SDL_winrtmouse.cpp
src/video/winrt/SDL_winrtvideo.cpp
     1.1 --- a/VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj	Tue Aug 27 13:03:43 2013 -0400
     1.2 +++ b/VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj	Tue Aug 27 21:21:09 2013 -0400
     1.3 @@ -70,6 +70,14 @@
     1.4        <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</CompileAsWinRT>
     1.5        <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</CompileAsWinRT>
     1.6      </ClCompile>
     1.7 +    <ClCompile Include="..\..\src\core\winrt\SDL_winrtxaml.cpp">
     1.8 +      <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</CompileAsWinRT>
     1.9 +      <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</CompileAsWinRT>
    1.10 +      <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</CompileAsWinRT>
    1.11 +      <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</CompileAsWinRT>
    1.12 +      <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</CompileAsWinRT>
    1.13 +      <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</CompileAsWinRT>
    1.14 +    </ClCompile>
    1.15      <ClCompile Include="..\..\src\cpuinfo\SDL_cpuinfo.c" />
    1.16      <ClCompile Include="..\..\src\events\SDL_clipboardevents.c" />
    1.17      <ClCompile Include="..\..\src\events\SDL_dropevents.c" />
     2.1 --- a/VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj.filters	Tue Aug 27 13:03:43 2013 -0400
     2.2 +++ b/VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj.filters	Tue Aug 27 21:21:09 2013 -0400
     2.3 @@ -270,6 +270,9 @@
     2.4      <ClCompile Include="..\..\src\joystick\winrt\SDL_xinputjoystick.c">
     2.5        <Filter>Source Files</Filter>
     2.6      </ClCompile>
     2.7 +    <ClCompile Include="..\..\src\core\winrt\SDL_winrtxaml.cpp">
     2.8 +      <Filter>Source Files</Filter>
     2.9 +    </ClCompile>
    2.10    </ItemGroup>
    2.11    <ItemGroup>
    2.12      <ClInclude Include="..\..\include\begin_code.h">
     3.1 --- a/include/SDL_system.h	Tue Aug 27 13:03:43 2013 -0400
     3.2 +++ b/include/SDL_system.h	Tue Aug 27 21:21:09 2013 -0400
     3.3 @@ -155,6 +155,20 @@
     3.4   */
     3.5  extern DECLSPEC const char * SDLCALL SDL_WinRTGetFSPathUTF8(SDL_WinRT_Path pathType);
     3.6  
     3.7 +#ifdef __cplusplus_winrt
     3.8 +/**
     3.9 + *  \brief Initializes a WinRT and XAML based application.
    3.10 + *
    3.11 + *  \param backgroundPanel The XAML background panel to draw onto and receive
    3.12 + *      events from.
    3.13 + *  \param mainFunction The SDL app's C-style main().
    3.14 + *  \ret 0 on success, -1 on failure.  On failure, use SDL_GetError to retrieve more
    3.15 + *      information on the failure.
    3.16 + */
    3.17 +/* TODO, WinRT: consider making SDL_WinRTInitXAMLApp accept a void pointer to IUnknown, rather than a C++/CX reference */
    3.18 +extern DECLSPEC int SDLCALL SDL_WinRTInitXAMLApp(Platform::Object^ backgroundPanel, int (*mainFunction)(int, char **));
    3.19 +
    3.20 +#endif // ifdef __cplusplus_winrt
    3.21  
    3.22  #endif /* __WINRT__ */
    3.23  
     4.1 --- a/src/core/winrt/SDL_winrtapp.cpp	Tue Aug 27 13:03:43 2013 -0400
     4.2 +++ b/src/core/winrt/SDL_winrtapp.cpp	Tue Aug 27 21:21:09 2013 -0400
     4.3 @@ -361,17 +361,17 @@
     4.4  
     4.5  void SDL_WinRTApp::OnPointerPressed(CoreWindow^ sender, PointerEventArgs^ args)
     4.6  {
     4.7 -    WINRT_ProcessPointerPressedEvent(WINRT_GlobalSDLWindow, args);
     4.8 +    WINRT_ProcessPointerPressedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
     4.9  }
    4.10  
    4.11  void SDL_WinRTApp::OnPointerReleased(CoreWindow^ sender, PointerEventArgs^ args)
    4.12  {
    4.13 -    WINRT_ProcessPointerReleasedEvent(WINRT_GlobalSDLWindow, args);
    4.14 +    WINRT_ProcessPointerReleasedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
    4.15  }
    4.16  
    4.17  void SDL_WinRTApp::OnPointerWheelChanged(CoreWindow^ sender, PointerEventArgs^ args)
    4.18  {
    4.19 -    WINRT_ProcessPointerWheelChangedEvent(WINRT_GlobalSDLWindow, args);
    4.20 +    WINRT_ProcessPointerWheelChangedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
    4.21  }
    4.22  
    4.23  void SDL_WinRTApp::OnMouseMoved(MouseDevice^ mouseDevice, MouseEventArgs^ args)
    4.24 @@ -381,7 +381,7 @@
    4.25  
    4.26  void SDL_WinRTApp::OnPointerMoved(CoreWindow^ sender, PointerEventArgs^ args)
    4.27  {
    4.28 -    WINRT_ProcessPointerMovedEvent(WINRT_GlobalSDLWindow, args);
    4.29 +    WINRT_ProcessPointerMovedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
    4.30  }
    4.31  
    4.32  void SDL_WinRTApp::OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args)
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/core/winrt/SDL_winrtxaml.cpp	Tue Aug 27 21:21:09 2013 -0400
     5.3 @@ -0,0 +1,162 @@
     5.4 +/*
     5.5 +  Simple DirectMedia Layer
     5.6 +  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
     5.7 +
     5.8 +  This software is provided 'as-is', without any express or implied
     5.9 +  warranty.  In no event will the authors be held liable for any damages
    5.10 +  arising from the use of this software.
    5.11 +
    5.12 +  Permission is granted to anyone to use this software for any purpose,
    5.13 +  including commercial applications, and to alter it and redistribute it
    5.14 +  freely, subject to the following restrictions:
    5.15 +
    5.16 +  1. The origin of this software must not be misrepresented; you must not
    5.17 +     claim that you wrote the original software. If you use this software
    5.18 +     in a product, an acknowledgment in the product documentation would be
    5.19 +     appreciated but is not required.
    5.20 +  2. Altered source versions must be plainly marked as such, and must not be
    5.21 +     misrepresented as being the original software.
    5.22 +  3. This notice may not be removed or altered from any source distribution.
    5.23 +*/
    5.24 +
    5.25 +/* Windows includes */
    5.26 +#include <agile.h>
    5.27 +#include <Windows.h>
    5.28 +
    5.29 +#if WINAPI_FAMILY == WINAPI_FAMILY_APP
    5.30 +#include <windows.ui.xaml.media.dxinterop.h>
    5.31 +#endif
    5.32 +
    5.33 +
    5.34 +/* SDL includes */
    5.35 +#include "SDL.h"
    5.36 +//#include "SDL_error.h"
    5.37 +//#include "SDL_log.h"
    5.38 +//#include "SDL_main.h"
    5.39 +//#include "SDL_system.h"
    5.40 +#include "../../video/winrt/SDL_winrtevents_c.h"
    5.41 +
    5.42 +
    5.43 +/* External globals: */
    5.44 +extern SDL_Window * WINRT_GlobalSDLWindow;
    5.45 +
    5.46 +
    5.47 +/* Internal globals: */
    5.48 +SDL_bool WINRT_XAMLWasEnabled = SDL_FALSE;
    5.49 +int (*WINRT_XAMLAppMainFunction)(int, char **) = NULL;
    5.50 +
    5.51 +#if WINAPI_FAMILY == WINAPI_FAMILY_APP
    5.52 +ISwapChainBackgroundPanelNative * WINRT_GlobalSwapChainBackgroundPanelNative = NULL;
    5.53 +static Windows::Foundation::EventRegistrationToken	WINRT_XAMLAppEventToken;
    5.54 +#endif
    5.55 +
    5.56 +
    5.57 +/*
    5.58 + * Input event handlers (XAML)
    5.59 + */
    5.60 +#if WINAPI_FAMILY == WINAPI_FAMILY_APP
    5.61 +
    5.62 +static void
    5.63 +WINRT_OnPointerPressedViaXAML(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ args)
    5.64 +{
    5.65 +    WINRT_ProcessPointerPressedEvent(WINRT_GlobalSDLWindow, args->GetCurrentPoint(nullptr));
    5.66 +}
    5.67 +
    5.68 +static void
    5.69 +WINRT_OnPointerReleasedViaXAML(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ args)
    5.70 +{
    5.71 +    WINRT_ProcessPointerReleasedEvent(WINRT_GlobalSDLWindow, args->GetCurrentPoint(nullptr));
    5.72 +}
    5.73 +
    5.74 +static void
    5.75 +WINRT_OnPointerWheelChangedViaXAML(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ args)
    5.76 +{
    5.77 +    WINRT_ProcessPointerWheelChangedEvent(WINRT_GlobalSDLWindow, args->GetCurrentPoint(nullptr));
    5.78 +}
    5.79 +
    5.80 +static void
    5.81 +WINRT_OnPointerMovedViaXAML(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ args)
    5.82 +{
    5.83 +    WINRT_ProcessPointerMovedEvent(WINRT_GlobalSDLWindow, args->GetCurrentPoint(nullptr));
    5.84 +}
    5.85 +
    5.86 +#endif // WINAPI_FAMILY == WINAPI_FAMILY_APP
    5.87 +
    5.88 +
    5.89 +/*
    5.90 + * XAML-to-SDL Rendering Callback
    5.91 + */
    5.92 +#if WINAPI_FAMILY == WINAPI_FAMILY_APP
    5.93 +
    5.94 +static void
    5.95 +WINRT_OnRenderViaXAML(_In_ Platform::Object^ sender, _In_ Platform::Object^ args)
    5.96 +{
    5.97 +    WINRT_CycleXAMLThread();
    5.98 +}
    5.99 +
   5.100 +#endif // WINAPI_FAMILY == WINAPI_FAMILY_APP
   5.101 +
   5.102 +
   5.103 +/*
   5.104 + * SDL + XAML Initialization
   5.105 + */
   5.106 +
   5.107 +extern "C" int
   5.108 +SDL_WinRTInitXAMLApp(Platform::Object ^backgroundPanel, int (*mainFunction)(int, char **))
   5.109 +{
   5.110 +#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
   5.111 +    return SDL_SetError("XAML support is not yet available in Windows Phone.");
   5.112 +#else
   5.113 +    // Declare C++/CX namespaces:
   5.114 +    using namespace Platform;
   5.115 +    using namespace Windows::Foundation;
   5.116 +    using namespace Windows::UI::Core;
   5.117 +    using namespace Windows::UI::Xaml;
   5.118 +    using namespace Windows::UI::Xaml::Controls;
   5.119 +    using namespace Windows::UI::Xaml::Input;
   5.120 +    using namespace Windows::UI::Xaml::Media;
   5.121 +
   5.122 +    // Make sure we have a valid XAML element (to draw onto):
   5.123 +    if ( ! backgroundPanel) {
   5.124 +        return SDL_SetError("'backgroundPanel' can't be NULL");
   5.125 +    }
   5.126 +
   5.127 +    SwapChainBackgroundPanel ^swapChainBackgroundPanel = dynamic_cast<SwapChainBackgroundPanel ^>(backgroundPanel);
   5.128 +    if ( ! swapChainBackgroundPanel) {
   5.129 +        return SDL_SetError("An unknown or unsupported type of XAML control was specified.");
   5.130 +    }
   5.131 +
   5.132 +    // Setup event handlers:
   5.133 +    swapChainBackgroundPanel->PointerPressed += ref new PointerEventHandler(WINRT_OnPointerPressedViaXAML);
   5.134 +    swapChainBackgroundPanel->PointerReleased += ref new PointerEventHandler(WINRT_OnPointerReleasedViaXAML);
   5.135 +    swapChainBackgroundPanel->PointerWheelChanged += ref new PointerEventHandler(WINRT_OnPointerWheelChangedViaXAML);
   5.136 +    swapChainBackgroundPanel->PointerMoved += ref new PointerEventHandler(WINRT_OnPointerMovedViaXAML);
   5.137 +
   5.138 +    // Setup for rendering:
   5.139 +    IInspectable *panelInspectable = (IInspectable*) reinterpret_cast<IInspectable*>(swapChainBackgroundPanel);
   5.140 +    panelInspectable->QueryInterface(__uuidof(ISwapChainBackgroundPanelNative), (void **)&WINRT_GlobalSwapChainBackgroundPanelNative);
   5.141 +
   5.142 +    WINRT_XAMLAppEventToken = CompositionTarget::Rendering::add(ref new EventHandler<Object^>(WINRT_OnRenderViaXAML));
   5.143 +
   5.144 +    // Make sure the app is ready to call the SDL-centric main() function:
   5.145 +    WINRT_XAMLAppMainFunction = mainFunction;
   5.146 +    SDL_SetMainReady();
   5.147 +
   5.148 +    // Make sure video-init knows that we're initializing XAML:
   5.149 +    SDL_bool oldXAMLWasEnabledValue = WINRT_XAMLWasEnabled;
   5.150 +    WINRT_XAMLWasEnabled = SDL_TRUE;
   5.151 +
   5.152 +    // Make sure video modes are detected now, while we still have access to the WinRT
   5.153 +    // CoreWindow.  WinRT will not allow the app's CoreWindow to be accessed via the
   5.154 +    // SDL/WinRT thread.
   5.155 +    if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
   5.156 +        // SDL_InitSubSystem will, on error, set the SDL error.  Let that propogate to
   5.157 +        // the caller to here:
   5.158 +        WINRT_XAMLWasEnabled = oldXAMLWasEnabledValue;
   5.159 +        return -1;
   5.160 +    }
   5.161 +
   5.162 +    // All done, for now.
   5.163 +    return 0;
   5.164 +#endif // WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP  /  else
   5.165 +}
     6.1 --- a/src/render/direct3d11/SDL_render_d3d11.cpp	Tue Aug 27 13:03:43 2013 -0400
     6.2 +++ b/src/render/direct3d11/SDL_render_d3d11.cpp	Tue Aug 27 21:21:09 2013 -0400
     6.3 @@ -26,6 +26,11 @@
     6.4  #ifdef __WINRT__
     6.5  #include <windows.ui.core.h>
     6.6  #include <windows.foundation.h>
     6.7 +
     6.8 +#if WINAPI_FAMILY == WINAPI_FAMILY_APP
     6.9 +#include <windows.ui.xaml.media.dxinterop.h>
    6.10 +#endif
    6.11 +
    6.12  #endif
    6.13  
    6.14  extern "C" {
    6.15 @@ -608,6 +613,13 @@
    6.16  }
    6.17  #endif
    6.18  
    6.19 +
    6.20 +#if WINAPI_FAMILY == WINAPI_FAMILY_APP
    6.21 +// TODO, WinRT, XAML: get the ISwapChainBackgroundPanelNative from something other than a global var
    6.22 +extern ISwapChainBackgroundPanelNative * WINRT_GlobalSwapChainBackgroundPanelNative;
    6.23 +#endif
    6.24 +
    6.25 +
    6.26  // Initialize all resources that change when the window's size changes.
    6.27  // TODO, WinRT: get D3D11_CreateWindowSizeDependentResources working on Win32
    6.28  HRESULT
    6.29 @@ -619,15 +631,28 @@
    6.30  
    6.31      // Store the window bounds so the next time we get a SizeChanged event we can
    6.32      // avoid rebuilding everything if the size is identical.
    6.33 -    ABI::Windows::Foundation::Rect coreWindowBounds;
    6.34 -    result = coreWindow->get_Bounds(&coreWindowBounds);
    6.35 -    if (FAILED(result)) {
    6.36 -        WIN_SetErrorFromHRESULT(__FUNCTION__", Get Window Bounds", result);
    6.37 -        return result;
    6.38 +    ABI::Windows::Foundation::Rect nativeWindowBounds;
    6.39 +    if (coreWindow) {
    6.40 +        result = coreWindow->get_Bounds(&nativeWindowBounds);
    6.41 +        if (FAILED(result)) {
    6.42 +            WIN_SetErrorFromHRESULT(__FUNCTION__", Get Window Bounds", result);
    6.43 +            return result;
    6.44 +        }
    6.45 +    } else {
    6.46 +        // TODO, WinRT, XAML: clean up window-bounds code in D3D11_CreateWindowSizeDependentResources
    6.47 +        SDL_DisplayMode displayMode;
    6.48 +        if (SDL_GetDesktopDisplayMode(0, &displayMode) < 0) {
    6.49 +            SDL_SetError(__FUNCTION__", Get Window Bounds (XAML): Unable to retrieve the native window's size");
    6.50 +            return E_FAIL;
    6.51 +        }
    6.52 +
    6.53 +        nativeWindowBounds.Width = (FLOAT) displayMode.w;
    6.54 +        nativeWindowBounds.Height = (FLOAT) displayMode.h;
    6.55      }
    6.56  
    6.57 -    data->windowSizeInDIPs.x = coreWindowBounds.Width;
    6.58 -    data->windowSizeInDIPs.y = coreWindowBounds.Height;
    6.59 +    // TODO, WinRT, XAML: see if window/control sizes are in DIPs, or something else.  If something else, then adjust renderer size tracking accordingly.
    6.60 +    data->windowSizeInDIPs.x = nativeWindowBounds.Width;
    6.61 +    data->windowSizeInDIPs.y = nativeWindowBounds.Height;
    6.62  
    6.63      // Calculate the necessary swap chain and render target size in pixels.
    6.64      float windowWidth = D3D11_ConvertDipsToPixels(data->windowSizeInDIPs.x);
    6.65 @@ -660,6 +685,8 @@
    6.66      }
    6.67      else
    6.68      {
    6.69 +        const bool usingXAML = (coreWindow == nullptr);
    6.70 +
    6.71          // Otherwise, create a new one using the same adapter as the existing Direct3D device.
    6.72          DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
    6.73          swapChainDesc.Width = static_cast<UINT>(data->renderTargetSize.x); // Match the size of the window.
    6.74 @@ -674,7 +701,11 @@
    6.75          swapChainDesc.Scaling = DXGI_SCALING_STRETCH; // On phone, only stretch and aspect-ratio stretch scaling are allowed.
    6.76          swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; // On phone, no swap effects are supported.
    6.77  #else
    6.78 -        swapChainDesc.Scaling = DXGI_SCALING_NONE;
    6.79 +        if (usingXAML) {
    6.80 +            swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
    6.81 +        } else {
    6.82 +            swapChainDesc.Scaling = DXGI_SCALING_NONE;
    6.83 +        }
    6.84          swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // All Windows Store apps must use this SwapEffect.
    6.85  #endif
    6.86          swapChainDesc.Flags = 0;
    6.87 @@ -703,25 +734,48 @@
    6.88              return result;
    6.89          }
    6.90  
    6.91 -        IUnknown * coreWindowAsIUnknown = nullptr;
    6.92 -        result = coreWindow->QueryInterface(&coreWindowAsIUnknown);
    6.93 -        if (FAILED(result)) {
    6.94 -            WIN_SetErrorFromHRESULT(__FUNCTION__ ", CoreWindow to IUnknown", result);
    6.95 -            return result;
    6.96 -        }
    6.97 +        if (usingXAML) {
    6.98 +            result = dxgiFactory->CreateSwapChainForComposition(
    6.99 +                data->d3dDevice.Get(),
   6.100 +                &swapChainDesc,
   6.101 +                nullptr,
   6.102 +                &data->swapChain);
   6.103 +            if (FAILED(result)) {
   6.104 +                WIN_SetErrorFromHRESULT(__FUNCTION__ ", CreateSwapChainForComposition", result);
   6.105 +                return result;
   6.106 +            }
   6.107  
   6.108 -        result = dxgiFactory->CreateSwapChainForCoreWindow(
   6.109 -            data->d3dDevice.Get(),
   6.110 -            coreWindowAsIUnknown,
   6.111 -            &swapChainDesc,
   6.112 -            nullptr, // Allow on all displays.
   6.113 -            &data->swapChain
   6.114 -            );
   6.115 -        if (FAILED(result)) {
   6.116 -            WIN_SetErrorFromHRESULT(__FUNCTION__, result);
   6.117 -            return result;
   6.118 +#if WINAPI_FAMILY == WINAPI_FAMILY_APP
   6.119 +            result = WINRT_GlobalSwapChainBackgroundPanelNative->SetSwapChain(data->swapChain.Get());
   6.120 +            if (FAILED(result)) {
   6.121 +                WIN_SetErrorFromHRESULT(__FUNCTION__ ", ISwapChainBackgroundPanelNative::SetSwapChain", result);
   6.122 +                return result;
   6.123 +            }
   6.124 +#else
   6.125 +            SDL_SetError(__FUNCTION__ ", XAML support is not yet available for Windows Phone");
   6.126 +            return E_FAIL;
   6.127 +#endif
   6.128 +        } else {
   6.129 +            IUnknown * coreWindowAsIUnknown = nullptr;
   6.130 +            result = coreWindow->QueryInterface(&coreWindowAsIUnknown);
   6.131 +            if (FAILED(result)) {
   6.132 +                WIN_SetErrorFromHRESULT(__FUNCTION__ ", CoreWindow to IUnknown", result);
   6.133 +                return result;
   6.134 +            }
   6.135 +
   6.136 +            result = dxgiFactory->CreateSwapChainForCoreWindow(
   6.137 +                data->d3dDevice.Get(),
   6.138 +                coreWindowAsIUnknown,
   6.139 +                &swapChainDesc,
   6.140 +                nullptr, // Allow on all displays.
   6.141 +                &data->swapChain
   6.142 +                );
   6.143 +            if (FAILED(result)) {
   6.144 +                WIN_SetErrorFromHRESULT(__FUNCTION__, result);
   6.145 +                return result;
   6.146 +            }
   6.147          }
   6.148 -            
   6.149 +        
   6.150          // Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and
   6.151          // ensures that the application will only render after each VSync, minimizing power consumption.
   6.152          result = dxgiDevice->SetMaximumFrameLatency(1);
     7.1 --- a/src/video/winrt/SDL_winrtevents.cpp	Tue Aug 27 13:03:43 2013 -0400
     7.2 +++ b/src/video/winrt/SDL_winrtevents.cpp	Tue Aug 27 21:21:09 2013 -0400
     7.3 @@ -25,23 +25,117 @@
     7.4  /* SDL includes */
     7.5  #include "SDL_winrtevents_c.h"
     7.6  #include "../../core/winrt/SDL_winrtapp.h"
     7.7 +#include "SDL_assert.h"
     7.8 +#include "SDL_system.h"
     7.9  
    7.10  extern "C" {
    7.11  #include "../SDL_sysvideo.h"
    7.12  #include "../../events/SDL_events_c.h"
    7.13  }
    7.14  
    7.15 +
    7.16 +/* Forward declarations and globals */
    7.17  extern SDL_WinRTApp ^ SDL_WinRTGlobalApp;
    7.18 +extern int (*WINRT_XAMLAppMainFunction)(int, char **);
    7.19 +extern void WINRT_YieldXAMLThread();
    7.20  
    7.21  
    7.22 -/* General event-management function(s) */
    7.23 +/* Global event management */
    7.24  
    7.25  void
    7.26  WINRT_PumpEvents(_THIS)
    7.27  {
    7.28 -    SDL_WinRTGlobalApp->PumpEvents();
    7.29 +    if (SDL_WinRTGlobalApp) {
    7.30 +        SDL_WinRTGlobalApp->PumpEvents();
    7.31 +    } else if (WINRT_XAMLAppMainFunction) {
    7.32 +        WINRT_YieldXAMLThread();
    7.33 +    }
    7.34  }
    7.35  
    7.36 +
    7.37 +/* XAML Thread management */
    7.38 +
    7.39 +enum SDL_XAMLAppThreadState
    7.40 +{
    7.41 +    ThreadState_NotLaunched = 0,
    7.42 +    ThreadState_Running,
    7.43 +    ThreadState_Yielding
    7.44 +};
    7.45 +
    7.46 +static SDL_XAMLAppThreadState _threadState = ThreadState_NotLaunched;
    7.47 +static SDL_Thread * _XAMLThread = nullptr;
    7.48 +static SDL_mutex * _mutex = nullptr;
    7.49 +static SDL_cond * _cond = nullptr;
    7.50 +
    7.51 +static void
    7.52 +WINRT_YieldXAMLThread()
    7.53 +{
    7.54 +    SDL_LockMutex(_mutex);
    7.55 +    SDL_assert(_threadState == ThreadState_Running);
    7.56 +    _threadState = ThreadState_Yielding;
    7.57 +    SDL_UnlockMutex(_mutex);
    7.58 +
    7.59 +    SDL_CondSignal(_cond);
    7.60 +
    7.61 +    SDL_LockMutex(_mutex);
    7.62 +    while (_threadState != ThreadState_Running) {
    7.63 +        SDL_CondWait(_cond, _mutex);
    7.64 +    }
    7.65 +    SDL_UnlockMutex(_mutex);
    7.66 +}
    7.67 +
    7.68 +static int
    7.69 +WINRT_XAMLThreadMain(void * userdata)
    7.70 +{
    7.71 +    return WINRT_XAMLAppMainFunction(0, NULL);
    7.72 +}
    7.73 +
    7.74 +void
    7.75 +WINRT_CycleXAMLThread()
    7.76 +{
    7.77 +    switch (_threadState) {
    7.78 +        case ThreadState_NotLaunched:
    7.79 +        {
    7.80 +            _cond = SDL_CreateCond();
    7.81 +
    7.82 +            _mutex = SDL_CreateMutex();
    7.83 +            _threadState = ThreadState_Running;
    7.84 +            _XAMLThread = SDL_CreateThread(WINRT_XAMLThreadMain, "SDL/XAML App Thread", nullptr);
    7.85 +
    7.86 +            SDL_LockMutex(_mutex);
    7.87 +            while (_threadState != ThreadState_Yielding) {
    7.88 +                SDL_CondWait(_cond, _mutex);
    7.89 +            }
    7.90 +            SDL_UnlockMutex(_mutex);
    7.91 +
    7.92 +            break;
    7.93 +        }
    7.94 +
    7.95 +        case ThreadState_Running:
    7.96 +        {
    7.97 +            SDL_assert(false);
    7.98 +            break;
    7.99 +        }
   7.100 +
   7.101 +        case ThreadState_Yielding:
   7.102 +        {
   7.103 +            SDL_LockMutex(_mutex);
   7.104 +            SDL_assert(_threadState == ThreadState_Yielding);
   7.105 +            _threadState = ThreadState_Running;
   7.106 +            SDL_UnlockMutex(_mutex);
   7.107 +
   7.108 +            SDL_CondSignal(_cond);
   7.109 +
   7.110 +            SDL_LockMutex(_mutex);
   7.111 +            while (_threadState != ThreadState_Yielding) {
   7.112 +                SDL_CondWait(_cond, _mutex);
   7.113 +            }
   7.114 +            SDL_UnlockMutex(_mutex);
   7.115 +        }
   7.116 +    }
   7.117 +}
   7.118 +
   7.119 +
   7.120  #endif /* SDL_VIDEO_DRIVER_WINRT */
   7.121  
   7.122  /* vi: set ts=4 sw=4 expandtab: */
     8.1 --- a/src/video/winrt/SDL_winrtevents_c.h	Tue Aug 27 13:03:43 2013 -0400
     8.2 +++ b/src/video/winrt/SDL_winrtevents_c.h	Tue Aug 27 21:21:09 2013 -0400
     8.3 @@ -50,10 +50,13 @@
     8.4  
     8.5  /* Pointers (Mice, Touch, etc.) */
     8.6  extern void WINRT_ProcessMouseMovedEvent(SDL_Window * window, Windows::Devices::Input::MouseEventArgs ^args);
     8.7 -extern void WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args);
     8.8 -extern void WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args);
     8.9 -extern void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args);
    8.10 -extern void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args);
    8.11 +extern void WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
    8.12 +extern void WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
    8.13 +extern void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
    8.14 +extern void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
    8.15 +
    8.16 +/* XAML Thread Management */
    8.17 +extern void WINRT_CycleXAMLThread();
    8.18  
    8.19  #endif
    8.20  
     9.1 --- a/src/video/winrt/SDL_winrtmouse.cpp	Tue Aug 27 13:03:43 2013 -0400
     9.2 +++ b/src/video/winrt/SDL_winrtmouse.cpp	Tue Aug 27 21:21:09 2013 -0400
     9.3 @@ -110,6 +110,11 @@
     9.4  static int
     9.5  WINRT_ShowCursor(SDL_Cursor * cursor)
     9.6  {
     9.7 +    // TODO, WinRT, XAML: make WINRT_ShowCursor work when XAML support is enabled.
     9.8 +    if ( ! CoreWindow::GetForCurrentThread()) {
     9.9 +        return 0;
    9.10 +    }
    9.11 +
    9.12      if (cursor) {
    9.13          CoreCursor ^* theCursor = (CoreCursor ^*) cursor->driverdata;
    9.14          CoreWindow::GetForCurrentThread()->PointerCursor = *theCursor;
    9.15 @@ -334,25 +339,25 @@
    9.16  }
    9.17  
    9.18  void
    9.19 -WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args)
    9.20 +WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
    9.21  {
    9.22  #if LOG_POINTER_EVENTS
    9.23 -    WINRT_LogPointerEvent("pointer moved", args, TransformCursor(args->CurrentPoint->Position));
    9.24 +    WINRT_LogPointerEvent("pointer moved", args, TransformCursor(pointerPoint->Position));
    9.25  #endif
    9.26  
    9.27      if (!window || WINRT_UseRelativeMouseMode) {
    9.28          return;
    9.29      }
    9.30  
    9.31 -    Windows::Foundation::Point transformedPoint = TransformCursor(window, args->CurrentPoint->Position);
    9.32 +    Windows::Foundation::Point transformedPoint = TransformCursor(window, pointerPoint->Position);
    9.33      SDL_SendMouseMotion(window, 0, 0, (int)transformedPoint.X, (int)transformedPoint.Y);
    9.34  }
    9.35  
    9.36  void
    9.37 -WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args)
    9.38 +WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
    9.39  {
    9.40  #if LOG_POINTER_EVENTS
    9.41 -    WINRT_LogPointerEvent("wheel changed", args, TransformCursor(args->CurrentPoint->Position));
    9.42 +    WINRT_LogPointerEvent("wheel changed", args, TransformCursor(pointerPoint->Position));
    9.43  #endif
    9.44  
    9.45      if (!window) {
    9.46 @@ -360,11 +365,11 @@
    9.47      }
    9.48  
    9.49      // FIXME: This may need to accumulate deltas up to WHEEL_DELTA
    9.50 -    short motion = args->CurrentPoint->Properties->MouseWheelDelta / WHEEL_DELTA;
    9.51 +    short motion = pointerPoint->Properties->MouseWheelDelta / WHEEL_DELTA;
    9.52      SDL_SendMouseWheel(window, 0, 0, motion);
    9.53  }
    9.54  
    9.55 -void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args)
    9.56 +void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
    9.57  {
    9.58  #if LOG_POINTER_EVENTS
    9.59      WINRT_LogPointerEvent("mouse up", args, TransformCursor(args->CurrentPoint->Position));
    9.60 @@ -374,13 +379,13 @@
    9.61          return;
    9.62      }
    9.63  
    9.64 -    Uint8 button = WINRT_GetSDLButtonForPointerPoint(args->CurrentPoint);
    9.65 +    Uint8 button = WINRT_GetSDLButtonForPointerPoint(pointerPoint);
    9.66      if (button) {
    9.67          SDL_SendMouseButton(window, 0, SDL_RELEASED, button);
    9.68      }
    9.69  }
    9.70  
    9.71 -void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args)
    9.72 +void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
    9.73  {
    9.74  #if LOG_POINTER_EVENTS
    9.75      WINRT_LogPointerEvent("mouse down", args, TransformCursor(args->CurrentPoint->Position));
    9.76 @@ -390,7 +395,7 @@
    9.77          return;
    9.78      }
    9.79  
    9.80 -    Uint8 button = WINRT_GetSDLButtonForPointerPoint(args->CurrentPoint);
    9.81 +    Uint8 button = WINRT_GetSDLButtonForPointerPoint(pointerPoint);
    9.82      if (button) {
    9.83          SDL_SendMouseButton(window, 0, SDL_PRESSED, button);
    9.84      }
    10.1 --- a/src/video/winrt/SDL_winrtvideo.cpp	Tue Aug 27 13:03:43 2013 -0400
    10.2 +++ b/src/video/winrt/SDL_winrtvideo.cpp	Tue Aug 27 21:21:09 2013 -0400
    10.3 @@ -47,8 +47,11 @@
    10.4  #include "../../core/winrt/SDL_winrtapp.h"
    10.5  #include "SDL_winrtevents_c.h"
    10.6  #include "SDL_winrtmouse.h"
    10.7 +#include "SDL_main.h"
    10.8 +#include "SDL_system.h"
    10.9  
   10.10  extern SDL_WinRTApp ^ SDL_WinRTGlobalApp;
   10.11 +extern SDL_bool WINRT_XAMLWasEnabled;
   10.12  
   10.13  
   10.14  /* Initialization/Query functions */
   10.15 @@ -84,6 +87,7 @@
   10.16  SDL_VideoDevice * WINRT_GlobalSDLVideoDevice = NULL;
   10.17  
   10.18  
   10.19 +
   10.20  /* WinRT driver bootstrap functions */
   10.21  
   10.22  static int
   10.23 @@ -154,6 +158,13 @@
   10.24      SDL_DisplayMode mode;
   10.25      SDL_zero(mode);
   10.26  
   10.27 +    // Go no further if a native window cannot be accessed.  This can happen,
   10.28 +    // for example, if this function is called from certain threads, such as
   10.29 +    // the SDL/XAML thread.
   10.30 +    if (!CoreWindow::GetForCurrentThread()) {
   10.31 +        return mode;
   10.32 +    }
   10.33 +
   10.34      // Fill in most fields:
   10.35      mode.format = SDL_PIXELFORMAT_RGB888;
   10.36      mode.refresh_rate = 0;  // TODO, WinRT: see if refresh rate data is available, or relevant (for WinRT apps)
   10.37 @@ -169,11 +180,15 @@
   10.38      return mode;
   10.39  }
   10.40  
   10.41 -
   10.42 -static int
   10.43 +int
   10.44  WINRT_InitModes(_THIS)
   10.45  {
   10.46 +    // Retrieve the display mode:
   10.47      SDL_DisplayMode mode = WINRT_CalcDisplayModeUsingNativeWindow();
   10.48 +    if (mode.w == 0 || mode.h == 0) {
   10.49 +        return SDL_SetError("Unable to calculate the WinRT window/display's size");
   10.50 +    }
   10.51 +
   10.52      if (SDL_AddBasicVideoDisplay(&mode) < 0) {
   10.53          return -1;
   10.54      }
   10.55 @@ -211,7 +226,16 @@
   10.56      }
   10.57      window->driverdata = data;
   10.58      data->sdlWindow = window;
   10.59 -    data->coreWindow = CoreWindow::GetForCurrentThread();
   10.60 +
   10.61 +    /* To note, when XAML support is enabled, access to the CoreWindow will not
   10.62 +       be possible, at least not via the SDL/XAML thread.  Attempts to access it
   10.63 +       from there will throw exceptions.  As such, the SDL_WindowData's
   10.64 +       'coreWindow' field will only be set (to a non-null value) if XAML isn't
   10.65 +       enabled.
   10.66 +    */
   10.67 +    if (!WINRT_XAMLWasEnabled) {
   10.68 +        data->coreWindow = CoreWindow::GetForCurrentThread();
   10.69 +    }
   10.70  
   10.71      /* Make sure the window is considered to be positioned at {0,0},
   10.72         and is considered fullscreen, shown, and the like.