WinRT: video code cleanup: combined files Direct3DBase.* and SDL_winrtrenderer.*
authorDavid Ludwig
Sun, 25 Nov 2012 19:05:56 -0500
changeset 83696dfc4ba22640
parent 8368 c611e5a2eab4
child 8370 a7b682df854c
WinRT: video code cleanup: combined files Direct3DBase.* and SDL_winrtrenderer.*
VisualC/SDL/SDL_VS2012_WinRT.vcxproj
src/video/windowsrt/Direct3DBase.cpp
src/video/windowsrt/Direct3DBase.h
src/video/windowsrt/SDL_winrtrenderer.cpp
src/video/windowsrt/SDL_winrtrenderer.h
     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, &parameters);
   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, &parameters);
   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  };