WinRT: video code cleanup: combined files Direct3DBase.* and SDL_winrtrenderer.*
1.1 --- a/VisualC/SDL/SDL_VS2012_WinRT.vcxproj Sun Nov 25 17:35:41 2012 -0500
1.2 +++ b/VisualC/SDL/SDL_VS2012_WinRT.vcxproj Sun Nov 25 19:05:56 2012 -0500
1.3 @@ -117,14 +117,6 @@
1.4 <ClCompile Include="..\..\src\video\SDL_stretch.c" />
1.5 <ClCompile Include="..\..\src\video\SDL_surface.c" />
1.6 <ClCompile Include="..\..\src\video\SDL_video.c" />
1.7 - <ClCompile Include="..\..\src\video\windowsrt\Direct3DBase.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\video\windowsrt\SDL_WinRTApp.cpp">
1.16 <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</CompileAsWinRT>
1.17 <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</CompileAsWinRT>
1.18 @@ -270,7 +262,6 @@
1.19 <ClInclude Include="..\..\src\video\SDL_RLEaccel_c.h" />
1.20 <ClInclude Include="..\..\src\video\SDL_shape_internals.h" />
1.21 <ClInclude Include="..\..\src\video\SDL_sysvideo.h" />
1.22 - <ClInclude Include="..\..\src\video\windowsrt\Direct3DBase.h" />
1.23 <ClInclude Include="..\..\src\video\windowsrt\DirectXHelper.h" />
1.24 <ClInclude Include="..\..\src\video\windowsrt\SDLmain_WinRT_common.h" />
1.25 <ClInclude Include="..\..\src\video\windowsrt\SDL_WinRTApp.h" />
2.1 --- a/src/video/windowsrt/Direct3DBase.cpp Sun Nov 25 17:35:41 2012 -0500
2.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2.3 @@ -1,344 +0,0 @@
2.4 -#include "SDLmain_WinRT_common.h"
2.5 -#include "Direct3DBase.h"
2.6 -
2.7 -using namespace DirectX;
2.8 -using namespace Microsoft::WRL;
2.9 -using namespace Windows::UI::Core;
2.10 -using namespace Windows::Foundation;
2.11 -using namespace Windows::Graphics::Display;
2.12 -
2.13 -// Constructor.
2.14 -Direct3DBase::Direct3DBase()
2.15 -{
2.16 -}
2.17 -
2.18 -// Initialize the Direct3D resources required to run.
2.19 -void Direct3DBase::Initialize(CoreWindow^ window)
2.20 -{
2.21 - m_window = window;
2.22 -
2.23 - CreateDeviceResources();
2.24 - CreateWindowSizeDependentResources();
2.25 -}
2.26 -
2.27 -// Recreate all device resources and set them back to the current state.
2.28 -void Direct3DBase::HandleDeviceLost()
2.29 -{
2.30 - // Reset these member variables to ensure that UpdateForWindowSizeChange recreates all resources.
2.31 - m_windowBounds.Width = 0;
2.32 - m_windowBounds.Height = 0;
2.33 - m_swapChain = nullptr;
2.34 -
2.35 - CreateDeviceResources();
2.36 - UpdateForWindowSizeChange();
2.37 -}
2.38 -
2.39 -// These are the resources that depend on the device.
2.40 -void Direct3DBase::CreateDeviceResources()
2.41 -{
2.42 - // This flag adds support for surfaces with a different color channel ordering
2.43 - // than the API default. It is required for compatibility with Direct2D.
2.44 - UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
2.45 -
2.46 -#if defined(_DEBUG)
2.47 - // If the project is in a debug build, enable debugging via SDK Layers with this flag.
2.48 - creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
2.49 -#endif
2.50 -
2.51 - // This array defines the set of DirectX hardware feature levels this app will support.
2.52 - // Note the ordering should be preserved.
2.53 - // Don't forget to declare your application's minimum required feature level in its
2.54 - // description. All applications are assumed to support 9.1 unless otherwise stated.
2.55 - D3D_FEATURE_LEVEL featureLevels[] =
2.56 - {
2.57 - D3D_FEATURE_LEVEL_11_1,
2.58 - D3D_FEATURE_LEVEL_11_0,
2.59 - D3D_FEATURE_LEVEL_10_1,
2.60 - D3D_FEATURE_LEVEL_10_0,
2.61 - D3D_FEATURE_LEVEL_9_3,
2.62 - D3D_FEATURE_LEVEL_9_2,
2.63 - D3D_FEATURE_LEVEL_9_1
2.64 - };
2.65 -
2.66 - // Create the Direct3D 11 API device object and a corresponding context.
2.67 - ComPtr<ID3D11Device> device;
2.68 - ComPtr<ID3D11DeviceContext> context;
2.69 - DX::ThrowIfFailed(
2.70 - D3D11CreateDevice(
2.71 - nullptr, // Specify nullptr to use the default adapter.
2.72 - D3D_DRIVER_TYPE_HARDWARE,
2.73 - nullptr,
2.74 - creationFlags, // Set set debug and Direct2D compatibility flags.
2.75 - featureLevels, // List of feature levels this app can support.
2.76 - ARRAYSIZE(featureLevels),
2.77 - D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps.
2.78 - &device, // Returns the Direct3D device created.
2.79 - &m_featureLevel, // Returns feature level of device created.
2.80 - &context // Returns the device immediate context.
2.81 - )
2.82 - );
2.83 -
2.84 - // Get the Direct3D 11.1 API device and context interfaces.
2.85 - DX::ThrowIfFailed(
2.86 - device.As(&m_d3dDevice)
2.87 - );
2.88 -
2.89 - DX::ThrowIfFailed(
2.90 - context.As(&m_d3dContext)
2.91 - );
2.92 -}
2.93 -
2.94 -// Allocate all memory resources that change on a window SizeChanged event.
2.95 -void Direct3DBase::CreateWindowSizeDependentResources()
2.96 -{
2.97 - // Store the window bounds so the next time we get a SizeChanged event we can
2.98 - // avoid rebuilding everything if the size is identical.
2.99 - m_windowBounds = m_window->Bounds;
2.100 -
2.101 - // Calculate the necessary swap chain and render target size in pixels.
2.102 - float windowWidth = ConvertDipsToPixels(m_windowBounds.Width);
2.103 - float windowHeight = ConvertDipsToPixels(m_windowBounds.Height);
2.104 -
2.105 - // The width and height of the swap chain must be based on the window's
2.106 - // landscape-oriented width and height. If the window is in a portrait
2.107 - // orientation, the dimensions must be reversed.
2.108 - m_orientation = DisplayProperties::CurrentOrientation;
2.109 - bool swapDimensions =
2.110 - m_orientation == DisplayOrientations::Portrait ||
2.111 - m_orientation == DisplayOrientations::PortraitFlipped;
2.112 - m_renderTargetSize.Width = swapDimensions ? windowHeight : windowWidth;
2.113 - m_renderTargetSize.Height = swapDimensions ? windowWidth : windowHeight;
2.114 -
2.115 - if(m_swapChain != nullptr)
2.116 - {
2.117 - // If the swap chain already exists, resize it.
2.118 - DX::ThrowIfFailed(
2.119 - m_swapChain->ResizeBuffers(
2.120 - 2, // Double-buffered swap chain.
2.121 - static_cast<UINT>(m_renderTargetSize.Width),
2.122 - static_cast<UINT>(m_renderTargetSize.Height),
2.123 - DXGI_FORMAT_B8G8R8A8_UNORM,
2.124 - 0
2.125 - )
2.126 - );
2.127 - }
2.128 - else
2.129 - {
2.130 - // Otherwise, create a new one using the same adapter as the existing Direct3D device.
2.131 - DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
2.132 - swapChainDesc.Width = static_cast<UINT>(m_renderTargetSize.Width); // Match the size of the window.
2.133 - swapChainDesc.Height = static_cast<UINT>(m_renderTargetSize.Height);
2.134 - swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // This is the most common swap chain format.
2.135 - swapChainDesc.Stereo = false;
2.136 - swapChainDesc.SampleDesc.Count = 1; // Don't use multi-sampling.
2.137 - swapChainDesc.SampleDesc.Quality = 0;
2.138 - swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
2.139 - swapChainDesc.BufferCount = 2; // Use double-buffering to minimize latency.
2.140 - swapChainDesc.Scaling = DXGI_SCALING_NONE;
2.141 - swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // All Windows Store apps must use this SwapEffect.
2.142 - swapChainDesc.Flags = 0;
2.143 -
2.144 - ComPtr<IDXGIDevice1> dxgiDevice;
2.145 - DX::ThrowIfFailed(
2.146 - m_d3dDevice.As(&dxgiDevice)
2.147 - );
2.148 -
2.149 - ComPtr<IDXGIAdapter> dxgiAdapter;
2.150 - DX::ThrowIfFailed(
2.151 - dxgiDevice->GetAdapter(&dxgiAdapter)
2.152 - );
2.153 -
2.154 - ComPtr<IDXGIFactory2> dxgiFactory;
2.155 - DX::ThrowIfFailed(
2.156 - dxgiAdapter->GetParent(
2.157 - __uuidof(IDXGIFactory2),
2.158 - &dxgiFactory
2.159 - )
2.160 - );
2.161 -
2.162 - Windows::UI::Core::CoreWindow^ window = m_window.Get();
2.163 - DX::ThrowIfFailed(
2.164 - dxgiFactory->CreateSwapChainForCoreWindow(
2.165 - m_d3dDevice.Get(),
2.166 - reinterpret_cast<IUnknown*>(window),
2.167 - &swapChainDesc,
2.168 - nullptr, // Allow on all displays.
2.169 - &m_swapChain
2.170 - )
2.171 - );
2.172 -
2.173 - // Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and
2.174 - // ensures that the application will only render after each VSync, minimizing power consumption.
2.175 - DX::ThrowIfFailed(
2.176 - dxgiDevice->SetMaximumFrameLatency(1)
2.177 - );
2.178 - }
2.179 -
2.180 - // Set the proper orientation for the swap chain, and generate the
2.181 - // 3D matrix transformation for rendering to the rotated swap chain.
2.182 - DXGI_MODE_ROTATION rotation = DXGI_MODE_ROTATION_UNSPECIFIED;
2.183 - switch (m_orientation)
2.184 - {
2.185 - case DisplayOrientations::Landscape:
2.186 - rotation = DXGI_MODE_ROTATION_IDENTITY;
2.187 - m_orientationTransform3D = XMFLOAT4X4( // 0-degree Z-rotation
2.188 - 1.0f, 0.0f, 0.0f, 0.0f,
2.189 - 0.0f, 1.0f, 0.0f, 0.0f,
2.190 - 0.0f, 0.0f, 1.0f, 0.0f,
2.191 - 0.0f, 0.0f, 0.0f, 1.0f
2.192 - );
2.193 - break;
2.194 -
2.195 - case DisplayOrientations::Portrait:
2.196 - rotation = DXGI_MODE_ROTATION_ROTATE270;
2.197 - m_orientationTransform3D = XMFLOAT4X4( // 90-degree Z-rotation
2.198 - 0.0f, 1.0f, 0.0f, 0.0f,
2.199 - -1.0f, 0.0f, 0.0f, 0.0f,
2.200 - 0.0f, 0.0f, 1.0f, 0.0f,
2.201 - 0.0f, 0.0f, 0.0f, 1.0f
2.202 - );
2.203 - break;
2.204 -
2.205 - case DisplayOrientations::LandscapeFlipped:
2.206 - rotation = DXGI_MODE_ROTATION_ROTATE180;
2.207 - m_orientationTransform3D = XMFLOAT4X4( // 180-degree Z-rotation
2.208 - -1.0f, 0.0f, 0.0f, 0.0f,
2.209 - 0.0f, -1.0f, 0.0f, 0.0f,
2.210 - 0.0f, 0.0f, 1.0f, 0.0f,
2.211 - 0.0f, 0.0f, 0.0f, 1.0f
2.212 - );
2.213 - break;
2.214 -
2.215 - case DisplayOrientations::PortraitFlipped:
2.216 - rotation = DXGI_MODE_ROTATION_ROTATE90;
2.217 - m_orientationTransform3D = XMFLOAT4X4( // 270-degree Z-rotation
2.218 - 0.0f, -1.0f, 0.0f, 0.0f,
2.219 - 1.0f, 0.0f, 0.0f, 0.0f,
2.220 - 0.0f, 0.0f, 1.0f, 0.0f,
2.221 - 0.0f, 0.0f, 0.0f, 1.0f
2.222 - );
2.223 - break;
2.224 -
2.225 - default:
2.226 - throw ref new Platform::FailureException();
2.227 - }
2.228 -
2.229 - DX::ThrowIfFailed(
2.230 - m_swapChain->SetRotation(rotation)
2.231 - );
2.232 -
2.233 - // Create a render target view of the swap chain back buffer.
2.234 - ComPtr<ID3D11Texture2D> backBuffer;
2.235 - DX::ThrowIfFailed(
2.236 - m_swapChain->GetBuffer(
2.237 - 0,
2.238 - __uuidof(ID3D11Texture2D),
2.239 - &backBuffer
2.240 - )
2.241 - );
2.242 -
2.243 - DX::ThrowIfFailed(
2.244 - m_d3dDevice->CreateRenderTargetView(
2.245 - backBuffer.Get(),
2.246 - nullptr,
2.247 - &m_renderTargetView
2.248 - )
2.249 - );
2.250 -
2.251 - // Create a depth stencil view.
2.252 - CD3D11_TEXTURE2D_DESC depthStencilDesc(
2.253 - DXGI_FORMAT_D24_UNORM_S8_UINT,
2.254 - static_cast<UINT>(m_renderTargetSize.Width),
2.255 - static_cast<UINT>(m_renderTargetSize.Height),
2.256 - 1,
2.257 - 1,
2.258 - D3D11_BIND_DEPTH_STENCIL
2.259 - );
2.260 -
2.261 - ComPtr<ID3D11Texture2D> depthStencil;
2.262 - DX::ThrowIfFailed(
2.263 - m_d3dDevice->CreateTexture2D(
2.264 - &depthStencilDesc,
2.265 - nullptr,
2.266 - &depthStencil
2.267 - )
2.268 - );
2.269 -
2.270 - CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D);
2.271 - DX::ThrowIfFailed(
2.272 - m_d3dDevice->CreateDepthStencilView(
2.273 - depthStencil.Get(),
2.274 - &depthStencilViewDesc,
2.275 - &m_depthStencilView
2.276 - )
2.277 - );
2.278 -
2.279 - // Set the rendering viewport to target the entire window.
2.280 - CD3D11_VIEWPORT viewport(
2.281 - 0.0f,
2.282 - 0.0f,
2.283 - m_renderTargetSize.Width,
2.284 - m_renderTargetSize.Height
2.285 - );
2.286 -
2.287 - m_d3dContext->RSSetViewports(1, &viewport);
2.288 -}
2.289 -
2.290 -// This method is called in the event handler for the SizeChanged event.
2.291 -void Direct3DBase::UpdateForWindowSizeChange()
2.292 -{
2.293 - if (m_window->Bounds.Width != m_windowBounds.Width ||
2.294 - m_window->Bounds.Height != m_windowBounds.Height ||
2.295 - m_orientation != DisplayProperties::CurrentOrientation)
2.296 - {
2.297 - ID3D11RenderTargetView* nullViews[] = {nullptr};
2.298 - m_d3dContext->OMSetRenderTargets(ARRAYSIZE(nullViews), nullViews, nullptr);
2.299 - m_renderTargetView = nullptr;
2.300 - m_depthStencilView = nullptr;
2.301 - m_d3dContext->Flush();
2.302 - CreateWindowSizeDependentResources();
2.303 - }
2.304 -}
2.305 -
2.306 -// Method to deliver the final image to the display.
2.307 -void Direct3DBase::Present()
2.308 -{
2.309 - // The application may optionally specify "dirty" or "scroll"
2.310 - // rects to improve efficiency in certain scenarios.
2.311 - DXGI_PRESENT_PARAMETERS parameters = {0};
2.312 - parameters.DirtyRectsCount = 0;
2.313 - parameters.pDirtyRects = nullptr;
2.314 - parameters.pScrollRect = nullptr;
2.315 - parameters.pScrollOffset = nullptr;
2.316 -
2.317 - // The first argument instructs DXGI to block until VSync, putting the application
2.318 - // to sleep until the next VSync. This ensures we don't waste any cycles rendering
2.319 - // frames that will never be displayed to the screen.
2.320 - HRESULT hr = m_swapChain->Present1(1, 0, ¶meters);
2.321 -
2.322 - // Discard the contents of the render target.
2.323 - // This is a valid operation only when the existing contents will be entirely
2.324 - // overwritten. If dirty or scroll rects are used, this call should be removed.
2.325 - m_d3dContext->DiscardView(m_renderTargetView.Get());
2.326 -
2.327 - // Discard the contents of the depth stencil.
2.328 - m_d3dContext->DiscardView(m_depthStencilView.Get());
2.329 -
2.330 - // If the device was removed either by a disconnect or a driver upgrade, we
2.331 - // must recreate all device resources.
2.332 - if (hr == DXGI_ERROR_DEVICE_REMOVED)
2.333 - {
2.334 - HandleDeviceLost();
2.335 - }
2.336 - else
2.337 - {
2.338 - DX::ThrowIfFailed(hr);
2.339 - }
2.340 -}
2.341 -
2.342 -// Method to convert a length in device-independent pixels (DIPs) to a length in physical pixels.
2.343 -float Direct3DBase::ConvertDipsToPixels(float dips)
2.344 -{
2.345 - static const float dipsPerInch = 96.0f;
2.346 - return floor(dips * DisplayProperties::LogicalDpi / dipsPerInch + 0.5f); // Round to nearest integer.
2.347 -}
3.1 --- a/src/video/windowsrt/Direct3DBase.h Sun Nov 25 17:35:41 2012 -0500
3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
3.3 @@ -1,41 +0,0 @@
3.4 -#pragma once
3.5 -
3.6 -#include "DirectXHelper.h"
3.7 -#include "SDL.h"
3.8 -
3.9 -// Helper class that initializes DirectX APIs for 3D rendering.
3.10 -ref class Direct3DBase abstract
3.11 -{
3.12 -internal:
3.13 - Direct3DBase();
3.14 -
3.15 -public:
3.16 - virtual void Initialize(Windows::UI::Core::CoreWindow^ window);
3.17 - virtual void HandleDeviceLost();
3.18 - virtual void CreateDeviceResources();
3.19 - virtual void CreateWindowSizeDependentResources();
3.20 - virtual void UpdateForWindowSizeChange();
3.21 - virtual void Present();
3.22 - virtual float ConvertDipsToPixels(float dips);
3.23 -
3.24 -internal:
3.25 - virtual void Render(SDL_Surface * surface, SDL_Rect * rects, int numrects) = 0;
3.26 -
3.27 -protected private:
3.28 - // Direct3D Objects.
3.29 - Microsoft::WRL::ComPtr<ID3D11Device1> m_d3dDevice;
3.30 - Microsoft::WRL::ComPtr<ID3D11DeviceContext1> m_d3dContext;
3.31 - Microsoft::WRL::ComPtr<IDXGISwapChain1> m_swapChain;
3.32 - Microsoft::WRL::ComPtr<ID3D11RenderTargetView> m_renderTargetView;
3.33 - Microsoft::WRL::ComPtr<ID3D11DepthStencilView> m_depthStencilView;
3.34 -
3.35 - // Cached renderer properties.
3.36 - D3D_FEATURE_LEVEL m_featureLevel;
3.37 - Windows::Foundation::Size m_renderTargetSize;
3.38 - Windows::Foundation::Rect m_windowBounds;
3.39 - Platform::Agile<Windows::UI::Core::CoreWindow> m_window;
3.40 - Windows::Graphics::Display::DisplayOrientations m_orientation;
3.41 -
3.42 - // Transform used for display orientation.
3.43 - DirectX::XMFLOAT4X4 m_orientationTransform3D;
3.44 -};
4.1 --- a/src/video/windowsrt/SDL_winrtrenderer.cpp Sun Nov 25 17:35:41 2012 -0500
4.2 +++ b/src/video/windowsrt/SDL_winrtrenderer.cpp Sun Nov 25 19:05:56 2012 -0500
4.3 @@ -3,20 +3,93 @@
4.4
4.5 using namespace DirectX;
4.6 using namespace Microsoft::WRL;
4.7 +using namespace Windows::UI::Core;
4.8 using namespace Windows::Foundation;
4.9 -using namespace Windows::UI::Core;
4.10 +using namespace Windows::Graphics::Display;
4.11
4.12 +// Constructor.
4.13 SDL_winrtrenderer::SDL_winrtrenderer() :
4.14 - m_loadingComplete(false),
4.15 + m_loadingComplete(false),
4.16 m_vertexCount(0)
4.17 {
4.18 }
4.19
4.20 +// Initialize the Direct3D resources required to run.
4.21 +void SDL_winrtrenderer::Initialize(CoreWindow^ window)
4.22 +{
4.23 + m_window = window;
4.24 +
4.25 + CreateDeviceResources();
4.26 + CreateWindowSizeDependentResources();
4.27 +}
4.28 +
4.29 +// Recreate all device resources and set them back to the current state.
4.30 +void SDL_winrtrenderer::HandleDeviceLost()
4.31 +{
4.32 + // Reset these member variables to ensure that UpdateForWindowSizeChange recreates all resources.
4.33 + m_windowBounds.Width = 0;
4.34 + m_windowBounds.Height = 0;
4.35 + m_swapChain = nullptr;
4.36 +
4.37 + CreateDeviceResources();
4.38 + UpdateForWindowSizeChange();
4.39 +}
4.40 +
4.41 +// These are the resources that depend on the device.
4.42 void SDL_winrtrenderer::CreateDeviceResources()
4.43 {
4.44 - Direct3DBase::CreateDeviceResources();
4.45 + // This flag adds support for surfaces with a different color channel ordering
4.46 + // than the API default. It is required for compatibility with Direct2D.
4.47 + UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
4.48 +
4.49 +#if defined(_DEBUG)
4.50 + // If the project is in a debug build, enable debugging via SDK Layers with this flag.
4.51 + creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
4.52 +#endif
4.53 +
4.54 + // This array defines the set of DirectX hardware feature levels this app will support.
4.55 + // Note the ordering should be preserved.
4.56 + // Don't forget to declare your application's minimum required feature level in its
4.57 + // description. All applications are assumed to support 9.1 unless otherwise stated.
4.58 + D3D_FEATURE_LEVEL featureLevels[] =
4.59 + {
4.60 + D3D_FEATURE_LEVEL_11_1,
4.61 + D3D_FEATURE_LEVEL_11_0,
4.62 + D3D_FEATURE_LEVEL_10_1,
4.63 + D3D_FEATURE_LEVEL_10_0,
4.64 + D3D_FEATURE_LEVEL_9_3,
4.65 + D3D_FEATURE_LEVEL_9_2,
4.66 + D3D_FEATURE_LEVEL_9_1
4.67 + };
4.68
4.69 - auto loadVSTask = DX::ReadDataAsync("SDL_VS2012_WinRT\\SimpleVertexShader.cso");
4.70 + // Create the Direct3D 11 API device object and a corresponding context.
4.71 + ComPtr<ID3D11Device> device;
4.72 + ComPtr<ID3D11DeviceContext> context;
4.73 + DX::ThrowIfFailed(
4.74 + D3D11CreateDevice(
4.75 + nullptr, // Specify nullptr to use the default adapter.
4.76 + D3D_DRIVER_TYPE_HARDWARE,
4.77 + nullptr,
4.78 + creationFlags, // Set set debug and Direct2D compatibility flags.
4.79 + featureLevels, // List of feature levels this app can support.
4.80 + ARRAYSIZE(featureLevels),
4.81 + D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps.
4.82 + &device, // Returns the Direct3D device created.
4.83 + &m_featureLevel, // Returns feature level of device created.
4.84 + &context // Returns the device immediate context.
4.85 + )
4.86 + );
4.87 +
4.88 + // Get the Direct3D 11.1 API device and context interfaces.
4.89 + DX::ThrowIfFailed(
4.90 + device.As(&m_d3dDevice)
4.91 + );
4.92 +
4.93 + DX::ThrowIfFailed(
4.94 + context.As(&m_d3dContext)
4.95 + );
4.96 +
4.97 + auto loadVSTask = DX::ReadDataAsync("SDL_VS2012_WinRT\\SimpleVertexShader.cso");
4.98 auto loadPSTask = DX::ReadDataAsync("SDL_VS2012_WinRT\\SimplePixelShader.cso");
4.99
4.100 auto createVSTask = loadVSTask.then([this](Platform::Array<byte>^ fileData) {
4.101 @@ -110,6 +183,202 @@
4.102 });
4.103 }
4.104
4.105 +// Allocate all memory resources that change on a window SizeChanged event.
4.106 +void SDL_winrtrenderer::CreateWindowSizeDependentResources()
4.107 +{
4.108 + // Store the window bounds so the next time we get a SizeChanged event we can
4.109 + // avoid rebuilding everything if the size is identical.
4.110 + m_windowBounds = m_window->Bounds;
4.111 +
4.112 + // Calculate the necessary swap chain and render target size in pixels.
4.113 + float windowWidth = ConvertDipsToPixels(m_windowBounds.Width);
4.114 + float windowHeight = ConvertDipsToPixels(m_windowBounds.Height);
4.115 +
4.116 + // The width and height of the swap chain must be based on the window's
4.117 + // landscape-oriented width and height. If the window is in a portrait
4.118 + // orientation, the dimensions must be reversed.
4.119 + m_orientation = DisplayProperties::CurrentOrientation;
4.120 + bool swapDimensions =
4.121 + m_orientation == DisplayOrientations::Portrait ||
4.122 + m_orientation == DisplayOrientations::PortraitFlipped;
4.123 + m_renderTargetSize.Width = swapDimensions ? windowHeight : windowWidth;
4.124 + m_renderTargetSize.Height = swapDimensions ? windowWidth : windowHeight;
4.125 +
4.126 + if(m_swapChain != nullptr)
4.127 + {
4.128 + // If the swap chain already exists, resize it.
4.129 + DX::ThrowIfFailed(
4.130 + m_swapChain->ResizeBuffers(
4.131 + 2, // Double-buffered swap chain.
4.132 + static_cast<UINT>(m_renderTargetSize.Width),
4.133 + static_cast<UINT>(m_renderTargetSize.Height),
4.134 + DXGI_FORMAT_B8G8R8A8_UNORM,
4.135 + 0
4.136 + )
4.137 + );
4.138 + }
4.139 + else
4.140 + {
4.141 + // Otherwise, create a new one using the same adapter as the existing Direct3D device.
4.142 + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
4.143 + swapChainDesc.Width = static_cast<UINT>(m_renderTargetSize.Width); // Match the size of the window.
4.144 + swapChainDesc.Height = static_cast<UINT>(m_renderTargetSize.Height);
4.145 + swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // This is the most common swap chain format.
4.146 + swapChainDesc.Stereo = false;
4.147 + swapChainDesc.SampleDesc.Count = 1; // Don't use multi-sampling.
4.148 + swapChainDesc.SampleDesc.Quality = 0;
4.149 + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
4.150 + swapChainDesc.BufferCount = 2; // Use double-buffering to minimize latency.
4.151 + swapChainDesc.Scaling = DXGI_SCALING_NONE;
4.152 + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // All Windows Store apps must use this SwapEffect.
4.153 + swapChainDesc.Flags = 0;
4.154 +
4.155 + ComPtr<IDXGIDevice1> dxgiDevice;
4.156 + DX::ThrowIfFailed(
4.157 + m_d3dDevice.As(&dxgiDevice)
4.158 + );
4.159 +
4.160 + ComPtr<IDXGIAdapter> dxgiAdapter;
4.161 + DX::ThrowIfFailed(
4.162 + dxgiDevice->GetAdapter(&dxgiAdapter)
4.163 + );
4.164 +
4.165 + ComPtr<IDXGIFactory2> dxgiFactory;
4.166 + DX::ThrowIfFailed(
4.167 + dxgiAdapter->GetParent(
4.168 + __uuidof(IDXGIFactory2),
4.169 + &dxgiFactory
4.170 + )
4.171 + );
4.172 +
4.173 + Windows::UI::Core::CoreWindow^ window = m_window.Get();
4.174 + DX::ThrowIfFailed(
4.175 + dxgiFactory->CreateSwapChainForCoreWindow(
4.176 + m_d3dDevice.Get(),
4.177 + reinterpret_cast<IUnknown*>(window),
4.178 + &swapChainDesc,
4.179 + nullptr, // Allow on all displays.
4.180 + &m_swapChain
4.181 + )
4.182 + );
4.183 +
4.184 + // Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and
4.185 + // ensures that the application will only render after each VSync, minimizing power consumption.
4.186 + DX::ThrowIfFailed(
4.187 + dxgiDevice->SetMaximumFrameLatency(1)
4.188 + );
4.189 + }
4.190 +
4.191 + // Set the proper orientation for the swap chain, and generate the
4.192 + // 3D matrix transformation for rendering to the rotated swap chain.
4.193 + DXGI_MODE_ROTATION rotation = DXGI_MODE_ROTATION_UNSPECIFIED;
4.194 + switch (m_orientation)
4.195 + {
4.196 + case DisplayOrientations::Landscape:
4.197 + rotation = DXGI_MODE_ROTATION_IDENTITY;
4.198 + m_orientationTransform3D = XMFLOAT4X4( // 0-degree Z-rotation
4.199 + 1.0f, 0.0f, 0.0f, 0.0f,
4.200 + 0.0f, 1.0f, 0.0f, 0.0f,
4.201 + 0.0f, 0.0f, 1.0f, 0.0f,
4.202 + 0.0f, 0.0f, 0.0f, 1.0f
4.203 + );
4.204 + break;
4.205 +
4.206 + case DisplayOrientations::Portrait:
4.207 + rotation = DXGI_MODE_ROTATION_ROTATE270;
4.208 + m_orientationTransform3D = XMFLOAT4X4( // 90-degree Z-rotation
4.209 + 0.0f, 1.0f, 0.0f, 0.0f,
4.210 + -1.0f, 0.0f, 0.0f, 0.0f,
4.211 + 0.0f, 0.0f, 1.0f, 0.0f,
4.212 + 0.0f, 0.0f, 0.0f, 1.0f
4.213 + );
4.214 + break;
4.215 +
4.216 + case DisplayOrientations::LandscapeFlipped:
4.217 + rotation = DXGI_MODE_ROTATION_ROTATE180;
4.218 + m_orientationTransform3D = XMFLOAT4X4( // 180-degree Z-rotation
4.219 + -1.0f, 0.0f, 0.0f, 0.0f,
4.220 + 0.0f, -1.0f, 0.0f, 0.0f,
4.221 + 0.0f, 0.0f, 1.0f, 0.0f,
4.222 + 0.0f, 0.0f, 0.0f, 1.0f
4.223 + );
4.224 + break;
4.225 +
4.226 + case DisplayOrientations::PortraitFlipped:
4.227 + rotation = DXGI_MODE_ROTATION_ROTATE90;
4.228 + m_orientationTransform3D = XMFLOAT4X4( // 270-degree Z-rotation
4.229 + 0.0f, -1.0f, 0.0f, 0.0f,
4.230 + 1.0f, 0.0f, 0.0f, 0.0f,
4.231 + 0.0f, 0.0f, 1.0f, 0.0f,
4.232 + 0.0f, 0.0f, 0.0f, 1.0f
4.233 + );
4.234 + break;
4.235 +
4.236 + default:
4.237 + throw ref new Platform::FailureException();
4.238 + }
4.239 +
4.240 + DX::ThrowIfFailed(
4.241 + m_swapChain->SetRotation(rotation)
4.242 + );
4.243 +
4.244 + // Create a render target view of the swap chain back buffer.
4.245 + ComPtr<ID3D11Texture2D> backBuffer;
4.246 + DX::ThrowIfFailed(
4.247 + m_swapChain->GetBuffer(
4.248 + 0,
4.249 + __uuidof(ID3D11Texture2D),
4.250 + &backBuffer
4.251 + )
4.252 + );
4.253 +
4.254 + DX::ThrowIfFailed(
4.255 + m_d3dDevice->CreateRenderTargetView(
4.256 + backBuffer.Get(),
4.257 + nullptr,
4.258 + &m_renderTargetView
4.259 + )
4.260 + );
4.261 +
4.262 + // Create a depth stencil view.
4.263 + CD3D11_TEXTURE2D_DESC depthStencilDesc(
4.264 + DXGI_FORMAT_D24_UNORM_S8_UINT,
4.265 + static_cast<UINT>(m_renderTargetSize.Width),
4.266 + static_cast<UINT>(m_renderTargetSize.Height),
4.267 + 1,
4.268 + 1,
4.269 + D3D11_BIND_DEPTH_STENCIL
4.270 + );
4.271 +
4.272 + ComPtr<ID3D11Texture2D> depthStencil;
4.273 + DX::ThrowIfFailed(
4.274 + m_d3dDevice->CreateTexture2D(
4.275 + &depthStencilDesc,
4.276 + nullptr,
4.277 + &depthStencil
4.278 + )
4.279 + );
4.280 +
4.281 + CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D);
4.282 + DX::ThrowIfFailed(
4.283 + m_d3dDevice->CreateDepthStencilView(
4.284 + depthStencil.Get(),
4.285 + &depthStencilViewDesc,
4.286 + &m_depthStencilView
4.287 + )
4.288 + );
4.289 +
4.290 + // Set the rendering viewport to target the entire window.
4.291 + CD3D11_VIEWPORT viewport(
4.292 + 0.0f,
4.293 + 0.0f,
4.294 + m_renderTargetSize.Width,
4.295 + m_renderTargetSize.Height
4.296 + );
4.297 +
4.298 + m_d3dContext->RSSetViewports(1, &viewport);
4.299 +}
4.300 +
4.301 void SDL_winrtrenderer::ResizeMainTexture(int w, int h)
4.302 {
4.303 D3D11_TEXTURE2D_DESC textureDesc = {0};
4.304 @@ -152,6 +421,22 @@
4.305 );
4.306 }
4.307
4.308 +// This method is called in the event handler for the SizeChanged event.
4.309 +void SDL_winrtrenderer::UpdateForWindowSizeChange()
4.310 +{
4.311 + if (m_window->Bounds.Width != m_windowBounds.Width ||
4.312 + m_window->Bounds.Height != m_windowBounds.Height ||
4.313 + m_orientation != DisplayProperties::CurrentOrientation)
4.314 + {
4.315 + ID3D11RenderTargetView* nullViews[] = {nullptr};
4.316 + m_d3dContext->OMSetRenderTargets(ARRAYSIZE(nullViews), nullViews, nullptr);
4.317 + m_renderTargetView = nullptr;
4.318 + m_depthStencilView = nullptr;
4.319 + m_d3dContext->Flush();
4.320 + CreateWindowSizeDependentResources();
4.321 + }
4.322 +}
4.323 +
4.324 void SDL_winrtrenderer::Render(SDL_Surface * surface, SDL_Rect * rects, int numrects)
4.325 {
4.326 const float blackColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
4.327 @@ -237,3 +522,46 @@
4.328
4.329 m_d3dContext->Draw(4, 0);
4.330 }
4.331 +
4.332 +// Method to deliver the final image to the display.
4.333 +void SDL_winrtrenderer::Present()
4.334 +{
4.335 + // The application may optionally specify "dirty" or "scroll"
4.336 + // rects to improve efficiency in certain scenarios.
4.337 + DXGI_PRESENT_PARAMETERS parameters = {0};
4.338 + parameters.DirtyRectsCount = 0;
4.339 + parameters.pDirtyRects = nullptr;
4.340 + parameters.pScrollRect = nullptr;
4.341 + parameters.pScrollOffset = nullptr;
4.342 +
4.343 + // The first argument instructs DXGI to block until VSync, putting the application
4.344 + // to sleep until the next VSync. This ensures we don't waste any cycles rendering
4.345 + // frames that will never be displayed to the screen.
4.346 + HRESULT hr = m_swapChain->Present1(1, 0, ¶meters);
4.347 +
4.348 + // Discard the contents of the render target.
4.349 + // This is a valid operation only when the existing contents will be entirely
4.350 + // overwritten. If dirty or scroll rects are used, this call should be removed.
4.351 + m_d3dContext->DiscardView(m_renderTargetView.Get());
4.352 +
4.353 + // Discard the contents of the depth stencil.
4.354 + m_d3dContext->DiscardView(m_depthStencilView.Get());
4.355 +
4.356 + // If the device was removed either by a disconnect or a driver upgrade, we
4.357 + // must recreate all device resources.
4.358 + if (hr == DXGI_ERROR_DEVICE_REMOVED)
4.359 + {
4.360 + HandleDeviceLost();
4.361 + }
4.362 + else
4.363 + {
4.364 + DX::ThrowIfFailed(hr);
4.365 + }
4.366 +}
4.367 +
4.368 +// Method to convert a length in device-independent pixels (DIPs) to a length in physical pixels.
4.369 +float SDL_winrtrenderer::ConvertDipsToPixels(float dips)
4.370 +{
4.371 + static const float dipsPerInch = 96.0f;
4.372 + return floor(dips * DisplayProperties::LogicalDpi / dipsPerInch + 0.5f); // Round to nearest integer.
4.373 +}
5.1 --- a/src/video/windowsrt/SDL_winrtrenderer.h Sun Nov 25 17:35:41 2012 -0500
5.2 +++ b/src/video/windowsrt/SDL_winrtrenderer.h Sun Nov 25 19:05:56 2012 -0500
5.3 @@ -1,6 +1,7 @@
5.4 #pragma once
5.5
5.6 -#include "Direct3DBase.h"
5.7 +#include "DirectXHelper.h"
5.8 +#include "SDL.h"
5.9
5.10 struct VertexPositionColor
5.11 {
5.12 @@ -8,22 +9,32 @@
5.13 DirectX::XMFLOAT2 tex;
5.14 };
5.15
5.16 -// This class renders a simple spinning cube.
5.17 -ref class SDL_winrtrenderer sealed : public Direct3DBase
5.18 +// Helper class that initializes DirectX APIs for 3D rendering.
5.19 +ref class SDL_winrtrenderer
5.20 {
5.21 -public:
5.22 +internal:
5.23 SDL_winrtrenderer();
5.24
5.25 - // Direct3DBase methods.
5.26 - virtual void CreateDeviceResources() override;
5.27 +public:
5.28 + virtual void Initialize(Windows::UI::Core::CoreWindow^ window);
5.29 + virtual void HandleDeviceLost();
5.30 + virtual void CreateDeviceResources();
5.31 + virtual void CreateWindowSizeDependentResources();
5.32 + virtual void UpdateForWindowSizeChange();
5.33 + virtual void Present();
5.34 + virtual float ConvertDipsToPixels(float dips);
5.35
5.36 internal:
5.37 - virtual void Render(SDL_Surface * surface, SDL_Rect * rects, int numrects) override;
5.38 + virtual void Render(SDL_Surface * surface, SDL_Rect * rects, int numrects);
5.39 void ResizeMainTexture(int w, int h);
5.40
5.41 -private:
5.42 - bool m_loadingComplete;
5.43 -
5.44 +protected private:
5.45 + // Direct3D Objects.
5.46 + Microsoft::WRL::ComPtr<ID3D11Device1> m_d3dDevice;
5.47 + Microsoft::WRL::ComPtr<ID3D11DeviceContext1> m_d3dContext;
5.48 + Microsoft::WRL::ComPtr<IDXGISwapChain1> m_swapChain;
5.49 + Microsoft::WRL::ComPtr<ID3D11RenderTargetView> m_renderTargetView;
5.50 + Microsoft::WRL::ComPtr<ID3D11DepthStencilView> m_depthStencilView;
5.51 Microsoft::WRL::ComPtr<ID3D11InputLayout> m_inputLayout;
5.52 Microsoft::WRL::ComPtr<ID3D11Buffer> m_vertexBuffer;
5.53 Microsoft::WRL::ComPtr<ID3D11VertexShader> m_vertexShader;
5.54 @@ -32,5 +43,17 @@
5.55 Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> m_mainTextureResourceView;
5.56 Microsoft::WRL::ComPtr<ID3D11SamplerState> m_mainSampler;
5.57
5.58 + // Cached renderer properties.
5.59 + D3D_FEATURE_LEVEL m_featureLevel;
5.60 + Windows::Foundation::Size m_renderTargetSize;
5.61 + Windows::Foundation::Rect m_windowBounds;
5.62 + Platform::Agile<Windows::UI::Core::CoreWindow> m_window;
5.63 + Windows::Graphics::Display::DisplayOrientations m_orientation;
5.64 uint32 m_vertexCount;
5.65 +
5.66 + // Transform used for display orientation.
5.67 + DirectX::XMFLOAT4X4 m_orientationTransform3D;
5.68 +
5.69 + // Has the renderer finished loading?
5.70 + bool m_loadingComplete;
5.71 };