Commit 0a879d63bddc6d58bbeb7bf7d377f9d36b335a01

David Ludwig 2014-05-09T20:16:21

Fixed rendering-alignment issues on WinPhone 8.1, when the device was rotated If a Windows Phone 8.1 device was rotated to anything but Portrait mode, the Direct3D 11 renderer's output wouldn't get aligned correctly with the screen.

diff --git a/src/core/winrt/SDL_winrtapp_direct3d.cpp b/src/core/winrt/SDL_winrtapp_direct3d.cpp
index 3a9f597..d17171b 100644
--- a/src/core/winrt/SDL_winrtapp_direct3d.cpp
+++ b/src/core/winrt/SDL_winrtapp_direct3d.cpp
@@ -229,36 +229,30 @@ WINRT_ProcessWindowSizeChange()
     }
 
     if (WINRT_GlobalSDLWindow) {
-        // Send a window-resize event to the rest of SDL, and to apps:
-        SDL_SendWindowEvent(
-            WINRT_GlobalSDLWindow,
-            SDL_WINDOWEVENT_RESIZED,
-            newDisplayMode.w,
-            newDisplayMode.h);
-
+        // If the window size changed, send a resize event to SDL and its host app:
+        int window_w = 0;
+        int window_h = 0;
+        SDL_GetWindowSize(WINRT_GlobalSDLWindow, &window_w, &window_h);
+        if ((window_w != newDisplayMode.w) || (window_h != newDisplayMode.h)) {
+            SDL_SendWindowEvent(
+                WINRT_GlobalSDLWindow,
+                SDL_WINDOWEVENT_RESIZED,
+                newDisplayMode.w,
+                newDisplayMode.h);
+        } else {
 #if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
-        // HACK: On Windows Phone, make sure that orientation changes from
-        // Landscape to LandscapeFlipped, Portrait to PortraitFlipped,
-        // or vice-versa on either of those two, lead to the Direct3D renderer
-        // getting updated.
-        const DisplayOrientations oldOrientation = ((SDL_DisplayModeData *)oldDisplayMode.driverdata)->currentOrientation;
-        const DisplayOrientations newOrientation = ((SDL_DisplayModeData *)newDisplayMode.driverdata)->currentOrientation;
-
-        if ((oldOrientation == DisplayOrientations::Landscape && newOrientation == DisplayOrientations::LandscapeFlipped) ||
-            (oldOrientation == DisplayOrientations::LandscapeFlipped && newOrientation == DisplayOrientations::Landscape) ||
-            (oldOrientation == DisplayOrientations::Portrait && newOrientation == DisplayOrientations::PortraitFlipped) ||
-            (oldOrientation == DisplayOrientations::PortraitFlipped && newOrientation == DisplayOrientations::Portrait))
-        {
-            // One of the reasons this event is getting sent out is because SDL
-            // will ignore requests to send out SDL_WINDOWEVENT_RESIZED events
-            // if and when the event size doesn't change (and the Direct3D 11.1
-            // renderer doesn't get the memo).
+            // HACK: Make sure that orientation changes
+            // lead to the Direct3D renderer's viewport getting updated:
             //
-            // Make sure that the display/window size really didn't change.  If
-            // it did, then a SDL_WINDOWEVENT_SIZE_CHANGED event got sent, and
-            // the Direct3D 11.1 renderer picked it up, presumably.
-            if (oldDisplayMode.w == newDisplayMode.w &&
-                oldDisplayMode.h == newDisplayMode.h)
+            // For some reason, this doesn't seem to need to be done on Windows 8.x,
+            // even when going from Landscape to LandscapeFlipped.  It only seems to
+            // be needed on Windows Phone, at least when I tested on my devices.
+            // I'm not currently sure why this is, but it seems to work fine. -- David L.
+            //
+            // TODO, WinRT: do more extensive research into why orientation changes on Win 8.x don't need D3D changes, or if they might, in some cases
+            const DisplayOrientations oldOrientation = ((SDL_DisplayModeData *)oldDisplayMode.driverdata)->currentOrientation;
+            const DisplayOrientations newOrientation = ((SDL_DisplayModeData *)newDisplayMode.driverdata)->currentOrientation;
+            if (oldOrientation != newOrientation)
             {
                 SDL_SendWindowEvent(
                     WINRT_GlobalSDLWindow,
@@ -266,8 +260,8 @@ WINRT_ProcessWindowSizeChange()
                     newDisplayMode.w,
                     newDisplayMode.h);
             }
-        }
 #endif
+        }
     }
     
     // Finally, free the 'driverdata' field of the old 'desktop_mode'.
@@ -309,26 +303,21 @@ void SDL_WinRTApp::OnOrientationChanged(Object^ sender)
     if (window) {
         SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d, CoreWindow Size={%f,%f}\n",
             __FUNCTION__,
-            (int)DisplayProperties::CurrentOrientation,
-            (int)DisplayProperties::NativeOrientation,
-            (int)DisplayProperties::AutoRotationPreferences,
+            WINRT_DISPLAY_PROPERTY(CurrentOrientation),
+            WINRT_DISPLAY_PROPERTY(NativeOrientation),
+            WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
             window->Bounds.Width,
             window->Bounds.Height);
     } else {
         SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d\n",
             __FUNCTION__,
-            (int)DisplayProperties::CurrentOrientation,
-            (int)DisplayProperties::NativeOrientation,
-            (int)DisplayProperties::AutoRotationPreferences);
+            WINRT_DISPLAY_PROPERTY(CurrentOrientation),
+            WINRT_DISPLAY_PROPERTY(NativeOrientation),
+            WINRT_DISPLAY_PROPERTY(AutoRotationPreferences));
     }
 #endif
 
-#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
-    // On Windows Phone, treat an orientation change as a change in window size.
-    // The native window's size doesn't seem to change, however SDL will simulate
-    // a window size change.
     WINRT_ProcessWindowSizeChange();
-#endif
 }
 
 void SDL_WinRTApp::SetWindow(CoreWindow^ window)
@@ -336,9 +325,9 @@ void SDL_WinRTApp::SetWindow(CoreWindow^ window)
 #if LOG_WINDOW_EVENTS==1
     SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d, window Size={%f,%f}\n",
         __FUNCTION__,
-        (int)DisplayProperties::CurrentOrientation,
-        (int)DisplayProperties::NativeOrientation,
-        (int)DisplayProperties::AutoRotationPreferences,
+        WINRT_DISPLAY_PROPERTY(CurrentOrientation),
+        WINRT_DISPLAY_PROPERTY(NativeOrientation),
+        WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
         window->Bounds.Width,
         window->Bounds.Height);
 #endif
@@ -540,9 +529,9 @@ void SDL_WinRTApp::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEven
     SDL_Log("%s, size={%f,%f}, current orientation=%d, native orientation=%d, auto rot. pref=%d, WINRT_GlobalSDLWindow?=%s\n",
         __FUNCTION__,
         args->Size.Width, args->Size.Height,
-        (int)DisplayProperties::CurrentOrientation,
-        (int)DisplayProperties::NativeOrientation,
-        (int)DisplayProperties::AutoRotationPreferences,
+        WINRT_DISPLAY_PROPERTY(CurrentOrientation),
+        WINRT_DISPLAY_PROPERTY(NativeOrientation),
+        WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
         (WINRT_GlobalSDLWindow ? "yes" : "no"));
 #endif
 
diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c
index 1e2b099..2f1164b 100644
--- a/src/render/direct3d11/SDL_render_d3d11.c
+++ b/src/render/direct3d11/SDL_render_d3d11.c
@@ -29,6 +29,7 @@
 #include "SDL_syswm.h"
 #include "../SDL_sysrender.h"
 #include "../SDL_d3dmath.h"
+/* #include "SDL_log.h" */
 
 #include <d3d11_1.h>
 
@@ -1390,6 +1391,7 @@ D3D11_CreateSwapChain(SDL_Renderer * renderer, int w, int h)
 #if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
     swapChainDesc.Scaling = DXGI_SCALING_STRETCH; /* On phone, only stretch and aspect-ratio stretch scaling are allowed. */
     swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; /* On phone, no swap effects are supported. */
+    /* TODO, WinRT: see if Win 8.x DXGI_SWAP_CHAIN_DESC1 settings are available on Windows Phone 8.1, and if there's any advantage to having them on */
 #else
     if (usingXAML) {
         swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
@@ -1484,6 +1486,7 @@ D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
      */
     SDL_GetWindowSize(renderer->window, &w, &h);
     data->rotation = D3D11_GetCurrentRotation();
+    /* SDL_Log("%s: windowSize={%d,%d}, orientation=%d\n", __FUNCTION__, w, h, (int)data->rotation); */
     if (D3D11_IsDisplayRotated90Degrees(data->rotation)) {
         int tmp = w;
         w = h;
@@ -1521,11 +1524,21 @@ D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
     }
     
 #if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
-    /* Set the proper rotation for the swap chain, and generate the
-     * 3D matrix transformation for rendering to the rotated swap chain.
+    /* Set the proper rotation for the swap chain.
      *
      * To note, the call for this, IDXGISwapChain1::SetRotation, is not necessary
-     * on Windows Phone, nor is it supported there.  It's only needed in Windows 8/RT.
+     * on Windows Phone 8.0, nor is it supported there.
+     *
+     * IDXGISwapChain1::SetRotation does seem to be available on Windows Phone 8.1,
+     * however I've yet to find a way to make it work.  It might have something to
+     * do with IDXGISwapChain::ResizeBuffers appearing to not being available on
+     * Windows Phone 8.1 (it wasn't on Windows Phone 8.0), but I'm not 100% sure of this.
+     * The call doesn't appear to be entirely necessary though, and is a performance-related
+     * call, at least according to the following page on MSDN:
+     * http://code.msdn.microsoft.com/windowsapps/DXGI-swap-chain-rotation-21d13d71
+     *   -- David L.
+     *
+     * TODO, WinRT: reexamine the docs for IDXGISwapChain1::SetRotation, see if might be available, usable, and prudent-to-call on WinPhone 8.1
      */
     if (data->swapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL) {
         result = IDXGISwapChain1_SetRotation(data->swapChain, data->rotation);
@@ -2144,6 +2157,7 @@ D3D11_UpdateViewport(SDL_Renderer * renderer)
          * SDL_CreateRenderer is calling it, and will call it again later
          * with a non-empty viewport.
          */
+        /* SDL_Log("%s, no viewport was set!\n", __FUNCTION__); */
         return 0;
     }
 
@@ -2223,6 +2237,7 @@ D3D11_UpdateViewport(SDL_Renderer * renderer)
     viewport.Height = orientationAlignedViewport.h;
     viewport.MinDepth = 0.0f;
     viewport.MaxDepth = 1.0f;
+    /* SDL_Log("%s: D3D viewport = {%f,%f,%f,%f}\n", __FUNCTION__, viewport.TopLeftX, viewport.TopLeftY, viewport.Width, viewport.Height); */
     ID3D11DeviceContext_RSSetViewports(data->d3dContext, 1, &viewport);
 
     return 0;
diff --git a/src/video/winrt/SDL_winrtvideo.cpp b/src/video/winrt/SDL_winrtvideo.cpp
index 6c6fce0..0443b99 100644
--- a/src/video/winrt/SDL_winrtvideo.cpp
+++ b/src/video/winrt/SDL_winrtvideo.cpp
@@ -53,6 +53,7 @@ extern "C" {
 #include "SDL_winrtmouse_c.h"
 #include "SDL_main.h"
 #include "SDL_system.h"
+//#include "SDL_log.h"
 
 
 /* Initialization/Query functions */
@@ -174,6 +175,14 @@ WINRT_CalcDisplayModeUsingNativeWindow(SDL_DisplayMode * mode)
         return SDL_SetError("SDL/WinRT display modes cannot be calculated outside of the main thread, such as in SDL's XAML thread");
     }
 
+    //SDL_Log("%s, size={%f,%f}, current orientation=%d, native orientation=%d, auto rot. pref=%d, DPI = %f\n",
+    //    __FUNCTION__,
+    //    CoreWindow::GetForCurrentThread()->Bounds.Width, CoreWindow::GetForCurrentThread()->Bounds.Height,
+    //    WINRT_DISPLAY_PROPERTY(CurrentOrientation),
+    //    WINRT_DISPLAY_PROPERTY(NativeOrientation),
+    //    WINRT_DISPLAY_PROPERTY(AutoRotationPreferences),
+    //    WINRT_DISPLAY_PROPERTY(LogicalDpi));
+
     // Calculate the display size given the window size, taking into account
     // the current display's DPI:
 #if NTDDI_VERSION > NTDDI_WIN8
@@ -208,10 +217,10 @@ WINRT_CalcDisplayModeUsingNativeWindow(SDL_DisplayMode * mode)
     driverdata->currentOrientation = DisplayProperties::CurrentOrientation;
 #endif
 
-#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
-    // On Windows Phone, the native window's size is always in portrait,
+#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) && (NTDDI_VERSION == NTDDI_WIN8)
+    // On Windows Phone 8.0, the native window's size is always in portrait,
     // regardless of the device's orientation.  This is in contrast to
-    // Windows 8/RT, which will resize the native window as the device's
+    // Windows 8.x/RT and Windows Phone 8.1, which will resize the native window as the device's
     // orientation changes.  In order to compensate for this behavior,
     // on Windows Phone, the mode's width and height will be swapped when
     // the device is in a landscape (non-portrait) mode.
diff --git a/src/video/winrt/SDL_winrtvideo_cpp.h b/src/video/winrt/SDL_winrtvideo_cpp.h
index a90f043..e327280 100644
--- a/src/video/winrt/SDL_winrtvideo_cpp.h
+++ b/src/video/winrt/SDL_winrtvideo_cpp.h
@@ -70,6 +70,13 @@ typedef struct
 
 #ifdef __cplusplus_winrt
 
+/* A convenience macro to get a WinRT display property */
+#if NTDDI_VERSION > NTDDI_WIN8
+#define WINRT_DISPLAY_PROPERTY(NAME) (Windows::Graphics::Display::DisplayInformation::GetForCurrentView()->NAME)
+#else
+#define WINRT_DISPLAY_PROPERTY(NAME) (Windows::Graphics::Display::DisplayProperties::NAME)
+#endif
+
 /* Internal window data */
 struct SDL_WindowData
 {