make Direct3D resources global

This commit is contained in:
Nomango 2020-05-22 21:07:32 +08:00
parent 1de59e3a15
commit 228fc45035
18 changed files with 463 additions and 334 deletions

View File

@ -79,6 +79,7 @@
<ClInclude Include="..\..\src\kiwano\render\DirectX\D2DDeviceResources.h" />
<ClInclude Include="..\..\src\kiwano\render\DirectX\D3D10DeviceResources.h" />
<ClInclude Include="..\..\src\kiwano\render\DirectX\D3D11DeviceResources.h" />
<ClInclude Include="..\..\src\kiwano\render\DirectX\D3DDeviceResources.h" />
<ClInclude Include="..\..\src\kiwano\render\DirectX\D3DDeviceResourcesBase.h" />
<ClInclude Include="..\..\src\kiwano\render\DirectX\FontCollectionLoader.h" />
<ClInclude Include="..\..\src\kiwano\render\DirectX\helper.h" />

View File

@ -336,6 +336,9 @@
<ClInclude Include="..\..\src\kiwano\core\EventTicker.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kiwano\render\DirectX\D3DDeviceResources.h">
<Filter>render\DirectX</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\kiwano\2d\Canvas.cpp">

View File

@ -7,13 +7,12 @@
#if !defined(KGE_USE_DIRECTX10)
#include <kiwano-imgui/imgui_impl/imgui_impl_dx11.h>
#include <kiwano/render/DirectX/RendererImpl.h>
#include <kiwano/render/DirectX/D3DDeviceResources.h>
inline bool ImGui_Impl_Init()
{
::kiwano::RendererImpl& renderer = ::kiwano::RendererImpl::GetInstance();
return ImGui_ImplDX11_Init(renderer.GetD3DDeviceResources()->GetDevice(),
renderer.GetD3DDeviceResources()->GetDeviceContext());
auto d3d = kiwano::graphics::directx::GetD3DDeviceResources();
return ImGui_ImplDX11_Init(d3d->GetDevice(), d3d->GetDeviceContext());
}
inline void ImGui_Impl_Shutdown()
@ -44,11 +43,12 @@ inline bool ImGui_Impl_CreateDeviceObjects()
#else
#include <kiwano-imgui/imgui_impl/imgui_impl_dx10.h>
#include <kiwano/render/DirectX/D3DDeviceResources.h>
inline bool ImGui_Impl_Init()
{
::kiwano::RendererImpl& renderer = ::kiwano::RendererImpl::GetInstance();
return ImGui_ImplDX10_Init(renderer.GetD3DDeviceResources()->GetDevice());
auto d3d = kiwano::graphics::directx::GetD3DDeviceResources();
return ImGui_ImplDX10_Init(d3d->GetDevice());
}
inline void ImGui_Impl_Shutdown()

View File

@ -84,11 +84,6 @@ void Window::SetShouldClose(bool should)
should_close_ = should;
}
void Window::SetFullscreenState(bool is_fullscreen)
{
is_fullscreen_ = is_fullscreen;
}
void Window::PushEvent(EventPtr evt)
{
event_queue_.push(evt);

View File

@ -45,6 +45,17 @@ enum class CursorType
SizeNWSE, ///< 指向左上到右下方向的箭头
};
/**
* \~chinese
* @brief
*/
struct Resolution
{
uint32_t width; ///< 分辨率宽度
uint32_t height; ///< 分辨率高度
uint32_t refresh_rate; ///< 刷新率
};
#if defined(KGE_PLATFORM_WINDOWS)
typedef HWND WindowHandle;
@ -143,6 +154,21 @@ public:
*/
virtual void SetCursor(CursorType cursor) = 0;
/**
* \~chinese
* @brief
* @param width
* @param height
* @param fullscreen
*/
virtual void SetResolution(uint32_t width, uint32_t height, bool fullscreen) = 0;
/**
* \~chinese
* @brief
*/
virtual Vector<Resolution> GetResolutions() = 0;
/**
* \~chinese
* @brief
@ -175,12 +201,6 @@ public:
*/
void SetShouldClose(bool should);
/**
* \~chinese
* @brief
*/
void SetFullscreenState(bool is_fullscreen);
protected:
Window();

View File

@ -32,6 +32,7 @@
#include <kiwano/core/event/WindowEvent.h>
#include <kiwano/platform/Application.h>
#include <kiwano/render/Renderer.h>
#include <kiwano/render/DirectX/D3DDeviceResources.h>
#include <Windowsx.h> // GET_X_LPARAM, GET_Y_LPARAM
#include <imm.h> // ImmAssociateContext
#pragma comment(lib, "imm32.lib")
@ -60,6 +61,10 @@ public:
void SetCursor(CursorType cursor) override;
void SetResolution(uint32_t width, uint32_t height, bool fullscreen) override;
Vector<Resolution> GetResolutions() override;
void PumpEvents() override;
DWORD GetStyle() const;
@ -77,6 +82,7 @@ private:
CursorType mouse_cursor_;
String device_name_;
Vector<Resolution> resolutions_;
std::array<KeyCode, 256> key_map_;
};
@ -338,6 +344,78 @@ void WindowWin32Impl::SetCursor(CursorType cursor)
mouse_cursor_ = cursor;
}
void WindowWin32Impl::SetResolution(uint32_t width, uint32_t height, bool fullscreen)
{
auto d3d = kiwano::graphics::directx::GetD3DDeviceResources();
if (fullscreen)
{
HRESULT hr = d3d->ResizeTarget(width, height);
KGE_THROW_IF_FAILED(hr, "DXGI ResizeTarget failed!");
hr = d3d->SetFullscreenState(fullscreen);
KGE_THROW_IF_FAILED(hr, "DXGI SetFullscreenState failed!");
}
else
{
HRESULT hr = d3d->SetFullscreenState(fullscreen);
KGE_THROW_IF_FAILED(hr, "DXGI SetFullscreenState failed!");
hr = d3d->ResizeTarget(width, height);
KGE_THROW_IF_FAILED(hr, "DXGI ResizeTarget failed!");
}
is_fullscreen_ = fullscreen;
}
Vector<Resolution> WindowWin32Impl::GetResolutions()
{
if (resolutions_.empty())
{
auto d3d = kiwano::graphics::directx::GetD3DDeviceResources();
DXGI_MODE_DESC* mode_descs = nullptr;
int mode_num = 0;
HRESULT hr = d3d->GetDisplaySettings(&mode_descs, &mode_num);
if (SUCCEEDED(hr))
{
std::unique_ptr<DXGI_MODE_DESC[]> mode_list(mode_descs);
if (mode_list)
{
for (int i = 0; i < mode_num; i++)
{
Resolution res;
res.width = mode_descs[i].Width;
res.height = mode_descs[i].Height;
res.refresh_rate = 0;
if (mode_descs[i].RefreshRate.Denominator > 0)
{
res.refresh_rate = mode_descs[i].RefreshRate.Numerator / mode_descs[i].RefreshRate.Denominator;
}
if (!resolutions_.empty())
{
auto& back = resolutions_.back();
if (back.width == res.width && back.height == res.height
&& back.refresh_rate == res.refresh_rate)
continue;
}
resolutions_.push_back(res);
}
}
}
else
{
KGE_THROW_IF_FAILED(hr, "DXGI GetDisplaySettings failed!");
}
}
return resolutions_;
}
DWORD WindowWin32Impl::GetStyle() const
{
return (resizable_ ? (WINDOW_RESIZABLE_STYLE) : (WINDOW_FIXED_STYLE));

View File

@ -26,6 +26,14 @@
namespace kiwano
{
namespace graphics
{
namespace directx
{
// Global pointer for Direct2D device resources
static ComPtr<ID2DDeviceResources> global_d2d_device_resource;
struct D2DDeviceResources : public ID2DDeviceResources
{
public:
@ -33,6 +41,8 @@ public:
virtual ~D2DDeviceResources();
HRESULT Initialize(_In_ ComPtr<IDXGIDevice> dxgi_device, _In_ ComPtr<IDXGISwapChain> dxgi_swap_chain) override;
HRESULT CreateDeviceIndependentResources();
HRESULT CreateDeviceResources(_In_ ComPtr<IDXGIDevice> dxgi_device, _In_ ComPtr<IDXGISwapChain> dxgi_swap_chain);
@ -57,8 +67,8 @@ public:
_In_ ComPtr<IDWriteFontCollection> collection, DWRITE_FONT_WEIGHT weight,
DWRITE_FONT_STYLE style, DWRITE_FONT_STRETCH stretch, FLOAT font_size) override;
HRESULT CreateTextLayout(_Out_ ComPtr<IDWriteTextLayout>& text_layout, _In_ LPCWSTR text,
UINT32 length, _In_ ComPtr<IDWriteTextFormat> text_format) override;
HRESULT CreateTextLayout(_Out_ ComPtr<IDWriteTextLayout>& text_layout, _In_ LPCWSTR text, UINT32 length,
_In_ ComPtr<IDWriteTextFormat> text_format) override;
HRESULT SetDpi(float dpi) override;
@ -85,40 +95,14 @@ private:
ComPtr<IDXGISwapChain> dxgi_swap_chain_;
};
HRESULT ID2DDeviceResources::Create(_Out_ ID2DDeviceResources** device_resources, _In_ ComPtr<IDXGIDevice> dxgi_device,
_In_ ComPtr<IDXGISwapChain> dxgi_swap_chain)
ComPtr<ID2DDeviceResources> GetD2DDeviceResources()
{
HRESULT hr = E_FAIL;
if (device_resources)
if (!global_d2d_device_resource)
{
D2DDeviceResources* res = new (std::nothrow) D2DDeviceResources;
if (res)
{
hr = res->CreateDeviceIndependentResources();
if (SUCCEEDED(hr))
{
hr = res->CreateDeviceResources(dxgi_device, dxgi_swap_chain);
}
if (SUCCEEDED(hr))
{
hr = res->CreateWindowSizeDependentResources();
}
}
if (SUCCEEDED(hr))
{
DX::SafeRelease(*device_resources);
(*device_resources) = DX::SafeAcquire(res);
}
else
{
delete res;
res = nullptr;
}
global_d2d_device_resource.Reset(new (std::nothrow) D2DDeviceResources);
}
return hr;
return global_d2d_device_resource;
}
D2DDeviceResources::D2DDeviceResources()
@ -132,6 +116,22 @@ D2DDeviceResources::~D2DDeviceResources()
DiscardResources();
}
HRESULT D2DDeviceResources::Initialize(ComPtr<IDXGIDevice> dxgi_device, ComPtr<IDXGISwapChain> dxgi_swap_chain)
{
HRESULT hr = this->CreateDeviceIndependentResources();
if (SUCCEEDED(hr))
{
hr = this->CreateDeviceResources(dxgi_device, dxgi_swap_chain);
}
if (SUCCEEDED(hr))
{
hr = this->CreateWindowSizeDependentResources();
}
return hr;
}
STDMETHODIMP_(unsigned long) D2DDeviceResources::AddRef()
{
return InterlockedIncrement(&ref_count_);
@ -423,8 +423,8 @@ HRESULT D2DDeviceResources::CreateTextFormat(_Out_ ComPtr<IDWriteTextFormat>& te
return E_UNEXPECTED;
ComPtr<IDWriteTextFormat> output;
HRESULT hr = dwrite_factory_->CreateTextFormat(family, collection.Get(), weight, style, stretch, font_size,
L"", &output);
HRESULT hr =
dwrite_factory_->CreateTextFormat(family, collection.Get(), weight, style, stretch, font_size, L"", &output);
if (SUCCEEDED(hr))
{
@ -450,4 +450,6 @@ HRESULT D2DDeviceResources::CreateTextLayout(_Out_ ComPtr<IDWriteTextLayout>& te
return hr;
}
} // namespace directx
} // namespace graphics
} // namespace kiwano

View File

@ -26,12 +26,16 @@
namespace kiwano
{
namespace graphics
{
namespace directx
{
MIDL_INTERFACE("5706684a-bf6d-4b03-b627-094758a33032")
KGE_API ID2DDeviceResources : public IUnknown
{
public:
static HRESULT Create(_Out_ ID2DDeviceResources * *device_resources, _In_ ComPtr<IDXGIDevice> dxgi_device,
_In_ ComPtr<IDXGISwapChain> dxgi_swap_chain);
virtual HRESULT Initialize(_In_ ComPtr<IDXGIDevice> dxgi_device, _In_ ComPtr<IDXGISwapChain> dxgi_swap_chain) = 0;
virtual HRESULT CreateBitmapConverter(_Out_ ComPtr<IWICFormatConverter> & converter,
_In_opt_ ComPtr<IWICBitmapSource> source, _In_ REFWICPixelFormatGUID format,
@ -51,8 +55,8 @@ public:
_In_ ComPtr<IDWriteFontCollection> collection, DWRITE_FONT_WEIGHT weight,
DWRITE_FONT_STYLE style, DWRITE_FONT_STRETCH stretch, FLOAT font_size) = 0;
virtual HRESULT CreateTextLayout(_Out_ ComPtr<IDWriteTextLayout> & text_layout, _In_ LPCWSTR text,
UINT32 length, _In_ ComPtr<IDWriteTextFormat> text_format) = 0;
virtual HRESULT CreateTextLayout(_Out_ ComPtr<IDWriteTextLayout> & text_layout, _In_ LPCWSTR text, UINT32 length,
_In_ ComPtr<IDWriteTextFormat> text_format) = 0;
virtual HRESULT SetDpi(float dpi) = 0;
@ -111,4 +115,9 @@ protected:
ComPtr<IDWriteFactory> dwrite_factory_;
};
extern ComPtr<ID2DDeviceResources> GetD2DDeviceResources();
}
}
} // namespace kiwano

View File

@ -25,9 +25,14 @@
namespace kiwano
{
namespace DX
namespace graphics
{
namespace directx
{
// Global pointer for Direct3D11 device resources
static ComPtr<ID3D10DeviceResources> global_d3d10_device_resources;
HRESULT CreateD3DDevice(IDXGIAdapter* adapter, D3D10_DRIVER_TYPE driver_type, uint32_t flags, ID3D10Device1** device)
{
HRESULT hr = S_OK;
@ -60,11 +65,11 @@ inline bool SdkLayersAvailable()
}
#endif
} // namespace DX
struct D3D10DeviceResources : public ID3D10DeviceResources
{
public:
HRESULT Initialize(HWND hwnd) override;
HRESULT Present(bool vsync) override;
void ClearRenderTarget(Color& clear_color) override;
@ -77,6 +82,8 @@ public:
HRESULT SetFullscreenState(bool fullscreen) override;
HRESULT GetFullscreenState(bool* fullscreen) override;
HRESULT ResizeTarget(UINT width, UINT height) override;
HRESULT GetDisplaySettings(DXGI_MODE_DESC** mode_descs, int* num) override;
@ -108,6 +115,16 @@ public:
DXGI_FORMAT desired_color_format_;
};
ComPtr<ID3D10DeviceResources> GetD3D10DeviceResources()
{
if (!global_d3d10_device_resources)
{
global_d3d10_device_resources.Reset(new (std::nothrow) D3D10DeviceResources);
}
return global_d3d10_device_resources;
}
D3D10DeviceResources::D3D10DeviceResources()
: ref_count_(0)
, hwnd_(nullptr)
@ -121,55 +138,34 @@ D3D10DeviceResources::~D3D10DeviceResources()
DiscardResources();
}
HRESULT ID3D10DeviceResources::Create(ID3D10DeviceResources** device_resources, HWND hwnd)
HRESULT D3D10DeviceResources::Initialize(HWND hwnd)
{
HRESULT hr = E_FAIL;
RECT rc;
::GetClientRect(hwnd, &rc);
if (device_resources)
this->hwnd_ = hwnd;
this->logical_size_.x = float(rc.right - rc.left);
this->logical_size_.y = float(rc.bottom - rc.top);
HRESULT hr = this->CreateDeviceResources();
if (SUCCEEDED(hr))
{
D3D10DeviceResources* res = new (std::nothrow) D3D10DeviceResources;
if (res)
{
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();
if (*device_resources)
{
(*device_resources)->Release();
}
(*device_resources) = res;
}
else
{
delete res;
res = nullptr;
}
}
hr = this->CreateWindowSizeDependentResources();
}
return hr;
}
HRESULT D3D10DeviceResources::Present(bool vsync)
{
KGE_ASSERT(dxgi_swap_chain_ != nullptr);
HRESULT hr = E_FAIL;
// The first argument instructs DXGI to block until VSync.
return dxgi_swap_chain_->Present(vsync ? 1 : 0, 0);
if (dxgi_swap_chain_)
{
// The first argument instructs DXGI to block until VSync.
hr = dxgi_swap_chain_->Present(vsync ? 1 : 0, DXGI_PRESENT_DO_NOT_WAIT);
}
return hr;
}
void D3D10DeviceResources::ClearRenderTarget(Color& clear_color)
@ -202,14 +198,14 @@ HRESULT D3D10DeviceResources::CreateDeviceResources()
uint32_t creation_flags = D3D10_CREATE_DEVICE_BGRA_SUPPORT;
#if defined(KGE_DEBUG) && defined(KGE_ENABLE_DX_DEBUG)
if (DX::SdkLayersAvailable())
if (SdkLayersAvailable())
{
creation_flags |= D3D10_CREATE_DEVICE_DEBUG;
}
#endif
ComPtr<ID3D10Device1> device;
hr = DX::CreateD3DDevice(NULL, D3D10_DRIVER_TYPE_HARDWARE, creation_flags, &device);
hr = CreateD3DDevice(NULL, D3D10_DRIVER_TYPE_HARDWARE, creation_flags, &device);
if (SUCCEEDED(hr))
{
@ -415,53 +411,79 @@ HRESULT D3D10DeviceResources::SetDpi(float dpi)
HRESULT D3D10DeviceResources::SetFullscreenState(bool fullscreen)
{
HRESULT hr = dxgi_swap_chain_->SetFullscreenState(fullscreen ? TRUE : FALSE, nullptr);
HRESULT hr = E_FAIL;
if (dxgi_swap_chain_)
{
hr = dxgi_swap_chain_->SetFullscreenState(fullscreen ? TRUE : FALSE, nullptr);
}
return hr;
}
HRESULT D3D10DeviceResources::GetFullscreenState(bool* fullscreen)
{
HRESULT hr = E_FAIL;
if (dxgi_swap_chain_)
{
BOOL is_fullscreen;
hr = dxgi_swap_chain_->GetFullscreenState(&is_fullscreen, nullptr);
if (SUCCEEDED(hr))
{
(*fullscreen) = (is_fullscreen == TRUE);
}
}
return hr;
}
HRESULT D3D10DeviceResources::ResizeTarget(UINT width, UINT height)
{
DXGI_MODE_DESC desc = { 0 };
desc.Width = width;
desc.Height = height;
desc.Format = DXGI_FORMAT_UNKNOWN;
HRESULT hr = E_FAIL;
if (dxgi_swap_chain_)
{
DXGI_MODE_DESC desc = { 0 };
desc.Width = width;
desc.Height = height;
desc.Format = DXGI_FORMAT_UNKNOWN;
HRESULT hr = dxgi_swap_chain_->ResizeTarget(&desc);
hr = dxgi_swap_chain_->ResizeTarget(&desc);
}
return hr;
}
HRESULT D3D10DeviceResources::GetDisplaySettings(DXGI_MODE_DESC** mode_descs, int* num)
{
KGE_ASSERT(dxgi_swap_chain_);
ComPtr<IDXGIOutput> output;
HRESULT hr = dxgi_swap_chain_->GetContainingOutput(&output);
if (SUCCEEDED(hr))
HRESULT hr = E_FAIL;
if (dxgi_swap_chain_)
{
UINT num_of_supported_modes = 0;
output->GetDisplayModeList(desired_color_format_, 0, &num_of_supported_modes, 0);
ComPtr<IDXGIOutput> output;
hr = dxgi_swap_chain_->GetContainingOutput(&output);
if (num_of_supported_modes > 0)
if (SUCCEEDED(hr))
{
DXGI_MODE_DESC* supported_modes = new DXGI_MODE_DESC[num_of_supported_modes];
ZeroMemory(supported_modes, sizeof(DXGI_MODE_DESC) * num_of_supported_modes);
UINT num_of_supported_modes = 0;
output->GetDisplayModeList(desired_color_format_, 0, &num_of_supported_modes, 0);
hr = output->GetDisplayModeList(desired_color_format_, 0, &num_of_supported_modes, supported_modes);
if (SUCCEEDED(hr) && mode_descs && num)
if (num_of_supported_modes > 0)
{
(*mode_descs) = supported_modes;
(*num) = (int)num_of_supported_modes;
DXGI_MODE_DESC* supported_modes = new DXGI_MODE_DESC[num_of_supported_modes];
ZeroMemory(supported_modes, sizeof(DXGI_MODE_DESC) * num_of_supported_modes);
hr = output->GetDisplayModeList(desired_color_format_, 0, &num_of_supported_modes, supported_modes);
if (SUCCEEDED(hr) && mode_descs && num)
{
(*mode_descs) = supported_modes;
(*num) = (int)num_of_supported_modes;
}
else
{
delete[] supported_modes;
}
}
else
{
delete[] supported_modes;
hr = E_FAIL;
}
}
else
{
hr = E_FAIL;
}
}
return hr;
}
@ -509,4 +531,6 @@ STDMETHODIMP D3D10DeviceResources::QueryInterface(const IID& riid, void** object
return S_OK;
}
} // namespace directx
} // namespace graphics
} // namespace kiwano

View File

@ -26,12 +26,15 @@
namespace kiwano
{
namespace graphics
{
namespace directx
{
MIDL_INTERFACE("3a150b9d-cc23-4022-a463-7e95452a54c4")
KGE_API ID3D10DeviceResources : public ID3DDeviceResourcesBase
{
public:
static HRESULT Create(ID3D10DeviceResources * *device_resources, HWND hwnd);
inline ID3D10Device* GetDevice()
{
KGE_ASSERT(device_);
@ -77,4 +80,8 @@ protected:
ComPtr<IDXGISwapChain> dxgi_swap_chain_;
};
extern ComPtr<ID3D10DeviceResources> GetD3D11DeviceResources();
} // namespace directx
} // namespace graphics
} // namespace kiwano

View File

@ -31,9 +31,16 @@ KGE_SUPPRESS_WARNING_POP
namespace kiwano
{
#if defined(KGE_DEBUG)
namespace DX
namespace graphics
{
namespace directx
{
// Global pointer for Direct3D11 device resources
static ComPtr<ID3D11DeviceResources> global_d3d11_device_resources;
#if defined(KGE_DEBUG)
inline bool SdkLayersAvailable()
{
HRESULT hr = D3D11CreateDevice(nullptr,
@ -46,15 +53,15 @@ inline bool SdkLayersAvailable()
nullptr, // No need to know the feature level.
nullptr // No need to keep the D3D device context reference.
);
return SUCCEEDED(hr);
}
} // namespace DX
#endif
struct D3D11DeviceResources : public ID3D11DeviceResources
{
public:
HRESULT Initialize(HWND hwnd) override;
HRESULT Present(bool vsync) override;
void ClearRenderTarget(Color& clear_color) override;
@ -67,6 +74,8 @@ public:
HRESULT SetFullscreenState(bool fullscreen) override;
HRESULT GetFullscreenState(bool* fullscreen) override;
HRESULT ResizeTarget(UINT width, UINT height) override;
HRESULT GetDisplaySettings(DXGI_MODE_DESC** mode_descs, int* num) override;
@ -100,6 +109,16 @@ public:
DXGI_FORMAT desired_color_format_;
};
ComPtr<ID3D11DeviceResources> GetD3D11DeviceResources()
{
if (!global_d3d11_device_resources)
{
global_d3d11_device_resources.Reset(new (std::nothrow) D3D11DeviceResources);
}
return global_d3d11_device_resources;
}
D3D11DeviceResources::D3D11DeviceResources()
: ref_count_(0)
, hwnd_(nullptr)
@ -114,55 +133,34 @@ D3D11DeviceResources::~D3D11DeviceResources()
DiscardResources();
}
HRESULT ID3D11DeviceResources::Create(ID3D11DeviceResources** device_resources, HWND hwnd)
HRESULT D3D11DeviceResources::Initialize(HWND hwnd)
{
HRESULT hr = E_FAIL;
RECT rc;
::GetClientRect(hwnd, &rc);
if (device_resources)
this->hwnd_ = hwnd;
this->logical_size_.x = float(rc.right - rc.left);
this->logical_size_.y = float(rc.bottom - rc.top);
HRESULT hr = this->CreateDeviceResources();
if (SUCCEEDED(hr))
{
D3D11DeviceResources* res = new (std::nothrow) D3D11DeviceResources;
if (res)
{
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();
if (*device_resources)
{
(*device_resources)->Release();
}
(*device_resources) = res;
}
else
{
delete res;
res = nullptr;
}
}
hr = this->CreateWindowSizeDependentResources();
}
return hr;
}
HRESULT D3D11DeviceResources::Present(bool vsync)
{
KGE_ASSERT(dxgi_swap_chain_ != nullptr);
HRESULT hr = E_FAIL;
// The first argument instructs DXGI to block until VSync.
return dxgi_swap_chain_->Present(vsync ? 1 : 0, 0);
if (dxgi_swap_chain_)
{
// The first argument instructs DXGI to block until VSync.
hr = dxgi_swap_chain_->Present(vsync ? 1 : 0, DXGI_PRESENT_DO_NOT_WAIT);
}
return hr;
}
void D3D11DeviceResources::ClearRenderTarget(Color& clear_color)
@ -204,7 +202,7 @@ HRESULT D3D11DeviceResources::CreateDeviceResources()
uint32_t creation_flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
#if defined(KGE_DEBUG) && defined(KGE_ENABLE_DX_DEBUG)
if (DX::SdkLayersAvailable())
if (SdkLayersAvailable())
{
creation_flags |= D3D11_CREATE_DEVICE_DEBUG;
}
@ -436,53 +434,79 @@ HRESULT D3D11DeviceResources::SetDpi(float dpi)
HRESULT D3D11DeviceResources::SetFullscreenState(bool fullscreen)
{
HRESULT hr = dxgi_swap_chain_->SetFullscreenState(fullscreen ? TRUE : FALSE, nullptr);
HRESULT hr = E_FAIL;
if (dxgi_swap_chain_)
{
hr = dxgi_swap_chain_->SetFullscreenState(fullscreen ? TRUE : FALSE, nullptr);
}
return hr;
}
HRESULT D3D11DeviceResources::GetFullscreenState(bool* fullscreen)
{
HRESULT hr = E_FAIL;
if (dxgi_swap_chain_)
{
BOOL is_fullscreen;
hr = dxgi_swap_chain_->GetFullscreenState(&is_fullscreen, nullptr);
if (SUCCEEDED(hr))
{
(*fullscreen) = (is_fullscreen == TRUE);
}
}
return hr;
}
HRESULT D3D11DeviceResources::ResizeTarget(UINT width, UINT height)
{
DXGI_MODE_DESC desc = { 0 };
desc.Width = width;
desc.Height = height;
desc.Format = DXGI_FORMAT_UNKNOWN;
HRESULT hr = E_FAIL;
if (dxgi_swap_chain_)
{
DXGI_MODE_DESC desc = { 0 };
desc.Width = width;
desc.Height = height;
desc.Format = DXGI_FORMAT_UNKNOWN;
HRESULT hr = dxgi_swap_chain_->ResizeTarget(&desc);
hr = dxgi_swap_chain_->ResizeTarget(&desc);
}
return hr;
}
HRESULT D3D11DeviceResources::GetDisplaySettings(DXGI_MODE_DESC** mode_descs, int* num)
{
KGE_ASSERT(dxgi_swap_chain_);
ComPtr<IDXGIOutput> output;
HRESULT hr = dxgi_swap_chain_->GetContainingOutput(&output);
if (SUCCEEDED(hr))
HRESULT hr = E_FAIL;
if (dxgi_swap_chain_)
{
UINT num_of_supported_modes = 0;
output->GetDisplayModeList(desired_color_format_, 0, &num_of_supported_modes, 0);
ComPtr<IDXGIOutput> output;
HRESULT hr = dxgi_swap_chain_->GetContainingOutput(&output);
if (num_of_supported_modes > 0)
if (SUCCEEDED(hr))
{
DXGI_MODE_DESC* supported_modes = new DXGI_MODE_DESC[num_of_supported_modes];
ZeroMemory(supported_modes, sizeof(DXGI_MODE_DESC) * num_of_supported_modes);
UINT num_of_supported_modes = 0;
output->GetDisplayModeList(desired_color_format_, 0, &num_of_supported_modes, 0);
hr = output->GetDisplayModeList(desired_color_format_, 0, &num_of_supported_modes, supported_modes);
if (SUCCEEDED(hr) && mode_descs && num)
if (num_of_supported_modes > 0)
{
(*mode_descs) = supported_modes;
(*num) = (int)num_of_supported_modes;
DXGI_MODE_DESC* supported_modes = new DXGI_MODE_DESC[num_of_supported_modes];
ZeroMemory(supported_modes, sizeof(DXGI_MODE_DESC) * num_of_supported_modes);
hr = output->GetDisplayModeList(desired_color_format_, 0, &num_of_supported_modes, supported_modes);
if (SUCCEEDED(hr) && mode_descs && num)
{
(*mode_descs) = supported_modes;
(*num) = (int)num_of_supported_modes;
}
else
{
delete[] supported_modes;
}
}
else
{
delete[] supported_modes;
hr = E_FAIL;
}
}
else
{
hr = E_FAIL;
}
}
return hr;
}
@ -530,4 +554,6 @@ STDMETHODIMP D3D11DeviceResources::QueryInterface(const IID& riid, void** object
return S_OK;
}
} // namespace directx
} // namespace graphics
} // namespace kiwano

View File

@ -26,13 +26,15 @@
namespace kiwano
{
namespace graphics
{
namespace directx
{
MIDL_INTERFACE("3ede2b87-a202-4799-a39b-2308ad34cae8")
KGE_API ID3D11DeviceResources : public ID3DDeviceResourcesBase
{
public:
static HRESULT Create(ID3D11DeviceResources * *device_resources, HWND hwnd);
inline ID3D11Device* GetDevice()
{
KGE_ASSERT(device_);
@ -85,4 +87,8 @@ protected:
ComPtr<IDXGISwapChain> dxgi_swap_chain_;
};
extern ComPtr<ID3D11DeviceResources> GetD3D11DeviceResources();
} // namespace directx
} // namespace graphics
} // namespace kiwano

View File

@ -0,0 +1,54 @@
// Copyright (c) 2016-2018 Kiwano - 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
#if defined(KGE_USE_DIRECTX10)
#include <kiwano/render/DirectX/D3D10DeviceResources.h>
#else
#include <kiwano/render/DirectX/D3D11DeviceResources.h>
#endif
namespace kiwano
{
namespace graphics
{
namespace directx
{
#if defined(KGE_USE_DIRECTX10)
using ID3DDeviceResources = kiwano::graphics::directx::ID3D10DeviceResources;
inline ComPtr<ID3D10DeviceResources> GetD3DDeviceResources()
{
return kiwano::graphics::directx::GetD3D10DeviceResources();
}
#else
using ID3DDeviceResources = kiwano::graphics::directx::ID3D11DeviceResources;
inline ComPtr<ID3D11DeviceResources> GetD3DDeviceResources()
{
return kiwano::graphics::directx::GetD3D11DeviceResources();
}
#endif
} // namespace directx
} // namespace graphics
} // namespace kiwano

View File

@ -23,10 +23,17 @@
namespace kiwano
{
namespace graphics
{
namespace directx
{
MIDL_INTERFACE("fb99fa64-d9cf-4e0e-9c75-90514797b01d")
ID3DDeviceResourcesBase : public IUnknown
{
public:
virtual HRESULT Initialize(HWND hwnd) = 0;
virtual HRESULT Present(bool vsync) = 0;
virtual void ClearRenderTarget(Color & clear_color) = 0;
@ -39,6 +46,8 @@ public:
virtual HRESULT SetFullscreenState(bool fullscreen) = 0;
virtual HRESULT GetFullscreenState(bool* fullscreen) = 0;
virtual HRESULT ResizeTarget(UINT width, UINT height) = 0;
virtual HRESULT GetDisplaySettings(DXGI_MODE_DESC** mode_descs, int* num) = 0;
@ -46,4 +55,6 @@ public:
virtual void DiscardResources() = 0;
};
} // namespace directx
} // namespace graphics
} // namespace kiwano

View File

@ -32,6 +32,8 @@
namespace kiwano
{
using namespace kiwano::graphics::directx;
Renderer& Renderer::GetInstance()
{
return RendererImpl::GetInstance();
@ -64,16 +66,26 @@ void RendererImpl::MakeContextForWindow(WindowPtr window)
// Direct3D device resources
if (SUCCEEDED(hr))
{
hr = ID3DDeviceResources::Create(&d3d_res_, target_window);
auto d3d_res = graphics::directx::GetD3DDeviceResources();
// Initialize Direct3D resources
hr = d3d_res->Initialize(target_window);
// Direct2D device resources
if (SUCCEEDED(hr))
{
hr = ID2DDeviceResources::Create(&d2d_res_, d3d_res_->GetDXGIDevice(), d3d_res_->GetDXGISwapChain());
d3d_res_ = d3d_res;
auto d2d_res = graphics::directx::GetD2DDeviceResources();
// Initialize Direct2D resources
hr = d2d_res->Initialize(d3d_res_->GetDXGIDevice(), d3d_res_->GetDXGISwapChain());
// Other device resources
if (SUCCEEDED(hr))
{
d2d_res_ = d2d_res;
// Initialize other device resources
RenderContextImplPtr ctx = memory::New<RenderContextImpl>();
hr = ctx->CreateDeviceResources(d2d_res_->GetFactory(), d2d_res_->GetDeviceContext());
@ -151,7 +163,10 @@ void RendererImpl::Present()
KGE_ASSERT(d3d_res_);
HRESULT hr = d3d_res_->Present(vsync_);
KGE_THROW_IF_FAILED(hr, "Unexpected DXGI exception");
if (FAILED(hr) && hr != DXGI_ERROR_WAS_STILL_DRAWING)
{
KGE_THROW_IF_FAILED(hr, "Unexpected DXGI exception");
}
}
void RendererImpl::CreateTexture(Texture& texture, const String& file_path)
@ -949,77 +964,6 @@ RenderContextPtr RendererImpl::CreateTextureRenderContext(Texture& texture, cons
return nullptr;
}
void RendererImpl::SetResolution(uint32_t width, uint32_t height, bool fullscreen)
{
KGE_ASSERT(d3d_res_);
if (fullscreen)
{
HRESULT hr = d3d_res_->ResizeTarget(width, height);
KGE_THROW_IF_FAILED(hr, "DXGI ResizeTarget failed!");
hr = d3d_res_->SetFullscreenState(fullscreen);
KGE_THROW_IF_FAILED(hr, "DXGI SetFullscreenState failed!");
}
else
{
HRESULT hr = d3d_res_->SetFullscreenState(fullscreen);
KGE_THROW_IF_FAILED(hr, "DXGI SetFullscreenState failed!");
hr = d3d_res_->ResizeTarget(width, height);
KGE_THROW_IF_FAILED(hr, "DXGI ResizeTarget failed!");
}
Application::GetInstance().GetMainWindow()->SetFullscreenState(fullscreen);
}
Vector<Resolution> RendererImpl::GetResolutions()
{
if (resolutions_.empty())
{
DXGI_MODE_DESC* mode_descs = nullptr;
int mode_num = 0;
HRESULT hr = d3d_res_->GetDisplaySettings(&mode_descs, &mode_num);
if (SUCCEEDED(hr))
{
std::unique_ptr<DXGI_MODE_DESC[]> mode_list(mode_descs);
if (mode_list)
{
for (int i = 0; i < mode_num; i++)
{
Resolution res;
res.width = mode_descs[i].Width;
res.height = mode_descs[i].Height;
res.refresh_rate = 0;
if (mode_descs[i].RefreshRate.Denominator > 0)
{
res.refresh_rate = mode_descs[i].RefreshRate.Numerator / mode_descs[i].RefreshRate.Denominator;
}
if (!resolutions_.empty())
{
auto& back = resolutions_.back();
if (back.width == res.width && back.height == res.height
&& back.refresh_rate == res.refresh_rate)
continue;
}
resolutions_.push_back(res);
}
}
}
else
{
KGE_THROW_IF_FAILED(hr, "DXGI GetDisplaySettings failed!");
}
}
return resolutions_;
}
void RendererImpl::Resize(uint32_t width, uint32_t height)
{
HRESULT hr = S_OK;

View File

@ -20,24 +20,14 @@
#pragma once
#include <kiwano/render/Renderer.h>
#include <kiwano/render/DirectX/D3DDeviceResources.h>
#include <kiwano/render/DirectX/FontCollectionLoader.h>
#include <kiwano/render/DirectX/RenderContextImpl.h>
#if defined(KGE_USE_DIRECTX10)
#include <kiwano/render/DirectX/D3D10DeviceResources.h>
#else
#include <kiwano/render/DirectX/D3D11DeviceResources.h>
#endif
namespace kiwano
{
#if defined(KGE_USE_DIRECTX10)
typedef ID3D10DeviceResources ID3DDeviceResources;
#else
typedef ID3D11DeviceResources ID3DDeviceResources;
#endif
class KGE_API RendererImpl
: public Renderer
{
@ -82,25 +72,11 @@ public:
RenderContextPtr CreateTextureRenderContext(Texture& texture, const Size* desired_size = nullptr) override;
void SetResolution(uint32_t width, uint32_t height, bool fullscreen) override;
Vector<Resolution> GetResolutions() override;
public:
void Clear() override;
void Present() override;
/// \~chinese
/// @brief 获取Direct2D设备资源
ID2DDeviceResources* GetD2DDeviceResources();
/// \~chinese
/// @brief 获取Direct3D设备资源
ID3DDeviceResources* GetD3DDeviceResources();
/// \~chinese
/// @brief 重设渲染输出大小
void Resize(uint32_t width, uint32_t height) override;
protected:
@ -111,27 +87,17 @@ protected:
void Destroy() override;
private:
using ID2DDeviceResources = kiwano::graphics::directx::ID2DDeviceResources;
using ID3DDeviceResources = kiwano::graphics::directx::ID3DDeviceResources;
ComPtr<ID2DDeviceResources> d2d_res_;
ComPtr<ID3DDeviceResources> d3d_res_;
ComPtr<IFontCollectionLoader> font_collection_loader_;
ComPtr<IResourceFontFileLoader> res_font_file_loader_;
ComPtr<IResourceFontCollectionLoader> res_font_collection_loader_;
Vector<Resolution> resolutions_;
};
/** @} */
inline ID2DDeviceResources* RendererImpl::GetD2DDeviceResources()
{
KGE_ASSERT(d2d_res_);
return d2d_res_.Get();
}
inline ID3DDeviceResources* RendererImpl::GetD3DDeviceResources()
{
KGE_ASSERT(d3d_res_);
return d3d_res_.Get();
}
} // namespace kiwano

View File

@ -29,6 +29,7 @@ namespace kiwano
{
namespace DX
{
template <typename T>
inline void SafeRelease(T*& ptr)
{
@ -174,5 +175,6 @@ inline float ConvertDipsToPixels(float dips, float dpi)
static const float dips_per_inch = 96.0f;
return math::Floor(dips * dpi / dips_per_inch + 0.5f); // Round to nearest integer.
}
} // namespace DX
} // namespace kiwano

View File

@ -39,17 +39,6 @@ namespace kiwano
* @{
*/
/**
* \~chinese
* @brief
*/
struct Resolution
{
uint32_t width; ///< 分辨率宽度
uint32_t height; ///< 分辨率高度
uint32_t refresh_rate; ///< 刷新率
};
/**
* \~chinese
@ -74,14 +63,6 @@ public:
/// @brief 开启或关闭垂直同步
virtual void SetVSyncEnabled(bool enabled);
/// \~chinese
/// @brief 设置分辨率
virtual void SetResolution(uint32_t width, uint32_t height, bool fullscreen) = 0;
/// \~chinese
/// @brief 获取屏幕分辨率
virtual Vector<Resolution> GetResolutions() = 0;
/// \~chinese
/// @brief 创建纹理内部资源
/// @param[out] texture 纹理