update render package

minor
This commit is contained in:
Nomango 2019-07-30 00:41:06 +08:00 committed by Nomango
parent 3ee2749b28
commit da7970bf34
20 changed files with 559 additions and 356 deletions

View File

@ -30,7 +30,7 @@ namespace kiwano
: cache_expired_(false) : cache_expired_(false)
, stroke_width_(1.0f) , stroke_width_(1.0f)
{ {
auto ctx = Renderer::Instance().GetDeviceResources()->GetD2DDeviceContext(); auto ctx = Renderer::Instance().GetD2DDeviceResources()->GetDeviceContext();
ThrowIfFailed( ThrowIfFailed(
ctx->CreateCompatibleRenderTarget(&render_target_) ctx->CreateCompatibleRenderTarget(&render_target_)
@ -123,7 +123,7 @@ namespace kiwano
void Canvas::SetOutlineJoinStyle(StrokeStyle outline_join) void Canvas::SetOutlineJoinStyle(StrokeStyle outline_join)
{ {
outline_join_style_ = Renderer::Instance().GetDeviceResources()->GetStrokeStyle(outline_join); outline_join_style_ = Renderer::Instance().GetD2DDeviceResources()->GetStrokeStyle(outline_join);
} }
void Canvas::SetTextStyle(Font const& font, TextStyle const & text_style) void Canvas::SetTextStyle(Font const& font, TextStyle const & text_style)
@ -136,7 +136,7 @@ namespace kiwano
text_style_.outline, text_style_.outline,
DX::ConvertToColorF(text_style_.outline_color), DX::ConvertToColorF(text_style_.outline_color),
text_style_.outline_width, text_style_.outline_width,
Renderer::Instance().GetDeviceResources()->GetStrokeStyle(text_style_.outline_stroke) Renderer::Instance().GetD2DDeviceResources()->GetStrokeStyle(text_style_.outline_stroke)
); );
// clear text format // clear text format
@ -272,7 +272,7 @@ namespace kiwano
if (!text_format_) if (!text_format_)
{ {
ThrowIfFailed( ThrowIfFailed(
Renderer::Instance().GetDeviceResources()->CreateTextFormat( Renderer::Instance().GetD2DDeviceResources()->CreateTextFormat(
text_format_, text_format_,
text_font_, text_font_,
text_style_ text_style_
@ -283,7 +283,7 @@ namespace kiwano
ComPtr<IDWriteTextLayout> text_layout; ComPtr<IDWriteTextLayout> text_layout;
Size layout_size; Size layout_size;
ThrowIfFailed( ThrowIfFailed(
Renderer::Instance().GetDeviceResources()->CreateTextLayout( Renderer::Instance().GetD2DDeviceResources()->CreateTextLayout(
text_layout, text_layout,
layout_size, layout_size,
text, text,
@ -392,7 +392,7 @@ namespace kiwano
current_geometry_ = nullptr; current_geometry_ = nullptr;
ThrowIfFailed( ThrowIfFailed(
Renderer::Instance().GetDeviceResources()->GetD2DFactory()->CreatePathGeometry(&current_geometry_) Renderer::Instance().GetD2DDeviceResources()->GetFactory()->CreatePathGeometry(&current_geometry_)
); );
ThrowIfFailed( ThrowIfFailed(

View File

@ -54,7 +54,7 @@ namespace kiwano
Renderer::Instance().SetTransform(Matrix{}); Renderer::Instance().SetTransform(Matrix{});
Renderer::Instance().GetSolidColorBrush()->SetColor(D2D1::ColorF(0.0f, 0.0f, 0.0f, 0.5f)); Renderer::Instance().GetSolidColorBrush()->SetColor(D2D1::ColorF(0.0f, 0.0f, 0.0f, 0.5f));
Renderer::Instance().GetDeviceResources()->GetD2DDeviceContext()->FillRectangle( Renderer::Instance().GetD2DDeviceResources()->GetDeviceContext()->FillRectangle(
D2D1_RECT_F{ 10, 10, 30 + debug_text_->GetLayoutSize().x, 30 + debug_text_->GetLayoutSize().y }, D2D1_RECT_F{ 10, 10, 30 + debug_text_->GetLayoutSize().x, 30 + debug_text_->GetLayoutSize().y },
Renderer::Instance().GetSolidColorBrush() Renderer::Instance().GetSolidColorBrush()
); );

View File

@ -128,7 +128,7 @@ namespace kiwano
ComPtr<ID2D1PathGeometry> path_geo; ComPtr<ID2D1PathGeometry> path_geo;
ComPtr<ID2D1GeometrySink> path_sink; ComPtr<ID2D1GeometrySink> path_sink;
HRESULT hr = Renderer::Instance().GetDeviceResources()->GetD2DFactory()->CreatePathGeometry(&path_geo); HRESULT hr = Renderer::Instance().GetD2DDeviceResources()->GetFactory()->CreatePathGeometry(&path_geo);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
@ -185,7 +185,7 @@ namespace kiwano
void RectangleGeometry::SetRect(Rect const & rect) void RectangleGeometry::SetRect(Rect const & rect)
{ {
ComPtr<ID2D1RectangleGeometry> geo; ComPtr<ID2D1RectangleGeometry> geo;
auto factory = Renderer::Instance().GetDeviceResources()->GetD2DFactory(); auto factory = Renderer::Instance().GetD2DDeviceResources()->GetFactory();
if (SUCCEEDED(factory->CreateRectangleGeometry(DX::ConvertToRectF(rect), &geo))) if (SUCCEEDED(factory->CreateRectangleGeometry(DX::ConvertToRectF(rect), &geo)))
{ {
@ -226,7 +226,7 @@ namespace kiwano
void CircleGeometry::SetCircle(Point const & center, float radius) void CircleGeometry::SetCircle(Point const & center, float radius)
{ {
ComPtr<ID2D1EllipseGeometry> geo; ComPtr<ID2D1EllipseGeometry> geo;
auto factory = Renderer::Instance().GetDeviceResources()->GetD2DFactory(); auto factory = Renderer::Instance().GetD2DDeviceResources()->GetFactory();
if (SUCCEEDED(factory->CreateEllipseGeometry( if (SUCCEEDED(factory->CreateEllipseGeometry(
D2D1::Ellipse( D2D1::Ellipse(
@ -274,7 +274,7 @@ namespace kiwano
void EllipseGeometry::SetEllipse(Point const & center, float radius_x, float radius_y) void EllipseGeometry::SetEllipse(Point const & center, float radius_x, float radius_y)
{ {
ComPtr<ID2D1EllipseGeometry> geo; ComPtr<ID2D1EllipseGeometry> geo;
auto factory = Renderer::Instance().GetDeviceResources()->GetD2DFactory(); auto factory = Renderer::Instance().GetD2DDeviceResources()->GetFactory();
if (SUCCEEDED(factory->CreateEllipseGeometry( if (SUCCEEDED(factory->CreateEllipseGeometry(
D2D1::Ellipse( D2D1::Ellipse(
@ -306,7 +306,7 @@ namespace kiwano
{ {
current_geometry_ = nullptr; current_geometry_ = nullptr;
auto factory = Renderer::Instance().GetDeviceResources()->GetD2DFactory(); auto factory = Renderer::Instance().GetD2DDeviceResources()->GetFactory();
ThrowIfFailed( ThrowIfFailed(
factory->CreatePathGeometry(&current_geometry_) factory->CreatePathGeometry(&current_geometry_)
@ -422,7 +422,7 @@ namespace kiwano
void RoundedRectGeometry::SetRoundedRect(Rect const & rect, float radius_x, float radius_y) void RoundedRectGeometry::SetRoundedRect(Rect const & rect, float radius_x, float radius_y)
{ {
ComPtr<ID2D1RoundedRectangleGeometry> geo; ComPtr<ID2D1RoundedRectangleGeometry> geo;
auto factory = Renderer::Instance().GetDeviceResources()->GetD2DFactory(); auto factory = Renderer::Instance().GetD2DDeviceResources()->GetFactory();
if (SUCCEEDED(factory->CreateRoundedRectangleGeometry( if (SUCCEEDED(factory->CreateRoundedRectangleGeometry(
D2D1::RoundedRect( D2D1::RoundedRect(

View File

@ -36,8 +36,8 @@ namespace kiwano
, frame_position_{} , frame_position_{}
, bg_color_{} , bg_color_{}
{ {
factory_ = Renderer::Instance().GetDeviceResources()->GetWICImagingFactory(); factory_ = Renderer::Instance().GetD2DDeviceResources()->GetWICImagingFactory();
auto ctx = Renderer::Instance().GetDeviceResources()->GetD2DDeviceContext(); auto ctx = Renderer::Instance().GetD2DDeviceResources()->GetDeviceContext();
ThrowIfFailed( ThrowIfFailed(
ctx->CreateCompatibleRenderTarget(&frame_rt_) ctx->CreateCompatibleRenderTarget(&frame_rt_)
@ -192,7 +192,7 @@ namespace kiwano
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
auto ctx = Renderer::Instance().GetDeviceResources()->GetD2DDeviceContext(); auto ctx = Renderer::Instance().GetD2DDeviceResources()->GetDeviceContext();
// Create a D2DBitmap from IWICBitmapSource // Create a D2DBitmap from IWICBitmapSource
raw_frame_.Reset(); raw_frame_.Reset();

View File

@ -69,11 +69,11 @@ namespace kiwano
return false; return false;
} }
#endif #endif
hr = Renderer::Instance().GetDeviceResources()->CreateBitmapFromFile(bitmap, res.GetFileName()); hr = Renderer::Instance().GetD2DDeviceResources()->CreateBitmapFromFile(bitmap, res.GetFileName());
} }
else else
{ {
hr = Renderer::Instance().GetDeviceResources()->CreateBitmapFromResource(bitmap, res); hr = Renderer::Instance().GetD2DDeviceResources()->CreateBitmapFromResource(bitmap, res);
} }
if (FAILED(hr)) if (FAILED(hr))

View File

@ -327,7 +327,7 @@ namespace kiwano
return; return;
ThrowIfFailed( ThrowIfFailed(
Renderer::Instance().GetDeviceResources()->CreateTextFormat( Renderer::Instance().GetD2DDeviceResources()->CreateTextFormat(
text_format_, text_format_,
font_, font_,
style_ style_
@ -335,7 +335,7 @@ namespace kiwano
); );
ThrowIfFailed( ThrowIfFailed(
Renderer::Instance().GetDeviceResources()->CreateTextLayout( Renderer::Instance().GetD2DDeviceResources()->CreateTextLayout(
text_layout_, text_layout_,
layout_size_, layout_size_,
text_, text_,

View File

@ -84,7 +84,7 @@
<ClInclude Include="renderer\D2DDeviceResources.h" /> <ClInclude Include="renderer\D2DDeviceResources.h" />
<ClInclude Include="renderer\D3D10DeviceResources.h" /> <ClInclude Include="renderer\D3D10DeviceResources.h" />
<ClInclude Include="renderer\D3D11DeviceResources.h" /> <ClInclude Include="renderer\D3D11DeviceResources.h" />
<ClInclude Include="renderer\DeviceResources.h" /> <ClInclude Include="renderer\D3DDeviceResourcesBase.h" />
<ClInclude Include="renderer\helper.hpp" /> <ClInclude Include="renderer\helper.hpp" />
<ClInclude Include="renderer\render.h" /> <ClInclude Include="renderer\render.h" />
<ClInclude Include="renderer\TextRenderer.h" /> <ClInclude Include="renderer\TextRenderer.h" />

View File

@ -183,9 +183,6 @@
<ClInclude Include="renderer\D3D11DeviceResources.h"> <ClInclude Include="renderer\D3D11DeviceResources.h">
<Filter>renderer</Filter> <Filter>renderer</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="renderer\DeviceResources.h">
<Filter>renderer</Filter>
</ClInclude>
<ClInclude Include="renderer\helper.hpp"> <ClInclude Include="renderer\helper.hpp">
<Filter>renderer</Filter> <Filter>renderer</Filter>
</ClInclude> </ClInclude>
@ -333,6 +330,9 @@
<ClInclude Include="utils\FileUtil.h"> <ClInclude Include="utils\FileUtil.h">
<Filter>utils</Filter> <Filter>utils</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="renderer\D3DDeviceResourcesBase.h">
<Filter>renderer</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="ui\Button.cpp"> <ClCompile Include="ui\Button.cpp">

View File

@ -6,7 +6,7 @@
#include "imgui_impl_dx11.h" #include "imgui_impl_dx11.h"
inline bool ImGui_Impl_Init(::kiwano::Renderer& renderer) { return ImGui_ImplDX11_Init(renderer.GetDeviceResources()->GetD3DDevice(), renderer.GetDeviceResources()->GetD3DDeviceContext()); } inline bool ImGui_Impl_Init(::kiwano::Renderer& renderer) { return ImGui_ImplDX11_Init(renderer.GetD3DDeviceResources()->GetDevice(), renderer.GetD3DDeviceResources()->GetDeviceContext()); }
inline void ImGui_Impl_Shutdown() { ImGui_ImplDX11_Shutdown(); } inline void ImGui_Impl_Shutdown() { ImGui_ImplDX11_Shutdown(); }
inline void ImGui_Impl_NewFrame() { ImGui_ImplDX11_NewFrame(); } inline void ImGui_Impl_NewFrame() { ImGui_ImplDX11_NewFrame(); }
inline void ImGui_Impl_RenderDrawData(ImDrawData* draw_data) { ImGui_ImplDX11_RenderDrawData(draw_data); } inline void ImGui_Impl_RenderDrawData(ImDrawData* draw_data) { ImGui_ImplDX11_RenderDrawData(draw_data); }
@ -18,7 +18,7 @@ inline bool ImGui_Impl_CreateDeviceObjects() { return ImGui_ImplDX11_Cre
#include "imgui_impl_dx10.h" #include "imgui_impl_dx10.h"
inline bool ImGui_Impl_Init(::kiwano::Renderer& renderer) { return ImGui_ImplDX10_Init(renderer.GetDeviceResources()->GetD3DDeviceContext()); } inline bool ImGui_Impl_Init(::kiwano::Renderer& renderer) { return ImGui_ImplDX10_Init(renderer.GetD3DDeviceResources()->GetDevice()); }
inline void ImGui_Impl_Shutdown() { ImGui_ImplDX10_Shutdown(); } inline void ImGui_Impl_Shutdown() { ImGui_ImplDX10_Shutdown(); }
inline void ImGui_Impl_NewFrame() { ImGui_ImplDX10_NewFrame(); } inline void ImGui_Impl_NewFrame() { ImGui_ImplDX10_NewFrame(); }
inline void ImGui_Impl_RenderDrawData(ImDrawData* draw_data) { ImGui_ImplDX10_RenderDrawData(draw_data); } inline void ImGui_Impl_RenderDrawData(ImDrawData* draw_data) { ImGui_ImplDX10_RenderDrawData(draw_data); }

View File

@ -28,12 +28,109 @@
namespace kiwano namespace kiwano
{ {
struct D2DDeviceResources
: public ID2DDeviceResources
{
public:
D2DDeviceResources();
virtual ~D2DDeviceResources();
HRESULT CreateDeviceIndependentResources();
public:
HRESULT CreateBitmapFromFile(
_Out_ ComPtr<ID2D1Bitmap>& bitmap,
_In_ String const& file_path
) override;
HRESULT CreateBitmapFromResource(
_Out_ ComPtr<ID2D1Bitmap>& bitmap,
_In_ Resource const& res
) override;
HRESULT CreateTextFormat(
_Out_ ComPtr<IDWriteTextFormat>& text_format,
_In_ Font const& font,
_In_ TextStyle const& text_style
) const override;
HRESULT CreateTextLayout(
_Out_ ComPtr<IDWriteTextLayout>& text_layout,
_Out_ Size& layout_size,
_In_ String const& text,
_In_ ComPtr<IDWriteTextFormat> const& text_format,
_In_ TextStyle const& text_style
) const override;
void ClearImageCache() override;
void DiscardResources() override;
HRESULT SetD2DDevice(
_In_ ComPtr<ID2D1Device> const& device
) override;
void SetTargetBitmap(
_In_ ComPtr<ID2D1Bitmap1> const& target
) override;
ID2D1StrokeStyle* GetStrokeStyle(StrokeStyle stroke) const override;
public:
unsigned long STDMETHODCALLTYPE AddRef();
unsigned long STDMETHODCALLTYPE Release();
HRESULT STDMETHODCALLTYPE QueryInterface(
IID const& riid,
void** ppvObject
);
protected:
unsigned long ref_count_;
float dpi_;
using BitmapMap = UnorderedMap<size_t, ComPtr<ID2D1Bitmap>>;
BitmapMap bitmap_cache_;
ComPtr<ID2D1StrokeStyle> d2d_miter_stroke_style_;
ComPtr<ID2D1StrokeStyle> d2d_bevel_stroke_style_;
ComPtr<ID2D1StrokeStyle> d2d_round_stroke_style_;
};
HRESULT ID2DDeviceResources::Create(ID2DDeviceResources** device_resources)
{
HRESULT hr = E_FAIL;
if (device_resources)
{
D2DDeviceResources* res = new (std::nothrow) D2DDeviceResources;
if (res)
{
hr = res->CreateDeviceIndependentResources();
}
if (SUCCEEDED(hr))
{
res->AddRef();
DX::SafeRelease(*device_resources);
(*device_resources) = res;
}
else
{
delete res;
res = nullptr;
}
}
return hr;
}
D2DDeviceResources::D2DDeviceResources() D2DDeviceResources::D2DDeviceResources()
: ref_count_(0) : ref_count_(0)
, dpi_(96.f) , dpi_(96.f)
{ {
CreateDeviceIndependentResources();
} }
D2DDeviceResources::~D2DDeviceResources() D2DDeviceResources::~D2DDeviceResources()
@ -59,11 +156,13 @@ namespace kiwano
return newCount; return newCount;
} }
STDMETHODIMP D2DDeviceResources::QueryInterface( STDMETHODIMP D2DDeviceResources::QueryInterface(IID const& riid, void** object)
IID const& riid,
void** object)
{ {
if (__uuidof(IUnknown) == riid) if (__uuidof(ID2DDeviceResources) == riid)
{
*object = this;
}
else if (__uuidof(IUnknown) == riid)
{ {
*object = this; *object = this;
} }
@ -82,10 +181,10 @@ namespace kiwano
{ {
ClearImageCache(); ClearImageCache();
d2d_factory_.Reset(); factory_.Reset();
d2d_device_.Reset(); device_.Reset();
d2d_device_context_.Reset(); device_context_.Reset();
d2d_target_bitmap_.Reset(); target_bitmap_.Reset();
imaging_factory_.Reset(); imaging_factory_.Reset();
dwrite_factory_.Reset(); dwrite_factory_.Reset();
@ -118,7 +217,7 @@ namespace kiwano
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
d2d_factory_ = d2d_factory; factory_ = d2d_factory;
hr = CoCreateInstance( hr = CoCreateInstance(
CLSID_WICImagingFactory, CLSID_WICImagingFactory,
@ -158,7 +257,7 @@ namespace kiwano
0.0f 0.0f
); );
hr = d2d_factory_->CreateStrokeStyle( hr = factory_->CreateStrokeStyle(
stroke_style, stroke_style,
nullptr, nullptr,
0, 0,
@ -168,7 +267,7 @@ namespace kiwano
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
stroke_style.lineJoin = D2D1_LINE_JOIN_BEVEL; stroke_style.lineJoin = D2D1_LINE_JOIN_BEVEL;
hr = d2d_factory_->CreateStrokeStyle( hr = factory_->CreateStrokeStyle(
stroke_style, stroke_style,
nullptr, nullptr,
0, 0,
@ -179,7 +278,7 @@ namespace kiwano
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
stroke_style.lineJoin = D2D1_LINE_JOIN_ROUND; stroke_style.lineJoin = D2D1_LINE_JOIN_ROUND;
hr = d2d_factory_->CreateStrokeStyle( hr = factory_->CreateStrokeStyle(
stroke_style, stroke_style,
nullptr, nullptr,
0, 0,
@ -209,9 +308,9 @@ namespace kiwano
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
d2d_device_ = device; device_ = device;
d2d_device_context_ = d2d_device_ctx; device_context_ = d2d_device_ctx;
d2d_device_context_->SetDpi(dpi_, dpi_); device_context_->SetDpi(dpi_, dpi_);
} }
return hr; return hr;
@ -219,14 +318,14 @@ namespace kiwano
void D2DDeviceResources::SetTargetBitmap(ComPtr<ID2D1Bitmap1> const& target) void D2DDeviceResources::SetTargetBitmap(ComPtr<ID2D1Bitmap1> const& target)
{ {
d2d_target_bitmap_ = target; target_bitmap_ = target;
if (d2d_device_context_) if (device_context_)
d2d_device_context_->SetTarget(d2d_target_bitmap_.Get()); device_context_->SetTarget(target_bitmap_.Get());
} }
HRESULT D2DDeviceResources::CreateBitmapFromFile(ComPtr<ID2D1Bitmap> & bitmap, String const & file_path) HRESULT D2DDeviceResources::CreateBitmapFromFile(ComPtr<ID2D1Bitmap> & bitmap, String const & file_path)
{ {
if (!imaging_factory_ || !d2d_device_context_) if (!imaging_factory_ || !device_context_)
return E_UNEXPECTED; return E_UNEXPECTED;
size_t hash_code = std::hash<String>{}(file_path); size_t hash_code = std::hash<String>{}(file_path);
@ -275,7 +374,7 @@ namespace kiwano
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = d2d_device_context_->CreateBitmapFromWicBitmap( hr = device_context_->CreateBitmapFromWicBitmap(
converter.Get(), converter.Get(),
nullptr, nullptr,
&bitmap_tmp &bitmap_tmp
@ -293,7 +392,7 @@ namespace kiwano
HRESULT D2DDeviceResources::CreateBitmapFromResource(ComPtr<ID2D1Bitmap> & bitmap, Resource const & res) HRESULT D2DDeviceResources::CreateBitmapFromResource(ComPtr<ID2D1Bitmap> & bitmap, Resource const & res)
{ {
if (!imaging_factory_ || !d2d_device_context_) if (!imaging_factory_ || !device_context_)
return E_UNEXPECTED; return E_UNEXPECTED;
size_t hash_code = res.GetHashCode(); size_t hash_code = res.GetHashCode();
@ -362,7 +461,7 @@ namespace kiwano
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = d2d_device_context_->CreateBitmapFromWicBitmap( hr = device_context_->CreateBitmapFromWicBitmap(
converter.Get(), converter.Get(),
nullptr, nullptr,
&bitmap_tmp &bitmap_tmp

View File

@ -29,90 +29,66 @@
namespace kiwano namespace kiwano
{ {
class KGE_API D2DDeviceResources MIDL_INTERFACE("5706684a-bf6d-4b03-b627-094758a33032")
KGE_API ID2DDeviceResources
: public IUnknown : public IUnknown
{ {
public: public:
HRESULT CreateBitmapFromFile( static HRESULT Create(ID2DDeviceResources** device_resources);
virtual HRESULT CreateBitmapFromFile(
_Out_ ComPtr<ID2D1Bitmap>& bitmap, _Out_ ComPtr<ID2D1Bitmap>& bitmap,
_In_ String const& file_path _In_ String const& file_path
); ) = 0;
HRESULT CreateBitmapFromResource( virtual HRESULT CreateBitmapFromResource(
_Out_ ComPtr<ID2D1Bitmap>& bitmap, _Out_ ComPtr<ID2D1Bitmap>& bitmap,
_In_ Resource const& res _In_ Resource const& res
); ) = 0;
HRESULT CreateTextFormat( virtual HRESULT CreateTextFormat(
_Out_ ComPtr<IDWriteTextFormat>& text_format, _Out_ ComPtr<IDWriteTextFormat>& text_format,
_In_ Font const& font, _In_ Font const& font,
_In_ TextStyle const& text_style _In_ TextStyle const& text_style
) const; ) const = 0;
HRESULT CreateTextLayout( virtual HRESULT CreateTextLayout(
_Out_ ComPtr<IDWriteTextLayout>& text_layout, _Out_ ComPtr<IDWriteTextLayout>& text_layout,
_Out_ Size& layout_size, _Out_ Size& layout_size,
_In_ String const& text, _In_ String const& text,
_In_ ComPtr<IDWriteTextFormat> const& text_format, _In_ ComPtr<IDWriteTextFormat> const& text_format,
_In_ TextStyle const& text_style _In_ TextStyle const& text_style
) const; ) const = 0;
void ClearImageCache(); virtual ID2D1StrokeStyle* GetStrokeStyle(StrokeStyle stroke) const = 0;
void DiscardResources(); virtual HRESULT SetD2DDevice(
HRESULT SetD2DDevice(
_In_ ComPtr<ID2D1Device> const& device _In_ ComPtr<ID2D1Device> const& device
); ) = 0;
void SetTargetBitmap( virtual void SetTargetBitmap(
_In_ ComPtr<ID2D1Bitmap1> const& target _In_ ComPtr<ID2D1Bitmap1> const& target
); ) = 0;
inline ID2D1Factory1* GetD2DFactory() const { KGE_ASSERT(d2d_factory_); return d2d_factory_.Get(); } virtual void ClearImageCache() = 0;
virtual void DiscardResources() = 0;
inline ID2D1Factory1* GetFactory() const { KGE_ASSERT(factory_); return factory_.Get(); }
inline IWICImagingFactory* GetWICImagingFactory() const { KGE_ASSERT(imaging_factory_); return imaging_factory_.Get(); } inline IWICImagingFactory* GetWICImagingFactory() const { KGE_ASSERT(imaging_factory_); return imaging_factory_.Get(); }
inline IDWriteFactory* GetDWriteFactory() const { KGE_ASSERT(dwrite_factory_); return dwrite_factory_.Get(); } inline IDWriteFactory* GetDWriteFactory() const { KGE_ASSERT(dwrite_factory_); return dwrite_factory_.Get(); }
inline ID2D1Device* GetD2DDevice() const { KGE_ASSERT(d2d_device_); return d2d_device_.Get(); } inline ID2D1Device* GetDevice() const { KGE_ASSERT(device_); return device_.Get(); }
inline ID2D1DeviceContext* GetD2DDeviceContext() const { KGE_ASSERT(d2d_device_context_); return d2d_device_context_.Get(); } inline ID2D1DeviceContext* GetDeviceContext() const { KGE_ASSERT(device_context_); return device_context_.Get(); }
inline ID2D1Bitmap1* GetD2DTargetBitmap() const { KGE_ASSERT(d2d_target_bitmap_); return d2d_target_bitmap_.Get(); } inline ID2D1Bitmap1* GetTargetBitmap() const { KGE_ASSERT(target_bitmap_); return target_bitmap_.Get(); }
ID2D1StrokeStyle* GetStrokeStyle(StrokeStyle stroke) const;
public:
unsigned long STDMETHODCALLTYPE AddRef();
unsigned long STDMETHODCALLTYPE Release();
HRESULT STDMETHODCALLTYPE QueryInterface(
IID const& riid,
void** ppvObject
);
protected: protected:
D2DDeviceResources(); ComPtr<ID2D1Factory1> factory_;
ComPtr<ID2D1Device> device_;
virtual ~D2DDeviceResources(); ComPtr<ID2D1DeviceContext> device_context_;
ComPtr<ID2D1Bitmap1> target_bitmap_;
HRESULT CreateDeviceIndependentResources();
private:
unsigned long ref_count_;
float dpi_;
using BitmapMap = UnorderedMap<size_t, ComPtr<ID2D1Bitmap>>;
BitmapMap bitmap_cache_;
ComPtr<ID2D1Factory1> d2d_factory_;
ComPtr<ID2D1Device> d2d_device_;
ComPtr<ID2D1DeviceContext> d2d_device_context_;
ComPtr<ID2D1Bitmap1> d2d_target_bitmap_;
ComPtr<IWICImagingFactory> imaging_factory_; ComPtr<IWICImagingFactory> imaging_factory_;
ComPtr<IDWriteFactory> dwrite_factory_; ComPtr<IDWriteFactory> dwrite_factory_;
ComPtr<ID2D1StrokeStyle> d2d_miter_stroke_style_;
ComPtr<ID2D1StrokeStyle> d2d_bevel_stroke_style_;
ComPtr<ID2D1StrokeStyle> d2d_round_stroke_style_;
}; };
} }

View File

@ -80,8 +80,55 @@ namespace kiwano
} // namespace DX } // namespace DX
struct D3D10DeviceResources
: public ID3D10DeviceResources
{
public:
HRESULT Present(bool vsync);
HRESULT ClearRenderTarget(Color& clear_color);
HRESULT HandleDeviceLost();
HRESULT SetLogicalSize(Size logical_size);
HRESULT SetDpi(float dpi);
void DiscardResources();
public:
unsigned long STDMETHODCALLTYPE AddRef();
unsigned long STDMETHODCALLTYPE Release();
HRESULT STDMETHODCALLTYPE QueryInterface(
IID const& riid,
void** ppvObject
);
public:
D3D10DeviceResources();
virtual ~D3D10DeviceResources();
HRESULT CreateDeviceResources();
HRESULT CreateWindowSizeDependentResources();
public:
HWND hwnd_;
float dpi_;
Size logical_size_;
Size output_size_;
unsigned long ref_count_;
ComPtr<ID2DDeviceResources> d2d_res_;
};
D3D10DeviceResources::D3D10DeviceResources() D3D10DeviceResources::D3D10DeviceResources()
: hwnd_(nullptr) : ref_count_(0)
, hwnd_(nullptr)
{ {
dpi_ = 96.f; // dpi_ = (float)GetDpiForWindow(hwnd); dpi_ = 96.f; // dpi_ = (float)GetDpiForWindow(hwnd);
} }
@ -91,28 +138,24 @@ namespace kiwano
DiscardResources(); DiscardResources();
} }
HRESULT D3D10DeviceResources::Create(D3D10DeviceResources** device_resources, HWND hwnd) HRESULT ID3D10DeviceResources::Create(ID3D10DeviceResources** device_resources, ID2DDeviceResources* d2d_device_res, HWND hwnd)
{ {
HRESULT hr = E_FAIL; HRESULT hr = E_FAIL;
if (device_resources) if (device_resources && d2d_device_res)
{ {
D3D10DeviceResources* res = new (std::nothrow) D3D10DeviceResources; D3D10DeviceResources* res = new (std::nothrow) D3D10DeviceResources;
if (res) if (res)
{
hr = res->CreateDeviceIndependentResources();
if (SUCCEEDED(hr))
{ {
RECT rc; RECT rc;
GetClientRect(hwnd, &rc); ::GetClientRect(hwnd, &rc);
res->hwnd_ = hwnd; res->hwnd_ = hwnd;
res->d2d_res_ = d2d_device_res;
res->logical_size_.x = float(rc.right - rc.left); res->logical_size_.x = float(rc.right - rc.left);
res->logical_size_.y = float(rc.bottom - rc.top); res->logical_size_.y = float(rc.bottom - rc.top);
hr = res->CreateDeviceResources(); hr = res->CreateDeviceResources();
}
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
@ -138,29 +181,28 @@ namespace kiwano
HRESULT D3D10DeviceResources::Present(bool vsync) HRESULT D3D10DeviceResources::Present(bool vsync)
{ {
KGE_ASSERT(dxgi_swap_chain_ != nullptr);
// The first argument instructs DXGI to block until VSync. // The first argument instructs DXGI to block until VSync.
return dxgi_swap_chain_->Present(vsync ? 1 : 0, 0); return dxgi_swap_chain_->Present(vsync ? 1 : 0, 0);
} }
HRESULT D3D10DeviceResources::ClearRenderTarget(Color& clear_color) HRESULT D3D10DeviceResources::ClearRenderTarget(Color& clear_color)
{ {
d3d_device_->OMSetRenderTargets( KGE_ASSERT(device_ != nullptr && rt_view_ != nullptr && ds_view_ != nullptr);
1,
&d3d_rt_view_, auto rt_view = rt_view_.Get();
d3d_ds_view_.Get() device_->OMSetRenderTargets(1, &rt_view, ds_view_.Get());
); device_->ClearRenderTargetView(rt_view, reinterpret_cast<float*>(&clear_color));
d3d_device_->ClearRenderTargetView(
d3d_rt_view_.Get(),
reinterpret_cast<float*>(&clear_color)
);
return S_OK; return S_OK;
} }
void D3D10DeviceResources::DiscardResources() void D3D10DeviceResources::DiscardResources()
{ {
d3d_device_.Reset(); d2d_res_.Reset();
d3d_rt_view_.Reset(); device_.Reset();
d3d_ds_view_.Reset(); rt_view_.Reset();
ds_view_.Reset();
dxgi_swap_chain_.Reset(); dxgi_swap_chain_.Reset();
dxgi_factory_.Reset(); dxgi_factory_.Reset();
@ -192,7 +234,7 @@ namespace kiwano
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
d3d_device_ = device; device_ = device;
ComPtr<IDXGIAdapter> dxgi_adapter; ComPtr<IDXGIAdapter> dxgi_adapter;
ComPtr<IDXGIDevice> dxgi_device; ComPtr<IDXGIDevice> dxgi_device;
@ -201,7 +243,7 @@ namespace kiwano
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = d3d_device_->QueryInterface(IID_PPV_ARGS(&dxgi_device)); hr = device_->QueryInterface(IID_PPV_ARGS(&dxgi_device));
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
@ -222,12 +264,12 @@ namespace kiwano
// Create the Direct2D device object and a corresponding context. // Create the Direct2D device object and a corresponding context.
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = GetD2DFactory()->CreateDevice(dxgi_device.Get(), &d2d_device); hr = d2d_res_->GetFactory()->CreateDevice(dxgi_device.Get(), &d2d_device);
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = SetD2DDevice(d2d_device); hr = d2d_res_->SetD2DDevice(d2d_device);
} }
} }
@ -253,7 +295,7 @@ namespace kiwano
ComPtr<IDXGIDevice> dxgi_device; ComPtr<IDXGIDevice> dxgi_device;
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = d3d_device_->QueryInterface(&dxgi_device); hr = device_->QueryInterface(&dxgi_device);
} }
ComPtr<IDXGIAdapter> dxgi_adapter; ComPtr<IDXGIAdapter> dxgi_adapter;
@ -271,7 +313,7 @@ namespace kiwano
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = dxgi_factory->CreateSwapChain( hr = dxgi_factory->CreateSwapChain(
d3d_device_.Get(), device_.Get(),
&swap_chain_desc, &swap_chain_desc,
&dxgi_swap_chain_); &dxgi_swap_chain_);
} }
@ -289,11 +331,11 @@ namespace kiwano
// Clear the previous window size specific context. // Clear the previous window size specific context.
ID3D10RenderTargetView* null_views[] = { nullptr }; ID3D10RenderTargetView* null_views[] = { nullptr };
d3d_device_->OMSetRenderTargets(ARRAYSIZE(null_views), null_views, nullptr); device_->OMSetRenderTargets(ARRAYSIZE(null_views), null_views, nullptr);
SetTargetBitmap(nullptr); d2d_res_->SetTargetBitmap(nullptr);
d3d_rt_view_ = nullptr; rt_view_ = nullptr;
d3d_ds_view_ = nullptr; ds_view_ = nullptr;
d3d_device_->Flush(); device_->Flush();
// Calculate the necessary render target size in pixels. // Calculate the necessary render target size in pixels.
output_size_.x = DX::ConvertDipsToPixels(logical_size_.x, dpi_); output_size_.x = DX::ConvertDipsToPixels(logical_size_.x, dpi_);
@ -327,8 +369,8 @@ namespace kiwano
renderDesc.ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2D; renderDesc.ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2D;
renderDesc.Texture2D.MipSlice = 0; renderDesc.Texture2D.MipSlice = 0;
d3d_rt_view_ = nullptr; rt_view_ = nullptr;
hr = d3d_device_->CreateRenderTargetView(dxgi_back_buffer.Get(), &renderDesc, &d3d_rt_view_); hr = device_->CreateRenderTargetView(dxgi_back_buffer.Get(), &renderDesc, &rt_view_);
} }
} }
@ -349,7 +391,7 @@ namespace kiwano
tex_desc.SampleDesc.Quality = 0; tex_desc.SampleDesc.Quality = 0;
tex_desc.Usage = D3D10_USAGE_DEFAULT; tex_desc.Usage = D3D10_USAGE_DEFAULT;
hr = d3d_device_->CreateTexture2D(&tex_desc, NULL, &depth_stencil); hr = device_->CreateTexture2D(&tex_desc, NULL, &depth_stencil);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
@ -358,14 +400,14 @@ namespace kiwano
desc.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2D; desc.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2D;
desc.Texture2D.MipSlice = 0; desc.Texture2D.MipSlice = 0;
d3d_ds_view_.Reset(); ds_view_.Reset();
hr = d3d_device_->CreateDepthStencilView(depth_stencil.Get(), &desc, &d3d_ds_view_); hr = device_->CreateDepthStencilView(depth_stencil.Get(), &desc, &ds_view_);
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
ID3D10RenderTargetView* main_view = d3d_rt_view_.Get(); ID3D10RenderTargetView* main_view = rt_view_.Get();
d3d_device_->OMSetRenderTargets(1, &main_view, d3d_ds_view_.Get()); device_->OMSetRenderTargets(1, &main_view, ds_view_.Get());
} }
} }
@ -380,7 +422,7 @@ namespace kiwano
viewport.MinDepth = 0; viewport.MinDepth = 0;
viewport.MaxDepth = 1; viewport.MaxDepth = 1;
d3d_device_->RSSetViewports(1, &viewport); device_->RSSetViewports(1, &viewport);
} }
// Create a Direct2D target bitmap associated with the // Create a Direct2D target bitmap associated with the
@ -393,7 +435,7 @@ namespace kiwano
ComPtr<ID2D1Bitmap1> target; ComPtr<ID2D1Bitmap1> target;
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = GetD2DDeviceContext()->CreateBitmapFromDxgiSurface( hr = d2d_res_->GetDeviceContext()->CreateBitmapFromDxgiSurface(
dxgi_back_buffer.Get(), dxgi_back_buffer.Get(),
D2D1::BitmapProperties1( D2D1::BitmapProperties1(
D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
@ -405,7 +447,7 @@ namespace kiwano
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
SetTargetBitmap(target); d2d_res_->SetTargetBitmap(target);
} }
} }
@ -448,13 +490,56 @@ namespace kiwano
logical_size_.x = float(rc.right - rc.left); logical_size_.x = float(rc.right - rc.left);
logical_size_.y = float(rc.bottom - rc.top); logical_size_.y = float(rc.bottom - rc.top);
GetD2DDeviceContext()->SetDpi(dpi_, dpi_); d2d_res_->GetDeviceContext()->SetDpi(dpi_, dpi_);
return CreateWindowSizeDependentResources(); return CreateWindowSizeDependentResources();
} }
return S_OK; return S_OK;
} }
STDMETHODIMP_(unsigned long) D3D10DeviceResources::AddRef()
{
return InterlockedIncrement(&ref_count_);
}
STDMETHODIMP_(unsigned long) D3D10DeviceResources::Release()
{
unsigned long newCount = InterlockedDecrement(&ref_count_);
if (newCount == 0)
{
delete this;
return 0;
}
return newCount;
}
STDMETHODIMP D3D10DeviceResources::QueryInterface(IID const& riid, void** object)
{
if (__uuidof(ID3D10DeviceResources) == riid)
{
*object = this;
}
else if (__uuidof(ID3DDeviceResourcesBase) == riid)
{
*object = this;
}
else if (__uuidof(IUnknown) == riid)
{
*object = this;
}
else
{
*object = nullptr;
return E_FAIL;
}
AddRef();
return S_OK;
}
} }
#endif // !KGE_USE_DIRECTX10 #endif // !KGE_USE_DIRECTX10

View File

@ -25,69 +25,28 @@
#if defined(KGE_USE_DIRECTX10) #if defined(KGE_USE_DIRECTX10)
#include "D2DDeviceResources.h" #include "D2DDeviceResources.h"
#include "D3DDeviceResourcesBase.h"
#include <d3d10_1.h> #include <d3d10_1.h>
namespace kiwano namespace kiwano
{ {
class KGE_API D3D10DeviceResources MIDL_INTERFACE("3a150b9d-cc23-4022-a463-7e95452a54c4")
: public D2DDeviceResources KGE_API ID3D10DeviceResources
: public ID3DDeviceResourcesBase
{ {
public: public:
static HRESULT Create( static HRESULT Create(ID3D10DeviceResources** device_resources, ID2DDeviceResources* d2d_device_res, HWND hwnd);
D3D10DeviceResources** device_resources,
HWND hwnd
);
HRESULT Present( inline ID3D10Device* GetDevice() const { KGE_ASSERT(device_); return device_.Get(); }
bool vsync inline ID3D10RenderTargetView* GetRenderTargetView() const { KGE_ASSERT(rt_view_); return rt_view_.Get(); }
); inline ID3D10DepthStencilView* GetDepthStencilView() const { KGE_ASSERT(ds_view_); return ds_view_.Get(); }
HRESULT ClearRenderTarget(
Color& clear_color
);
HRESULT HandleDeviceLost();
HRESULT SetLogicalSize(
Size logical_size
);
HRESULT SetDpi(
float dpi
);
void DiscardResources();
inline ID3D10Device* GetD3DDevice() const { KGE_ASSERT(d3d_device_); return d3d_device_.Get(); }
inline ID3D10Device* GetD3DDeviceContext() const { KGE_ASSERT(d3d_device_); return d3d_device_.Get(); }
inline ID3D10RenderTargetView* GetD3DRenderTargetView() const { KGE_ASSERT(d3d_rt_view_); return d3d_rt_view_.Get(); }
inline ID3D10DepthStencilView* GetD3DDepthStencilView() const { KGE_ASSERT(d3d_ds_view_); return d3d_ds_view_.Get(); }
inline IDXGIFactory* GetDXGIFactory() const { KGE_ASSERT(dxgi_factory_); return dxgi_factory_.Get(); } inline IDXGIFactory* GetDXGIFactory() const { KGE_ASSERT(dxgi_factory_); return dxgi_factory_.Get(); }
inline IDXGISwapChain* GetDXGISwapChain() const { KGE_ASSERT(dxgi_swap_chain_); return dxgi_swap_chain_.Get(); } inline IDXGISwapChain* GetDXGISwapChain() const { KGE_ASSERT(dxgi_swap_chain_); 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: protected:
D3D10DeviceResources(); ComPtr<ID3D10Device> device_;
ComPtr<ID3D10RenderTargetView> rt_view_;
virtual ~D3D10DeviceResources(); ComPtr<ID3D10DepthStencilView> ds_view_;
protected:
HRESULT CreateDeviceResources();
HRESULT CreateWindowSizeDependentResources();
private:
HWND hwnd_;
float dpi_;
Size logical_size_;
Size output_size_;
ComPtr<ID3D10Device> d3d_device_;
ComPtr<ID3D10RenderTargetView> d3d_rt_view_;
ComPtr<ID3D10DepthStencilView> d3d_ds_view_;
ComPtr<IDXGISwapChain> dxgi_swap_chain_; ComPtr<IDXGISwapChain> dxgi_swap_chain_;
ComPtr<IDXGIFactory> dxgi_factory_; ComPtr<IDXGIFactory> dxgi_factory_;
}; };

View File

@ -52,8 +52,57 @@ namespace kiwano
} }
#endif #endif
struct D3D11DeviceResources
: public ID3D11DeviceResources
{
public:
HRESULT Present(bool vsync) override;
HRESULT ClearRenderTarget(Color& clear_color) override;
HRESULT HandleDeviceLost() override;
HRESULT SetLogicalSize(Size logical_size) override;
HRESULT SetDpi(float dpi) override;
void DiscardResources() override;
public:
unsigned long STDMETHODCALLTYPE AddRef();
unsigned long STDMETHODCALLTYPE Release();
HRESULT STDMETHODCALLTYPE QueryInterface(
IID const& riid,
void** ppvObject
);
public:
D3D11DeviceResources();
virtual ~D3D11DeviceResources();
HRESULT CreateDeviceResources();
HRESULT CreateWindowSizeDependentResources();
public:
HWND hwnd_;
float dpi_;
Size logical_size_;
Size output_size_;
unsigned long ref_count_;
D3D_FEATURE_LEVEL d3d_feature_level_;
ComPtr<ID2DDeviceResources> d2d_res_;
};
D3D11DeviceResources::D3D11DeviceResources() D3D11DeviceResources::D3D11DeviceResources()
: hwnd_(nullptr) : ref_count_(0)
, hwnd_(nullptr)
, d3d_feature_level_(D3D_FEATURE_LEVEL_9_1) , d3d_feature_level_(D3D_FEATURE_LEVEL_9_1)
{ {
dpi_ = 96.f; // dpi_ = (float)GetDpiForWindow(hwnd); dpi_ = 96.f; // dpi_ = (float)GetDpiForWindow(hwnd);
@ -64,28 +113,24 @@ namespace kiwano
DiscardResources(); DiscardResources();
} }
HRESULT D3D11DeviceResources::Create(D3D11DeviceResources** device_resources, HWND hwnd) HRESULT ID3D11DeviceResources::Create(ID3D11DeviceResources** device_resources, ID2DDeviceResources* d2d_device_res, HWND hwnd)
{ {
HRESULT hr = E_FAIL; HRESULT hr = E_FAIL;
if (device_resources) if (device_resources && d2d_device_res)
{ {
D3D11DeviceResources* res = new (std::nothrow) D3D11DeviceResources; D3D11DeviceResources* res = new (std::nothrow) D3D11DeviceResources;
if (res) if (res)
{
hr = res->CreateDeviceIndependentResources();
if (SUCCEEDED(hr))
{ {
RECT rc; RECT rc;
GetClientRect(hwnd, &rc); ::GetClientRect(hwnd, &rc);
res->hwnd_ = hwnd; res->hwnd_ = hwnd;
res->d2d_res_ = d2d_device_res;
res->logical_size_.x = float(rc.right - rc.left); res->logical_size_.x = float(rc.right - rc.left);
res->logical_size_.y = float(rc.bottom - rc.top); res->logical_size_.y = float(rc.bottom - rc.top);
hr = res->CreateDeviceResources(); hr = res->CreateDeviceResources();
}
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
@ -111,30 +156,29 @@ namespace kiwano
HRESULT D3D11DeviceResources::Present(bool vsync) HRESULT D3D11DeviceResources::Present(bool vsync)
{ {
KGE_ASSERT(dxgi_swap_chain_ != nullptr);
// The first argument instructs DXGI to block until VSync. // The first argument instructs DXGI to block until VSync.
return dxgi_swap_chain_->Present(vsync ? 1 : 0, 0); return dxgi_swap_chain_->Present(vsync ? 1 : 0, 0);
} }
HRESULT D3D11DeviceResources::ClearRenderTarget(Color& clear_color) HRESULT D3D11DeviceResources::ClearRenderTarget(Color& clear_color)
{ {
d3d_device_context_->OMSetRenderTargets( KGE_ASSERT(device_context_ != nullptr && rt_view_ != nullptr && ds_view_ != nullptr);
1,
&d3d_rt_view_, auto rt_view = rt_view_.Get();
d3d_ds_view_.Get() device_context_->OMSetRenderTargets(1, &rt_view, ds_view_.Get());
); device_context_->ClearRenderTargetView(rt_view, reinterpret_cast<float*>(&clear_color));
d3d_device_context_->ClearRenderTargetView(
d3d_rt_view_.Get(),
reinterpret_cast<float*>(&clear_color)
);
return S_OK; return S_OK;
} }
void D3D11DeviceResources::DiscardResources() void D3D11DeviceResources::DiscardResources()
{ {
d3d_device_.Reset(); d2d_res_.Reset();
d3d_device_context_.Reset(); device_.Reset();
d3d_rt_view_.Reset(); device_context_.Reset();
d3d_ds_view_.Reset(); rt_view_.Reset();
ds_view_.Reset();
dxgi_swap_chain_.Reset(); dxgi_swap_chain_.Reset();
dxgi_factory_.Reset(); dxgi_factory_.Reset();
@ -204,8 +248,8 @@ namespace kiwano
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
d3d_device_ = device; device_ = device;
d3d_device_context_ = context; device_context_ = context;
ComPtr<IDXGIAdapter> dxgi_adapter; ComPtr<IDXGIAdapter> dxgi_adapter;
ComPtr<IDXGIDevice> dxgi_device; ComPtr<IDXGIDevice> dxgi_device;
@ -214,7 +258,7 @@ namespace kiwano
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = d3d_device_->QueryInterface(IID_PPV_ARGS(&dxgi_device)); hr = device_->QueryInterface(IID_PPV_ARGS(&dxgi_device));
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
@ -235,12 +279,12 @@ namespace kiwano
// Create the Direct2D device object and a corresponding context. // Create the Direct2D device object and a corresponding context.
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = GetD2DFactory()->CreateDevice(dxgi_device.Get(), &d2d_device); hr = d2d_res_->GetFactory()->CreateDevice(dxgi_device.Get(), &d2d_device);
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = SetD2DDevice(d2d_device); hr = d2d_res_->SetD2DDevice(d2d_device);
} }
} }
@ -273,7 +317,7 @@ namespace kiwano
ComPtr<IDXGIDevice> dxgi_device; ComPtr<IDXGIDevice> dxgi_device;
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = d3d_device_->QueryInterface(&dxgi_device); hr = device_->QueryInterface(&dxgi_device);
} }
ComPtr<IDXGIAdapter> dxgi_adapter; ComPtr<IDXGIAdapter> dxgi_adapter;
@ -291,7 +335,7 @@ namespace kiwano
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = dxgi_factory->CreateSwapChain( hr = dxgi_factory->CreateSwapChain(
d3d_device_.Get(), device_.Get(),
&swap_chain_desc, &swap_chain_desc,
&dxgi_swap_chain_); &dxgi_swap_chain_);
} }
@ -309,11 +353,11 @@ namespace kiwano
// Clear the previous window size specific context. // Clear the previous window size specific context.
ID3D11RenderTargetView* null_views[] = { nullptr }; ID3D11RenderTargetView* null_views[] = { nullptr };
d3d_device_context_->OMSetRenderTargets(ARRAYSIZE(null_views), null_views, nullptr); device_context_->OMSetRenderTargets(ARRAYSIZE(null_views), null_views, nullptr);
SetTargetBitmap(nullptr); d2d_res_->SetTargetBitmap(nullptr);
d3d_rt_view_ = nullptr; rt_view_ = nullptr;
d3d_ds_view_ = nullptr; ds_view_ = nullptr;
d3d_device_context_->Flush(); device_context_->Flush();
// Calculate the necessary render target size in pixels. // Calculate the necessary render target size in pixels.
output_size_.x = DX::ConvertDipsToPixels(logical_size_.x, dpi_); output_size_.x = DX::ConvertDipsToPixels(logical_size_.x, dpi_);
@ -339,8 +383,8 @@ namespace kiwano
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
d3d_rt_view_ = nullptr; rt_view_ = nullptr;
hr = d3d_device_->CreateRenderTargetView(dxgi_back_buffer.Get(), nullptr, &d3d_rt_view_); hr = device_->CreateRenderTargetView(dxgi_back_buffer.Get(), nullptr, &rt_view_);
} }
} }
@ -357,20 +401,20 @@ namespace kiwano
D3D11_BIND_DEPTH_STENCIL D3D11_BIND_DEPTH_STENCIL
); );
hr = d3d_device_->CreateTexture2D(&tex_desc, nullptr, &depth_stencil); hr = device_->CreateTexture2D(&tex_desc, nullptr, &depth_stencil);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
CD3D11_DEPTH_STENCIL_VIEW_DESC desc(D3D11_DSV_DIMENSION_TEXTURE2D); CD3D11_DEPTH_STENCIL_VIEW_DESC desc(D3D11_DSV_DIMENSION_TEXTURE2D);
d3d_ds_view_.Reset(); ds_view_.Reset();
hr = d3d_device_->CreateDepthStencilView(depth_stencil.Get(), &desc, &d3d_ds_view_); hr = device_->CreateDepthStencilView(depth_stencil.Get(), &desc, &ds_view_);
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
ID3D11RenderTargetView* main_view = d3d_rt_view_.Get(); ID3D11RenderTargetView* main_view = rt_view_.Get();
d3d_device_context_->OMSetRenderTargets(1, &main_view, d3d_ds_view_.Get()); device_context_->OMSetRenderTargets(1, &main_view, ds_view_.Get());
} }
} }
@ -383,7 +427,7 @@ namespace kiwano
output_size_.x, output_size_.x,
output_size_.y); output_size_.y);
d3d_device_context_->RSSetViewports(1, &screen_viewport); device_context_->RSSetViewports(1, &screen_viewport);
} }
// Create a Direct2D target bitmap associated with the // Create a Direct2D target bitmap associated with the
@ -396,7 +440,7 @@ namespace kiwano
ComPtr<ID2D1Bitmap1> target; ComPtr<ID2D1Bitmap1> target;
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = GetD2DDeviceContext()->CreateBitmapFromDxgiSurface( hr = d2d_res_->GetDeviceContext()->CreateBitmapFromDxgiSurface(
dxgi_back_buffer.Get(), dxgi_back_buffer.Get(),
D2D1::BitmapProperties1( D2D1::BitmapProperties1(
D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
@ -408,7 +452,7 @@ namespace kiwano
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
SetTargetBitmap(target); d2d_res_->SetTargetBitmap(target);
} }
} }
@ -451,13 +495,56 @@ namespace kiwano
logical_size_.x = float(rc.right - rc.left); logical_size_.x = float(rc.right - rc.left);
logical_size_.y = float(rc.bottom - rc.top); logical_size_.y = float(rc.bottom - rc.top);
GetD2DDeviceContext()->SetDpi(dpi_, dpi_); d2d_res_->GetDeviceContext()->SetDpi(dpi_, dpi_);
return CreateWindowSizeDependentResources(); return CreateWindowSizeDependentResources();
} }
return S_OK; return S_OK;
} }
STDMETHODIMP_(unsigned long) D3D11DeviceResources::AddRef()
{
return InterlockedIncrement(&ref_count_);
}
STDMETHODIMP_(unsigned long) D3D11DeviceResources::Release()
{
unsigned long newCount = InterlockedDecrement(&ref_count_);
if (newCount == 0)
{
delete this;
return 0;
}
return newCount;
}
STDMETHODIMP D3D11DeviceResources::QueryInterface(IID const& riid, void** object)
{
if (__uuidof(ID3D11DeviceResources) == riid)
{
*object = this;
}
else if (__uuidof(ID3DDeviceResourcesBase) == riid)
{
*object = this;
}
else if (__uuidof(IUnknown) == riid)
{
*object = this;
}
else
{
*object = nullptr;
return E_FAIL;
}
AddRef();
return S_OK;
}
} }
#endif // !KGE_USE_DIRECTX10 #endif // !KGE_USE_DIRECTX10

View File

@ -25,73 +25,30 @@
#if !defined(KGE_USE_DIRECTX10) #if !defined(KGE_USE_DIRECTX10)
#include "D2DDeviceResources.h" #include "D2DDeviceResources.h"
#include "D3DDeviceResourcesBase.h"
#include <d3d11.h> #include <d3d11.h>
namespace kiwano namespace kiwano
{ {
class KGE_API D3D11DeviceResources MIDL_INTERFACE("3ede2b87-a202-4799-a39b-2308ad34cae8")
: public D2DDeviceResources KGE_API ID3D11DeviceResources
: public ID3DDeviceResourcesBase
{ {
public: public:
static HRESULT Create( static HRESULT Create(ID3D11DeviceResources** device_resources, ID2DDeviceResources* d2d_device_res, HWND hwnd);
D3D11DeviceResources** device_resources,
HWND hwnd
);
HRESULT Present( inline ID3D11Device* GetDevice() const { KGE_ASSERT(device_); return device_.Get(); }
bool vsync inline ID3D11DeviceContext* GetDeviceContext() const { KGE_ASSERT(device_context_); return device_context_.Get(); }
); inline ID3D11RenderTargetView* GetRenderTargetView() const { KGE_ASSERT(rt_view_); return rt_view_.Get(); }
inline ID3D11DepthStencilView* GetDepthStencilView() const { KGE_ASSERT(ds_view_); return ds_view_.Get(); }
HRESULT ClearRenderTarget(
Color& clear_color
);
HRESULT HandleDeviceLost();
HRESULT SetLogicalSize(
Size logical_size
);
HRESULT SetDpi(
float dpi
);
void DiscardResources();
inline ID3D11Device* GetD3DDevice() const { KGE_ASSERT(d3d_device_); return d3d_device_.Get(); }
inline ID3D11DeviceContext* GetD3DDeviceContext() const { KGE_ASSERT(d3d_device_context_); return d3d_device_context_.Get(); }
inline ID3D11RenderTargetView* GetD3DRenderTargetView() const { KGE_ASSERT(d3d_rt_view_); return d3d_rt_view_.Get(); }
inline ID3D11DepthStencilView* GetD3DDepthStencilView() const { KGE_ASSERT(d3d_ds_view_); return d3d_ds_view_.Get(); }
inline IDXGIFactory* GetDXGIFactory() const { KGE_ASSERT(dxgi_factory_); return dxgi_factory_.Get(); } inline IDXGIFactory* GetDXGIFactory() const { KGE_ASSERT(dxgi_factory_); return dxgi_factory_.Get(); }
inline IDXGISwapChain* GetDXGISwapChain() const { KGE_ASSERT(dxgi_swap_chain_); return dxgi_swap_chain_.Get(); } inline IDXGISwapChain* GetDXGISwapChain() const { KGE_ASSERT(dxgi_swap_chain_); return dxgi_swap_chain_.Get(); }
inline D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return d3d_feature_level_; }
inline Size const& GetLogicalSize() const { return logical_size_; }
inline Size const& GetOutputSize() const { return output_size_; }
inline float GetDpi() const { return dpi_; }
protected: protected:
D3D11DeviceResources(); ComPtr<ID3D11Device> device_;
ComPtr<ID3D11DeviceContext> device_context_;
virtual ~D3D11DeviceResources(); ComPtr<ID3D11RenderTargetView> rt_view_;
ComPtr<ID3D11DepthStencilView> ds_view_;
protected:
HRESULT CreateDeviceResources();
HRESULT CreateWindowSizeDependentResources();
private:
HWND hwnd_;
float dpi_;
Size logical_size_;
Size output_size_;
D3D_FEATURE_LEVEL d3d_feature_level_;
ComPtr<ID3D11Device> d3d_device_;
ComPtr<ID3D11DeviceContext> d3d_device_context_;
ComPtr<ID3D11RenderTargetView> d3d_rt_view_;
ComPtr<ID3D11DepthStencilView> d3d_ds_view_;
ComPtr<IDXGISwapChain> dxgi_swap_chain_; ComPtr<IDXGISwapChain> dxgi_swap_chain_;
ComPtr<IDXGIFactory> dxgi_factory_; ComPtr<IDXGIFactory> dxgi_factory_;
}; };

View File

@ -20,20 +20,28 @@
#pragma once #pragma once
#include "../macros.h" #include "../macros.h"
#include "../math/helper.h"
#if defined(KGE_USE_DIRECTX10) #include "../2d/Color.h"
# include "D3D10DeviceResources.h" #include <Unknwnbase.h>
#else
# include "D3D11DeviceResources.h"
#endif
namespace kiwano namespace kiwano
{ {
#if defined(KGE_USE_DIRECTX10) MIDL_INTERFACE("fb99fa64-d9cf-4e0e-9c75-90514797b01d")
using DeviceResources = D3D10DeviceResources; KGE_API ID3DDeviceResourcesBase : public IUnknown
#else {
using DeviceResources = D3D11DeviceResources; public:
#endif virtual HRESULT Present(bool vsync) = 0;
virtual HRESULT ClearRenderTarget(Color& clear_color) = 0;
virtual HRESULT HandleDeviceLost() = 0;
virtual HRESULT SetLogicalSize(Size logical_size) = 0;
virtual HRESULT SetDpi(float dpi) = 0;
virtual void DiscardResources() = 0;
};
} }

View File

@ -500,7 +500,11 @@ namespace kiwano
IID const& riid, IID const& riid,
void** ppvObject) void** ppvObject)
{ {
if (__uuidof(IDWriteTextRenderer) == riid) if (__uuidof(ITextRenderer) == riid)
{
*ppvObject = this;
}
else if (__uuidof(IDWriteTextRenderer) == riid)
{ {
*ppvObject = this; *ppvObject = this;
} }

View File

@ -24,7 +24,7 @@
namespace kiwano namespace kiwano
{ {
interface ITextRenderer interface DWRITE_DECLARE_INTERFACE("b293e798-9916-4096-a3c1-e5d4039dfa64") ITextRenderer
: public IDWriteTextRenderer : public IDWriteTextRenderer
{ {
public: public:

View File

@ -49,21 +49,36 @@ namespace kiwano
ThrowIfFailed(hwnd_ ? S_OK : E_FAIL); ThrowIfFailed(hwnd_ ? S_OK : E_FAIL);
device_resources_ = nullptr; d2d_res_ = nullptr;
d3d_res_ = nullptr;
drawing_state_block_ = nullptr; drawing_state_block_ = nullptr;
ThrowIfFailed( ThrowIfFailed(
DeviceResources::Create( ID2DDeviceResources::Create(
&device_resources_, &d2d_res_
hwnd_
) )
); );
factory_ = device_resources_->GetD2DFactory(); ThrowIfFailed(
device_context_ = device_resources_->GetD2DDeviceContext(); #if defined(KGE_USE_DIRECTX10)
ID3D10DeviceResources::Create(
&d3d_res_,
d2d_res_.Get(),
hwnd_
)
#else
ID3D11DeviceResources::Create(
&d3d_res_,
d2d_res_.Get(),
hwnd_
)
#endif
);
device_context_ = d2d_res_->GetDeviceContext();
ThrowIfFailed( ThrowIfFailed(
factory_->CreateDrawingStateBlock( d2d_res_->GetFactory()->CreateDrawingStateBlock(
&drawing_state_block_ &drawing_state_block_
) )
); );
@ -80,11 +95,9 @@ namespace kiwano
KGE_LOG(L"Destroying device resources"); KGE_LOG(L"Destroying device resources");
drawing_state_block_.Reset(); drawing_state_block_.Reset();
text_renderer_.Reset();
solid_color_brush_.Reset(); solid_color_brush_.Reset();
device_context_.Reset(); d2d_res_.Reset();
factory_.Reset(); d3d_res_.Reset();
device_resources_.Reset();
} }
HRESULT Renderer::CreateDeviceResources() HRESULT Renderer::CreateDeviceResources()
@ -114,7 +127,7 @@ namespace kiwano
HRESULT Renderer::HandleDeviceLost() HRESULT Renderer::HandleDeviceLost()
{ {
HRESULT hr = device_resources_->HandleDeviceLost(); HRESULT hr = d3d_res_->HandleDeviceLost();
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
@ -151,12 +164,12 @@ namespace kiwano
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = device_resources_->Present(vsync_); hr = d3d_res_->Present(vsync_);
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = device_resources_->ClearRenderTarget(clear_color_); hr = d3d_res_->ClearRenderTarget(clear_color_);
} }
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
@ -197,7 +210,7 @@ namespace kiwano
geometry.Get(), geometry.Get(),
solid_color_brush_.Get(), solid_color_brush_.Get(),
stroke_width, stroke_width,
device_resources_->GetStrokeStyle(stroke) d2d_res_->GetStrokeStyle(stroke)
); );
if (collecting_status_) if (collecting_status_)
@ -332,9 +345,9 @@ namespace kiwano
{ {
output_size_.x = static_cast<float>(width); output_size_.x = static_cast<float>(width);
output_size_.y = static_cast<float>(height); output_size_.y = static_cast<float>(height);
if (device_resources_) if (d3d_res_)
{ {
return device_resources_->SetLogicalSize(output_size_); return d3d_res_->SetLogicalSize(output_size_);
} }
return S_OK; return S_OK;
} }
@ -375,7 +388,7 @@ namespace kiwano
StrokeStyle outline_stroke StrokeStyle outline_stroke
) )
{ {
if (!text_renderer_ || !device_resources_) if (!text_renderer_ || !d3d_res_)
return E_UNEXPECTED; return E_UNEXPECTED;
text_renderer_->SetTextStyle( text_renderer_->SetTextStyle(
@ -383,7 +396,7 @@ namespace kiwano
has_outline, has_outline,
DX::ConvertToColorF(outline_color), DX::ConvertToColorF(outline_color),
outline_width, outline_width,
device_resources_->GetStrokeStyle(outline_stroke) d2d_res_->GetStrokeStyle(outline_stroke)
); );
return S_OK; return S_OK;
} }

View File

@ -26,17 +26,23 @@
#include "../2d/Font.hpp" #include "../2d/Font.hpp"
#include "../2d/TextStyle.hpp" #include "../2d/TextStyle.hpp"
#include "helper.hpp" #include "helper.hpp"
#include "DeviceResources.h"
#include "TextRenderer.h" #include "TextRenderer.h"
#include "D2DDeviceResources.h"
#if defined(KGE_USE_DIRECTX10)
# include "D3D10DeviceResources.h"
#else
# include "D3D11DeviceResources.h"
#endif
namespace kiwano namespace kiwano
{ {
struct RenderStatus
{ #if defined(KGE_USE_DIRECTX10)
Time start; typedef ID3D10DeviceResources ID3DDeviceResources;
Duration duration; #else
int primitives; typedef ID3D11DeviceResources ID3DDeviceResources;
}; #endif
class KGE_API Renderer class KGE_API Renderer
: public Singleton<Renderer> : public Singleton<Renderer>
@ -137,6 +143,13 @@ namespace kiwano
); );
public: public:
struct Status
{
Time start;
Duration duration;
int primitives;
};
void SetupComponent(Application*) override; void SetupComponent(Application*) override;
void DestroyComponent() override; void DestroyComponent() override;
@ -145,11 +158,13 @@ namespace kiwano
inline HWND GetTargetWindow() const { return hwnd_; } inline HWND GetTargetWindow() const { return hwnd_; }
inline RenderStatus const& GetStatus() const { return status_; } inline Status const& GetStatus() const { return status_; }
inline Size const& GetOutputSize() const { return output_size_; } inline Size const& GetOutputSize() const { return output_size_; }
inline DeviceResources* GetDeviceResources() const { KGE_ASSERT(device_resources_); return device_resources_.Get(); } inline ID2DDeviceResources* GetD2DDeviceResources() const { KGE_ASSERT(d2d_res_); return d2d_res_.Get(); }
inline ID3DDeviceResources* GetD3DDeviceResources() const { KGE_ASSERT(d3d_res_); return d3d_res_.Get(); }
inline ITextRenderer* GetTextRenderer() const { KGE_ASSERT(text_renderer_); return text_renderer_.Get(); } inline ITextRenderer* GetTextRenderer() const { KGE_ASSERT(text_renderer_); return text_renderer_.Get(); }
@ -176,10 +191,10 @@ namespace kiwano
Size output_size_; Size output_size_;
Color clear_color_; Color clear_color_;
TextAntialias text_antialias_; TextAntialias text_antialias_;
RenderStatus status_; Status status_;
ComPtr<DeviceResources> device_resources_; ComPtr<ID2DDeviceResources> d2d_res_;
ComPtr<ID2D1Factory1> factory_; ComPtr<ID3DDeviceResources> d3d_res_;
ComPtr<ID2D1DeviceContext> device_context_; ComPtr<ID2D1DeviceContext> device_context_;
ComPtr<ID2D1DrawingStateBlock> drawing_state_block_; ComPtr<ID2D1DrawingStateBlock> drawing_state_block_;
ComPtr<ITextRenderer> text_renderer_; ComPtr<ITextRenderer> text_renderer_;