diff --git a/VisualC/SDL/SDL_VS2012_WinRT.vcxproj b/VisualC/SDL/SDL_VS2012_WinRT.vcxproj
index 7d6deb876..3db48e32d 100644
--- a/VisualC/SDL/SDL_VS2012_WinRT.vcxproj
+++ b/VisualC/SDL/SDL_VS2012_WinRT.vcxproj
@@ -117,14 +117,6 @@
-
- true
- true
- true
- true
- true
- true
-
true
true
@@ -270,7 +262,6 @@
-
diff --git a/src/video/windowsrt/Direct3DBase.cpp b/src/video/windowsrt/Direct3DBase.cpp
deleted file mode 100644
index bb0ea593d..000000000
--- a/src/video/windowsrt/Direct3DBase.cpp
+++ /dev/null
@@ -1,344 +0,0 @@
-#include "SDLmain_WinRT_common.h"
-#include "Direct3DBase.h"
-
-using namespace DirectX;
-using namespace Microsoft::WRL;
-using namespace Windows::UI::Core;
-using namespace Windows::Foundation;
-using namespace Windows::Graphics::Display;
-
-// Constructor.
-Direct3DBase::Direct3DBase()
-{
-}
-
-// Initialize the Direct3D resources required to run.
-void Direct3DBase::Initialize(CoreWindow^ window)
-{
- m_window = window;
-
- CreateDeviceResources();
- CreateWindowSizeDependentResources();
-}
-
-// Recreate all device resources and set them back to the current state.
-void Direct3DBase::HandleDeviceLost()
-{
- // Reset these member variables to ensure that UpdateForWindowSizeChange recreates all resources.
- m_windowBounds.Width = 0;
- m_windowBounds.Height = 0;
- m_swapChain = nullptr;
-
- CreateDeviceResources();
- UpdateForWindowSizeChange();
-}
-
-// These are the resources that depend on the device.
-void Direct3DBase::CreateDeviceResources()
-{
- // This flag adds support for surfaces with a different color channel ordering
- // than the API default. It is required for compatibility with Direct2D.
- UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
-
-#if defined(_DEBUG)
- // If the project is in a debug build, enable debugging via SDK Layers with this flag.
- creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
-#endif
-
- // This array defines the set of DirectX hardware feature levels this app will support.
- // Note the ordering should be preserved.
- // Don't forget to declare your application's minimum required feature level in its
- // description. All applications are assumed to support 9.1 unless otherwise stated.
- D3D_FEATURE_LEVEL featureLevels[] =
- {
- D3D_FEATURE_LEVEL_11_1,
- D3D_FEATURE_LEVEL_11_0,
- D3D_FEATURE_LEVEL_10_1,
- D3D_FEATURE_LEVEL_10_0,
- D3D_FEATURE_LEVEL_9_3,
- D3D_FEATURE_LEVEL_9_2,
- D3D_FEATURE_LEVEL_9_1
- };
-
- // Create the Direct3D 11 API device object and a corresponding context.
- ComPtr device;
- ComPtr context;
- DX::ThrowIfFailed(
- D3D11CreateDevice(
- nullptr, // Specify nullptr to use the default adapter.
- D3D_DRIVER_TYPE_HARDWARE,
- nullptr,
- creationFlags, // Set set debug and Direct2D compatibility flags.
- featureLevels, // List of feature levels this app can support.
- ARRAYSIZE(featureLevels),
- D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps.
- &device, // Returns the Direct3D device created.
- &m_featureLevel, // Returns feature level of device created.
- &context // Returns the device immediate context.
- )
- );
-
- // Get the Direct3D 11.1 API device and context interfaces.
- DX::ThrowIfFailed(
- device.As(&m_d3dDevice)
- );
-
- DX::ThrowIfFailed(
- context.As(&m_d3dContext)
- );
-}
-
-// Allocate all memory resources that change on a window SizeChanged event.
-void Direct3DBase::CreateWindowSizeDependentResources()
-{
- // Store the window bounds so the next time we get a SizeChanged event we can
- // avoid rebuilding everything if the size is identical.
- m_windowBounds = m_window->Bounds;
-
- // Calculate the necessary swap chain and render target size in pixels.
- float windowWidth = ConvertDipsToPixels(m_windowBounds.Width);
- float windowHeight = ConvertDipsToPixels(m_windowBounds.Height);
-
- // The width and height of the swap chain must be based on the window's
- // landscape-oriented width and height. If the window is in a portrait
- // orientation, the dimensions must be reversed.
- m_orientation = DisplayProperties::CurrentOrientation;
- bool swapDimensions =
- m_orientation == DisplayOrientations::Portrait ||
- m_orientation == DisplayOrientations::PortraitFlipped;
- m_renderTargetSize.Width = swapDimensions ? windowHeight : windowWidth;
- m_renderTargetSize.Height = swapDimensions ? windowWidth : windowHeight;
-
- if(m_swapChain != nullptr)
- {
- // If the swap chain already exists, resize it.
- DX::ThrowIfFailed(
- m_swapChain->ResizeBuffers(
- 2, // Double-buffered swap chain.
- static_cast(m_renderTargetSize.Width),
- static_cast(m_renderTargetSize.Height),
- DXGI_FORMAT_B8G8R8A8_UNORM,
- 0
- )
- );
- }
- else
- {
- // Otherwise, create a new one using the same adapter as the existing Direct3D device.
- DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
- swapChainDesc.Width = static_cast(m_renderTargetSize.Width); // Match the size of the window.
- swapChainDesc.Height = static_cast(m_renderTargetSize.Height);
- swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // This is the most common swap chain format.
- swapChainDesc.Stereo = false;
- swapChainDesc.SampleDesc.Count = 1; // Don't use multi-sampling.
- swapChainDesc.SampleDesc.Quality = 0;
- swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
- swapChainDesc.BufferCount = 2; // Use double-buffering to minimize latency.
- swapChainDesc.Scaling = DXGI_SCALING_NONE;
- swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // All Windows Store apps must use this SwapEffect.
- swapChainDesc.Flags = 0;
-
- ComPtr dxgiDevice;
- DX::ThrowIfFailed(
- m_d3dDevice.As(&dxgiDevice)
- );
-
- ComPtr dxgiAdapter;
- DX::ThrowIfFailed(
- dxgiDevice->GetAdapter(&dxgiAdapter)
- );
-
- ComPtr dxgiFactory;
- DX::ThrowIfFailed(
- dxgiAdapter->GetParent(
- __uuidof(IDXGIFactory2),
- &dxgiFactory
- )
- );
-
- Windows::UI::Core::CoreWindow^ window = m_window.Get();
- DX::ThrowIfFailed(
- dxgiFactory->CreateSwapChainForCoreWindow(
- m_d3dDevice.Get(),
- reinterpret_cast(window),
- &swapChainDesc,
- nullptr, // Allow on all displays.
- &m_swapChain
- )
- );
-
- // Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and
- // ensures that the application will only render after each VSync, minimizing power consumption.
- DX::ThrowIfFailed(
- dxgiDevice->SetMaximumFrameLatency(1)
- );
- }
-
- // Set the proper orientation for the swap chain, and generate the
- // 3D matrix transformation for rendering to the rotated swap chain.
- DXGI_MODE_ROTATION rotation = DXGI_MODE_ROTATION_UNSPECIFIED;
- switch (m_orientation)
- {
- case DisplayOrientations::Landscape:
- rotation = DXGI_MODE_ROTATION_IDENTITY;
- m_orientationTransform3D = XMFLOAT4X4( // 0-degree Z-rotation
- 1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 1.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 1.0f
- );
- break;
-
- case DisplayOrientations::Portrait:
- rotation = DXGI_MODE_ROTATION_ROTATE270;
- m_orientationTransform3D = XMFLOAT4X4( // 90-degree Z-rotation
- 0.0f, 1.0f, 0.0f, 0.0f,
- -1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 1.0f
- );
- break;
-
- case DisplayOrientations::LandscapeFlipped:
- rotation = DXGI_MODE_ROTATION_ROTATE180;
- m_orientationTransform3D = XMFLOAT4X4( // 180-degree Z-rotation
- -1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, -1.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 1.0f
- );
- break;
-
- case DisplayOrientations::PortraitFlipped:
- rotation = DXGI_MODE_ROTATION_ROTATE90;
- m_orientationTransform3D = XMFLOAT4X4( // 270-degree Z-rotation
- 0.0f, -1.0f, 0.0f, 0.0f,
- 1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 1.0f
- );
- break;
-
- default:
- throw ref new Platform::FailureException();
- }
-
- DX::ThrowIfFailed(
- m_swapChain->SetRotation(rotation)
- );
-
- // Create a render target view of the swap chain back buffer.
- ComPtr backBuffer;
- DX::ThrowIfFailed(
- m_swapChain->GetBuffer(
- 0,
- __uuidof(ID3D11Texture2D),
- &backBuffer
- )
- );
-
- DX::ThrowIfFailed(
- m_d3dDevice->CreateRenderTargetView(
- backBuffer.Get(),
- nullptr,
- &m_renderTargetView
- )
- );
-
- // Create a depth stencil view.
- CD3D11_TEXTURE2D_DESC depthStencilDesc(
- DXGI_FORMAT_D24_UNORM_S8_UINT,
- static_cast(m_renderTargetSize.Width),
- static_cast(m_renderTargetSize.Height),
- 1,
- 1,
- D3D11_BIND_DEPTH_STENCIL
- );
-
- ComPtr depthStencil;
- DX::ThrowIfFailed(
- m_d3dDevice->CreateTexture2D(
- &depthStencilDesc,
- nullptr,
- &depthStencil
- )
- );
-
- CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D);
- DX::ThrowIfFailed(
- m_d3dDevice->CreateDepthStencilView(
- depthStencil.Get(),
- &depthStencilViewDesc,
- &m_depthStencilView
- )
- );
-
- // Set the rendering viewport to target the entire window.
- CD3D11_VIEWPORT viewport(
- 0.0f,
- 0.0f,
- m_renderTargetSize.Width,
- m_renderTargetSize.Height
- );
-
- m_d3dContext->RSSetViewports(1, &viewport);
-}
-
-// This method is called in the event handler for the SizeChanged event.
-void Direct3DBase::UpdateForWindowSizeChange()
-{
- if (m_window->Bounds.Width != m_windowBounds.Width ||
- m_window->Bounds.Height != m_windowBounds.Height ||
- m_orientation != DisplayProperties::CurrentOrientation)
- {
- ID3D11RenderTargetView* nullViews[] = {nullptr};
- m_d3dContext->OMSetRenderTargets(ARRAYSIZE(nullViews), nullViews, nullptr);
- m_renderTargetView = nullptr;
- m_depthStencilView = nullptr;
- m_d3dContext->Flush();
- CreateWindowSizeDependentResources();
- }
-}
-
-// Method to deliver the final image to the display.
-void Direct3DBase::Present()
-{
- // The application may optionally specify "dirty" or "scroll"
- // rects to improve efficiency in certain scenarios.
- DXGI_PRESENT_PARAMETERS parameters = {0};
- parameters.DirtyRectsCount = 0;
- parameters.pDirtyRects = nullptr;
- parameters.pScrollRect = nullptr;
- parameters.pScrollOffset = nullptr;
-
- // The first argument instructs DXGI to block until VSync, putting the application
- // to sleep until the next VSync. This ensures we don't waste any cycles rendering
- // frames that will never be displayed to the screen.
- HRESULT hr = m_swapChain->Present1(1, 0, ¶meters);
-
- // Discard the contents of the render target.
- // This is a valid operation only when the existing contents will be entirely
- // overwritten. If dirty or scroll rects are used, this call should be removed.
- m_d3dContext->DiscardView(m_renderTargetView.Get());
-
- // Discard the contents of the depth stencil.
- m_d3dContext->DiscardView(m_depthStencilView.Get());
-
- // If the device was removed either by a disconnect or a driver upgrade, we
- // must recreate all device resources.
- if (hr == DXGI_ERROR_DEVICE_REMOVED)
- {
- HandleDeviceLost();
- }
- else
- {
- DX::ThrowIfFailed(hr);
- }
-}
-
-// Method to convert a length in device-independent pixels (DIPs) to a length in physical pixels.
-float Direct3DBase::ConvertDipsToPixels(float dips)
-{
- static const float dipsPerInch = 96.0f;
- return floor(dips * DisplayProperties::LogicalDpi / dipsPerInch + 0.5f); // Round to nearest integer.
-}
diff --git a/src/video/windowsrt/Direct3DBase.h b/src/video/windowsrt/Direct3DBase.h
deleted file mode 100644
index eab1a178e..000000000
--- a/src/video/windowsrt/Direct3DBase.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#pragma once
-
-#include "DirectXHelper.h"
-#include "SDL.h"
-
-// Helper class that initializes DirectX APIs for 3D rendering.
-ref class Direct3DBase abstract
-{
-internal:
- Direct3DBase();
-
-public:
- virtual void Initialize(Windows::UI::Core::CoreWindow^ window);
- virtual void HandleDeviceLost();
- virtual void CreateDeviceResources();
- virtual void CreateWindowSizeDependentResources();
- virtual void UpdateForWindowSizeChange();
- virtual void Present();
- virtual float ConvertDipsToPixels(float dips);
-
-internal:
- virtual void Render(SDL_Surface * surface, SDL_Rect * rects, int numrects) = 0;
-
-protected private:
- // Direct3D Objects.
- Microsoft::WRL::ComPtr m_d3dDevice;
- Microsoft::WRL::ComPtr m_d3dContext;
- Microsoft::WRL::ComPtr m_swapChain;
- Microsoft::WRL::ComPtr m_renderTargetView;
- Microsoft::WRL::ComPtr m_depthStencilView;
-
- // Cached renderer properties.
- D3D_FEATURE_LEVEL m_featureLevel;
- Windows::Foundation::Size m_renderTargetSize;
- Windows::Foundation::Rect m_windowBounds;
- Platform::Agile m_window;
- Windows::Graphics::Display::DisplayOrientations m_orientation;
-
- // Transform used for display orientation.
- DirectX::XMFLOAT4X4 m_orientationTransform3D;
-};
diff --git a/src/video/windowsrt/SDL_winrtrenderer.cpp b/src/video/windowsrt/SDL_winrtrenderer.cpp
index 99a7824f1..a64cfddae 100644
--- a/src/video/windowsrt/SDL_winrtrenderer.cpp
+++ b/src/video/windowsrt/SDL_winrtrenderer.cpp
@@ -3,20 +3,93 @@
using namespace DirectX;
using namespace Microsoft::WRL;
-using namespace Windows::Foundation;
using namespace Windows::UI::Core;
+using namespace Windows::Foundation;
+using namespace Windows::Graphics::Display;
+// Constructor.
SDL_winrtrenderer::SDL_winrtrenderer() :
- m_loadingComplete(false),
+ m_loadingComplete(false),
m_vertexCount(0)
{
}
+// Initialize the Direct3D resources required to run.
+void SDL_winrtrenderer::Initialize(CoreWindow^ window)
+{
+ m_window = window;
+
+ CreateDeviceResources();
+ CreateWindowSizeDependentResources();
+}
+
+// Recreate all device resources and set them back to the current state.
+void SDL_winrtrenderer::HandleDeviceLost()
+{
+ // Reset these member variables to ensure that UpdateForWindowSizeChange recreates all resources.
+ m_windowBounds.Width = 0;
+ m_windowBounds.Height = 0;
+ m_swapChain = nullptr;
+
+ CreateDeviceResources();
+ UpdateForWindowSizeChange();
+}
+
+// These are the resources that depend on the device.
void SDL_winrtrenderer::CreateDeviceResources()
{
- Direct3DBase::CreateDeviceResources();
+ // This flag adds support for surfaces with a different color channel ordering
+ // than the API default. It is required for compatibility with Direct2D.
+ UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
- auto loadVSTask = DX::ReadDataAsync("SDL_VS2012_WinRT\\SimpleVertexShader.cso");
+#if defined(_DEBUG)
+ // If the project is in a debug build, enable debugging via SDK Layers with this flag.
+ creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
+#endif
+
+ // This array defines the set of DirectX hardware feature levels this app will support.
+ // Note the ordering should be preserved.
+ // Don't forget to declare your application's minimum required feature level in its
+ // description. All applications are assumed to support 9.1 unless otherwise stated.
+ D3D_FEATURE_LEVEL featureLevels[] =
+ {
+ D3D_FEATURE_LEVEL_11_1,
+ D3D_FEATURE_LEVEL_11_0,
+ D3D_FEATURE_LEVEL_10_1,
+ D3D_FEATURE_LEVEL_10_0,
+ D3D_FEATURE_LEVEL_9_3,
+ D3D_FEATURE_LEVEL_9_2,
+ D3D_FEATURE_LEVEL_9_1
+ };
+
+ // Create the Direct3D 11 API device object and a corresponding context.
+ ComPtr device;
+ ComPtr context;
+ DX::ThrowIfFailed(
+ D3D11CreateDevice(
+ nullptr, // Specify nullptr to use the default adapter.
+ D3D_DRIVER_TYPE_HARDWARE,
+ nullptr,
+ creationFlags, // Set set debug and Direct2D compatibility flags.
+ featureLevels, // List of feature levels this app can support.
+ ARRAYSIZE(featureLevels),
+ D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps.
+ &device, // Returns the Direct3D device created.
+ &m_featureLevel, // Returns feature level of device created.
+ &context // Returns the device immediate context.
+ )
+ );
+
+ // Get the Direct3D 11.1 API device and context interfaces.
+ DX::ThrowIfFailed(
+ device.As(&m_d3dDevice)
+ );
+
+ DX::ThrowIfFailed(
+ context.As(&m_d3dContext)
+ );
+
+ auto loadVSTask = DX::ReadDataAsync("SDL_VS2012_WinRT\\SimpleVertexShader.cso");
auto loadPSTask = DX::ReadDataAsync("SDL_VS2012_WinRT\\SimplePixelShader.cso");
auto createVSTask = loadVSTask.then([this](Platform::Array^ fileData) {
@@ -110,6 +183,202 @@ void SDL_winrtrenderer::CreateDeviceResources()
});
}
+// Allocate all memory resources that change on a window SizeChanged event.
+void SDL_winrtrenderer::CreateWindowSizeDependentResources()
+{
+ // Store the window bounds so the next time we get a SizeChanged event we can
+ // avoid rebuilding everything if the size is identical.
+ m_windowBounds = m_window->Bounds;
+
+ // Calculate the necessary swap chain and render target size in pixels.
+ float windowWidth = ConvertDipsToPixels(m_windowBounds.Width);
+ float windowHeight = ConvertDipsToPixels(m_windowBounds.Height);
+
+ // The width and height of the swap chain must be based on the window's
+ // landscape-oriented width and height. If the window is in a portrait
+ // orientation, the dimensions must be reversed.
+ m_orientation = DisplayProperties::CurrentOrientation;
+ bool swapDimensions =
+ m_orientation == DisplayOrientations::Portrait ||
+ m_orientation == DisplayOrientations::PortraitFlipped;
+ m_renderTargetSize.Width = swapDimensions ? windowHeight : windowWidth;
+ m_renderTargetSize.Height = swapDimensions ? windowWidth : windowHeight;
+
+ if(m_swapChain != nullptr)
+ {
+ // If the swap chain already exists, resize it.
+ DX::ThrowIfFailed(
+ m_swapChain->ResizeBuffers(
+ 2, // Double-buffered swap chain.
+ static_cast(m_renderTargetSize.Width),
+ static_cast(m_renderTargetSize.Height),
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ 0
+ )
+ );
+ }
+ else
+ {
+ // Otherwise, create a new one using the same adapter as the existing Direct3D device.
+ DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
+ swapChainDesc.Width = static_cast(m_renderTargetSize.Width); // Match the size of the window.
+ swapChainDesc.Height = static_cast(m_renderTargetSize.Height);
+ swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // This is the most common swap chain format.
+ swapChainDesc.Stereo = false;
+ swapChainDesc.SampleDesc.Count = 1; // Don't use multi-sampling.
+ swapChainDesc.SampleDesc.Quality = 0;
+ swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ swapChainDesc.BufferCount = 2; // Use double-buffering to minimize latency.
+ swapChainDesc.Scaling = DXGI_SCALING_NONE;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // All Windows Store apps must use this SwapEffect.
+ swapChainDesc.Flags = 0;
+
+ ComPtr dxgiDevice;
+ DX::ThrowIfFailed(
+ m_d3dDevice.As(&dxgiDevice)
+ );
+
+ ComPtr dxgiAdapter;
+ DX::ThrowIfFailed(
+ dxgiDevice->GetAdapter(&dxgiAdapter)
+ );
+
+ ComPtr dxgiFactory;
+ DX::ThrowIfFailed(
+ dxgiAdapter->GetParent(
+ __uuidof(IDXGIFactory2),
+ &dxgiFactory
+ )
+ );
+
+ Windows::UI::Core::CoreWindow^ window = m_window.Get();
+ DX::ThrowIfFailed(
+ dxgiFactory->CreateSwapChainForCoreWindow(
+ m_d3dDevice.Get(),
+ reinterpret_cast(window),
+ &swapChainDesc,
+ nullptr, // Allow on all displays.
+ &m_swapChain
+ )
+ );
+
+ // Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and
+ // ensures that the application will only render after each VSync, minimizing power consumption.
+ DX::ThrowIfFailed(
+ dxgiDevice->SetMaximumFrameLatency(1)
+ );
+ }
+
+ // Set the proper orientation for the swap chain, and generate the
+ // 3D matrix transformation for rendering to the rotated swap chain.
+ DXGI_MODE_ROTATION rotation = DXGI_MODE_ROTATION_UNSPECIFIED;
+ switch (m_orientation)
+ {
+ case DisplayOrientations::Landscape:
+ rotation = DXGI_MODE_ROTATION_IDENTITY;
+ m_orientationTransform3D = XMFLOAT4X4( // 0-degree Z-rotation
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ );
+ break;
+
+ case DisplayOrientations::Portrait:
+ rotation = DXGI_MODE_ROTATION_ROTATE270;
+ m_orientationTransform3D = XMFLOAT4X4( // 90-degree Z-rotation
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ -1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ );
+ break;
+
+ case DisplayOrientations::LandscapeFlipped:
+ rotation = DXGI_MODE_ROTATION_ROTATE180;
+ m_orientationTransform3D = XMFLOAT4X4( // 180-degree Z-rotation
+ -1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, -1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ );
+ break;
+
+ case DisplayOrientations::PortraitFlipped:
+ rotation = DXGI_MODE_ROTATION_ROTATE90;
+ m_orientationTransform3D = XMFLOAT4X4( // 270-degree Z-rotation
+ 0.0f, -1.0f, 0.0f, 0.0f,
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ );
+ break;
+
+ default:
+ throw ref new Platform::FailureException();
+ }
+
+ DX::ThrowIfFailed(
+ m_swapChain->SetRotation(rotation)
+ );
+
+ // Create a render target view of the swap chain back buffer.
+ ComPtr backBuffer;
+ DX::ThrowIfFailed(
+ m_swapChain->GetBuffer(
+ 0,
+ __uuidof(ID3D11Texture2D),
+ &backBuffer
+ )
+ );
+
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateRenderTargetView(
+ backBuffer.Get(),
+ nullptr,
+ &m_renderTargetView
+ )
+ );
+
+ // Create a depth stencil view.
+ CD3D11_TEXTURE2D_DESC depthStencilDesc(
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ static_cast(m_renderTargetSize.Width),
+ static_cast(m_renderTargetSize.Height),
+ 1,
+ 1,
+ D3D11_BIND_DEPTH_STENCIL
+ );
+
+ ComPtr depthStencil;
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateTexture2D(
+ &depthStencilDesc,
+ nullptr,
+ &depthStencil
+ )
+ );
+
+ CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D);
+ DX::ThrowIfFailed(
+ m_d3dDevice->CreateDepthStencilView(
+ depthStencil.Get(),
+ &depthStencilViewDesc,
+ &m_depthStencilView
+ )
+ );
+
+ // Set the rendering viewport to target the entire window.
+ CD3D11_VIEWPORT viewport(
+ 0.0f,
+ 0.0f,
+ m_renderTargetSize.Width,
+ m_renderTargetSize.Height
+ );
+
+ m_d3dContext->RSSetViewports(1, &viewport);
+}
+
void SDL_winrtrenderer::ResizeMainTexture(int w, int h)
{
D3D11_TEXTURE2D_DESC textureDesc = {0};
@@ -152,6 +421,22 @@ void SDL_winrtrenderer::ResizeMainTexture(int w, int h)
);
}
+// This method is called in the event handler for the SizeChanged event.
+void SDL_winrtrenderer::UpdateForWindowSizeChange()
+{
+ if (m_window->Bounds.Width != m_windowBounds.Width ||
+ m_window->Bounds.Height != m_windowBounds.Height ||
+ m_orientation != DisplayProperties::CurrentOrientation)
+ {
+ ID3D11RenderTargetView* nullViews[] = {nullptr};
+ m_d3dContext->OMSetRenderTargets(ARRAYSIZE(nullViews), nullViews, nullptr);
+ m_renderTargetView = nullptr;
+ m_depthStencilView = nullptr;
+ m_d3dContext->Flush();
+ CreateWindowSizeDependentResources();
+ }
+}
+
void SDL_winrtrenderer::Render(SDL_Surface * surface, SDL_Rect * rects, int numrects)
{
const float blackColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
@@ -237,3 +522,46 @@ void SDL_winrtrenderer::Render(SDL_Surface * surface, SDL_Rect * rects, int numr
m_d3dContext->Draw(4, 0);
}
+
+// Method to deliver the final image to the display.
+void SDL_winrtrenderer::Present()
+{
+ // The application may optionally specify "dirty" or "scroll"
+ // rects to improve efficiency in certain scenarios.
+ DXGI_PRESENT_PARAMETERS parameters = {0};
+ parameters.DirtyRectsCount = 0;
+ parameters.pDirtyRects = nullptr;
+ parameters.pScrollRect = nullptr;
+ parameters.pScrollOffset = nullptr;
+
+ // The first argument instructs DXGI to block until VSync, putting the application
+ // to sleep until the next VSync. This ensures we don't waste any cycles rendering
+ // frames that will never be displayed to the screen.
+ HRESULT hr = m_swapChain->Present1(1, 0, ¶meters);
+
+ // Discard the contents of the render target.
+ // This is a valid operation only when the existing contents will be entirely
+ // overwritten. If dirty or scroll rects are used, this call should be removed.
+ m_d3dContext->DiscardView(m_renderTargetView.Get());
+
+ // Discard the contents of the depth stencil.
+ m_d3dContext->DiscardView(m_depthStencilView.Get());
+
+ // If the device was removed either by a disconnect or a driver upgrade, we
+ // must recreate all device resources.
+ if (hr == DXGI_ERROR_DEVICE_REMOVED)
+ {
+ HandleDeviceLost();
+ }
+ else
+ {
+ DX::ThrowIfFailed(hr);
+ }
+}
+
+// Method to convert a length in device-independent pixels (DIPs) to a length in physical pixels.
+float SDL_winrtrenderer::ConvertDipsToPixels(float dips)
+{
+ static const float dipsPerInch = 96.0f;
+ return floor(dips * DisplayProperties::LogicalDpi / dipsPerInch + 0.5f); // Round to nearest integer.
+}
diff --git a/src/video/windowsrt/SDL_winrtrenderer.h b/src/video/windowsrt/SDL_winrtrenderer.h
index 7d39a26fa..a32697b76 100644
--- a/src/video/windowsrt/SDL_winrtrenderer.h
+++ b/src/video/windowsrt/SDL_winrtrenderer.h
@@ -1,6 +1,7 @@
#pragma once
-#include "Direct3DBase.h"
+#include "DirectXHelper.h"
+#include "SDL.h"
struct VertexPositionColor
{
@@ -8,22 +9,32 @@ struct VertexPositionColor
DirectX::XMFLOAT2 tex;
};
-// This class renders a simple spinning cube.
-ref class SDL_winrtrenderer sealed : public Direct3DBase
+// Helper class that initializes DirectX APIs for 3D rendering.
+ref class SDL_winrtrenderer
{
-public:
+internal:
SDL_winrtrenderer();
- // Direct3DBase methods.
- virtual void CreateDeviceResources() override;
+public:
+ virtual void Initialize(Windows::UI::Core::CoreWindow^ window);
+ virtual void HandleDeviceLost();
+ virtual void CreateDeviceResources();
+ virtual void CreateWindowSizeDependentResources();
+ virtual void UpdateForWindowSizeChange();
+ virtual void Present();
+ virtual float ConvertDipsToPixels(float dips);
internal:
- virtual void Render(SDL_Surface * surface, SDL_Rect * rects, int numrects) override;
+ virtual void Render(SDL_Surface * surface, SDL_Rect * rects, int numrects);
void ResizeMainTexture(int w, int h);
-private:
- bool m_loadingComplete;
-
+protected private:
+ // Direct3D Objects.
+ Microsoft::WRL::ComPtr m_d3dDevice;
+ Microsoft::WRL::ComPtr m_d3dContext;
+ Microsoft::WRL::ComPtr m_swapChain;
+ Microsoft::WRL::ComPtr m_renderTargetView;
+ Microsoft::WRL::ComPtr m_depthStencilView;
Microsoft::WRL::ComPtr m_inputLayout;
Microsoft::WRL::ComPtr m_vertexBuffer;
Microsoft::WRL::ComPtr m_vertexShader;
@@ -32,5 +43,17 @@ private:
Microsoft::WRL::ComPtr m_mainTextureResourceView;
Microsoft::WRL::ComPtr m_mainSampler;
+ // Cached renderer properties.
+ D3D_FEATURE_LEVEL m_featureLevel;
+ Windows::Foundation::Size m_renderTargetSize;
+ Windows::Foundation::Rect m_windowBounds;
+ Platform::Agile m_window;
+ Windows::Graphics::Display::DisplayOrientations m_orientation;
uint32 m_vertexCount;
+
+ // Transform used for display orientation.
+ DirectX::XMFLOAT4X4 m_orientationTransform3D;
+
+ // Has the renderer finished loading?
+ bool m_loadingComplete;
};