src/video/windowsrt/SDL_winrtrenderer.cpp
author David Ludwig <dludwig@pobox.com>
Sun, 25 Nov 2012 19:13:45 -0500
changeset 8371 0814a5de5b48
parent 8370 a7b682df854c
child 8375 e33eb49b7f42
permissions -rw-r--r--
WinRT: minor code cleanup regarding some variable names
dludwig@8322
     1
#include "SDLmain_WinRT_common.h"
dludwig@8342
     2
#include "SDL_winrtrenderer.h"
dludwig@8322
     3
dludwig@8322
     4
using namespace DirectX;
dludwig@8322
     5
using namespace Microsoft::WRL;
dludwig@8369
     6
using namespace Windows::UI::Core;
dludwig@8322
     7
using namespace Windows::Foundation;
dludwig@8369
     8
using namespace Windows::Graphics::Display;
dludwig@8322
     9
dludwig@8369
    10
// Constructor.
dludwig@8342
    11
SDL_winrtrenderer::SDL_winrtrenderer() :
dludwig@8369
    12
    m_loadingComplete(false),
dludwig@8342
    13
	m_vertexCount(0)
dludwig@8322
    14
{
dludwig@8322
    15
}
dludwig@8322
    16
dludwig@8369
    17
// Initialize the Direct3D resources required to run.
dludwig@8369
    18
void SDL_winrtrenderer::Initialize(CoreWindow^ window)
dludwig@8369
    19
{
dludwig@8369
    20
	m_window = window;
dludwig@8369
    21
	
dludwig@8369
    22
	CreateDeviceResources();
dludwig@8369
    23
	CreateWindowSizeDependentResources();
dludwig@8369
    24
}
dludwig@8369
    25
dludwig@8369
    26
// Recreate all device resources and set them back to the current state.
dludwig@8369
    27
void SDL_winrtrenderer::HandleDeviceLost()
dludwig@8369
    28
{
dludwig@8369
    29
	// Reset these member variables to ensure that UpdateForWindowSizeChange recreates all resources.
dludwig@8369
    30
	m_windowBounds.Width = 0;
dludwig@8369
    31
	m_windowBounds.Height = 0;
dludwig@8369
    32
	m_swapChain = nullptr;
dludwig@8369
    33
dludwig@8369
    34
	CreateDeviceResources();
dludwig@8369
    35
	UpdateForWindowSizeChange();
dludwig@8369
    36
}
dludwig@8369
    37
dludwig@8369
    38
// These are the resources that depend on the device.
dludwig@8342
    39
void SDL_winrtrenderer::CreateDeviceResources()
dludwig@8322
    40
{
dludwig@8369
    41
	// This flag adds support for surfaces with a different color channel ordering
dludwig@8369
    42
	// than the API default. It is required for compatibility with Direct2D.
dludwig@8369
    43
	UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
dludwig@8322
    44
dludwig@8369
    45
#if defined(_DEBUG)
dludwig@8369
    46
	// If the project is in a debug build, enable debugging via SDK Layers with this flag.
dludwig@8369
    47
	creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
dludwig@8369
    48
#endif
dludwig@8369
    49
dludwig@8369
    50
	// This array defines the set of DirectX hardware feature levels this app will support.
dludwig@8369
    51
	// Note the ordering should be preserved.
dludwig@8369
    52
	// Don't forget to declare your application's minimum required feature level in its
dludwig@8369
    53
	// description.  All applications are assumed to support 9.1 unless otherwise stated.
dludwig@8369
    54
	D3D_FEATURE_LEVEL featureLevels[] = 
dludwig@8369
    55
	{
dludwig@8369
    56
		D3D_FEATURE_LEVEL_11_1,
dludwig@8369
    57
		D3D_FEATURE_LEVEL_11_0,
dludwig@8369
    58
		D3D_FEATURE_LEVEL_10_1,
dludwig@8369
    59
		D3D_FEATURE_LEVEL_10_0,
dludwig@8369
    60
		D3D_FEATURE_LEVEL_9_3,
dludwig@8369
    61
		D3D_FEATURE_LEVEL_9_2,
dludwig@8369
    62
		D3D_FEATURE_LEVEL_9_1
dludwig@8369
    63
	};
dludwig@8369
    64
dludwig@8369
    65
	// Create the Direct3D 11 API device object and a corresponding context.
dludwig@8369
    66
	ComPtr<ID3D11Device> device;
dludwig@8369
    67
	ComPtr<ID3D11DeviceContext> context;
dludwig@8369
    68
	DX::ThrowIfFailed(
dludwig@8369
    69
		D3D11CreateDevice(
dludwig@8369
    70
			nullptr, // Specify nullptr to use the default adapter.
dludwig@8369
    71
			D3D_DRIVER_TYPE_HARDWARE,
dludwig@8369
    72
			nullptr,
dludwig@8369
    73
			creationFlags, // Set set debug and Direct2D compatibility flags.
dludwig@8369
    74
			featureLevels, // List of feature levels this app can support.
dludwig@8369
    75
			ARRAYSIZE(featureLevels),
dludwig@8369
    76
			D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps.
dludwig@8369
    77
			&device, // Returns the Direct3D device created.
dludwig@8369
    78
			&m_featureLevel, // Returns feature level of device created.
dludwig@8369
    79
			&context // Returns the device immediate context.
dludwig@8369
    80
			)
dludwig@8369
    81
		);
dludwig@8369
    82
dludwig@8369
    83
	// Get the Direct3D 11.1 API device and context interfaces.
dludwig@8369
    84
	DX::ThrowIfFailed(
dludwig@8369
    85
		device.As(&m_d3dDevice)
dludwig@8369
    86
		);
dludwig@8369
    87
dludwig@8369
    88
	DX::ThrowIfFailed(
dludwig@8369
    89
		context.As(&m_d3dContext)
dludwig@8369
    90
		);
dludwig@8369
    91
dludwig@8369
    92
    auto loadVSTask = DX::ReadDataAsync("SDL_VS2012_WinRT\\SimpleVertexShader.cso");
dludwig@8346
    93
	auto loadPSTask = DX::ReadDataAsync("SDL_VS2012_WinRT\\SimplePixelShader.cso");
dludwig@8322
    94
dludwig@8322
    95
	auto createVSTask = loadVSTask.then([this](Platform::Array<byte>^ fileData) {
dludwig@8322
    96
		DX::ThrowIfFailed(
dludwig@8322
    97
			m_d3dDevice->CreateVertexShader(
dludwig@8322
    98
 				fileData->Data,
dludwig@8322
    99
				fileData->Length,
dludwig@8322
   100
				nullptr,
dludwig@8322
   101
				&m_vertexShader
dludwig@8322
   102
				)
dludwig@8322
   103
			);
dludwig@8322
   104
dludwig@8322
   105
		const D3D11_INPUT_ELEMENT_DESC vertexDesc[] = 
dludwig@8322
   106
		{
dludwig@8322
   107
			{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,  D3D11_INPUT_PER_VERTEX_DATA, 0 },
dludwig@8348
   108
			{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
dludwig@8322
   109
		};
dludwig@8322
   110
dludwig@8322
   111
		DX::ThrowIfFailed(
dludwig@8322
   112
			m_d3dDevice->CreateInputLayout(
dludwig@8322
   113
				vertexDesc,
dludwig@8322
   114
				ARRAYSIZE(vertexDesc),
dludwig@8322
   115
				fileData->Data,
dludwig@8322
   116
				fileData->Length,
dludwig@8322
   117
				&m_inputLayout
dludwig@8322
   118
				)
dludwig@8322
   119
			);
dludwig@8322
   120
	});
dludwig@8322
   121
dludwig@8322
   122
	auto createPSTask = loadPSTask.then([this](Platform::Array<byte>^ fileData) {
dludwig@8322
   123
		DX::ThrowIfFailed(
dludwig@8322
   124
			m_d3dDevice->CreatePixelShader(
dludwig@8322
   125
				fileData->Data,
dludwig@8322
   126
				fileData->Length,
dludwig@8322
   127
				nullptr,
dludwig@8322
   128
				&m_pixelShader
dludwig@8322
   129
				)
dludwig@8322
   130
			);
dludwig@8322
   131
	});
dludwig@8322
   132
dludwig@8371
   133
	auto createVertexBuffer = (createPSTask && createVSTask).then([this] () {
dludwig@8371
   134
		VertexPositionColor vertices[] = 
dludwig@8322
   135
		{
dludwig@8350
   136
			{XMFLOAT3(-1.0f, -1.0f, 0.0f),  XMFLOAT2(0.0f, 1.0f)},
dludwig@8350
   137
			{XMFLOAT3(-1.0f, 1.0f, 0.0f), XMFLOAT2(0.0f, 0.0f)},
dludwig@8350
   138
			{XMFLOAT3(1.0f, -1.0f, 0.0f), XMFLOAT2(1.0f, 1.0f)},
dludwig@8350
   139
			{XMFLOAT3(1.0f, 1.0f, 0.0f), XMFLOAT2(1.0f, 0.0f)},
dludwig@8322
   140
		};
dludwig@8322
   141
dludwig@8371
   142
		m_vertexCount = ARRAYSIZE(vertices);
dludwig@8342
   143
dludwig@8322
   144
		D3D11_SUBRESOURCE_DATA vertexBufferData = {0};
dludwig@8371
   145
		vertexBufferData.pSysMem = vertices;
dludwig@8322
   146
		vertexBufferData.SysMemPitch = 0;
dludwig@8322
   147
		vertexBufferData.SysMemSlicePitch = 0;
dludwig@8371
   148
		CD3D11_BUFFER_DESC vertexBufferDesc(sizeof(vertices), D3D11_BIND_VERTEX_BUFFER);
dludwig@8322
   149
		DX::ThrowIfFailed(
dludwig@8322
   150
			m_d3dDevice->CreateBuffer(
dludwig@8322
   151
				&vertexBufferDesc,
dludwig@8322
   152
				&vertexBufferData,
dludwig@8322
   153
				&m_vertexBuffer
dludwig@8322
   154
				)
dludwig@8322
   155
			);
dludwig@8322
   156
	});
dludwig@8322
   157
dludwig@8371
   158
    auto createMainSamplerTask = createVertexBuffer.then([this] () {
dludwig@8347
   159
		D3D11_SAMPLER_DESC samplerDesc;
dludwig@8347
   160
		samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
dludwig@8347
   161
		samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
dludwig@8347
   162
		samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
dludwig@8347
   163
		samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
dludwig@8347
   164
		samplerDesc.MipLODBias = 0.0f;
dludwig@8347
   165
		samplerDesc.MaxAnisotropy = 1;
dludwig@8347
   166
		samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
dludwig@8347
   167
		samplerDesc.BorderColor[0] = 0.0f;
dludwig@8347
   168
		samplerDesc.BorderColor[1] = 0.0f;
dludwig@8347
   169
		samplerDesc.BorderColor[2] = 0.0f;
dludwig@8347
   170
		samplerDesc.BorderColor[3] = 0.0f;
dludwig@8347
   171
		samplerDesc.MinLOD = 0.0f;
dludwig@8347
   172
		samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
dludwig@8347
   173
		DX::ThrowIfFailed(
dludwig@8347
   174
			m_d3dDevice->CreateSamplerState(
dludwig@8347
   175
				&samplerDesc,
dludwig@8347
   176
				&m_mainSampler
dludwig@8347
   177
				)
dludwig@8347
   178
			);
dludwig@8347
   179
	});
dludwig@8347
   180
dludwig@8347
   181
	createMainSamplerTask.then([this] () {
dludwig@8322
   182
		m_loadingComplete = true;
dludwig@8322
   183
	});
dludwig@8322
   184
}
dludwig@8322
   185
dludwig@8369
   186
// Allocate all memory resources that change on a window SizeChanged event.
dludwig@8369
   187
void SDL_winrtrenderer::CreateWindowSizeDependentResources()
dludwig@8369
   188
{ 
dludwig@8369
   189
	// Store the window bounds so the next time we get a SizeChanged event we can
dludwig@8369
   190
	// avoid rebuilding everything if the size is identical.
dludwig@8369
   191
	m_windowBounds = m_window->Bounds;
dludwig@8369
   192
dludwig@8369
   193
	// Calculate the necessary swap chain and render target size in pixels.
dludwig@8369
   194
	float windowWidth = ConvertDipsToPixels(m_windowBounds.Width);
dludwig@8369
   195
	float windowHeight = ConvertDipsToPixels(m_windowBounds.Height);
dludwig@8369
   196
dludwig@8369
   197
	// The width and height of the swap chain must be based on the window's
dludwig@8369
   198
	// landscape-oriented width and height. If the window is in a portrait
dludwig@8369
   199
	// orientation, the dimensions must be reversed.
dludwig@8369
   200
	m_orientation = DisplayProperties::CurrentOrientation;
dludwig@8369
   201
	bool swapDimensions =
dludwig@8369
   202
		m_orientation == DisplayOrientations::Portrait ||
dludwig@8369
   203
		m_orientation == DisplayOrientations::PortraitFlipped;
dludwig@8369
   204
	m_renderTargetSize.Width = swapDimensions ? windowHeight : windowWidth;
dludwig@8369
   205
	m_renderTargetSize.Height = swapDimensions ? windowWidth : windowHeight;
dludwig@8369
   206
dludwig@8369
   207
	if(m_swapChain != nullptr)
dludwig@8369
   208
	{
dludwig@8369
   209
		// If the swap chain already exists, resize it.
dludwig@8369
   210
		DX::ThrowIfFailed(
dludwig@8369
   211
			m_swapChain->ResizeBuffers(
dludwig@8369
   212
				2, // Double-buffered swap chain.
dludwig@8369
   213
				static_cast<UINT>(m_renderTargetSize.Width),
dludwig@8369
   214
				static_cast<UINT>(m_renderTargetSize.Height),
dludwig@8369
   215
				DXGI_FORMAT_B8G8R8A8_UNORM,
dludwig@8369
   216
				0
dludwig@8369
   217
				)
dludwig@8369
   218
			);
dludwig@8369
   219
	}
dludwig@8369
   220
	else
dludwig@8369
   221
	{
dludwig@8369
   222
		// Otherwise, create a new one using the same adapter as the existing Direct3D device.
dludwig@8369
   223
		DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
dludwig@8369
   224
		swapChainDesc.Width = static_cast<UINT>(m_renderTargetSize.Width); // Match the size of the window.
dludwig@8369
   225
		swapChainDesc.Height = static_cast<UINT>(m_renderTargetSize.Height);
dludwig@8369
   226
		swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // This is the most common swap chain format.
dludwig@8369
   227
		swapChainDesc.Stereo = false;
dludwig@8369
   228
		swapChainDesc.SampleDesc.Count = 1; // Don't use multi-sampling.
dludwig@8369
   229
		swapChainDesc.SampleDesc.Quality = 0;
dludwig@8369
   230
		swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
dludwig@8369
   231
		swapChainDesc.BufferCount = 2; // Use double-buffering to minimize latency.
dludwig@8369
   232
		swapChainDesc.Scaling = DXGI_SCALING_NONE;
dludwig@8369
   233
		swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // All Windows Store apps must use this SwapEffect.
dludwig@8369
   234
		swapChainDesc.Flags = 0;
dludwig@8369
   235
dludwig@8369
   236
		ComPtr<IDXGIDevice1>  dxgiDevice;
dludwig@8369
   237
		DX::ThrowIfFailed(
dludwig@8369
   238
			m_d3dDevice.As(&dxgiDevice)
dludwig@8369
   239
			);
dludwig@8369
   240
dludwig@8369
   241
		ComPtr<IDXGIAdapter> dxgiAdapter;
dludwig@8369
   242
		DX::ThrowIfFailed(
dludwig@8369
   243
			dxgiDevice->GetAdapter(&dxgiAdapter)
dludwig@8369
   244
			);
dludwig@8369
   245
dludwig@8369
   246
		ComPtr<IDXGIFactory2> dxgiFactory;
dludwig@8369
   247
		DX::ThrowIfFailed(
dludwig@8369
   248
			dxgiAdapter->GetParent(
dludwig@8369
   249
				__uuidof(IDXGIFactory2), 
dludwig@8369
   250
				&dxgiFactory
dludwig@8369
   251
				)
dludwig@8369
   252
			);
dludwig@8369
   253
dludwig@8369
   254
		Windows::UI::Core::CoreWindow^ window = m_window.Get();
dludwig@8369
   255
		DX::ThrowIfFailed(
dludwig@8369
   256
			dxgiFactory->CreateSwapChainForCoreWindow(
dludwig@8369
   257
				m_d3dDevice.Get(),
dludwig@8369
   258
				reinterpret_cast<IUnknown*>(window),
dludwig@8369
   259
				&swapChainDesc,
dludwig@8369
   260
				nullptr, // Allow on all displays.
dludwig@8369
   261
				&m_swapChain
dludwig@8369
   262
				)
dludwig@8369
   263
			);
dludwig@8369
   264
			
dludwig@8369
   265
		// Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and
dludwig@8369
   266
		// ensures that the application will only render after each VSync, minimizing power consumption.
dludwig@8369
   267
		DX::ThrowIfFailed(
dludwig@8369
   268
			dxgiDevice->SetMaximumFrameLatency(1)
dludwig@8369
   269
			);
dludwig@8369
   270
	}
dludwig@8369
   271
	
dludwig@8369
   272
	// Set the proper orientation for the swap chain, and generate the
dludwig@8369
   273
	// 3D matrix transformation for rendering to the rotated swap chain.
dludwig@8369
   274
	DXGI_MODE_ROTATION rotation = DXGI_MODE_ROTATION_UNSPECIFIED;
dludwig@8369
   275
	switch (m_orientation)
dludwig@8369
   276
	{
dludwig@8369
   277
		case DisplayOrientations::Landscape:
dludwig@8369
   278
			rotation = DXGI_MODE_ROTATION_IDENTITY;
dludwig@8369
   279
			m_orientationTransform3D = XMFLOAT4X4( // 0-degree Z-rotation
dludwig@8369
   280
				1.0f, 0.0f, 0.0f, 0.0f,
dludwig@8369
   281
				0.0f, 1.0f, 0.0f, 0.0f,
dludwig@8369
   282
				0.0f, 0.0f, 1.0f, 0.0f,
dludwig@8369
   283
				0.0f, 0.0f, 0.0f, 1.0f
dludwig@8369
   284
				);
dludwig@8369
   285
			break;
dludwig@8369
   286
dludwig@8369
   287
		case DisplayOrientations::Portrait:
dludwig@8369
   288
			rotation = DXGI_MODE_ROTATION_ROTATE270;
dludwig@8369
   289
			m_orientationTransform3D = XMFLOAT4X4( // 90-degree Z-rotation
dludwig@8369
   290
				0.0f, 1.0f, 0.0f, 0.0f,
dludwig@8369
   291
				-1.0f, 0.0f, 0.0f, 0.0f,
dludwig@8369
   292
				0.0f, 0.0f, 1.0f, 0.0f,
dludwig@8369
   293
				0.0f, 0.0f, 0.0f, 1.0f
dludwig@8369
   294
				);
dludwig@8369
   295
			break;
dludwig@8369
   296
dludwig@8369
   297
		case DisplayOrientations::LandscapeFlipped:
dludwig@8369
   298
			rotation = DXGI_MODE_ROTATION_ROTATE180;
dludwig@8369
   299
			m_orientationTransform3D = XMFLOAT4X4( // 180-degree Z-rotation
dludwig@8369
   300
				-1.0f, 0.0f, 0.0f, 0.0f,
dludwig@8369
   301
				0.0f, -1.0f, 0.0f, 0.0f,
dludwig@8369
   302
				0.0f, 0.0f, 1.0f, 0.0f,
dludwig@8369
   303
				0.0f, 0.0f, 0.0f, 1.0f
dludwig@8369
   304
				);
dludwig@8369
   305
			break;
dludwig@8369
   306
dludwig@8369
   307
		case DisplayOrientations::PortraitFlipped:
dludwig@8369
   308
			rotation = DXGI_MODE_ROTATION_ROTATE90;
dludwig@8369
   309
			m_orientationTransform3D = XMFLOAT4X4( // 270-degree Z-rotation
dludwig@8369
   310
				0.0f, -1.0f, 0.0f, 0.0f,
dludwig@8369
   311
				1.0f, 0.0f, 0.0f, 0.0f,
dludwig@8369
   312
				0.0f, 0.0f, 1.0f, 0.0f,
dludwig@8369
   313
				0.0f, 0.0f, 0.0f, 1.0f
dludwig@8369
   314
				);
dludwig@8369
   315
			break;
dludwig@8369
   316
dludwig@8369
   317
		default:
dludwig@8369
   318
			throw ref new Platform::FailureException();
dludwig@8369
   319
	}
dludwig@8369
   320
dludwig@8369
   321
	DX::ThrowIfFailed(
dludwig@8369
   322
		m_swapChain->SetRotation(rotation)
dludwig@8369
   323
		);
dludwig@8369
   324
dludwig@8369
   325
	// Create a render target view of the swap chain back buffer.
dludwig@8369
   326
	ComPtr<ID3D11Texture2D> backBuffer;
dludwig@8369
   327
	DX::ThrowIfFailed(
dludwig@8369
   328
		m_swapChain->GetBuffer(
dludwig@8369
   329
			0,
dludwig@8369
   330
			__uuidof(ID3D11Texture2D),
dludwig@8369
   331
			&backBuffer
dludwig@8369
   332
			)
dludwig@8369
   333
		);
dludwig@8369
   334
dludwig@8369
   335
	DX::ThrowIfFailed(
dludwig@8369
   336
		m_d3dDevice->CreateRenderTargetView(
dludwig@8369
   337
			backBuffer.Get(),
dludwig@8369
   338
			nullptr,
dludwig@8369
   339
			&m_renderTargetView
dludwig@8369
   340
			)
dludwig@8369
   341
		);
dludwig@8369
   342
dludwig@8369
   343
	// Create a depth stencil view.
dludwig@8369
   344
	CD3D11_TEXTURE2D_DESC depthStencilDesc(
dludwig@8369
   345
		DXGI_FORMAT_D24_UNORM_S8_UINT, 
dludwig@8369
   346
		static_cast<UINT>(m_renderTargetSize.Width),
dludwig@8369
   347
		static_cast<UINT>(m_renderTargetSize.Height),
dludwig@8369
   348
		1,
dludwig@8369
   349
		1,
dludwig@8369
   350
		D3D11_BIND_DEPTH_STENCIL
dludwig@8369
   351
		);
dludwig@8369
   352
dludwig@8369
   353
	ComPtr<ID3D11Texture2D> depthStencil;
dludwig@8369
   354
	DX::ThrowIfFailed(
dludwig@8369
   355
		m_d3dDevice->CreateTexture2D(
dludwig@8369
   356
			&depthStencilDesc,
dludwig@8369
   357
			nullptr,
dludwig@8369
   358
			&depthStencil
dludwig@8369
   359
			)
dludwig@8369
   360
		);
dludwig@8369
   361
dludwig@8369
   362
	// Set the rendering viewport to target the entire window.
dludwig@8369
   363
	CD3D11_VIEWPORT viewport(
dludwig@8369
   364
		0.0f,
dludwig@8369
   365
		0.0f,
dludwig@8369
   366
		m_renderTargetSize.Width,
dludwig@8369
   367
		m_renderTargetSize.Height
dludwig@8369
   368
		);
dludwig@8369
   369
dludwig@8369
   370
	m_d3dContext->RSSetViewports(1, &viewport);
dludwig@8369
   371
}
dludwig@8369
   372
dludwig@8367
   373
void SDL_winrtrenderer::ResizeMainTexture(int w, int h)
dludwig@8367
   374
{
dludwig@8367
   375
    D3D11_TEXTURE2D_DESC textureDesc = {0};
dludwig@8367
   376
	textureDesc.Width = w;
dludwig@8367
   377
	textureDesc.Height = h;
dludwig@8367
   378
	textureDesc.MipLevels = 1;
dludwig@8367
   379
	textureDesc.ArraySize = 1;
dludwig@8367
   380
	textureDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
dludwig@8367
   381
	textureDesc.SampleDesc.Count = 1;
dludwig@8367
   382
	textureDesc.SampleDesc.Quality = 0;
dludwig@8367
   383
	textureDesc.Usage = D3D11_USAGE_DYNAMIC;
dludwig@8367
   384
	textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
dludwig@8367
   385
	textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
dludwig@8367
   386
	textureDesc.MiscFlags = 0;
dludwig@8367
   387
dludwig@8367
   388
	const int numPixels = textureDesc.Width * textureDesc.Height;
dludwig@8367
   389
	std::vector<uint8> initialTexturePixels(numPixels * 4, 0x00);
dludwig@8367
   390
	D3D11_SUBRESOURCE_DATA initialTextureData = {0};
dludwig@8367
   391
	initialTextureData.pSysMem = (void *)&(initialTexturePixels[0]);
dludwig@8367
   392
	initialTextureData.SysMemPitch = textureDesc.Width * 4;
dludwig@8367
   393
	initialTextureData.SysMemSlicePitch = numPixels * 4;
dludwig@8367
   394
	DX::ThrowIfFailed(
dludwig@8367
   395
		m_d3dDevice->CreateTexture2D(
dludwig@8367
   396
			&textureDesc,
dludwig@8367
   397
			&initialTextureData,
dludwig@8367
   398
			&m_mainTexture
dludwig@8367
   399
			)
dludwig@8367
   400
		);
dludwig@8367
   401
dludwig@8367
   402
	D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
dludwig@8367
   403
	resourceViewDesc.Format = textureDesc.Format;
dludwig@8367
   404
	resourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
dludwig@8367
   405
	resourceViewDesc.Texture2D.MostDetailedMip = 0;
dludwig@8367
   406
	resourceViewDesc.Texture2D.MipLevels = textureDesc.MipLevels;
dludwig@8367
   407
	DX::ThrowIfFailed(
dludwig@8367
   408
		m_d3dDevice->CreateShaderResourceView(
dludwig@8367
   409
			m_mainTexture.Get(),
dludwig@8367
   410
			&resourceViewDesc,
dludwig@8367
   411
			&m_mainTextureResourceView)
dludwig@8367
   412
		);
dludwig@8367
   413
}
dludwig@8367
   414
dludwig@8369
   415
// This method is called in the event handler for the SizeChanged event.
dludwig@8369
   416
void SDL_winrtrenderer::UpdateForWindowSizeChange()
dludwig@8369
   417
{
dludwig@8369
   418
	if (m_window->Bounds.Width  != m_windowBounds.Width ||
dludwig@8369
   419
		m_window->Bounds.Height != m_windowBounds.Height ||
dludwig@8369
   420
		m_orientation != DisplayProperties::CurrentOrientation)
dludwig@8369
   421
	{
dludwig@8369
   422
		ID3D11RenderTargetView* nullViews[] = {nullptr};
dludwig@8369
   423
		m_d3dContext->OMSetRenderTargets(ARRAYSIZE(nullViews), nullViews, nullptr);
dludwig@8369
   424
		m_renderTargetView = nullptr;
dludwig@8369
   425
		m_d3dContext->Flush();
dludwig@8369
   426
		CreateWindowSizeDependentResources();
dludwig@8369
   427
	}
dludwig@8369
   428
}
dludwig@8369
   429
dludwig@8350
   430
void SDL_winrtrenderer::Render(SDL_Surface * surface, SDL_Rect * rects, int numrects)
dludwig@8322
   431
{
dludwig@8350
   432
	const float blackColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
dludwig@8322
   433
	m_d3dContext->ClearRenderTargetView(
dludwig@8322
   434
		m_renderTargetView.Get(),
dludwig@8350
   435
		blackColor
dludwig@8322
   436
		);
dludwig@8322
   437
dludwig@8371
   438
	// Only draw the screen once it is loaded (some loading is asynchronous).
dludwig@8322
   439
	if (!m_loadingComplete)
dludwig@8322
   440
	{
dludwig@8322
   441
		return;
dludwig@8322
   442
	}
dludwig@8367
   443
    if (!m_mainTextureResourceView)
dludwig@8367
   444
    {
dludwig@8367
   445
        return;
dludwig@8367
   446
    }
dludwig@8322
   447
dludwig@8349
   448
	// Update the main texture (for SDL usage):
dludwig@8349
   449
	D3D11_MAPPED_SUBRESOURCE textureMemory = {0};
dludwig@8349
   450
	DX::ThrowIfFailed(
dludwig@8349
   451
		m_d3dContext->Map(
dludwig@8349
   452
			m_mainTexture.Get(),
dludwig@8349
   453
			0,
dludwig@8349
   454
			D3D11_MAP_WRITE_DISCARD,
dludwig@8349
   455
			0,
dludwig@8349
   456
			&textureMemory)
dludwig@8349
   457
		);
dludwig@8349
   458
dludwig@8350
   459
	// TODO, WinRT: only copy over the requested rects (via SDL_BlitSurface, perhaps?)
dludwig@8350
   460
	// TODO, WinRT: do a sanity check on the src and dest data when updating the window surface
dludwig@8367
   461
    D3D11_TEXTURE2D_DESC textureDesc = {0};
dludwig@8367
   462
    m_mainTexture->GetDesc(&textureDesc);
dludwig@8367
   463
	const unsigned int numBytes = textureDesc.Width * textureDesc.Height * 4;
dludwig@8350
   464
	memcpy(textureMemory.pData, surface->pixels, numBytes);
dludwig@8349
   465
dludwig@8349
   466
	m_d3dContext->Unmap(
dludwig@8349
   467
		m_mainTexture.Get(),
dludwig@8349
   468
		0);
dludwig@8349
   469
dludwig@8322
   470
	m_d3dContext->OMSetRenderTargets(
dludwig@8322
   471
		1,
dludwig@8322
   472
		m_renderTargetView.GetAddressOf(),
dludwig@8370
   473
		nullptr
dludwig@8322
   474
		);
dludwig@8322
   475
dludwig@8322
   476
	UINT stride = sizeof(VertexPositionColor);
dludwig@8322
   477
	UINT offset = 0;
dludwig@8322
   478
	m_d3dContext->IASetVertexBuffers(
dludwig@8322
   479
		0,
dludwig@8322
   480
		1,
dludwig@8322
   481
		m_vertexBuffer.GetAddressOf(),
dludwig@8322
   482
		&stride,
dludwig@8322
   483
		&offset
dludwig@8322
   484
		);
dludwig@8322
   485
dludwig@8342
   486
	m_d3dContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
dludwig@8322
   487
dludwig@8322
   488
	m_d3dContext->IASetInputLayout(m_inputLayout.Get());
dludwig@8322
   489
dludwig@8322
   490
	m_d3dContext->VSSetShader(
dludwig@8322
   491
		m_vertexShader.Get(),
dludwig@8322
   492
		nullptr,
dludwig@8322
   493
		0
dludwig@8322
   494
		);
dludwig@8322
   495
dludwig@8322
   496
	m_d3dContext->PSSetShader(
dludwig@8322
   497
		m_pixelShader.Get(),
dludwig@8322
   498
		nullptr,
dludwig@8322
   499
		0
dludwig@8322
   500
		);
dludwig@8322
   501
dludwig@8347
   502
	m_d3dContext->PSSetShaderResources(0, 1, m_mainTextureResourceView.GetAddressOf());
dludwig@8347
   503
dludwig@8347
   504
	m_d3dContext->PSSetSamplers(0, 1, m_mainSampler.GetAddressOf());
dludwig@8347
   505
dludwig@8342
   506
	m_d3dContext->Draw(4, 0);
dludwig@8322
   507
}
dludwig@8369
   508
dludwig@8369
   509
// Method to deliver the final image to the display.
dludwig@8369
   510
void SDL_winrtrenderer::Present()
dludwig@8369
   511
{
dludwig@8369
   512
	// The application may optionally specify "dirty" or "scroll"
dludwig@8369
   513
	// rects to improve efficiency in certain scenarios.
dludwig@8369
   514
	DXGI_PRESENT_PARAMETERS parameters = {0};
dludwig@8369
   515
	parameters.DirtyRectsCount = 0;
dludwig@8369
   516
	parameters.pDirtyRects = nullptr;
dludwig@8369
   517
	parameters.pScrollRect = nullptr;
dludwig@8369
   518
	parameters.pScrollOffset = nullptr;
dludwig@8369
   519
	
dludwig@8369
   520
	// The first argument instructs DXGI to block until VSync, putting the application
dludwig@8369
   521
	// to sleep until the next VSync. This ensures we don't waste any cycles rendering
dludwig@8369
   522
	// frames that will never be displayed to the screen.
dludwig@8369
   523
	HRESULT hr = m_swapChain->Present1(1, 0, &parameters);
dludwig@8369
   524
dludwig@8369
   525
	// Discard the contents of the render target.
dludwig@8369
   526
	// This is a valid operation only when the existing contents will be entirely
dludwig@8369
   527
	// overwritten. If dirty or scroll rects are used, this call should be removed.
dludwig@8369
   528
	m_d3dContext->DiscardView(m_renderTargetView.Get());
dludwig@8369
   529
dludwig@8369
   530
	// If the device was removed either by a disconnect or a driver upgrade, we 
dludwig@8369
   531
	// must recreate all device resources.
dludwig@8369
   532
	if (hr == DXGI_ERROR_DEVICE_REMOVED)
dludwig@8369
   533
	{
dludwig@8369
   534
		HandleDeviceLost();
dludwig@8369
   535
	}
dludwig@8369
   536
	else
dludwig@8369
   537
	{
dludwig@8369
   538
		DX::ThrowIfFailed(hr);
dludwig@8369
   539
	}
dludwig@8369
   540
}
dludwig@8369
   541
dludwig@8369
   542
// Method to convert a length in device-independent pixels (DIPs) to a length in physical pixels.
dludwig@8369
   543
float SDL_winrtrenderer::ConvertDipsToPixels(float dips)
dludwig@8369
   544
{
dludwig@8369
   545
	static const float dipsPerInch = 96.0f;
dludwig@8369
   546
	return floor(dips * DisplayProperties::LogicalDpi / dipsPerInch + 0.5f); // Round to nearest integer.
dludwig@8369
   547
}