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