diff --git a/projects/kiwano/kiwano.vcxproj b/projects/kiwano/kiwano.vcxproj index 2fbffc54..02f57773 100644 --- a/projects/kiwano/kiwano.vcxproj +++ b/projects/kiwano/kiwano.vcxproj @@ -75,6 +75,7 @@ + diff --git a/projects/kiwano/kiwano.vcxproj.filters b/projects/kiwano/kiwano.vcxproj.filters index e008fce2..e2f3e4d4 100644 --- a/projects/kiwano/kiwano.vcxproj.filters +++ b/projects/kiwano/kiwano.vcxproj.filters @@ -267,6 +267,9 @@ renderer + + renderer\win32 + diff --git a/src/kiwano/2d/Stage.cpp b/src/kiwano/2d/Stage.cpp index 1a8b676e..2e95a1ef 100644 --- a/src/kiwano/2d/Stage.cpp +++ b/src/kiwano/2d/Stage.cpp @@ -38,12 +38,12 @@ namespace kiwano void Stage::OnEnter() { - // KGE_SYS_LOG(L"Stage entered"); + KGE_SYS_LOG(L"Stage entered"); } void Stage::OnExit() { - // KGE_SYS_LOG(L"Stage exited"); + KGE_SYS_LOG(L"Stage exited"); } void Stage::RenderBorder(RenderTarget* rt) diff --git a/src/kiwano/core/win32/helper.h b/src/kiwano/core/win32/helper.h index b7b5e0bf..a8c1d8b7 100644 --- a/src/kiwano/core/win32/helper.h +++ b/src/kiwano/core/win32/helper.h @@ -18,18 +18,16 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include +#include +#include #include <3rd-party/StackWalker/StackWalker.h> namespace kiwano { - // Display stack trace on exception inline void ThrowIfFailed(HRESULT hr) { if (FAILED(hr)) { - KGE_ERROR(L"Failed with HRESULT of %08X", hr); - StackWalker{}.ShowCallstack(); static char buffer[1024 + 1]; diff --git a/src/kiwano/platform/Application.cpp b/src/kiwano/platform/Application.cpp index 07edba88..25f1cdb1 100644 --- a/src/kiwano/platform/Application.cpp +++ b/src/kiwano/platform/Application.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -148,8 +149,6 @@ namespace kiwano comps_.clear(); } - Input::instance().Destroy(); - Renderer::instance().Destroy(); Window::instance().Destroy(); } @@ -304,14 +303,12 @@ namespace kiwano { KeyDownEvent evt; evt.code = static_cast(wparam); - // evt.count = static_cast(lparam & 0xFF); app->DispatchEvent(evt); } else { KeyUpEvent evt; evt.code = static_cast(wparam); - // evt.count = static_cast(lparam & 0xFF); app->DispatchEvent(evt); } } @@ -321,7 +318,6 @@ namespace kiwano { KeyCharEvent evt; evt.value = static_cast(wparam); - // evt.count = static_cast(lparam & 0xFF); app->DispatchEvent(evt); } break; @@ -383,7 +379,7 @@ namespace kiwano { if (SIZE_MAXHIDE == wparam || SIZE_MINIMIZED == wparam) { - // KGE_SYS_LOG(L"Window minimized"); + KGE_SYS_LOG(L"Window minimized"); } else { @@ -425,7 +421,7 @@ namespace kiwano case WM_SETTEXT: { - // KGE_SYS_LOG(L"Window title changed"); + KGE_SYS_LOG(L"Window title changed"); WindowTitleChangedEvent evt; evt.title = reinterpret_cast(lparam); @@ -435,13 +431,13 @@ namespace kiwano case WM_SETICON: { - // KGE_SYS_LOG(L"Window icon changed"); + KGE_SYS_LOG(L"Window icon changed"); } break; case WM_DISPLAYCHANGE: { - // KGE_SYS_LOG(L"The display resolution has changed"); + KGE_SYS_LOG(L"The display resolution has changed"); ::InvalidateRect(hwnd, nullptr, FALSE); } @@ -455,7 +451,7 @@ namespace kiwano case WM_CLOSE: { - // KGE_SYS_LOG(L"Window is closing"); + KGE_SYS_LOG(L"Window is closing"); if (!app->OnClosing()) { diff --git a/src/kiwano/platform/Input.cpp b/src/kiwano/platform/Input.cpp index 98416b96..9803760c 100644 --- a/src/kiwano/platform/Input.cpp +++ b/src/kiwano/platform/Input.cpp @@ -140,8 +140,4 @@ namespace kiwano { return Point{ mouse_pos_x_, mouse_pos_y_ }; } - - void Input::Destroy() - { - } } diff --git a/src/kiwano/platform/Input.h b/src/kiwano/platform/Input.h index 2bdd7d11..0daebfab 100644 --- a/src/kiwano/platform/Input.h +++ b/src/kiwano/platform/Input.h @@ -100,8 +100,6 @@ namespace kiwano void UpdateMousePos(float, float); - void Destroy(); - private: Input(); diff --git a/src/kiwano/platform/Window.cpp b/src/kiwano/platform/Window.cpp index f70f6a19..5f7f5cef 100644 --- a/src/kiwano/platform/Window.cpp +++ b/src/kiwano/platform/Window.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #define WINDOW_FIXED_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX diff --git a/src/kiwano/renderer/RenderTarget.cpp b/src/kiwano/renderer/RenderTarget.cpp index 22192bb8..14a1bf27 100644 --- a/src/kiwano/renderer/RenderTarget.cpp +++ b/src/kiwano/renderer/RenderTarget.cpp @@ -20,6 +20,7 @@ #include #include +#include namespace kiwano { @@ -36,32 +37,64 @@ namespace kiwano status_.primitives = 0; } - HRESULT RenderTarget::CreateDeviceResources(ComPtr rt, ComPtr dev_res) + HRESULT RenderTarget::CreateDeviceResources(ComPtr factory, ComPtr rt) { - HRESULT hr = E_FAIL; + if (!factory || !rt) + return E_INVALIDARG; - if (rt && dev_res) - { - render_target_ = rt; - device_resources_ = dev_res; - hr = S_OK; - } + render_target_ = rt; + text_renderer_.reset(); + current_brush_.reset(); - if (SUCCEEDED(hr)) - { - text_renderer_.reset(); - hr = ITextRenderer::Create( - &text_renderer_, - render_target_.get() - ); - } + HRESULT hr = ITextRenderer::Create( + &text_renderer_, + render_target_.get() + ); if (SUCCEEDED(hr)) { SetAntialiasMode(antialias_); SetTextAntialiasMode(text_antialias_); - current_brush_.reset(); + Resize(reinterpret_cast(GetRenderTarget()->GetSize())); + } + + if (SUCCEEDED(hr)) + { + ComPtr miter_stroke_style; + ComPtr bevel_stroke_style; + ComPtr round_stroke_style; + + D2D1_STROKE_STYLE_PROPERTIES stroke_style = D2D1::StrokeStyleProperties( + D2D1_CAP_STYLE_FLAT, + D2D1_CAP_STYLE_FLAT, + D2D1_CAP_STYLE_FLAT, + D2D1_LINE_JOIN_MITER, + 2.0f, + D2D1_DASH_STYLE_SOLID, + 0.0f + ); + + hr = factory->CreateStrokeStyle(stroke_style, nullptr, 0, &miter_stroke_style); + + if (SUCCEEDED(hr)) + { + stroke_style.lineJoin = D2D1_LINE_JOIN_BEVEL; + hr = factory->CreateStrokeStyle(stroke_style, nullptr, 0, &bevel_stroke_style); + } + + if (SUCCEEDED(hr)) + { + stroke_style.lineJoin = D2D1_LINE_JOIN_ROUND; + hr = factory->CreateStrokeStyle(stroke_style, nullptr, 0, &round_stroke_style); + } + + if (SUCCEEDED(hr)) + { + miter_stroke_style_ = miter_stroke_style; + bevel_stroke_style_ = bevel_stroke_style; + round_stroke_style_ = round_stroke_style; + } } return hr; @@ -69,15 +102,18 @@ namespace kiwano void RenderTarget::DiscardDeviceResources() { + miter_stroke_style_.reset(); + bevel_stroke_style_.reset(); + round_stroke_style_.reset(); + text_renderer_.reset(); render_target_.reset(); current_brush_.reset(); - device_resources_.reset(); } bool RenderTarget::IsValid() const { - return render_target_ && device_resources_; + return render_target_ != nullptr; } void RenderTarget::BeginDraw() @@ -106,13 +142,10 @@ namespace kiwano void RenderTarget::DrawGeometry(Geometry const& geometry, float stroke_width, StrokeStyle stroke) { - HRESULT hr = S_OK; - if (!render_target_ || !current_brush_) - { - hr = E_UNEXPECTED; - } + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); + KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!"); - if (SUCCEEDED(hr) && geometry.GetGeometry()) + if (geometry.IsValid()) { render_target_->DrawGeometry( geometry.GetGeometry().get(), @@ -123,19 +156,14 @@ namespace kiwano IncreasePrimitivesCount(); } - - ThrowIfFailed(hr); } void RenderTarget::FillGeometry(Geometry const& geometry) { - HRESULT hr = S_OK; - if (!render_target_ || !current_brush_) - { - hr = E_UNEXPECTED; - } + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); + KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!"); - if (SUCCEEDED(hr) && geometry.GetGeometry()) + if (geometry.IsValid()) { render_target_->FillGeometry( geometry.GetGeometry().get(), @@ -144,181 +172,122 @@ namespace kiwano IncreasePrimitivesCount(); } - - ThrowIfFailed(hr); } void RenderTarget::DrawLine(Point const& point1, Point const& point2, float stroke_width, StrokeStyle stroke) { - HRESULT hr = S_OK; - if (!render_target_ || !current_brush_) - { - hr = E_UNEXPECTED; - } + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); + KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!"); - if (SUCCEEDED(hr)) - { - render_target_->DrawLine( - DX::ConvertToPoint2F(point1), - DX::ConvertToPoint2F(point2), - current_brush_->GetBrush().get(), - stroke_width, - GetStrokeStyle(stroke).get() - ); + render_target_->DrawLine( + DX::ConvertToPoint2F(point1), + DX::ConvertToPoint2F(point2), + current_brush_->GetBrush().get(), + stroke_width, + GetStrokeStyle(stroke).get() + ); - IncreasePrimitivesCount(); - } - - ThrowIfFailed(hr); + IncreasePrimitivesCount(); } void RenderTarget::DrawRectangle(Rect const& rect, float stroke_width, StrokeStyle stroke) { - HRESULT hr = S_OK; + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); + KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!"); - if (!render_target_ || !current_brush_) - { - hr = E_UNEXPECTED; - } + render_target_->DrawRectangle( + DX::ConvertToRectF(rect), + current_brush_->GetBrush().get(), + stroke_width, + GetStrokeStyle(stroke).get() + ); - if (SUCCEEDED(hr)) - { - render_target_->DrawRectangle( - DX::ConvertToRectF(rect), - current_brush_->GetBrush().get(), - stroke_width, - GetStrokeStyle(stroke).get() - ); - - IncreasePrimitivesCount(); - } - - ThrowIfFailed(hr); + IncreasePrimitivesCount(); } void RenderTarget::FillRectangle(Rect const& rect) { - HRESULT hr = S_OK; - if (!render_target_ || !current_brush_) - { - hr = E_UNEXPECTED; - } + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); + KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!"); - if (SUCCEEDED(hr)) - { - render_target_->FillRectangle( - DX::ConvertToRectF(rect), - current_brush_->GetBrush().get() - ); + render_target_->FillRectangle( + DX::ConvertToRectF(rect), + current_brush_->GetBrush().get() + ); - IncreasePrimitivesCount(); - } - - ThrowIfFailed(hr); + IncreasePrimitivesCount(); } void RenderTarget::DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, float stroke_width, StrokeStyle stroke) { - HRESULT hr = S_OK; - if (!render_target_ || !current_brush_) - { - hr = E_UNEXPECTED; - } + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); + KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!"); - if (SUCCEEDED(hr)) - { - render_target_->DrawRoundedRectangle( - D2D1::RoundedRect( - DX::ConvertToRectF(rect), - radius.x, - radius.y - ), - current_brush_->GetBrush().get(), - stroke_width, - GetStrokeStyle(stroke).get() - ); + render_target_->DrawRoundedRectangle( + D2D1::RoundedRect( + DX::ConvertToRectF(rect), + radius.x, + radius.y + ), + current_brush_->GetBrush().get(), + stroke_width, + GetStrokeStyle(stroke).get() + ); - IncreasePrimitivesCount(); - } - - ThrowIfFailed(hr); + IncreasePrimitivesCount(); } void RenderTarget::FillRoundedRectangle(Rect const& rect, Vec2 const& radius) { - HRESULT hr = S_OK; - if (!render_target_ || !current_brush_) - { - hr = E_UNEXPECTED; - } + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); + KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!"); - if (SUCCEEDED(hr)) - { - render_target_->FillRoundedRectangle( - D2D1::RoundedRect( - DX::ConvertToRectF(rect), - radius.x, - radius.y - ), - current_brush_->GetBrush().get() - ); + render_target_->FillRoundedRectangle( + D2D1::RoundedRect( + DX::ConvertToRectF(rect), + radius.x, + radius.y + ), + current_brush_->GetBrush().get() + ); - IncreasePrimitivesCount(); - } - - ThrowIfFailed(hr); + IncreasePrimitivesCount(); } void RenderTarget::DrawEllipse(Point const& center, Vec2 const& radius, float stroke_width, StrokeStyle stroke) { - HRESULT hr = S_OK; - if (!render_target_ || !current_brush_) - { - hr = E_UNEXPECTED; - } + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); + KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!"); - if (SUCCEEDED(hr)) - { - render_target_->DrawEllipse( - D2D1::Ellipse( - DX::ConvertToPoint2F(center), - radius.x, - radius.y - ), - current_brush_->GetBrush().get(), - stroke_width, - GetStrokeStyle(stroke).get() - ); + render_target_->DrawEllipse( + D2D1::Ellipse( + DX::ConvertToPoint2F(center), + radius.x, + radius.y + ), + current_brush_->GetBrush().get(), + stroke_width, + GetStrokeStyle(stroke).get() + ); - IncreasePrimitivesCount(); - } - - ThrowIfFailed(hr); + IncreasePrimitivesCount(); } void RenderTarget::FillEllipse(Point const& center, Vec2 const& radius) { - HRESULT hr = S_OK; - if (!render_target_ || !current_brush_) - { - hr = E_UNEXPECTED; - } + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); + KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!"); - if (SUCCEEDED(hr)) - { - render_target_->FillEllipse( - D2D1::Ellipse( - DX::ConvertToPoint2F(center), - radius.x, - radius.y - ), - current_brush_->GetBrush().get() - ); + render_target_->FillEllipse( + D2D1::Ellipse( + DX::ConvertToPoint2F(center), + radius.x, + radius.y + ), + current_brush_->GetBrush().get() + ); - IncreasePrimitivesCount(); - } - - ThrowIfFailed(hr); + IncreasePrimitivesCount(); } void RenderTarget::DrawTexture(Texture const& texture, Rect const& src_rect, Rect const& dest_rect, float opacity) @@ -328,13 +297,9 @@ namespace kiwano void RenderTarget::DrawTexture(Texture const& texture, const Rect* src_rect, const Rect* dest_rect, float opacity) { - HRESULT hr = S_OK; - if (!render_target_) - { - hr = E_UNEXPECTED; - } + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); - if (SUCCEEDED(hr) && texture.IsValid()) + if (texture.IsValid()) { auto mode = (texture.GetBitmapInterpolationMode() == InterpolationMode::Linear) ? D2D1_BITMAP_INTERPOLATION_MODE_LINEAR @@ -350,134 +315,87 @@ namespace kiwano IncreasePrimitivesCount(); } - - ThrowIfFailed(hr); } void RenderTarget::DrawTextLayout(TextLayout const& layout, Point const& offset) { - HRESULT hr = S_OK; - if (!text_renderer_) - { - hr = E_UNEXPECTED; - } + KGE_ASSERT(text_renderer_ && "Text renderer has not been initialized!"); - if (SUCCEEDED(hr)) - { - const TextStyle& style = layout.GetStyle(); - text_renderer_->SetStyle( - style.fill_brush ? style.fill_brush->GetBrush().get() : nullptr, - style.outline_brush ? style.outline_brush->GetBrush().get() : nullptr, - style.outline_width, - GetStrokeStyle(style.outline_stroke).get() - ); + const TextStyle& style = layout.GetStyle(); + text_renderer_->SetStyle( + style.fill_brush ? style.fill_brush->GetBrush().get() : nullptr, + style.outline_brush ? style.outline_brush->GetBrush().get() : nullptr, + style.outline_width, + GetStrokeStyle(style.outline_stroke).get() + ); - hr = layout.GetTextLayout()->Draw(nullptr, text_renderer_.get(), offset.x, offset.y); - } + HRESULT hr = layout.GetTextLayout()->Draw(nullptr, text_renderer_.get(), offset.x, offset.y); if (SUCCEEDED(hr)) { IncreasePrimitivesCount(); } - - ThrowIfFailed(hr); + else + { + KGE_ERROR(L"Failed to draw text layout with HRESULT of %08X", hr); + } } void RenderTarget::CreateTexture(Texture& texture, math::Vec2T size, D2D1_PIXEL_FORMAT format) { - HRESULT hr = S_OK; + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); - if (!render_target_) - { - hr = E_UNEXPECTED; - } + ComPtr saved_bitmap; + HRESULT hr = render_target_->CreateBitmap( + D2D1::SizeU(size.x, size.y), + D2D1::BitmapProperties(format), + &saved_bitmap + ); if (SUCCEEDED(hr)) { - ComPtr saved_bitmap; - hr = render_target_->CreateBitmap(D2D1::SizeU(size.x, size.y), D2D1::BitmapProperties(format), &saved_bitmap); - - if (SUCCEEDED(hr)) - { - texture.SetBitmap(saved_bitmap); - } + texture.SetBitmap(saved_bitmap); + } + else + { + ThrowIfFailed(hr); } - - ThrowIfFailed(hr); } - void RenderTarget::CreateLayer(LayerArea& layer) + void RenderTarget::PushClipRect(Rect const& clip_rect) { - HRESULT hr = S_OK; + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); + render_target_->PushAxisAlignedClip( + DX::ConvertToRectF(clip_rect), + antialias_ ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED + ); + } - if (!render_target_) - { - hr = E_UNEXPECTED; - } + void RenderTarget::PopClipRect() + { + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); + render_target_->PopAxisAlignedClip(); + } - if (SUCCEEDED(hr)) + void RenderTarget::PushLayer(LayerArea& layer) + { + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); + if (!layer.IsValid()) { ComPtr output; - hr = render_target_->CreateLayer(&output); + HRESULT hr = render_target_->CreateLayer(&output); if (SUCCEEDED(hr)) { layer.SetLayer(output); } + else + { + ThrowIfFailed(hr); + } } - ThrowIfFailed(hr); - } - - void RenderTarget::PushClipRect(Rect const& clip_rect) - { - HRESULT hr = S_OK; - if (!render_target_) - { - hr = E_UNEXPECTED; - } - - if (SUCCEEDED(hr)) - { - render_target_->PushAxisAlignedClip( - DX::ConvertToRectF(clip_rect), - antialias_ ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED - ); - } - - ThrowIfFailed(hr); - } - - void RenderTarget::PopClipRect() - { - HRESULT hr = S_OK; - if (!render_target_) - { - hr = E_UNEXPECTED; - } - - if (SUCCEEDED(hr)) - { - render_target_->PopAxisAlignedClip(); - } - - ThrowIfFailed(hr); - } - - void RenderTarget::PushLayer(LayerArea& layer) - { - HRESULT hr = S_OK; - if (!render_target_) - { - hr = E_UNEXPECTED; - } - - if (!layer.IsValid()) - { - CreateLayer(layer); - } - - if (SUCCEEDED(hr) && layer.IsValid()) + if (layer.IsValid()) { render_target_->PushLayer( D2D1::LayerParameters( @@ -492,85 +410,50 @@ namespace kiwano layer.GetLayer().get() ); } - - ThrowIfFailed(hr); } void RenderTarget::PopLayer() { - HRESULT hr = S_OK; - if (!render_target_) - { - hr = E_UNEXPECTED; - } - - if (SUCCEEDED(hr)) - { - render_target_->PopLayer(); - } - - ThrowIfFailed(hr); + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); + render_target_->PopLayer(); } void RenderTarget::Clear() { - HRESULT hr = E_FAIL; - - if (render_target_) - { - render_target_->Clear(); - hr = S_OK; - } - - ThrowIfFailed(hr); + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); + render_target_->Clear(); } void RenderTarget::Clear(Color const& clear_color) { - HRESULT hr = E_FAIL; - - if (render_target_) - { - render_target_->Clear(DX::ConvertToColorF(clear_color)); - hr = S_OK; - } - - ThrowIfFailed(hr); + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); + render_target_->Clear(DX::ConvertToColorF(clear_color)); } ComPtr RenderTarget::GetStrokeStyle(StrokeStyle style) { switch (style) { - case StrokeStyle::Miter: return device_resources_->GetMiterStrokeStyle(); break; - case StrokeStyle::Bevel: return device_resources_->GetBevelStrokeStyle(); break; - case StrokeStyle::Round: return device_resources_->GetRoundStrokeStyle(); break; + case StrokeStyle::Miter: return miter_stroke_style_; + case StrokeStyle::Bevel: return bevel_stroke_style_; + case StrokeStyle::Round: return round_stroke_style_; } return nullptr; } void RenderTarget::SetTransform(const Matrix3x2& matrix) { - HRESULT hr = S_OK; - if (!render_target_) - { - hr = E_UNEXPECTED; - } + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); - if (SUCCEEDED(hr)) + if (fast_global_transform_) { - if (fast_global_transform_) - { - render_target_->SetTransform(DX::ConvertToMatrix3x2F(&matrix)); - } - else - { - Matrix3x2 result = matrix * global_transform_; - render_target_->SetTransform(DX::ConvertToMatrix3x2F(&result)); - } + render_target_->SetTransform(DX::ConvertToMatrix3x2F(&matrix)); + } + else + { + Matrix3x2 result = matrix * global_transform_; + render_target_->SetTransform(DX::ConvertToMatrix3x2F(&result)); } - - ThrowIfFailed(hr); } void RenderTarget::SetGlobalTransform(const Matrix3x2* matrix) @@ -588,66 +471,53 @@ namespace kiwano void RenderTarget::SetAntialiasMode(bool enabled) { - HRESULT hr = S_OK; - if (!render_target_) - { - hr = E_UNEXPECTED; - } + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); - if (SUCCEEDED(hr)) - { - render_target_->SetAntialiasMode( - enabled ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED - ); - antialias_ = enabled; - } - - ThrowIfFailed(hr); + render_target_->SetAntialiasMode(enabled ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED); + antialias_ = enabled; } void RenderTarget::SetTextAntialiasMode(TextAntialiasMode mode) { - HRESULT hr = S_OK; - if (!render_target_) + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); + + D2D1_TEXT_ANTIALIAS_MODE antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE; + switch (mode) { - hr = E_UNEXPECTED; + case TextAntialiasMode::Default: + antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT; + break; + case TextAntialiasMode::ClearType: + antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE; + break; + case TextAntialiasMode::GrayScale: + antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE; + break; + case TextAntialiasMode::None: + antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED; + break; + default: + break; } - if (SUCCEEDED(hr)) - { - text_antialias_ = mode; - D2D1_TEXT_ANTIALIAS_MODE antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE; - switch (text_antialias_) - { - case TextAntialiasMode::Default: - antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT; - break; - case TextAntialiasMode::ClearType: - antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE; - break; - case TextAntialiasMode::GrayScale: - antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE; - break; - case TextAntialiasMode::None: - antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED; - break; - default: - break; - } - render_target_->SetTextAntialiasMode(antialias_mode); - } - - ThrowIfFailed(hr); + text_antialias_ = mode; + render_target_->SetTextAntialiasMode(antialias_mode); } bool RenderTarget::CheckVisibility(Rect const& bounds, Matrix3x2 const& transform) { - Rect visible_size = { Point{}, reinterpret_cast(render_target_->GetSize()) }; + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); + if (fast_global_transform_) { - return visible_size.Intersects(transform.Transform(bounds)); + return visible_size_.Intersects(transform.Transform(bounds)); } - return visible_size.Intersects(Matrix3x2(transform * global_transform_).Transform(bounds)); + return visible_size_.Intersects(Matrix3x2(transform * global_transform_).Transform(bounds)); + } + + void RenderTarget::Resize(Size const& size) + { + visible_size_ = Rect(Point(), size); } void RenderTarget::SetCollectingStatus(bool collecting) diff --git a/src/kiwano/renderer/RenderTarget.h b/src/kiwano/renderer/RenderTarget.h index d9c0a1f3..ed3ffb36 100644 --- a/src/kiwano/renderer/RenderTarget.h +++ b/src/kiwano/renderer/RenderTarget.h @@ -50,6 +50,8 @@ namespace kiwano class KGE_API RenderTarget : public ObjectBase { + friend class Renderer; + public: bool IsValid() const; @@ -133,27 +135,17 @@ namespace kiwano D2D1_PIXEL_FORMAT format ); - void CreateLayer( - LayerArea& layer - ); - - void PushClipRect( - Rect const& clip_rect - ); + void PushClipRect(Rect const& clip_rect); void PopClipRect(); - void PushLayer( - LayerArea& layer - ); + void PushLayer(LayerArea& layer); void PopLayer(); void Clear(); - void Clear( - Color const& clear_color - ); + void Clear(Color const& clear_color); BrushPtr GetCurrentBrush() const; @@ -191,6 +183,10 @@ namespace kiwano Matrix3x2 const& transform ); + void Resize( + Size const& size + ); + public: struct Status { @@ -208,30 +204,34 @@ namespace kiwano inline Status const& GetStatus() const { return status_; } protected: + RenderTarget(); + inline ComPtr GetRenderTarget() const { KGE_ASSERT(render_target_); return render_target_; } inline ComPtr GetTextRenderer() const { KGE_ASSERT(text_renderer_); return text_renderer_; } ComPtr GetStrokeStyle(StrokeStyle style); - protected: - RenderTarget(); - - HRESULT CreateDeviceResources(ComPtr rt, ComPtr dev_res); + private: + HRESULT CreateDeviceResources(ComPtr factory, ComPtr rt); void DiscardDeviceResources(); private: bool antialias_; bool fast_global_transform_; - mutable bool collecting_status_; - mutable Status status_; TextAntialiasMode text_antialias_; ComPtr text_renderer_; ComPtr render_target_; - ComPtr device_resources_; + ComPtr miter_stroke_style_; + ComPtr bevel_stroke_style_; + ComPtr round_stroke_style_; BrushPtr current_brush_; + Rect visible_size_; Matrix3x2 global_transform_; + + mutable bool collecting_status_; + mutable Status status_; }; diff --git a/src/kiwano/renderer/Renderer.cpp b/src/kiwano/renderer/Renderer.cpp index f51d42ce..4f2a93ec 100644 --- a/src/kiwano/renderer/Renderer.cpp +++ b/src/kiwano/renderer/Renderer.cpp @@ -19,6 +19,7 @@ // THE SOFTWARE. #include +#include #include #include #include @@ -61,20 +62,16 @@ namespace kiwano HRESULT hr = hwnd_ ? S_OK : E_FAIL; - // Direct2D device resources - if (SUCCEEDED(hr)) - { - hr = ID2DDeviceResources::Create(&d2d_res_); - } - // Direct3D device resources if (SUCCEEDED(hr)) { - hr = ID3DDeviceResources::Create( - &d3d_res_, - d2d_res_.get(), - hwnd_ - ); + hr = ID3DDeviceResources::Create(&d3d_res_, hwnd_); + } + + // Direct2D device resources + if (SUCCEEDED(hr)) + { + hr = ID2DDeviceResources::Create(&d2d_res_, d3d_res_->GetDXGIDevice(), d3d_res_->GetDXGISwapChain()); } // DrawingStateBlock @@ -88,7 +85,7 @@ namespace kiwano // Other device resources if (SUCCEEDED(hr)) { - hr = CreateDeviceResources(); + hr = CreateDeviceResources(d2d_res_->GetFactory(), d2d_res_->GetDeviceContext()); } // FontFileLoader and FontCollectionLoader @@ -130,7 +127,7 @@ namespace kiwano { KGE_SYS_LOG(L"Destroying device resources"); - RenderTarget::DiscardDeviceResources(); + DiscardDeviceResources(); d2d_res_->GetDWriteFactory()->UnregisterFontFileLoader(res_font_file_loader_.get()); res_font_file_loader_.reset(); @@ -145,17 +142,9 @@ namespace kiwano void Renderer::BeforeRender() { - HRESULT hr = S_OK; + KGE_ASSERT(d3d_res_ && IsValid()); - if (!IsValid()) - { - hr = E_UNEXPECTED; - } - - if (SUCCEEDED(hr)) - { - hr = d3d_res_->ClearRenderTarget(clear_color_); - } + HRESULT hr = d3d_res_->ClearRenderTarget(clear_color_); if (SUCCEEDED(hr)) { @@ -168,24 +157,12 @@ namespace kiwano void Renderer::AfterRender() { - HRESULT hr = S_OK; - - if (!IsValid()) - { - hr = E_UNEXPECTED; - } + KGE_ASSERT(d3d_res_ && IsValid()); - if (SUCCEEDED(hr)) - { - EndDraw(); + EndDraw(); + GetRenderTarget()->RestoreDrawingState(drawing_state_block_.get()); - GetRenderTarget()->RestoreDrawingState(drawing_state_block_.get()); - } - - if (SUCCEEDED(hr)) - { - hr = d3d_res_->Present(vsync_); - } + HRESULT hr = d3d_res_->Present(vsync_); if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) { @@ -211,24 +188,20 @@ namespace kiwano } } - HRESULT Renderer::CreateDeviceResources() - { - KGE_ASSERT(d2d_res_); - - HRESULT hr = RenderTarget::CreateDeviceResources( - d2d_res_->GetDeviceContext(), - d2d_res_ - ); - return hr; - } - HRESULT Renderer::HandleDeviceLost() { + KGE_ASSERT(d3d_res_ && d2d_res_ && render_target_); + HRESULT hr = d3d_res_->HandleDeviceLost(); if (SUCCEEDED(hr)) { - hr = CreateDeviceResources(); + hr = d2d_res_->HandleDeviceLost(d3d_res_->GetDXGIDevice(), d3d_res_->GetDXGISwapChain()); + } + + if (SUCCEEDED(hr)) + { + hr = CreateDeviceResources(d2d_res_->GetFactory(), d2d_res_->GetDeviceContext()); } return hr; } @@ -998,6 +971,19 @@ namespace kiwano ThrowIfFailed(hr); } + void Renderer::SetDpi(float dpi) + { + KGE_ASSERT(d3d_res_ && d2d_res_); + + HRESULT hr = d3d_res_->SetDpi(dpi); + if (SUCCEEDED(hr)) + { + hr = d2d_res_->SetDpi(dpi); + } + + ThrowIfFailed(hr); + } + void Renderer::SetVSyncEnabled(bool enabled) { vsync_ = enabled; @@ -1011,10 +997,9 @@ namespace kiwano void Renderer::ResizeTarget(uint32_t width, uint32_t height) { HRESULT hr = S_OK; + if (!d3d_res_) - { hr = E_UNEXPECTED; - } if (SUCCEEDED(hr)) { @@ -1023,19 +1008,17 @@ namespace kiwano hr = d3d_res_->SetLogicalSize(output_size_); } + if (SUCCEEDED(hr)) + { + hr = d2d_res_->SetLogicalSize(output_size_); + } + + if (SUCCEEDED(hr)) + { + Resize(reinterpret_cast(GetRenderTarget()->GetSize())); + } + ThrowIfFailed(hr); } - void Renderer::Destroy() - { - DiscardDeviceResources(); - - d2d_res_.reset(); - d3d_res_.reset(); - drawing_state_block_.reset(); - font_collection_loader_.reset(); - res_font_file_loader_.reset(); - res_font_collection_loader_.reset(); - } - } diff --git a/src/kiwano/renderer/Renderer.h b/src/kiwano/renderer/Renderer.h index d73155d2..2c8e6ada 100644 --- a/src/kiwano/renderer/Renderer.h +++ b/src/kiwano/renderer/Renderer.h @@ -171,6 +171,10 @@ namespace kiwano GradientExtendMode extend_mode ); + void SetDpi( + float dpi + ); + public: void Init(RenderConfig const& config); @@ -184,8 +188,6 @@ namespace kiwano void HandleMessage(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam) override; - void Destroy(); - public: inline HWND GetTargetWindow() const { return hwnd_; } @@ -202,8 +204,6 @@ namespace kiwano ~Renderer(); - HRESULT CreateDeviceResources(); - HRESULT HandleDeviceLost(); void ResizeTarget(uint32_t width, uint32_t height); diff --git a/src/kiwano/renderer/win32/D2DDeviceResources.cpp b/src/kiwano/renderer/win32/D2DDeviceResources.cpp index 47c63a67..140eaca1 100644 --- a/src/kiwano/renderer/win32/D2DDeviceResources.cpp +++ b/src/kiwano/renderer/win32/D2DDeviceResources.cpp @@ -36,7 +36,13 @@ namespace kiwano HRESULT CreateDeviceIndependentResources(); - public: + HRESULT CreateDeviceResources( + _In_ ComPtr dxgi_device, + _In_ ComPtr dxgi_swap_chain + ); + + HRESULT CreateWindowSizeDependentResources(); + HRESULT CreateBitmapConverter( _Out_ ComPtr& converter, _In_opt_ ComPtr source, @@ -65,26 +71,31 @@ namespace kiwano HRESULT CreateTextFormat( _Out_ ComPtr& text_format, - _In_ String const& family, + String const& family, _In_ ComPtr collection, - _In_ DWRITE_FONT_WEIGHT weight, - _In_ DWRITE_FONT_STYLE style, - _In_ DWRITE_FONT_STRETCH stretch, - _In_ FLOAT font_size + DWRITE_FONT_WEIGHT weight, + DWRITE_FONT_STYLE style, + DWRITE_FONT_STRETCH stretch, + FLOAT font_size ) override; HRESULT CreateTextLayout( _Out_ ComPtr& text_layout, - _In_ String const& text, + String const& text, _In_ ComPtr text_format ) override; - HRESULT SetD2DDevice( - _In_ ComPtr device + HRESULT SetDpi( + float dpi ) override; - void SetTargetBitmap( - _In_ ComPtr target + HRESULT SetLogicalSize( + Size logical_size + ) override; + + HRESULT HandleDeviceLost( + _In_ ComPtr dxgi_device, + _In_ ComPtr dxgi_swap_chain ) override; void DiscardResources() override; @@ -102,10 +113,15 @@ namespace kiwano private: unsigned long ref_count_; float dpi_; + + ComPtr dxgi_swap_chain_; }; - HRESULT ID2DDeviceResources::Create(ID2DDeviceResources** device_resources) + HRESULT ID2DDeviceResources::Create( + _Out_ ID2DDeviceResources** device_resources, + _In_ ComPtr dxgi_device, + _In_ ComPtr dxgi_swap_chain) { HRESULT hr = E_FAIL; if (device_resources) @@ -114,17 +130,22 @@ namespace kiwano 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)) { - res->AddRef(); - - if (*device_resources) - { - (*device_resources)->Release(); - } - (*device_resources) = res; + DX::SafeRelease(*device_resources); + (*device_resources) = DX::SafeAcquire(res); } else { @@ -194,10 +215,6 @@ namespace kiwano imaging_factory_.reset(); dwrite_factory_.reset(); - - miter_stroke_style_.reset(); - bevel_stroke_style_.reset(); - round_stroke_style_.reset(); } HRESULT D2DDeviceResources::CreateDeviceIndependentResources() @@ -224,7 +241,10 @@ namespace kiwano if (SUCCEEDED(hr)) { factory_ = factory; + } + if (SUCCEEDED(hr)) + { hr = CoCreateInstance( CLSID_WICImagingFactory, nullptr, @@ -232,101 +252,114 @@ namespace kiwano __uuidof(IWICImagingFactory), reinterpret_cast(&imaging_factory) ); + + if (SUCCEEDED(hr)) + { + imaging_factory_ = imaging_factory; + } } if (SUCCEEDED(hr)) { - imaging_factory_ = imaging_factory; - hr = DWriteCreateFactory( DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast(&dwrite_factory) ); + + if (SUCCEEDED(hr)) + { + dwrite_factory_ = dwrite_factory; + } } + return hr; + } + + HRESULT D2DDeviceResources::CreateDeviceResources(_In_ ComPtr dxgi_device, _In_ ComPtr dxgi_swap_chain) + { + if (!factory_) + return E_UNEXPECTED; + + // Create the Direct2D device object and a corresponding context. + ComPtr device; + HRESULT hr = factory_->CreateDevice(dxgi_device.get(), &device); if (SUCCEEDED(hr)) { - dwrite_factory_ = dwrite_factory; + ComPtr device_ctx; - ComPtr miter_stroke_style; - ComPtr bevel_stroke_style; - ComPtr round_stroke_style; - - D2D1_STROKE_STYLE_PROPERTIES stroke_style = D2D1::StrokeStyleProperties( - D2D1_CAP_STYLE_FLAT, - D2D1_CAP_STYLE_FLAT, - D2D1_CAP_STYLE_FLAT, - D2D1_LINE_JOIN_MITER, - 2.0f, - D2D1_DASH_STYLE_SOLID, - 0.0f - ); - - hr = factory_->CreateStrokeStyle( - stroke_style, - nullptr, - 0, - &miter_stroke_style + hr = device->CreateDeviceContext( + D2D1_DEVICE_CONTEXT_OPTIONS_NONE, + &device_ctx ); if (SUCCEEDED(hr)) { - stroke_style.lineJoin = D2D1_LINE_JOIN_BEVEL; - hr = factory_->CreateStrokeStyle( - stroke_style, - nullptr, - 0, - &bevel_stroke_style - ); - } - - if (SUCCEEDED(hr)) - { - stroke_style.lineJoin = D2D1_LINE_JOIN_ROUND; - hr = factory_->CreateStrokeStyle( - stroke_style, - nullptr, - 0, - &round_stroke_style - ); - } - - if (SUCCEEDED(hr)) - { - miter_stroke_style_ = miter_stroke_style; - bevel_stroke_style_ = bevel_stroke_style; - round_stroke_style_ = round_stroke_style; + device_ = device; + device_context_ = device_ctx; + device_context_->SetDpi(dpi_, dpi_); + dxgi_swap_chain_ = dxgi_swap_chain; } } - return hr; } - HRESULT D2DDeviceResources::SetD2DDevice(_In_ ComPtr device) + HRESULT D2DDeviceResources::CreateWindowSizeDependentResources() { - ComPtr device_ctx; + if (!dxgi_swap_chain_ || !device_context_) + return E_UNEXPECTED; - HRESULT hr = device->CreateDeviceContext( - D2D1_DEVICE_CONTEXT_OPTIONS_NONE, - &device_ctx - ); + // Create a Direct2D target bitmap associated with the + // swap chain back buffer and set it as the current target. + ComPtr dxgi_back_buffer; + HRESULT hr = dxgi_swap_chain_->GetBuffer(0, IID_PPV_ARGS(&dxgi_back_buffer)); if (SUCCEEDED(hr)) { - device_ = device; - device_context_ = device_ctx; - device_context_->SetDpi(dpi_, dpi_); - } + ComPtr target; + hr = device_context_->CreateBitmapFromDxgiSurface( + dxgi_back_buffer.get(), + D2D1::BitmapProperties1( + D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, + D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED), + dpi_, + dpi_), + &target); - return hr; + if (SUCCEEDED(hr)) + { + target_bitmap_ = target; + device_context_->SetTarget(target_bitmap_.get()); + } + } + return E_NOTIMPL; } - void D2DDeviceResources::SetTargetBitmap(_In_ ComPtr target) + HRESULT D2DDeviceResources::SetDpi(float dpi) { - target_bitmap_ = target; - if (device_context_) - device_context_->SetTarget(target_bitmap_.get()); + if (!device_context_) + return E_UNEXPECTED; + + device_context_->SetDpi(dpi, dpi); + return CreateWindowSizeDependentResources(); + } + + HRESULT D2DDeviceResources::SetLogicalSize(Size) + { + return CreateWindowSizeDependentResources(); + } + + HRESULT D2DDeviceResources::HandleDeviceLost(_In_ ComPtr dxgi_device, _In_ ComPtr dxgi_swap_chain) + { + dxgi_swap_chain_ = nullptr; + + HRESULT hr = CreateDeviceResources(dxgi_device, dxgi_swap_chain); + + if (SUCCEEDED(hr)) + { + hr = CreateWindowSizeDependentResources(); + } + return hr; } HRESULT D2DDeviceResources::CreateBitmapConverter(_Out_ ComPtr& converter, _In_opt_ ComPtr source, @@ -440,8 +473,8 @@ namespace kiwano return hr; } - HRESULT D2DDeviceResources::CreateTextFormat(_Out_ ComPtr & text_format, _In_ String const& family, _In_ ComPtr collection, - _In_ DWRITE_FONT_WEIGHT weight, _In_ DWRITE_FONT_STYLE style, _In_ DWRITE_FONT_STRETCH stretch, _In_ FLOAT font_size) + HRESULT D2DDeviceResources::CreateTextFormat(_Out_ ComPtr & text_format, String const& family, _In_ ComPtr collection, + DWRITE_FONT_WEIGHT weight, DWRITE_FONT_STYLE style, DWRITE_FONT_STRETCH stretch, FLOAT font_size) { if (!dwrite_factory_) return E_UNEXPECTED; @@ -465,7 +498,7 @@ namespace kiwano return hr; } - HRESULT D2DDeviceResources::CreateTextLayout(_Out_ ComPtr& text_layout, _In_ String const& text, + HRESULT D2DDeviceResources::CreateTextLayout(_Out_ ComPtr& text_layout, String const& text, _In_ ComPtr text_format) { if (!dwrite_factory_) diff --git a/src/kiwano/renderer/win32/D2DDeviceResources.h b/src/kiwano/renderer/win32/D2DDeviceResources.h index 04565b8b..b9f9a943 100644 --- a/src/kiwano/renderer/win32/D2DDeviceResources.h +++ b/src/kiwano/renderer/win32/D2DDeviceResources.h @@ -19,166 +19,12 @@ // THE SOFTWARE. #pragma once -#include #include -#include -#include +#include #include #include #include -namespace kiwano -{ - namespace DX - { - template - inline void SafeRelease(T*& ptr) - { - if (ptr != nullptr) - { - ptr->Release(); - ptr = nullptr; - } - } - - template - inline T* SafeAcquire(T* ptr) - { - if (ptr != nullptr) - { - ptr->AddRef(); - } - return ptr; - } - - // - // Point2F - // - - inline D2D1_POINT_2F const& ConvertToPoint2F(Vec2 const& vec2) - { - return reinterpret_cast(vec2); - } - - inline D2D1_POINT_2F& ConvertToPoint2F(Vec2& vec2) - { - return reinterpret_cast(vec2); - } - - inline const D2D1_POINT_2F* ConvertToPoint2F(const Vec2* vec2) - { - return reinterpret_cast(vec2); - } - - inline D2D1_POINT_2F* ConvertToPoint2F(Vec2* vec2) - { - return reinterpret_cast(vec2); - } - - // - // SizeF - // - - inline D2D1_SIZE_F const& ConvertToSizeF(Vec2 const& vec2) - { - return reinterpret_cast(vec2); - } - - inline D2D1_SIZE_F& ConvertToSizeF(Vec2& vec2) - { - return reinterpret_cast(vec2); - } - - inline const D2D1_SIZE_F* ConvertToSizeF(const Vec2* vec2) - { - return reinterpret_cast(vec2); - } - - inline D2D1_SIZE_F* ConvertToSizeF(Vec2* vec2) - { - return reinterpret_cast(vec2); - } - - // - // RectF - // - - inline D2D1_RECT_F const& ConvertToRectF(Rect const& rect) - { - return reinterpret_cast(rect); - } - - inline D2D1_RECT_F& ConvertToRectF(Rect& rect) - { - return reinterpret_cast(rect); - } - - inline const D2D1_RECT_F* ConvertToRectF(const Rect* rect) - { - return reinterpret_cast(rect); - } - - inline D2D1_RECT_F* ConvertToRectF(Rect* rect) - { - return reinterpret_cast(rect); - } - - // - // ColorF - // - inline D2D1_COLOR_F const& ConvertToColorF(Color const& color) - { - return reinterpret_cast(color); - } - - inline D2D1_COLOR_F& ConvertToColorF(Color& color) - { - return reinterpret_cast(color); - } - - inline const D2D1_COLOR_F* ConvertToColorF(const Color* color) - { - return reinterpret_cast(color); - } - - inline D2D1_COLOR_F* ConvertToColorF(Color* color) - { - return reinterpret_cast(color); - } - - // - // MatrixF - // - - inline D2D1_MATRIX_3X2_F const& ConvertToMatrix3x2F(Matrix3x2 const& matrix) - { - return reinterpret_cast(matrix); - } - - inline D2D1_MATRIX_3X2_F& ConvertToMatrix3x2F(Matrix3x2& matrix) - { - return reinterpret_cast(matrix); - } - - inline const D2D1_MATRIX_3X2_F* ConvertToMatrix3x2F(const Matrix3x2* matrix) - { - return reinterpret_cast(matrix); - } - - inline D2D1_MATRIX_3X2_F* ConvertToMatrix3x2F(Matrix3x2* matrix) - { - return reinterpret_cast(matrix); - } - - // Converts a length in device-independent pixels (DIPs) to a length in physical pixels. - 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 kiwano { MIDL_INTERFACE("5706684a-bf6d-4b03-b627-094758a33032") @@ -186,7 +32,11 @@ namespace kiwano : public IUnknown { public: - static HRESULT Create(ID2DDeviceResources** device_resources); + static HRESULT Create( + _Out_ ID2DDeviceResources** device_resources, + _In_ ComPtr dxgi_device, + _In_ ComPtr dxgi_swap_chain + ); virtual HRESULT CreateBitmapConverter( _Out_ ComPtr& converter, @@ -216,26 +66,31 @@ namespace kiwano virtual HRESULT CreateTextFormat( _Out_ ComPtr& text_format, - _In_ String const& family, + String const& family, _In_ ComPtr collection, - _In_ DWRITE_FONT_WEIGHT weight, - _In_ DWRITE_FONT_STYLE style, - _In_ DWRITE_FONT_STRETCH stretch, - _In_ FLOAT font_size + DWRITE_FONT_WEIGHT weight, + DWRITE_FONT_STYLE style, + DWRITE_FONT_STRETCH stretch, + FLOAT font_size ) = 0; virtual HRESULT CreateTextLayout( _Out_ ComPtr& text_layout, - _In_ String const& text, + String const& text, _In_ ComPtr text_format ) = 0; - virtual HRESULT SetD2DDevice( - _In_ ComPtr device + virtual HRESULT SetDpi( + float dpi ) = 0; - virtual void SetTargetBitmap( - _In_ ComPtr target + virtual HRESULT SetLogicalSize( + Size logical_size + ) = 0; + + virtual HRESULT HandleDeviceLost( + _In_ ComPtr dxgi_device, + _In_ ComPtr dxgi_swap_chain ) = 0; virtual void DiscardResources() = 0; @@ -247,10 +102,6 @@ namespace kiwano inline ID2D1DeviceContext* GetDeviceContext() { KGE_ASSERT(device_context_); return device_context_.get(); } inline ID2D1Bitmap1* GetTargetBitmap() { KGE_ASSERT(target_bitmap_); return target_bitmap_.get(); } - inline ID2D1StrokeStyle* GetMiterStrokeStyle() { KGE_ASSERT(miter_stroke_style_); return miter_stroke_style_.get(); } - inline ID2D1StrokeStyle* GetBevelStrokeStyle() { KGE_ASSERT(bevel_stroke_style_); return bevel_stroke_style_.get(); } - inline ID2D1StrokeStyle* GetRoundStrokeStyle() { KGE_ASSERT(round_stroke_style_); return round_stroke_style_.get(); } - protected: ComPtr factory_; ComPtr device_; @@ -259,10 +110,6 @@ namespace kiwano ComPtr imaging_factory_; ComPtr dwrite_factory_; - - ComPtr miter_stroke_style_; - ComPtr bevel_stroke_style_; - ComPtr round_stroke_style_; }; } diff --git a/src/kiwano/renderer/win32/D3D10DeviceResources.cpp b/src/kiwano/renderer/win32/D3D10DeviceResources.cpp index 274618ec..72ad2574 100644 --- a/src/kiwano/renderer/win32/D3D10DeviceResources.cpp +++ b/src/kiwano/renderer/win32/D3D10DeviceResources.cpp @@ -118,8 +118,6 @@ namespace kiwano Size logical_size_; Size output_size_; unsigned long ref_count_; - - ComPtr d2d_res_; }; @@ -135,11 +133,11 @@ namespace kiwano DiscardResources(); } - HRESULT ID3D10DeviceResources::Create(ID3D10DeviceResources** device_resources, ID2DDeviceResources* d2d_device_res, HWND hwnd) + HRESULT ID3D10DeviceResources::Create(ID3D10DeviceResources** device_resources, HWND hwnd) { HRESULT hr = E_FAIL; - if (device_resources && d2d_device_res) + if (device_resources) { D3D10DeviceResources* res = new (std::nothrow) D3D10DeviceResources; if (res) @@ -148,7 +146,6 @@ namespace kiwano ::GetClientRect(hwnd, &rc); res->hwnd_ = hwnd; - res->d2d_res_ = d2d_device_res; res->logical_size_.x = float(rc.right - rc.left); res->logical_size_.y = float(rc.bottom - rc.top); @@ -199,10 +196,10 @@ namespace kiwano void D3D10DeviceResources::DiscardResources() { - d2d_res_.reset(); device_.reset(); rt_view_.reset(); ds_view_.reset(); + dxgi_device_.reset(); dxgi_swap_chain_.reset(); dxgi_factory_.reset(); @@ -236,40 +233,29 @@ namespace kiwano { device_ = device; - ComPtr dxgi_adapter; - ComPtr dxgi_device; - ComPtr dxgi_factory; - ComPtr d2d_device; - if (SUCCEEDED(hr)) { + ComPtr dxgi_device; hr = device_->QueryInterface(IID_PPV_ARGS(&dxgi_device)); - } - if (SUCCEEDED(hr)) - { - hr = dxgi_device->GetAdapter(&dxgi_adapter); - } + if (SUCCEEDED(hr)) + { + dxgi_device_ = dxgi_device; - if (SUCCEEDED(hr)) - { - hr = dxgi_adapter->GetParent(IID_PPV_ARGS(&dxgi_factory)); - } + ComPtr dxgi_adapter; + hr = dxgi_device_->GetAdapter(&dxgi_adapter); - if (SUCCEEDED(hr)) - { - dxgi_factory_ = dxgi_factory; - } + if (SUCCEEDED(hr)) + { + ComPtr dxgi_factory; + hr = dxgi_adapter->GetParent(IID_PPV_ARGS(&dxgi_factory)); - // Create the Direct2D device object and a corresponding context. - if (SUCCEEDED(hr)) - { - hr = d2d_res_->GetFactory()->CreateDevice(dxgi_device.get(), &d2d_device); - } - - if (SUCCEEDED(hr)) - { - hr = d2d_res_->SetD2DDevice(d2d_device); + if (SUCCEEDED(hr)) + { + dxgi_factory_ = dxgi_factory; + } + } + } } } @@ -292,31 +278,11 @@ namespace kiwano swap_chain_desc.Windowed = TRUE; swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; - ComPtr dxgi_device; - if (SUCCEEDED(hr)) - { - hr = 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( - device_.get(), - &swap_chain_desc, - &dxgi_swap_chain_); - } + hr = dxgi_factory_->CreateSwapChain( + device_.get(), + &swap_chain_desc, + &dxgi_swap_chain_ + ); } return hr; @@ -332,7 +298,6 @@ namespace kiwano // Clear the previous window size specific context. ID3D10RenderTargetView* null_views[] = { nullptr }; device_->OMSetRenderTargets(ARRAYSIZE(null_views), null_views, nullptr); - d2d_res_->SetTargetBitmap(nullptr); rt_view_ = nullptr; ds_view_ = nullptr; device_->Flush(); @@ -424,33 +389,6 @@ namespace kiwano 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 = d2d_res_->GetDeviceContext()->CreateBitmapFromDxgiSurface( - dxgi_back_buffer.get(), - D2D1::BitmapProperties1( - D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, - D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED), - dpi_, - dpi_), - &target); - } - - if (SUCCEEDED(hr)) - { - d2d_res_->SetTargetBitmap(target); - } - } - return hr; } @@ -490,8 +428,6 @@ namespace kiwano logical_size_.x = float(rc.right - rc.left); logical_size_.y = float(rc.bottom - rc.top); - d2d_res_->GetDeviceContext()->SetDpi(dpi_, dpi_); - return CreateWindowSizeDependentResources(); } return S_OK; diff --git a/src/kiwano/renderer/win32/D3D10DeviceResources.h b/src/kiwano/renderer/win32/D3D10DeviceResources.h index 1d72688c..40e3f6dc 100644 --- a/src/kiwano/renderer/win32/D3D10DeviceResources.h +++ b/src/kiwano/renderer/win32/D3D10DeviceResources.h @@ -21,8 +21,7 @@ #pragma once #include - -#include +#include #include #include @@ -33,20 +32,22 @@ namespace kiwano : public ID3DDeviceResourcesBase { public: - static HRESULT Create(ID3D10DeviceResources** device_resources, ID2DDeviceResources* d2d_device_res, HWND hwnd); + static HRESULT Create(ID3D10DeviceResources** device_resources, HWND hwnd); inline ID3D10Device* GetDevice() { KGE_ASSERT(device_); return device_.get(); } inline ID3D10RenderTargetView* GetRenderTargetView() { KGE_ASSERT(rt_view_); return rt_view_.get(); } inline ID3D10DepthStencilView* GetDepthStencilView() { KGE_ASSERT(ds_view_); return ds_view_.get(); } inline IDXGIFactory* GetDXGIFactory() { KGE_ASSERT(dxgi_factory_); return dxgi_factory_.get(); } + inline IDXGIDevice* GetDXGIDevice() { KGE_ASSERT(dxgi_device_); return dxgi_device_.get(); } inline IDXGISwapChain* GetDXGISwapChain() { KGE_ASSERT(dxgi_swap_chain_); return dxgi_swap_chain_.get(); } protected: ComPtr device_; ComPtr rt_view_; ComPtr ds_view_; - ComPtr dxgi_swap_chain_; ComPtr dxgi_factory_; + ComPtr dxgi_device_; + ComPtr dxgi_swap_chain_; }; } diff --git a/src/kiwano/renderer/win32/D3D11DeviceResources.cpp b/src/kiwano/renderer/win32/D3D11DeviceResources.cpp index b6ebbd6c..5145978c 100644 --- a/src/kiwano/renderer/win32/D3D11DeviceResources.cpp +++ b/src/kiwano/renderer/win32/D3D11DeviceResources.cpp @@ -19,8 +19,8 @@ // THE SOFTWARE. #include - #include + #include // IsWindows10OrGreater #pragma comment(lib, "d3d11.lib") @@ -95,7 +95,6 @@ namespace kiwano unsigned long ref_count_; D3D_FEATURE_LEVEL d3d_feature_level_; - ComPtr d2d_res_; }; @@ -112,11 +111,11 @@ namespace kiwano DiscardResources(); } - HRESULT ID3D11DeviceResources::Create(ID3D11DeviceResources** device_resources, ID2DDeviceResources* d2d_device_res, HWND hwnd) + HRESULT ID3D11DeviceResources::Create(ID3D11DeviceResources** device_resources, HWND hwnd) { HRESULT hr = E_FAIL; - if (device_resources && d2d_device_res) + if (device_resources) { D3D11DeviceResources* res = new (std::nothrow) D3D11DeviceResources; if (res) @@ -125,7 +124,6 @@ namespace kiwano ::GetClientRect(hwnd, &rc); res->hwnd_ = hwnd; - res->d2d_res_ = d2d_device_res; res->logical_size_.x = float(rc.right - rc.left); res->logical_size_.y = float(rc.bottom - rc.top); @@ -176,11 +174,11 @@ namespace kiwano void D3D11DeviceResources::DiscardResources() { - d2d_res_.reset(); device_.reset(); device_context_.reset(); rt_view_.reset(); ds_view_.reset(); + dxgi_device_.reset(); dxgi_swap_chain_.reset(); dxgi_factory_.reset(); @@ -253,40 +251,29 @@ namespace kiwano device_ = device; device_context_ = context; - ComPtr dxgi_adapter; - ComPtr dxgi_device; - ComPtr dxgi_factory; - ComPtr d2d_device; - if (SUCCEEDED(hr)) { + ComPtr dxgi_device; hr = device_->QueryInterface(IID_PPV_ARGS(&dxgi_device)); - } - if (SUCCEEDED(hr)) - { - hr = dxgi_device->GetAdapter(&dxgi_adapter); - } + if (SUCCEEDED(hr)) + { + dxgi_device_ = dxgi_device; - if (SUCCEEDED(hr)) - { - hr = dxgi_adapter->GetParent(IID_PPV_ARGS(&dxgi_factory)); - } + ComPtr dxgi_adapter; + hr = dxgi_device_->GetAdapter(&dxgi_adapter); - if (SUCCEEDED(hr)) - { - dxgi_factory_ = dxgi_factory; - } + if (SUCCEEDED(hr)) + { + ComPtr dxgi_factory; + hr = dxgi_adapter->GetParent(IID_PPV_ARGS(&dxgi_factory)); - // Create the Direct2D device object and a corresponding context. - if (SUCCEEDED(hr)) - { - hr = d2d_res_->GetFactory()->CreateDevice(dxgi_device.get(), &d2d_device); - } - - if (SUCCEEDED(hr)) - { - hr = d2d_res_->SetD2DDevice(d2d_device); + if (SUCCEEDED(hr)) + { + dxgi_factory_ = dxgi_factory; + } + } + } } } @@ -328,33 +315,12 @@ namespace kiwano swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; } - ComPtr dxgi_device; - if (SUCCEEDED(hr)) - { - hr = 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( - device_.get(), - &swap_chain_desc, - &dxgi_swap_chain_); - } + hr = dxgi_factory_->CreateSwapChain( + device_.get(), + &swap_chain_desc, + &dxgi_swap_chain_ + ); } - return hr; } @@ -368,7 +334,6 @@ namespace kiwano // Clear the previous window size specific context. ID3D11RenderTargetView* null_views[] = { nullptr }; device_context_->OMSetRenderTargets(ARRAYSIZE(null_views), null_views, nullptr); - d2d_res_->SetTargetBitmap(nullptr); rt_view_ = nullptr; ds_view_ = nullptr; device_context_->Flush(); @@ -444,32 +409,6 @@ namespace kiwano device_context_->RSSetViewports(1, &screen_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 = d2d_res_->GetDeviceContext()->CreateBitmapFromDxgiSurface( - dxgi_back_buffer.get(), - D2D1::BitmapProperties1( - D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, - D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED), - dpi_, - dpi_), - &target); - } - - if (SUCCEEDED(hr)) - { - d2d_res_->SetTargetBitmap(target); - } - } - return hr; } @@ -509,8 +448,6 @@ namespace kiwano logical_size_.x = float(rc.right - rc.left); logical_size_.y = float(rc.bottom - rc.top); - d2d_res_->GetDeviceContext()->SetDpi(dpi_, dpi_); - return CreateWindowSizeDependentResources(); } return S_OK; diff --git a/src/kiwano/renderer/win32/D3D11DeviceResources.h b/src/kiwano/renderer/win32/D3D11DeviceResources.h index a7b9d65a..c10cb1e0 100644 --- a/src/kiwano/renderer/win32/D3D11DeviceResources.h +++ b/src/kiwano/renderer/win32/D3D11DeviceResources.h @@ -21,8 +21,7 @@ #pragma once #include - -#include +#include #include #include @@ -33,13 +32,14 @@ namespace kiwano : public ID3DDeviceResourcesBase { public: - static HRESULT Create(ID3D11DeviceResources** device_resources, ID2DDeviceResources* d2d_device_res, HWND hwnd); + static HRESULT Create(ID3D11DeviceResources** device_resources, HWND hwnd); inline ID3D11Device* GetDevice() { KGE_ASSERT(device_); return device_.get(); } inline ID3D11DeviceContext* GetDeviceContext() { KGE_ASSERT(device_context_); return device_context_.get(); } inline ID3D11RenderTargetView* GetRenderTargetView() { KGE_ASSERT(rt_view_); return rt_view_.get(); } inline ID3D11DepthStencilView* GetDepthStencilView() { KGE_ASSERT(ds_view_); return ds_view_.get(); } inline IDXGIFactory* GetDXGIFactory() { KGE_ASSERT(dxgi_factory_); return dxgi_factory_.get(); } + inline IDXGIDevice* GetDXGIDevice() { KGE_ASSERT(dxgi_device_); return dxgi_device_.get(); } inline IDXGISwapChain* GetDXGISwapChain() { KGE_ASSERT(dxgi_swap_chain_); return dxgi_swap_chain_.get(); } protected: @@ -47,8 +47,9 @@ namespace kiwano ComPtr device_context_; ComPtr rt_view_; ComPtr ds_view_; - ComPtr dxgi_swap_chain_; ComPtr dxgi_factory_; + ComPtr dxgi_device_; + ComPtr dxgi_swap_chain_; }; } diff --git a/src/kiwano/renderer/win32/helper.h b/src/kiwano/renderer/win32/helper.h new file mode 100644 index 00000000..ff1c22ed --- /dev/null +++ b/src/kiwano/renderer/win32/helper.h @@ -0,0 +1,177 @@ +// 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 +#include +#include +#include +#include + +namespace kiwano +{ + namespace DX + { + template + inline void SafeRelease(T*& ptr) + { + if (ptr != nullptr) + { + ptr->Release(); + ptr = nullptr; + } + } + + template + inline T* SafeAcquire(T* ptr) + { + if (ptr != nullptr) + { + ptr->AddRef(); + } + return ptr; + } + + // + // Point2F + // + + inline D2D1_POINT_2F const& ConvertToPoint2F(Vec2 const& vec2) + { + return reinterpret_cast(vec2); + } + + inline D2D1_POINT_2F& ConvertToPoint2F(Vec2& vec2) + { + return reinterpret_cast(vec2); + } + + inline const D2D1_POINT_2F* ConvertToPoint2F(const Vec2* vec2) + { + return reinterpret_cast(vec2); + } + + inline D2D1_POINT_2F* ConvertToPoint2F(Vec2* vec2) + { + return reinterpret_cast(vec2); + } + + // + // SizeF + // + + inline D2D1_SIZE_F const& ConvertToSizeF(Vec2 const& vec2) + { + return reinterpret_cast(vec2); + } + + inline D2D1_SIZE_F& ConvertToSizeF(Vec2& vec2) + { + return reinterpret_cast(vec2); + } + + inline const D2D1_SIZE_F* ConvertToSizeF(const Vec2* vec2) + { + return reinterpret_cast(vec2); + } + + inline D2D1_SIZE_F* ConvertToSizeF(Vec2* vec2) + { + return reinterpret_cast(vec2); + } + + // + // RectF + // + + inline D2D1_RECT_F const& ConvertToRectF(Rect const& rect) + { + return reinterpret_cast(rect); + } + + inline D2D1_RECT_F& ConvertToRectF(Rect& rect) + { + return reinterpret_cast(rect); + } + + inline const D2D1_RECT_F* ConvertToRectF(const Rect* rect) + { + return reinterpret_cast(rect); + } + + inline D2D1_RECT_F* ConvertToRectF(Rect* rect) + { + return reinterpret_cast(rect); + } + + // + // ColorF + // + inline D2D1_COLOR_F const& ConvertToColorF(Color const& color) + { + return reinterpret_cast(color); + } + + inline D2D1_COLOR_F& ConvertToColorF(Color& color) + { + return reinterpret_cast(color); + } + + inline const D2D1_COLOR_F* ConvertToColorF(const Color* color) + { + return reinterpret_cast(color); + } + + inline D2D1_COLOR_F* ConvertToColorF(Color* color) + { + return reinterpret_cast(color); + } + + // + // MatrixF + // + + inline D2D1_MATRIX_3X2_F const& ConvertToMatrix3x2F(Matrix3x2 const& matrix) + { + return reinterpret_cast(matrix); + } + + inline D2D1_MATRIX_3X2_F& ConvertToMatrix3x2F(Matrix3x2& matrix) + { + return reinterpret_cast(matrix); + } + + inline const D2D1_MATRIX_3X2_F* ConvertToMatrix3x2F(const Matrix3x2* matrix) + { + return reinterpret_cast(matrix); + } + + inline D2D1_MATRIX_3X2_F* ConvertToMatrix3x2F(Matrix3x2* matrix) + { + return reinterpret_cast(matrix); + } + + // Converts a length in device-independent pixels (DIPs) to a length in physical pixels. + 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. + } + } +}