WinRT: made rendering work with orientation changes on Windows Phone
Pointer event geometry still needs to be adjusted on Windows Phone, to note.
--- a/src/core/winrt/SDL_winrtapp.cpp Wed Aug 28 12:45:43 2013 -0400
+++ b/src/core/winrt/SDL_winrtapp.cpp Wed Aug 28 15:27:01 2013 -0400
@@ -145,6 +145,77 @@
DisplayProperties::AutoRotationPreferences = (DisplayOrientations) orientationFlags;
}
+static void
+WINRT_ProcessWindowSizeChange()
+{
+ // Make the new window size be the one true fullscreen mode.
+ // This change was initially done, in part, to allow the Direct3D 11.1
+ // renderer to receive window-resize events as a device rotates.
+ // Before, rotating a device from landscape, to portrait, and then
+ // back to landscape would cause the Direct3D 11.1 swap buffer to
+ // not get resized appropriately. SDL would, on the rotation from
+ // landscape to portrait, re-resize the SDL window to it's initial
+ // size (landscape). On the subsequent rotation, SDL would drop the
+ // window-resize event as it appeared the SDL window didn't change
+ // size, and the Direct3D 11.1 renderer wouldn't resize its swap
+ // chain.
+ SDL_DisplayMode resizedDisplayMode = WINRT_CalcDisplayModeUsingNativeWindow();
+ if (resizedDisplayMode.w == 0 || resizedDisplayMode.h == 0) {
+ return;
+ }
+
+ SDL_DisplayMode oldDisplayMode;
+ SDL_zero(oldDisplayMode);
+ if (WINRT_GlobalSDLVideoDevice) {
+ oldDisplayMode = WINRT_GlobalSDLVideoDevice->displays[0].desktop_mode;
+ WINRT_GlobalSDLVideoDevice->displays[0].current_mode = resizedDisplayMode;
+ WINRT_GlobalSDLVideoDevice->displays[0].desktop_mode = resizedDisplayMode;
+ WINRT_GlobalSDLVideoDevice->displays[0].display_modes[0] = resizedDisplayMode;
+ }
+
+ if (WINRT_GlobalSDLWindow) {
+ // Send a window-resize event to the rest of SDL, and to apps:
+ SDL_SendWindowEvent(
+ WINRT_GlobalSDLWindow,
+ SDL_WINDOWEVENT_RESIZED,
+ resizedDisplayMode.w,
+ resizedDisplayMode.h);
+
+#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 = (DisplayOrientations) (unsigned int) oldDisplayMode.driverdata;
+ const DisplayOrientations newOrientation = (DisplayOrientations) (unsigned int) resizedDisplayMode.driverdata;
+
+ 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).
+ //
+ // 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 == resizedDisplayMode.w &&
+ oldDisplayMode.h == resizedDisplayMode.h)
+ {
+ SDL_SendWindowEvent(
+ WINRT_GlobalSDLWindow,
+ SDL_WINDOWEVENT_SIZE_CHANGED,
+ resizedDisplayMode.w,
+ resizedDisplayMode.h);
+ }
+ }
+#endif
+ }
+}
+
SDL_WinRTApp::SDL_WinRTApp() :
m_windowClosed(false),
m_windowVisible(true)
@@ -194,6 +265,13 @@
(int)DisplayProperties::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)
@@ -294,32 +372,7 @@
(WINRT_GlobalSDLWindow ? "yes" : "no"));
#endif
- if (WINRT_GlobalSDLWindow) {
- // Make the new window size be the one true fullscreen mode.
- // This change was initially done, in part, to allow the Direct3D 11.1
- // renderer to receive window-resize events as a device rotates.
- // Before, rotating a device from landscape, to portrait, and then
- // back to landscape would cause the Direct3D 11.1 swap buffer to
- // not get resized appropriately. SDL would, on the rotation from
- // landscape to portrait, re-resize the SDL window to it's initial
- // size (landscape). On the subsequent rotation, SDL would drop the
- // window-resize event as it appeared the SDL window didn't change
- // size, and the Direct3D 11.1 renderer wouldn't resize its swap
- // chain.
- SDL_DisplayMode resizedDisplayMode = WINRT_CalcDisplayModeUsingNativeWindow();
- WINRT_GlobalSDLVideoDevice->displays[0].current_mode = resizedDisplayMode;
- WINRT_GlobalSDLVideoDevice->displays[0].desktop_mode = resizedDisplayMode;
- WINRT_GlobalSDLVideoDevice->displays[0].display_modes[0] = resizedDisplayMode;
-
- // Send the window-resize event to the rest of SDL, and to apps:
- const int windowWidth = (int) ceil(args->Size.Width);
- const int windowHeight = (int) ceil(args->Size.Height);
- SDL_SendWindowEvent(
- WINRT_GlobalSDLWindow,
- SDL_WINDOWEVENT_RESIZED,
- windowWidth,
- windowHeight);
- }
+ WINRT_ProcessWindowSizeChange();
}
void SDL_WinRTApp::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args)
--- a/src/render/direct3d11/SDL_render_d3d11.cpp Wed Aug 28 12:45:43 2013 -0400
+++ b/src/render/direct3d11/SDL_render_d3d11.cpp Wed Aug 28 15:27:01 2013 -0400
@@ -920,7 +920,7 @@
{
//D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
- if (event->event == SDL_WINDOWEVENT_RESIZED) {
+ if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) {
D3D11_UpdateForWindowSizeChange(renderer);
}
}
@@ -1215,16 +1215,16 @@
// Windows Phone rotations
//
case DisplayOrientations::Landscape:
- // 90-degree Z-rotation
- XMStoreFloat4x4(&data->vertexShaderConstantsData.projection, XMMatrixRotationZ(XM_PIDIV2));
+ // 270-degree (-90 degree) Z-rotation
+ XMStoreFloat4x4(&data->vertexShaderConstantsData.projection, XMMatrixRotationZ(-XM_PIDIV2));
break;
case DisplayOrientations::Portrait:
// 0-degree Z-rotation
XMStoreFloat4x4(&data->vertexShaderConstantsData.projection, XMMatrixIdentity());
break;
case DisplayOrientations::LandscapeFlipped:
- // 270-degree (-90 degree) Z-rotation
- XMStoreFloat4x4(&data->vertexShaderConstantsData.projection, XMMatrixRotationZ(-XM_PIDIV2));
+ // 90-degree Z-rotation
+ XMStoreFloat4x4(&data->vertexShaderConstantsData.projection, XMMatrixRotationZ(XM_PIDIV2));
break;
case DisplayOrientations::PortraitFlipped:
// 180-degree Z-rotation
@@ -1280,11 +1280,15 @@
//
// Update the Direct3D viewport, which seems to be aligned to the
- // swap buffer's coordinate space, which is always in landscape:
+ // swap buffer's coordinate space, which is always in either
+ // a landscape mode, for all Windows 8/RT devices, or a portrait mode,
+ // for Windows Phone devices.
//
SDL_FRect orientationAlignedViewport;
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
- const bool swapDimensions = false;
+ const bool swapDimensions =
+ data->orientation == DisplayOrientations::Landscape ||
+ data->orientation == DisplayOrientations::LandscapeFlipped;
#else
const bool swapDimensions =
data->orientation == DisplayOrientations::Portrait ||
--- a/src/video/winrt/SDL_winrtvideo.cpp Wed Aug 28 12:45:43 2013 -0400
+++ b/src/video/winrt/SDL_winrtvideo.cpp Wed Aug 28 15:27:01 2013 -0400
@@ -154,6 +154,8 @@
SDL_DisplayMode
WINRT_CalcDisplayModeUsingNativeWindow()
{
+ using namespace Windows::Graphics::Display;
+
// Create an empty, zeroed-out display mode:
SDL_DisplayMode mode;
SDL_zero(mode);
@@ -168,7 +170,7 @@
// Fill in most fields:
mode.format = SDL_PIXELFORMAT_RGB888;
mode.refresh_rate = 0; // TODO, WinRT: see if refresh rate data is available, or relevant (for WinRT apps)
- mode.driverdata = NULL;
+ mode.driverdata = (void *) DisplayProperties::CurrentOrientation;
// Calculate the display size given the window size, taking into account
// the current display's DPI:
@@ -177,6 +179,30 @@
mode.w = (int) ((CoreWindow::GetForCurrentThread()->Bounds.Width * currentDPI) / dipsPerInch);
mode.h = (int) ((CoreWindow::GetForCurrentThread()->Bounds.Height * currentDPI) / dipsPerInch);
+#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
+ // On Windows Phone, 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
+ // 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.
+ switch (DisplayProperties::CurrentOrientation) {
+ case DisplayOrientations::Landscape:
+ case DisplayOrientations::LandscapeFlipped:
+ {
+ const int tmp = mode.h;
+ mode.h = mode.w;
+ mode.w = tmp;
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ // Attach the mode to te
+#endif
+
return mode;
}