WinRT: bug fixes for device orientation + Direct3D 11.1 rendering
authorDavid Ludwig <dludwig@pobox.com>
Sun, 17 Feb 2013 23:23:59 -0500
changeset 84333017f87e4479
parent 8432 929e53386278
child 8434 c49d0a46f516
WinRT: bug fixes for device orientation + Direct3D 11.1 rendering
src/render/direct3d11/SDL_render_d3d11.cpp
src/video/windowsrt/SDL_WinRTApp.cpp
src/video/windowsrt/SDL_WinRTApp.h
src/video/windowsrt/SDL_winrtvideo.cpp
     1.1 --- a/src/render/direct3d11/SDL_render_d3d11.cpp	Sun Feb 17 11:09:07 2013 -0500
     1.2 +++ b/src/render/direct3d11/SDL_render_d3d11.cpp	Sun Feb 17 23:23:59 2013 -0500
     1.3 @@ -30,6 +30,8 @@
     1.4  #include "SDL_system.h"
     1.5  #include "SDL_syswm.h"
     1.6  #include "../SDL_sysrender.h"
     1.7 +#include "SDL_log.h"
     1.8 +#include "../../video/SDL_sysvideo.h"
     1.9  //#include "stdio.h"
    1.10  }
    1.11  
    1.12 @@ -561,7 +563,7 @@
    1.13      // landscape-oriented width and height. If the window is in a portrait
    1.14      // orientation, the dimensions must be reversed.
    1.15      data->orientation = DisplayProperties::CurrentOrientation;
    1.16 -    bool swapDimensions =
    1.17 +    const bool swapDimensions =
    1.18          data->orientation == DisplayOrientations::Portrait ||
    1.19          data->orientation == DisplayOrientations::PortraitFlipped;
    1.20      data->renderTargetSize.x = swapDimensions ? windowHeight : windowWidth;
    1.21 @@ -930,9 +932,9 @@
    1.22              break;
    1.23  
    1.24          case DisplayOrientations::Portrait:
    1.25 -            data->vertexShaderConstantsData.projection = XMFLOAT4X4( // 270-degree Z-rotation
    1.26 -                0.0f, -1.0f, 0.0f, 0.0f,
    1.27 -                1.0f, 0.0f, 0.0f, 0.0f,
    1.28 +            data->vertexShaderConstantsData.projection = XMFLOAT4X4( // 90-degree Z-rotation
    1.29 +                0.0f, 1.0f, 0.0f, 0.0f,
    1.30 +                -1.0f, 0.0f, 0.0f, 0.0f,
    1.31                  0.0f, 0.0f, 1.0f, 0.0f,
    1.32                  0.0f, 0.0f, 0.0f, 1.0f
    1.33                  );
    1.34 @@ -948,9 +950,9 @@
    1.35              break;
    1.36  
    1.37          case DisplayOrientations::PortraitFlipped:
    1.38 -            data->vertexShaderConstantsData.projection = XMFLOAT4X4( // 90-degree Z-rotation
    1.39 -                0.0f, 1.0f, 0.0f, 0.0f,
    1.40 -                -1.0f, 0.0f, 0.0f, 0.0f,
    1.41 +            data->vertexShaderConstantsData.projection = XMFLOAT4X4( // 270-degree Z-rotation
    1.42 +                0.0f, -1.0f, 0.0f, 0.0f,
    1.43 +                1.0f, 0.0f, 0.0f, 0.0f,
    1.44                  0.0f, 0.0f, 1.0f, 0.0f,
    1.45                  0.0f, 0.0f, 0.0f, 1.0f
    1.46                  );
    1.47 @@ -964,26 +966,58 @@
    1.48      //
    1.49      // Update the view matrix
    1.50      //
    1.51 -    float windowWidth = (float) renderer->viewport.w;
    1.52 -    float windowHeight = (float) renderer->viewport.h;
    1.53 -    XMStoreFloat4x4(&data->vertexShaderConstantsData.view,  // (4)
    1.54 +    float viewportWidth = (float) renderer->viewport.w;
    1.55 +    float viewportHeight = (float) renderer->viewport.h;
    1.56 +    XMStoreFloat4x4(&data->vertexShaderConstantsData.view,
    1.57          XMMatrixMultiply(
    1.58 -            XMMatrixScaling(2.0f / windowWidth, 2.0f / windowHeight, 1.0f),
    1.59 +            XMMatrixScaling(2.0f / viewportWidth, 2.0f / viewportHeight, 1.0f),
    1.60              XMMatrixMultiply(
    1.61                  XMMatrixTranslation(-1, -1, 0),
    1.62                  XMMatrixRotationX(XM_PI)
    1.63                  )));
    1.64 +
    1.65 +    //
    1.66 +    // Update the Direct3D viewport, which seems to be aligned to the
    1.67 +    // swap buffer's coordinate space, which is always in landscape:
    1.68 +    //
    1.69 +    SDL_FRect orientationAlignedViewport;
    1.70 +    const bool swapDimensions =
    1.71 +        data->orientation == DisplayOrientations::Portrait ||
    1.72 +        data->orientation == DisplayOrientations::PortraitFlipped;
    1.73 +    if (swapDimensions) {
    1.74 +        orientationAlignedViewport.x = (float) renderer->viewport.y;
    1.75 +        orientationAlignedViewport.y = (float) renderer->viewport.x;
    1.76 +        orientationAlignedViewport.w = (float) renderer->viewport.h;
    1.77 +        orientationAlignedViewport.h = (float) renderer->viewport.w;
    1.78 +    } else {
    1.79 +        orientationAlignedViewport.x = (float) renderer->viewport.x;
    1.80 +        orientationAlignedViewport.y = (float) renderer->viewport.y;
    1.81 +        orientationAlignedViewport.w = (float) renderer->viewport.w;
    1.82 +        orientationAlignedViewport.h = (float) renderer->viewport.h;
    1.83 +    }
    1.84 +    // WinRT, TODO: get custom viewports working with non-Landscape modes (Portrait, PortraitFlipped, and LandscapeFlipped)
    1.85  
    1.86      D3D11_VIEWPORT viewport;
    1.87      memset(&viewport, 0, sizeof(viewport));
    1.88 -    viewport.TopLeftX = (float) renderer->viewport.x;
    1.89 -    viewport.TopLeftY = (float) renderer->viewport.y;
    1.90 -    viewport.Width = (float) renderer->viewport.w;
    1.91 -    viewport.Height = (float) renderer->viewport.h;
    1.92 +    viewport.TopLeftX = orientationAlignedViewport.x;
    1.93 +    viewport.TopLeftY = orientationAlignedViewport.y;
    1.94 +    viewport.Width = orientationAlignedViewport.w;
    1.95 +    viewport.Height = orientationAlignedViewport.h;
    1.96      viewport.MinDepth = 0.0f;
    1.97      viewport.MaxDepth = 1.0f;
    1.98      data->d3dContext->RSSetViewports(1, &viewport);
    1.99  
   1.100 +#if 0
   1.101 +    SDL_Log("%s, oav={%.0f,%.0f,%.0f,%.0f}, rend={%.0f,%.0f}\n",
   1.102 +        __FUNCTION__,
   1.103 +        orientationAlignedViewport.x,
   1.104 +        orientationAlignedViewport.y,
   1.105 +        orientationAlignedViewport.w,
   1.106 +        orientationAlignedViewport.h,
   1.107 +        data->renderTargetSize.x,
   1.108 +        data->renderTargetSize.y);
   1.109 +#endif
   1.110 +
   1.111      return 0;
   1.112  }
   1.113  
   1.114 @@ -1116,9 +1150,33 @@
   1.115      b = (float)(renderer->b / 255.0f);
   1.116      a = (float)(renderer->a / 255.0f);
   1.117  
   1.118 -    D3D11_RenderStartDrawOp(renderer);
   1.119 +#if 0
   1.120 +    // Set up a test pattern:
   1.121 +    SDL_FRect rects[] = {
   1.122 +        {-1.1f, 1.1f, 1.1f, -1.1f},
   1.123 +        {-1.0f, 1.0f, 1.0f, -1.0f},     // red
   1.124 +        {0.0f, 1.0f, 1.0f, -1.0f},      // green
   1.125 +        {-1.0f, 0.0f, 1.0f, -1.0f},     // blue
   1.126 +        {0.0f, 0.0f, 1.0f, -1.0f}       // white
   1.127 +    };
   1.128 +    count = sizeof(rects) / sizeof(SDL_FRect);
   1.129 +#endif
   1.130  
   1.131      for (int i = 0; i < count; ++i) {
   1.132 +        D3D11_RenderStartDrawOp(renderer);
   1.133 +
   1.134 +#if 0
   1.135 +        // Set colors for the test pattern:
   1.136 +        a = 1.0f;
   1.137 +        switch (i) {
   1.138 +            case 0: r = 1.0f; g = 1.0f; b = 0.0f; break;
   1.139 +            case 1: r = 1.0f; g = 0.0f; b = 0.0f; break;
   1.140 +            case 2: r = 0.0f; g = 1.0f; b = 0.0f; break;
   1.141 +            case 3: r = 0.0f; g = 0.0f; b = 1.0f; break;
   1.142 +            case 4: r = 1.0f; g = 1.0f; b = 1.0f; break;
   1.143 +        }
   1.144 +#endif
   1.145 +
   1.146          VertexPositionColor vertices[] = {
   1.147              {XMFLOAT3(rects[i].x, rects[i].y, 0.0f),                           XMFLOAT2(0.0f, 0.0f), XMFLOAT4(r, g, b, a)},
   1.148              {XMFLOAT3(rects[i].x, rects[i].y + rects[i].h, 0.0f),              XMFLOAT2(0.0f, 0.0f), XMFLOAT4(r, g, b, a)},
     2.1 --- a/src/video/windowsrt/SDL_WinRTApp.cpp	Sun Feb 17 11:09:07 2013 -0500
     2.2 +++ b/src/video/windowsrt/SDL_WinRTApp.cpp	Sun Feb 17 23:23:59 2013 -0500
     2.3 @@ -51,6 +51,7 @@
     2.4      m_windowClosed(false),
     2.5      m_windowVisible(true),
     2.6      m_sdlWindowData(NULL),
     2.7 +    m_sdlVideoDevice(NULL),
     2.8      m_useRelativeMouseMode(false)
     2.9  {
    2.10  }
    2.11 @@ -146,11 +147,35 @@
    2.12  
    2.13  void SDL_WinRTApp::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args)
    2.14  {
    2.15 -    SDL_SendWindowEvent(
    2.16 -        m_sdlWindowData->sdlWindow,
    2.17 -        SDL_WINDOWEVENT_RESIZED,
    2.18 -        (int) ceil(args->Size.Width),
    2.19 -        (int) ceil(args->Size.Height));
    2.20 +#if 0
    2.21 +    SDL_Log("%s, {%f,%f}\n", __FUNCTION__, args->Size.Width, args->Size.Height);
    2.22 +#endif
    2.23 +
    2.24 +    if (m_sdlWindowData) {
    2.25 +        // Make the new window size be the one true fullscreen mode.
    2.26 +        // This change was done, in part, to allow the Direct3D 11.1 renderer
    2.27 +        // to receive window-resize events as a device rotates.
    2.28 +        // Before, rotating a device from landscape, to portrait, and then
    2.29 +        // back to landscape would cause the Direct3D 11.1 swap buffer to
    2.30 +        // not get resized appropriately.  SDL would, on the rotation from
    2.31 +        // landscape to portrait, re-resize the SDL window to it's initial
    2.32 +        // size (landscape).  On the subsequent rotation, SDL would drop the
    2.33 +        // window-resize event as it appeared the SDL window didn't change
    2.34 +        // size, and the Direct3D 11.1 renderer wouldn't resize its swap
    2.35 +        // chain.
    2.36 +        //
    2.37 +        // TODO, WinRT: consider dropping old display modes after the fullscreen window changes size (from rotations, etc.)
    2.38 +        m_sdlWindowData->sdlWindow->fullscreen_mode = SDL_WinRTGlobalApp->GetMainDisplayMode();
    2.39 +        SDL_AddDisplayMode(&m_sdlVideoDevice->displays[0], &m_sdlWindowData->sdlWindow->fullscreen_mode);
    2.40 +
    2.41 +        const int windowWidth = (int) ceil(args->Size.Width);
    2.42 +        const int windowHeight = (int) ceil(args->Size.Height);
    2.43 +        SDL_SendWindowEvent(
    2.44 +            m_sdlWindowData->sdlWindow,
    2.45 +            SDL_WINDOWEVENT_RESIZED,
    2.46 +            windowWidth,
    2.47 +            windowHeight);
    2.48 +    }
    2.49  }
    2.50  
    2.51  void SDL_WinRTApp::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args)
    2.52 @@ -739,11 +764,16 @@
    2.53      m_useRelativeMouseMode = enable;
    2.54  }
    2.55  
    2.56 -void SDL_WinRTApp::SetSDLWindowData(const SDL_WindowData* windowData)
    2.57 +void SDL_WinRTApp::SetSDLWindowData(const SDL_WindowData * windowData)
    2.58  {
    2.59      m_sdlWindowData = windowData;
    2.60  }
    2.61  
    2.62 +void SDL_WinRTApp::SetSDLVideoDevice(const SDL_VideoDevice * videoDevice)
    2.63 +{
    2.64 +    m_sdlVideoDevice = videoDevice;
    2.65 +}
    2.66 +
    2.67  IFrameworkView^ Direct3DApplicationSource::CreateView()
    2.68  {
    2.69      // TODO, WinRT: see if this function (CreateView) can ever get called
     3.1 --- a/src/video/windowsrt/SDL_WinRTApp.h	Sun Feb 17 11:09:07 2013 -0500
     3.2 +++ b/src/video/windowsrt/SDL_WinRTApp.h	Sun Feb 17 23:23:59 2013 -0500
     3.3 @@ -26,6 +26,7 @@
     3.4      bool HasSDLWindowData() const;
     3.5      void SetRelativeMouseMode(bool enable);
     3.6      void SetSDLWindowData(const SDL_WindowData * windowData);
     3.7 +    void SetSDLVideoDevice(const SDL_VideoDevice * videoDevice);
     3.8      Windows::Foundation::Point TransformCursor(Windows::Foundation::Point rawPosition);
     3.9  
    3.10  protected:
    3.11 @@ -49,6 +50,7 @@
    3.12      bool m_windowClosed;
    3.13      bool m_windowVisible;
    3.14      const SDL_WindowData* m_sdlWindowData;
    3.15 +    const SDL_VideoDevice* m_sdlVideoDevice;
    3.16      bool m_useRelativeMouseMode;
    3.17  };
    3.18  
     4.1 --- a/src/video/windowsrt/SDL_winrtvideo.cpp	Sun Feb 17 11:09:07 2013 -0500
     4.2 +++ b/src/video/windowsrt/SDL_winrtvideo.cpp	Sun Feb 17 23:23:59 2013 -0500
     4.3 @@ -74,6 +74,7 @@
     4.4  static void
     4.5  WINRT_DeleteDevice(SDL_VideoDevice * device)
     4.6  {
     4.7 +    SDL_WinRTGlobalApp->SetSDLVideoDevice(NULL);
     4.8      SDL_free(device);
     4.9  }
    4.10  
    4.11 @@ -103,8 +104,9 @@
    4.12      //device->UpdateWindowFramebuffer = SDL_WINRT_UpdateWindowFramebuffer;
    4.13      //device->DestroyWindowFramebuffer = SDL_WINRT_DestroyWindowFramebuffer;
    4.14      device->GetWindowWMInfo = WINRT_GetWindowWMInfo;
    4.15 +    device->free = WINRT_DeleteDevice;
    4.16  
    4.17 -    device->free = WINRT_DeleteDevice;
    4.18 +    SDL_WinRTGlobalApp->SetSDLVideoDevice(device);
    4.19  
    4.20      return device;
    4.21  }