From 0ae0ba63c086a529b4849647317ea02d9f829267 Mon Sep 17 00:00:00 2001 From: Nomango <569629550@qq.com> Date: Sun, 10 Mar 2019 19:44:28 +0800 Subject: [PATCH] Direct3D10 support --- project/Easy2D/Easy2D.vcxproj | 2 + project/Easy2D/Easy2D.vcxproj.filters | 6 + src/core/Singleton.hpp | 2 +- src/core/config.h | 2 + src/core/modules.cpp | 36 --- src/core/modules.h | 28 -- src/core/render.h | 2 - src/dx/D2DDeviceResources.cpp | 11 +- src/dx/D2DDeviceResources.h | 1 + src/dx/D3D10DeviceResources.cpp | 434 ++++++++++++++++++++++++++ src/dx/D3D10DeviceResources.h | 87 ++++++ src/dx/D3D11DeviceResources.cpp | 140 ++++++--- src/dx/D3D11DeviceResources.h | 26 +- src/dx/DeviceResources.h | 14 +- src/math/Matrix.hpp | 2 +- 15 files changed, 665 insertions(+), 128 deletions(-) create mode 100644 src/dx/D3D10DeviceResources.cpp create mode 100644 src/dx/D3D10DeviceResources.h diff --git a/project/Easy2D/Easy2D.vcxproj b/project/Easy2D/Easy2D.vcxproj index a5a99d20..82024beb 100644 --- a/project/Easy2D/Easy2D.vcxproj +++ b/project/Easy2D/Easy2D.vcxproj @@ -51,6 +51,7 @@ + @@ -107,6 +108,7 @@ + diff --git a/project/Easy2D/Easy2D.vcxproj.filters b/project/Easy2D/Easy2D.vcxproj.filters index 4ca70313..bed14fd0 100644 --- a/project/Easy2D/Easy2D.vcxproj.filters +++ b/project/Easy2D/Easy2D.vcxproj.filters @@ -229,6 +229,9 @@ dx + + dx + @@ -366,5 +369,8 @@ dx + + dx + \ No newline at end of file diff --git a/src/core/Singleton.hpp b/src/core/Singleton.hpp index c7f4b099..d5d630ff 100644 --- a/src/core/Singleton.hpp +++ b/src/core/Singleton.hpp @@ -43,7 +43,7 @@ namespace easy2d } // Class that will implement the singleton mode, -// must use the macro in it's delare file +// must use the macro in its delare file #ifndef E2D_DECLARE_SINGLETON #define E2D_DECLARE_SINGLETON( type ) \ diff --git a/src/core/config.h b/src/core/config.h index cd378bfd..14a053df 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -21,3 +21,5 @@ //#define E2D_API __declspec( dllexport ) //#define E2D_API __declspec( dllimport ) +//---- Define DirectX version. Defaults to using Direct3D11 +//#define E2D_USE_DIRECTX10 diff --git a/src/core/modules.cpp b/src/core/modules.cpp index 5bc4e84c..5292d6f4 100644 --- a/src/core/modules.cpp +++ b/src/core/modules.cpp @@ -42,42 +42,6 @@ namespace easy2d } } - DirectX::DirectX() - { - d2d = LoadLibraryW(L"d2d1.dll"); - if (d2d) - { - D2D1CreateFactory = (PFN_D2D1CreateFactory) - GetProcAddress(d2d, "D2D1CreateFactory"); - } - else - { - E2D_LOG(L"load d2d.dll failed"); - } - - dwrite = LoadLibraryW(L"dwrite.dll"); - if (dwrite) - { - DWriteCreateFactory = (PFN_DWriteCreateFactory) - GetProcAddress(dwrite, "DWriteCreateFactory"); - } - else - { - E2D_LOG(L"load dwrite.dll failed"); - } - - d3d11 = LoadLibraryW(L"d3d11.dll"); - if (d3d11) - { - D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE) - GetProcAddress(d3d11, "D3D11CreateDevice"); - } - else - { - E2D_LOG(L"load d3d11.dll failed"); - } - } - XAudio2::XAudio2() { const auto xaudio2_dll_names = diff --git a/src/core/modules.h b/src/core/modules.h index 998eee76..339d263f 100644 --- a/src/core/modules.h +++ b/src/core/modules.h @@ -20,13 +20,10 @@ #pragma once #include "macros.h" -#include -#include #include #include #include #include -#include namespace easy2d { @@ -54,31 +51,6 @@ namespace easy2d }; - class E2D_API DirectX - { - DirectX(); - - HMODULE d3d11; - HMODULE d2d; - HMODULE dwrite; - - // DirectX functions - typedef HRESULT(WINAPI *PFN_D2D1CreateFactory)(D2D1_FACTORY_TYPE, const IID&, const D2D1_FACTORY_OPTIONS*, void **); - typedef HRESULT(WINAPI *PFN_DWriteCreateFactory)(DWRITE_FACTORY_TYPE, const IID&, IUnknown **); - - public: - static DirectX& Get() - { - static DirectX instance; - return instance; - } - - PFN_D2D1CreateFactory D2D1CreateFactory; - PFN_DWriteCreateFactory DWriteCreateFactory; - PFN_D3D11_CREATE_DEVICE D3D11CreateDevice; - }; - - class E2D_API XAudio2 { XAudio2(); diff --git a/src/core/render.h b/src/core/render.h index 79135d98..d7458d0b 100644 --- a/src/core/render.h +++ b/src/core/render.h @@ -28,8 +28,6 @@ #include "../DX/DeviceResources.h" #include "../DX/TextRenderer.h" #include "time.h" -#include -#include namespace easy2d { diff --git a/src/dx/D2DDeviceResources.cpp b/src/dx/D2DDeviceResources.cpp index 78bfd705..821bab11 100644 --- a/src/dx/D2DDeviceResources.cpp +++ b/src/dx/D2DDeviceResources.cpp @@ -18,11 +18,14 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include "DeviceResources.h" +#include "D2DDeviceResources.h" #include "../core/Image.h" #include "../core/modules.h" #include "../core/logs.h" +#pragma comment(lib, "d2d1.lib") +#pragma comment(lib, "dwrite.lib") + namespace easy2d { @@ -106,7 +109,7 @@ namespace easy2d options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION; #endif - hr = modules::DirectX::Get().D2D1CreateFactory( + hr = D2D1CreateFactory( D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory1), &options, @@ -117,7 +120,7 @@ namespace easy2d { d2d_factory_ = d2d_factory; - CoCreateInstance( + hr = CoCreateInstance( CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, @@ -130,7 +133,7 @@ namespace easy2d { imaging_factory_ = imaging_factory; - modules::DirectX::Get().DWriteCreateFactory( + hr = DWriteCreateFactory( DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast(&dwrite_factory) diff --git a/src/dx/D2DDeviceResources.h b/src/dx/D2DDeviceResources.h index e9555828..4eabae91 100644 --- a/src/dx/D2DDeviceResources.h +++ b/src/dx/D2DDeviceResources.h @@ -23,6 +23,7 @@ #include "../core/Resource.h" #include "../core/Font.hpp" #include "../core/TextStyle.hpp" +#include #include #include diff --git a/src/dx/D3D10DeviceResources.cpp b/src/dx/D3D10DeviceResources.cpp new file mode 100644 index 00000000..3b0d4a4c --- /dev/null +++ b/src/dx/D3D10DeviceResources.cpp @@ -0,0 +1,434 @@ +// Copyright (c) 2016-2018 Easy2D - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include "D3D10DeviceResources.h" + +#ifdef E2D_USE_DIRECTX10 + +#include "../core/Image.h" +#include "../core/logs.h" + +#pragma comment(lib, "d3d10_1.lib") + +namespace easy2d +{ +#if defined(_DEBUG) + namespace DX + { + HRESULT CreateD3DDevice(IDXGIAdapter *adapter, D3D10_DRIVER_TYPE driver_type, UINT flags, ID3D10Device1 **device) + { + HRESULT hr = S_OK; + + static const D3D10_FEATURE_LEVEL1 levels[] = + { + D3D10_FEATURE_LEVEL_10_1, + D3D10_FEATURE_LEVEL_10_0, + D3D10_FEATURE_LEVEL_9_3, + D3D10_FEATURE_LEVEL_9_2, + D3D10_FEATURE_LEVEL_9_1, + }; + + for (UINT level = 0; level < ARRAYSIZE(levels); level++) + { + hr = D3D10CreateDevice1( + adapter, + driver_type, + NULL, + flags, + levels[level], + D3D10_1_SDK_VERSION, + device + ); + + if (SUCCEEDED(hr)) + break; + } + return hr; + } + + inline bool SdkLayersAvailable() + { + HRESULT hr = CreateD3DDevice( + NULL, + D3D10_DRIVER_TYPE_NULL, // There is no need to create a real hardware device. + D3D10_CREATE_DEVICE_DEBUG, // Check for the SDK layers. + nullptr // No need to keep the D3D device reference. + ); + + return SUCCEEDED(hr); + } + } +#endif + + D3D10DeviceResources::D3D10DeviceResources() + : hwnd_(nullptr) + { + dpi_ = 96.f; // dpi_ = (float)GetDpiForWindow(hwnd); + } + + D3D10DeviceResources::~D3D10DeviceResources() + { + DiscardResources(); + } + + HRESULT D3D10DeviceResources::Create(D3D10DeviceResources** device_resources, HWND hwnd) + { + HRESULT hr = E_FAIL; + + if (device_resources) + { + D3D10DeviceResources* res = new (std::nothrow) D3D10DeviceResources; + if (res) + { + hr = res->CreateDeviceIndependentResources(); + + if (SUCCEEDED(hr)) + { + RECT rc; + GetClientRect(hwnd, &rc); + + res->hwnd_ = hwnd; + res->logical_size_.x = float(rc.right - rc.left); + res->logical_size_.y = float(rc.bottom - rc.top); + + hr = res->CreateDeviceResources(); + } + + if (SUCCEEDED(hr)) + { + hr = res->CreateWindowSizeDependentResources(); + } + + if (SUCCEEDED(hr)) + { + res->AddRef(); + + DX::SafeRelease(*device_resources); + (*device_resources) = res; + } + else + { + delete res; + res = nullptr; + } + } + } + return hr; + } + + void D3D10DeviceResources::DiscardResources() + { + d3d_device_.Reset(); + d3d_rt_view_.Reset(); + d3d_ds_view_.Reset(); + dxgi_swap_chain_.Reset(); + dxgi_factory_.Reset(); + + hwnd_ = nullptr; + } + + HRESULT D3D10DeviceResources::CreateDeviceResources() + { + HRESULT hr = S_OK; + + // This flag adds support for surfaces with a different color channel ordering + // than the API default. It is required for compatibility with Direct2D. + UINT creation_flags = D3D10_CREATE_DEVICE_BGRA_SUPPORT; + +#if defined(E2D_DEBUG) + if (DX::SdkLayersAvailable()) + { + creation_flags |= D3D10_CREATE_DEVICE_DEBUG; + } +#endif + + ComPtr device; + hr = DX::CreateD3DDevice( + NULL, + D3D10_DRIVER_TYPE_HARDWARE, + creation_flags, + &device + ); + + if (SUCCEEDED(hr)) + { + d3d_device_ = device; + + ComPtr dxgi_adapter; + ComPtr dxgi_device; + ComPtr dxgi_factory; + ComPtr d2d_device; + + if (SUCCEEDED(hr)) + { + hr = d3d_device_->QueryInterface(IID_PPV_ARGS(&dxgi_device)); + } + + if (SUCCEEDED(hr)) + { + hr = dxgi_device->GetAdapter(&dxgi_adapter); + } + + if (SUCCEEDED(hr)) + { + hr = dxgi_adapter->GetParent(IID_PPV_ARGS(&dxgi_factory)); + } + + if (SUCCEEDED(hr)) + { + dxgi_factory_ = dxgi_factory; + } + + // Create the Direct2D device object and a corresponding context. + if (SUCCEEDED(hr)) + { + hr = GetD2DFactory()->CreateDevice(dxgi_device.Get(), &d2d_device); + } + + if (SUCCEEDED(hr)) + { + hr = SetD2DDevice(d2d_device); + } + } + + if (SUCCEEDED(hr)) + { + // Setup swap chain + DXGI_SWAP_CHAIN_DESC swap_chain_desc = { 0 }; + + swap_chain_desc.BufferCount = 2; + swap_chain_desc.BufferDesc.Width = ::lround(output_size_.x); + swap_chain_desc.BufferDesc.Height = ::lround(output_size_.y); + swap_chain_desc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + swap_chain_desc.BufferDesc.RefreshRate.Numerator = 60; + swap_chain_desc.BufferDesc.RefreshRate.Denominator = 1; + swap_chain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; + swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swap_chain_desc.OutputWindow = hwnd_; + swap_chain_desc.SampleDesc.Count = 1; + swap_chain_desc.SampleDesc.Quality = 0; + swap_chain_desc.Windowed = TRUE; + swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + + ComPtr dxgi_device; + if (SUCCEEDED(hr)) + { + hr = d3d_device_->QueryInterface(&dxgi_device); + } + + ComPtr dxgi_adapter; + if (SUCCEEDED(hr)) + { + hr = dxgi_device->GetAdapter(&dxgi_adapter); + } + + ComPtr dxgi_factory; + if (SUCCEEDED(hr)) + { + hr = dxgi_adapter->GetParent(IID_PPV_ARGS(&dxgi_factory)); + } + + if (SUCCEEDED(hr)) + { + hr = dxgi_factory->CreateSwapChain( + d3d_device_.Get(), + &swap_chain_desc, + &dxgi_swap_chain_); + } + } + + return hr; + } + + HRESULT D3D10DeviceResources::CreateWindowSizeDependentResources() + { + if (!dxgi_swap_chain_) + return E_UNEXPECTED; + + HRESULT hr = S_OK; + + // Clear the previous window size specific context. + ID3D10RenderTargetView* null_views[] = { nullptr }; + SetTargetBitmap(nullptr); + d3d_device_->OMSetRenderTargets(ARRAYSIZE(null_views), null_views, nullptr); + d3d_device_->Flush(); + + // Calculate the necessary render target size in pixels. + output_size_.x = DX::ConvertDipsToPixels(logical_size_.x, dpi_); + output_size_.y = DX::ConvertDipsToPixels(logical_size_.y, dpi_); + + // Prevent zero size DirectX content from being created. + output_size_.x = std::max(output_size_.x, 1.f); + output_size_.y = std::max(output_size_.y, 1.f); + + // If the swap chain already exists, resize it. + hr = dxgi_swap_chain_->ResizeBuffers( + 2, // Double-buffered swap chain. + ::lround(output_size_.x), + ::lround(output_size_.y), + DXGI_FORMAT_B8G8R8A8_UNORM, + 0); + + if (SUCCEEDED(hr)) + { + // Create the render target view and set it on the device + ComPtr dxgi_back_buffer; + + hr = dxgi_swap_chain_->GetBuffer( + 0, + IID_PPV_ARGS(&dxgi_back_buffer) + ); + + if (SUCCEEDED(hr)) + { + D3D10_RENDER_TARGET_VIEW_DESC renderDesc; + renderDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + renderDesc.ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2D; + renderDesc.Texture2D.MipSlice = 0; + + d3d_rt_view_ = nullptr; + hr = d3d_device_->CreateRenderTargetView(dxgi_back_buffer.Get(), &renderDesc, &d3d_rt_view_); + } + + ComPtr depth_stencil; + if (SUCCEEDED(hr)) + { + D3D10_TEXTURE2D_DESC tex_desc; + tex_desc.ArraySize = 1; + tex_desc.BindFlags = D3D10_BIND_DEPTH_STENCIL; + tex_desc.CPUAccessFlags = 0; + tex_desc.Format = DXGI_FORMAT_D16_UNORM; + tex_desc.Width = static_cast(output_size_.x); + tex_desc.Height = static_cast(output_size_.y); + tex_desc.MipLevels = 1; + tex_desc.MiscFlags = 0; + tex_desc.SampleDesc.Count = 1; + tex_desc.SampleDesc.Quality = 0; + tex_desc.Usage = D3D10_USAGE_DEFAULT; + + hr = d3d_device_->CreateTexture2D(&tex_desc, NULL, &depth_stencil); + } + + if (SUCCEEDED(hr)) + { + D3D10_DEPTH_STENCIL_VIEW_DESC desc; + desc.Format = DXGI_FORMAT_D16_UNORM; + desc.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2D; + desc.Texture2D.MipSlice = 0; + + d3d_ds_view_.Reset(); + hr = d3d_device_->CreateDepthStencilView(depth_stencil.Get(), &desc, &d3d_ds_view_); + } + } + + if (SUCCEEDED(hr)) + { + ID3D10RenderTargetView* views[] = { d3d_rt_view_.Get() }; + d3d_device_->OMSetRenderTargets(1, views, d3d_ds_view_.Get()); + + // Set a new viewport based on the new dimensions + D3D10_VIEWPORT viewport; + viewport.Width = static_cast(output_size_.x); + viewport.Height = static_cast(output_size_.y); + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.MinDepth = 0; + viewport.MaxDepth = 1; + + d3d_device_->RSSetViewports(1, &viewport); + } + + // Create a Direct2D target bitmap associated with the + // swap chain back buffer and set it as the current target. + if (SUCCEEDED(hr)) + { + ComPtr dxgi_back_buffer; + hr = dxgi_swap_chain_->GetBuffer(0, IID_PPV_ARGS(&dxgi_back_buffer)); + + ComPtr target; + if (SUCCEEDED(hr)) + { + hr = GetD2DDeviceContext()->CreateBitmapFromDxgiSurface( + dxgi_back_buffer.Get(), + D2D1::BitmapProperties1( + D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, + D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED), + dpi_, + dpi_), + &target); + } + + if (SUCCEEDED(hr)) + { + SetTargetBitmap(target); + } + } + + return hr; + } + + HRESULT D3D10DeviceResources::HandleDeviceLost() + { + dxgi_swap_chain_ = nullptr; + + HRESULT hr = CreateDeviceResources(); + + if (SUCCEEDED(hr)) + { + hr = CreateWindowSizeDependentResources(); + } + return hr; + } + + void D3D10DeviceResources::SetLogicalSize(Size logical_size) + { + if (logical_size_ != logical_size) + { + logical_size_ = logical_size; + + ThrowIfFailed( + CreateWindowSizeDependentResources() + ); + } + } + + void D3D10DeviceResources::SetDpi(float dpi) + { + if (dpi != dpi_) + { + dpi_ = dpi; + + RECT rc; + GetClientRect(hwnd_, &rc); + + logical_size_.x = float(rc.right - rc.left); + logical_size_.y = float(rc.bottom - rc.top); + + GetD2DDeviceContext()->SetDpi(dpi_, dpi_); + + ThrowIfFailed( + CreateWindowSizeDependentResources() + ); + } + } + +} + +#endif // !E2D_USE_DIRECTX10 diff --git a/src/dx/D3D10DeviceResources.h b/src/dx/D3D10DeviceResources.h new file mode 100644 index 00000000..fcd9fd6f --- /dev/null +++ b/src/dx/D3D10DeviceResources.h @@ -0,0 +1,87 @@ +// Copyright (c) 2016-2018 Easy2D - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once + +#ifdef E2D_USE_DIRECTX10 + +#include "helper.hpp" +#include "D2DDeviceResources.h" +#include + +namespace easy2d +{ + class E2D_API D3D10DeviceResources + : public D2DDeviceResources + { + public: + static HRESULT Create( + D3D10DeviceResources** device_resources, + HWND hwnd + ); + + HRESULT HandleDeviceLost(); + + void SetLogicalSize( + Size logical_size + ); + + void SetDpi( + float dpi + ); + + void DiscardResources(); + + inline ID3D10Device* GetD3DDevice() const { return d3d_device_.Get(); } + inline ID3D10RenderTargetView* GetD3DRenderTargetView() const { return d3d_rt_view_.Get(); } + inline ID3D10DepthStencilView* GetD3DDepthStencilView() const { return d3d_ds_view_.Get(); } + inline IDXGIFactory* GetDXGIFactory() const { return dxgi_factory_.Get(); } + inline IDXGISwapChain* GetDXGISwapChain() const { return dxgi_swap_chain_.Get(); } + + inline Size const& GetLogicalSize() const { return logical_size_; } + inline Size const& GetOutputSize() const { return output_size_; } + inline float GetDpi() const { return dpi_; } + + protected: + D3D10DeviceResources(); + + virtual ~D3D10DeviceResources(); + + protected: + HRESULT CreateDeviceResources(); + + HRESULT CreateWindowSizeDependentResources(); + + private: + HWND hwnd_; + float dpi_; + Size logical_size_; + Size output_size_; + + ComPtr d3d_device_; + ComPtr d3d_rt_view_; + ComPtr d3d_ds_view_; + ComPtr dxgi_swap_chain_; + ComPtr dxgi_factory_; + }; + +} + +#endif // !E2D_USE_DIRECTX10 diff --git a/src/dx/D3D11DeviceResources.cpp b/src/dx/D3D11DeviceResources.cpp index eff5f86b..9c652c34 100644 --- a/src/dx/D3D11DeviceResources.cpp +++ b/src/dx/D3D11DeviceResources.cpp @@ -18,11 +18,15 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include "DeviceResources.h" +#include "D3D11DeviceResources.h" + +#ifndef E2D_USE_DIRECTX10 + #include "../core/Image.h" -#include "../core/modules.h" #include "../core/logs.h" +#pragma comment(lib, "d3d11.lib") + namespace easy2d { #if defined(_DEBUG) @@ -30,14 +34,14 @@ namespace easy2d { inline bool SdkLayersAvailable() { - HRESULT hr = modules::DirectX::Get().D3D11CreateDevice( + HRESULT hr = D3D11CreateDevice( nullptr, D3D_DRIVER_TYPE_NULL, // There is no need to create a real hardware device. 0, D3D11_CREATE_DEVICE_DEBUG, // Check for the SDK layers. nullptr, // Any feature level will do. 0, - D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Runtime apps. + D3D11_SDK_VERSION, nullptr, // No need to keep the D3D device reference. nullptr, // No need to know the feature level. nullptr // No need to keep the D3D device context reference. @@ -109,6 +113,8 @@ namespace easy2d { d3d_device_.Reset(); d3d_device_context_.Reset(); + d3d_rt_view_.Reset(); + d3d_ds_view_.Reset(); dxgi_swap_chain_.Reset(); dxgi_factory_.Reset(); @@ -119,7 +125,7 @@ namespace easy2d { HRESULT hr = S_OK; - D3D_FEATURE_LEVEL feature_levels[] = + static const D3D_FEATURE_LEVEL feature_levels[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, @@ -144,7 +150,7 @@ namespace easy2d } #endif - hr = modules::DirectX::Get().D3D11CreateDevice( + hr = D3D11CreateDevice( nullptr, // Specify nullptr to use the default adapter. D3D_DRIVER_TYPE_HARDWARE, 0, // Should be 0 unless the driver is D3D_DRIVER_TYPE_SOFTWARE. @@ -162,7 +168,7 @@ namespace easy2d // If the initialization fails, fall back to the WARP device. // For more information on WARP, see: // http://go.microsoft.com/fwlink/?LinkId=286690 - hr = modules::DirectX::Get().D3D11CreateDevice( + hr = D3D11CreateDevice( nullptr, D3D_DRIVER_TYPE_WARP, // Create a WARP device instead of a hardware device. 0, @@ -218,38 +224,7 @@ namespace easy2d } } - return hr; - } - - HRESULT D3D11DeviceResources::CreateWindowSizeDependentResources() - { - HRESULT hr = S_OK; - - // Clear the previous window size specific context. - ID3D11RenderTargetView* null_views[] = { nullptr }; - SetTargetBitmap(nullptr); - d3d_device_context_->OMSetRenderTargets(ARRAYSIZE(null_views), null_views, nullptr); - d3d_device_context_->Flush(); - - // Calculate the necessary render target size in pixels. - output_size_.x = DX::ConvertDipsToPixels(logical_size_.x, dpi_); - output_size_.y = DX::ConvertDipsToPixels(logical_size_.y, dpi_); - - // Prevent zero size DirectX content from being created. - output_size_.x = std::max(output_size_.x, 1.f); - output_size_.y = std::max(output_size_.y, 1.f); - - if (dxgi_swap_chain_) - { - // If the swap chain already exists, resize it. - hr = dxgi_swap_chain_->ResizeBuffers( - 2, // Double-buffered swap chain. - ::lround(output_size_.x), - ::lround(output_size_.y), - DXGI_FORMAT_B8G8R8A8_UNORM, - 0); - } - else + if (SUCCEEDED(hr)) { // Setup swap chain DXGI_SWAP_CHAIN_DESC swap_chain_desc = { 0 }; @@ -295,8 +270,80 @@ namespace easy2d } } + return hr; + } + + HRESULT D3D11DeviceResources::CreateWindowSizeDependentResources() + { + if (!dxgi_swap_chain_) + return E_UNEXPECTED; + + HRESULT hr = S_OK; + + // Clear the previous window size specific context. + ID3D11RenderTargetView* null_views[] = { nullptr }; + SetTargetBitmap(nullptr); + d3d_device_context_->OMSetRenderTargets(ARRAYSIZE(null_views), null_views, nullptr); + d3d_device_context_->Flush(); + + // Calculate the necessary render target size in pixels. + output_size_.x = DX::ConvertDipsToPixels(logical_size_.x, dpi_); + output_size_.y = DX::ConvertDipsToPixels(logical_size_.y, dpi_); + + // Prevent zero size DirectX content from being created. + output_size_.x = std::max(output_size_.x, 1.f); + output_size_.y = std::max(output_size_.y, 1.f); + + // If the swap chain already exists, resize it. + hr = dxgi_swap_chain_->ResizeBuffers( + 2, // Double-buffered swap chain. + ::lround(output_size_.x), + ::lround(output_size_.y), + DXGI_FORMAT_B8G8R8A8_UNORM, + 0); + if (SUCCEEDED(hr)) { + // Create the render target view and set it on the device + ComPtr dxgi_back_buffer; + + hr = dxgi_swap_chain_->GetBuffer(0, IID_PPV_ARGS(&dxgi_back_buffer)); + + if (SUCCEEDED(hr)) + { + d3d_rt_view_ = nullptr; + hr = d3d_device_->CreateRenderTargetView(dxgi_back_buffer.Get(), nullptr, &d3d_rt_view_); + } + + ComPtr depth_stencil; + if (SUCCEEDED(hr)) + { + CD3D11_TEXTURE2D_DESC tex_desc( + DXGI_FORMAT_D24_UNORM_S8_UINT, + static_cast(output_size_.x), + static_cast(output_size_.y), + 1, // This depth stencil view has only one texture. + 1, // Use a single mipmap level. + D3D11_BIND_DEPTH_STENCIL + ); + + hr = d3d_device_->CreateTexture2D(&tex_desc, nullptr, &depth_stencil); + } + + if (SUCCEEDED(hr)) + { + CD3D11_DEPTH_STENCIL_VIEW_DESC desc(D3D11_DSV_DIMENSION_TEXTURE2D); + + d3d_ds_view_.Reset(); + hr = d3d_device_->CreateDepthStencilView(depth_stencil.Get(), &desc, &d3d_ds_view_); + } + } + + if (SUCCEEDED(hr)) + { + ID3D11RenderTargetView* views[] = { d3d_rt_view_.Get() }; + d3d_device_context_->OMSetRenderTargets(1, views, d3d_ds_view_.Get()); + // Set the 3D rendering viewport to target the entire window. CD3D11_VIEWPORT screen_viewport( 0.0f, @@ -311,13 +358,6 @@ namespace easy2d // swap chain back buffer and set it as the current target. if (SUCCEEDED(hr)) { - D2D1_BITMAP_PROPERTIES1 bitmap_props = - D2D1::BitmapProperties1( - D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, - D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED), - dpi_, - dpi_); - ComPtr dxgi_back_buffer; hr = dxgi_swap_chain_->GetBuffer(0, IID_PPV_ARGS(&dxgi_back_buffer)); @@ -326,7 +366,11 @@ namespace easy2d { hr = GetD2DDeviceContext()->CreateBitmapFromDxgiSurface( dxgi_back_buffer.Get(), - &bitmap_props, + D2D1::BitmapProperties1( + D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, + D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED), + dpi_, + dpi_), &target); } @@ -385,3 +429,5 @@ namespace easy2d } } + +#endif // !E2D_USE_DIRECTX10 diff --git a/src/dx/D3D11DeviceResources.h b/src/dx/D3D11DeviceResources.h index 329b575c..8782966a 100644 --- a/src/dx/D3D11DeviceResources.h +++ b/src/dx/D3D11DeviceResources.h @@ -19,6 +19,9 @@ // THE SOFTWARE. #pragma once + +#ifndef E2D_USE_DIRECTX10 + #include "helper.hpp" #include "D2DDeviceResources.h" #include @@ -48,6 +51,8 @@ namespace easy2d inline ID3D11Device* GetD3DDevice() const { return d3d_device_.Get(); } inline ID3D11DeviceContext* GetD3DDeviceContext() const { return d3d_device_context_.Get(); } + inline ID3D11RenderTargetView* GetD3DRenderTargetView() const { return d3d_rt_view_.Get(); } + inline ID3D11DepthStencilView* GetD3DDepthStencilView() const { return d3d_ds_view_.Get(); } inline IDXGIFactory* GetDXGIFactory() const { return dxgi_factory_.Get(); } inline IDXGISwapChain* GetDXGISwapChain() const { return dxgi_swap_chain_.Get(); } @@ -67,16 +72,21 @@ namespace easy2d HRESULT CreateWindowSizeDependentResources(); private: - HWND hwnd_; - float dpi_; - Size logical_size_; - Size output_size_; + HWND hwnd_; + float dpi_; + Size logical_size_; + Size output_size_; + D3D_FEATURE_LEVEL d3d_feature_level_; - ComPtr d3d_device_; - ComPtr d3d_device_context_; - ComPtr dxgi_swap_chain_; - ComPtr dxgi_factory_; + ComPtr d3d_device_; + ComPtr d3d_device_context_; + ComPtr d3d_rt_view_; + ComPtr d3d_ds_view_; + ComPtr dxgi_swap_chain_; + ComPtr dxgi_factory_; }; } + +#endif // !E2D_USE_DIRECTX10 diff --git a/src/dx/DeviceResources.h b/src/dx/DeviceResources.h index fc502d68..f5fb34d3 100644 --- a/src/dx/DeviceResources.h +++ b/src/dx/DeviceResources.h @@ -19,9 +19,21 @@ // THE SOFTWARE. #pragma once -#include "D3D11DeviceResources.h" +#include "../core/macros.h" + +#ifdef E2D_USE_DIRECTX10 +# include "D3D10DeviceResources.h" +#else +# include "D3D11DeviceResources.h" +#endif namespace easy2d { + +#ifdef E2D_USE_DIRECTX10 + using DeviceResources = D3D10DeviceResources; +#else using DeviceResources = D3D11DeviceResources; +#endif + } diff --git a/src/math/Matrix.hpp b/src/math/Matrix.hpp index 851487c3..e56be3ff 100644 --- a/src/math/Matrix.hpp +++ b/src/math/Matrix.hpp @@ -57,7 +57,7 @@ namespace easy2d { } - Matrix(const float* p) + explicit Matrix(const float* p) { for (int i = 0; i < 6; i++) m[i] = p[i];