From 9ea6781f0eccbbe5ce309167efb126d92ca555e3 Mon Sep 17 00:00:00 2001 From: Nomango Date: Mon, 3 Feb 2020 14:15:30 +0800 Subject: [PATCH] [deploy] Separating Renderer from the RenderContext --- Doxyfile | 5 +- src/kiwano-imgui/ImGuiModule.cpp | 36 ++--- src/kiwano-imgui/ImGuiModule.h | 4 - src/kiwano/2d/DebugActor.cpp | 7 +- src/kiwano/platform/Application.cpp | 12 +- .../render/DirectX/D2DDeviceResources.cpp | 12 +- src/kiwano/render/RenderContext.cpp | 126 +++++++++++------- src/kiwano/render/RenderContext.h | 37 +++-- src/kiwano/render/Renderer.cpp | 59 ++++---- src/kiwano/render/Renderer.h | 41 ++++-- 10 files changed, 196 insertions(+), 143 deletions(-) diff --git a/Doxyfile b/Doxyfile index 146898d9..8245e52a 100644 --- a/Doxyfile +++ b/Doxyfile @@ -56,7 +56,10 @@ EXCLUDE = src/3rd-party \ ENABLE_PREPROCESSING = YES MACRO_EXPANSION = YES PREDEFINED = KGE_API= \ - KGE_DOXYGEN_DO_NOT_INCLUDE= + KGE_DOXYGEN_DO_NOT_INCLUDE= \ + _Out_= \ + _In_= \ + _In_opt_= # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by the diff --git a/src/kiwano-imgui/ImGuiModule.cpp b/src/kiwano-imgui/ImGuiModule.cpp index 2cb8fcdf..61d20f63 100644 --- a/src/kiwano-imgui/ImGuiModule.cpp +++ b/src/kiwano-imgui/ImGuiModule.cpp @@ -90,12 +90,23 @@ void ImGuiModule::OnUpdate(Duration dt) void ImGuiModule::BeforeRender() { - NewFrame(); + ImGui_Impl_NewFrame(); + + ImGuiIO& io = ImGui::GetIO(); + KGE_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built!"); + + // Setup display size (every frame to accommodate for window resizing) + Size display_size = Renderer::Instance().GetOutputSize(); + io.DisplaySize = ImVec2(display_size.x, display_size.y); + + ImGui::NewFrame(); } void ImGuiModule::AfterRender() { - Render(); + ImGui::Render(); + + ImGui_Impl_RenderDrawData(ImGui::GetDrawData()); } void ImGuiModule::HandleEvent(Event* evt) @@ -157,27 +168,6 @@ void ImGuiModule::HandleEvent(Event* evt) } } -void ImGuiModule::NewFrame() -{ - ImGui_Impl_NewFrame(); - - ImGuiIO& io = ImGui::GetIO(); - KGE_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built!"); - - // Setup display size (every frame to accommodate for window resizing) - Size display_size = Renderer::Instance().GetOutputSize(); - io.DisplaySize = ImVec2(display_size.x, display_size.y); - - ImGui::NewFrame(); -} - -void ImGuiModule::Render() -{ - ImGui::Render(); - - ImGui_Impl_RenderDrawData(ImGui::GetDrawData()); -} - void ImGuiModule::UpdateMousePos() { ImGuiIO& io = ImGui::GetIO(); diff --git a/src/kiwano-imgui/ImGuiModule.h b/src/kiwano-imgui/ImGuiModule.h index 33a2a2f5..6f726d2c 100644 --- a/src/kiwano-imgui/ImGuiModule.h +++ b/src/kiwano-imgui/ImGuiModule.h @@ -54,10 +54,6 @@ public: void OnUpdate(Duration dt) override; private: - void NewFrame(); - - void Render(); - void UpdateMousePos(); void UpdateMouseCursor(); diff --git a/src/kiwano/2d/DebugActor.cpp b/src/kiwano/2d/DebugActor.cpp index 8e40b65a..4c27c6fb 100644 --- a/src/kiwano/2d/DebugActor.cpp +++ b/src/kiwano/2d/DebugActor.cpp @@ -104,10 +104,11 @@ void DebugActor::OnUpdate(Duration dt) } #endif - ss << "Render: " << Renderer::Instance().GetStatus().duration.Milliseconds() << "ms" << std::endl; + const auto& status = Renderer::Instance().GetContext().GetStatus(); - ss << "Primitives / sec: " << std::fixed << Renderer::Instance().GetStatus().primitives * frame_time_.size() - << std::endl; + ss << "Render: " << status.duration.Milliseconds() << "ms" << std::endl; + + ss << "Primitives / sec: " << std::fixed << status.primitives * frame_time_.size() << std::endl; ss << "Memory: "; { diff --git a/src/kiwano/platform/Application.cpp b/src/kiwano/platform/Application.cpp index 0cb1e912..0059be04 100644 --- a/src/kiwano/platform/Application.cpp +++ b/src/kiwano/platform/Application.cpp @@ -62,7 +62,7 @@ void Application::Run(bool debug) if (debug) { Director::Instance().ShowDebugInfo(true); - Renderer::Instance().SetCollectingStatus(true); + Renderer::Instance().GetContext().SetCollectingStatus(true); } // Everything is ready @@ -185,6 +185,9 @@ void Application::Update() void Application::Render() { + Renderer& renderer = Renderer::Instance(); + renderer.Clear(); + // Before render for (auto c : render_comps_) { @@ -192,17 +195,20 @@ void Application::Render() } // Rendering - Renderer& renderer = Renderer::Instance(); + renderer.BeginDraw(); for (auto c : render_comps_) { - c->OnRender(renderer); + c->OnRender(renderer.GetContext()); } + renderer.EndDraw(); // After render for (auto rit = render_comps_.rbegin(); rit != render_comps_.rend(); ++rit) { (*rit)->AfterRender(); } + + renderer.Present(); } void Application::DispatchEvent(Event* evt) diff --git a/src/kiwano/render/DirectX/D2DDeviceResources.cpp b/src/kiwano/render/DirectX/D2DDeviceResources.cpp index feb93632..0e81ea37 100644 --- a/src/kiwano/render/DirectX/D2DDeviceResources.cpp +++ b/src/kiwano/render/DirectX/D2DDeviceResources.cpp @@ -234,7 +234,8 @@ HRESULT D2DDeviceResources::CreateDeviceResources(_In_ ComPtr dxgi_ // Create the Direct2D device object and a corresponding context. ComPtr device; - HRESULT hr = factory_->CreateDevice(dxgi_device.get(), &device); + + HRESULT hr = factory_->CreateDevice(dxgi_device.get(), &device); if (SUCCEEDED(hr)) { @@ -261,7 +262,8 @@ HRESULT D2DDeviceResources::CreateWindowSizeDependentResources() // 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)); + + HRESULT hr = dxgi_swap_chain_->GetBuffer(0, IID_PPV_ARGS(&dxgi_back_buffer)); if (SUCCEEDED(hr)) { @@ -342,7 +344,8 @@ HRESULT D2DDeviceResources::CreateBitmapFromConverter(_Out_ ComPtr& return E_UNEXPECTED; ComPtr output; - HRESULT hr = device_context_->CreateBitmapFromWicBitmap(converter.get(), properties, &output); + + HRESULT hr = device_context_->CreateBitmapFromWicBitmap(converter.get(), properties, &output); if (SUCCEEDED(hr)) { @@ -358,7 +361,8 @@ HRESULT D2DDeviceResources::CreateBitmapDecoderFromFile(_Out_ ComPtr decoder_output; - HRESULT hr = imaging_factory_->CreateDecoderFromFilename(file_path.c_str(), nullptr, GENERIC_READ, + + HRESULT hr = imaging_factory_->CreateDecoderFromFilename(file_path.c_str(), nullptr, GENERIC_READ, WICDecodeMetadataCacheOnLoad, &decoder_output); if (SUCCEEDED(hr)) diff --git a/src/kiwano/render/RenderContext.cpp b/src/kiwano/render/RenderContext.cpp index 6fa13278..db4e26af 100644 --- a/src/kiwano/render/RenderContext.cpp +++ b/src/kiwano/render/RenderContext.cpp @@ -42,11 +42,11 @@ HRESULT RenderContext::CreateDeviceResources(ComPtr factory, ComPt if (!factory || !ctx) return E_INVALIDARG; - render_ctx_ = ctx; + render_target_ = ctx; text_renderer_.reset(); current_brush_.reset(); - HRESULT hr = ITextRenderer::Create(&text_renderer_, render_ctx_.get()); + HRESULT hr = ITextRenderer::Create(&text_renderer_, render_target_.get()); if (SUCCEEDED(hr)) { @@ -56,19 +56,25 @@ HRESULT RenderContext::CreateDeviceResources(ComPtr factory, ComPt Resize(reinterpret_cast(GetRenderTarget()->GetSize())); } + // DrawingStateBlock + if (SUCCEEDED(hr)) + { + hr = factory->CreateDrawingStateBlock(&drawing_state_); + } + return hr; } void RenderContext::DiscardDeviceResources() { text_renderer_.reset(); - render_ctx_.reset(); + render_target_.reset(); current_brush_.reset(); } bool RenderContext::IsValid() const { - return render_ctx_ != nullptr; + return render_target_ != nullptr; } void RenderContext::BeginDraw() @@ -79,15 +85,15 @@ void RenderContext::BeginDraw() status_.primitives = 0; } - if (render_ctx_) + if (render_target_) { - render_ctx_->BeginDraw(); + render_target_->BeginDraw(); } } void RenderContext::EndDraw() { - win32::ThrowIfFailed(render_ctx_->EndDraw()); + win32::ThrowIfFailed(render_target_->EndDraw()); if (collecting_status_) { @@ -97,12 +103,12 @@ void RenderContext::EndDraw() void RenderContext::DrawGeometry(Geometry const& geometry, float stroke_width, const StrokeStyle& stroke) { - KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!"); if (geometry.IsValid()) { - render_ctx_->DrawGeometry(geometry.GetGeometry().get(), current_brush_->GetBrush().get(), stroke_width, + render_target_->DrawGeometry(geometry.GetGeometry().get(), current_brush_->GetBrush().get(), stroke_width, stroke.GetStrokeStyle().get()); IncreasePrimitivesCount(); @@ -111,12 +117,12 @@ void RenderContext::DrawGeometry(Geometry const& geometry, float stroke_width, c void RenderContext::FillGeometry(Geometry const& geometry) { - KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!"); if (geometry.IsValid()) { - render_ctx_->FillGeometry(geometry.GetGeometry().get(), current_brush_->GetBrush().get()); + render_target_->FillGeometry(geometry.GetGeometry().get(), current_brush_->GetBrush().get()); IncreasePrimitivesCount(); } @@ -124,10 +130,10 @@ void RenderContext::FillGeometry(Geometry const& geometry) void RenderContext::DrawLine(Point const& point1, Point const& point2, float stroke_width, const StrokeStyle& stroke) { - KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!"); - render_ctx_->DrawLine(DX::ConvertToPoint2F(point1), DX::ConvertToPoint2F(point2), current_brush_->GetBrush().get(), + render_target_->DrawLine(DX::ConvertToPoint2F(point1), DX::ConvertToPoint2F(point2), current_brush_->GetBrush().get(), stroke_width, stroke.GetStrokeStyle().get()); IncreasePrimitivesCount(); @@ -135,10 +141,10 @@ void RenderContext::DrawLine(Point const& point1, Point const& point2, float str void RenderContext::DrawRectangle(Rect const& rect, float stroke_width, const StrokeStyle& stroke) { - KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!"); - render_ctx_->DrawRectangle(DX::ConvertToRectF(rect), current_brush_->GetBrush().get(), stroke_width, + render_target_->DrawRectangle(DX::ConvertToRectF(rect), current_brush_->GetBrush().get(), stroke_width, stroke.GetStrokeStyle().get()); IncreasePrimitivesCount(); @@ -146,10 +152,10 @@ void RenderContext::DrawRectangle(Rect const& rect, float stroke_width, const St void RenderContext::FillRectangle(Rect const& rect) { - KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!"); - render_ctx_->FillRectangle(DX::ConvertToRectF(rect), current_brush_->GetBrush().get()); + render_target_->FillRectangle(DX::ConvertToRectF(rect), current_brush_->GetBrush().get()); IncreasePrimitivesCount(); } @@ -157,10 +163,10 @@ void RenderContext::FillRectangle(Rect const& rect) void RenderContext::DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, float stroke_width, const StrokeStyle& stroke) { - KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!"); - render_ctx_->DrawRoundedRectangle(D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y), + render_target_->DrawRoundedRectangle(D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y), current_brush_->GetBrush().get(), stroke_width, stroke.GetStrokeStyle().get()); IncreasePrimitivesCount(); @@ -168,10 +174,10 @@ void RenderContext::DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, f void RenderContext::FillRoundedRectangle(Rect const& rect, Vec2 const& radius) { - KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!"); - render_ctx_->FillRoundedRectangle(D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y), + render_target_->FillRoundedRectangle(D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y), current_brush_->GetBrush().get()); IncreasePrimitivesCount(); @@ -179,10 +185,10 @@ void RenderContext::FillRoundedRectangle(Rect const& rect, Vec2 const& radius) void RenderContext::DrawEllipse(Point const& center, Vec2 const& radius, float stroke_width, const StrokeStyle& stroke) { - KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!"); - render_ctx_->DrawEllipse(D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y), + render_target_->DrawEllipse(D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y), current_brush_->GetBrush().get(), stroke_width, stroke.GetStrokeStyle().get()); IncreasePrimitivesCount(); @@ -190,10 +196,10 @@ void RenderContext::DrawEllipse(Point const& center, Vec2 const& radius, float s void RenderContext::FillEllipse(Point const& center, Vec2 const& radius) { - KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!"); - render_ctx_->FillEllipse(D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y), + render_target_->FillEllipse(D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y), current_brush_->GetBrush().get()); IncreasePrimitivesCount(); @@ -206,7 +212,7 @@ void RenderContext::DrawTexture(Texture const& texture, Rect const& src_rect, Re void RenderContext::DrawTexture(Texture const& texture, const Rect* src_rect, const Rect* dest_rect) { - KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); if (texture.IsValid()) { @@ -214,7 +220,7 @@ void RenderContext::DrawTexture(Texture const& texture, const Rect* src_rect, co ? D2D1_BITMAP_INTERPOLATION_MODE_LINEAR : D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR; - render_ctx_->DrawBitmap(texture.GetBitmap().get(), dest_rect ? &DX::ConvertToRectF(*dest_rect) : nullptr, + render_target_->DrawBitmap(texture.GetBitmap().get(), dest_rect ? &DX::ConvertToRectF(*dest_rect) : nullptr, brush_opacity_, mode, src_rect ? &DX::ConvertToRectF(*src_rect) : nullptr); IncreasePrimitivesCount(); @@ -260,10 +266,10 @@ void RenderContext::DrawTextLayout(TextLayout const& layout, Point const& offset void RenderContext::CreateTexture(Texture& texture, math::Vec2T size, D2D1_PIXEL_FORMAT format) { - KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); ComPtr saved_bitmap; - HRESULT hr = render_ctx_->CreateBitmap(D2D1::SizeU(size.x, size.y), D2D1::BitmapProperties(format), &saved_bitmap); + HRESULT hr = render_target_->CreateBitmap(D2D1::SizeU(size.x, size.y), D2D1::BitmapProperties(format), &saved_bitmap); if (SUCCEEDED(hr)) { @@ -277,24 +283,24 @@ void RenderContext::CreateTexture(Texture& texture, math::Vec2T size, void RenderContext::PushClipRect(Rect const& clip_rect) { - KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); - render_ctx_->PushAxisAlignedClip(DX::ConvertToRectF(clip_rect), + 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); } void RenderContext::PopClipRect() { - KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); - render_ctx_->PopAxisAlignedClip(); + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); + render_target_->PopAxisAlignedClip(); } void RenderContext::PushLayer(LayerArea& layer) { - KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); if (!layer.IsValid()) { ComPtr output; - HRESULT hr = render_ctx_->CreateLayer(&output); + HRESULT hr = render_target_->CreateLayer(&output); if (SUCCEEDED(hr)) { @@ -308,7 +314,7 @@ void RenderContext::PushLayer(LayerArea& layer) if (layer.IsValid()) { - render_ctx_->PushLayer( + render_target_->PushLayer( D2D1::LayerParameters(DX::ConvertToRectF(layer.GetAreaRect()), layer.GetMaskGeometry().GetGeometry().get(), antialias_ ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED, DX::ConvertToMatrix3x2F(layer.GetMaskTransform()), layer.GetOpacity(), nullptr, @@ -319,34 +325,34 @@ void RenderContext::PushLayer(LayerArea& layer) void RenderContext::PopLayer() { - KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); - render_ctx_->PopLayer(); + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); + render_target_->PopLayer(); } void RenderContext::Clear() { - KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); - render_ctx_->Clear(); + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); + render_target_->Clear(); } void RenderContext::Clear(Color const& clear_color) { - KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); - render_ctx_->Clear(DX::ConvertToColorF(clear_color)); + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); + render_target_->Clear(DX::ConvertToColorF(clear_color)); } void RenderContext::SetTransform(const Matrix3x2& matrix) { - KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); if (fast_global_transform_) { - render_ctx_->SetTransform(DX::ConvertToMatrix3x2F(&matrix)); + render_target_->SetTransform(DX::ConvertToMatrix3x2F(&matrix)); } else { Matrix3x2 result = matrix * global_transform_; - render_ctx_->SetTransform(DX::ConvertToMatrix3x2F(&result)); + render_target_->SetTransform(DX::ConvertToMatrix3x2F(&result)); } } @@ -365,15 +371,15 @@ void RenderContext::SetGlobalTransform(const Matrix3x2* matrix) void RenderContext::SetAntialiasMode(bool enabled) { - KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); - render_ctx_->SetAntialiasMode(enabled ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED); + render_target_->SetAntialiasMode(enabled ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED); antialias_ = enabled; } void RenderContext::SetTextAntialiasMode(TextAntialiasMode mode) { - KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); D2D1_TEXT_ANTIALIAS_MODE antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE; switch (mode) @@ -395,12 +401,12 @@ void RenderContext::SetTextAntialiasMode(TextAntialiasMode mode) } text_antialias_ = mode; - render_ctx_->SetTextAntialiasMode(antialias_mode); + render_target_->SetTextAntialiasMode(antialias_mode); } bool RenderContext::CheckVisibility(Rect const& bounds, Matrix3x2 const& transform) { - KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); + KGE_ASSERT(render_target_ && "Render target has not been initialized!"); if (fast_global_transform_) { @@ -427,6 +433,26 @@ void RenderContext::IncreasePrimitivesCount(uint32_t increase) const } } +void RenderContext::SaveDrawingState() +{ + KGE_ASSERT(IsValid()); + + if (drawing_state_) + { + render_target_->SaveDrawingState(drawing_state_.get()); + } +} + +void RenderContext::RestoreDrawingState() +{ + KGE_ASSERT(IsValid()); + + if (drawing_state_) + { + render_target_->RestoreDrawingState(drawing_state_.get()); + } +} + // // TextureRenderContext // diff --git a/src/kiwano/render/RenderContext.h b/src/kiwano/render/RenderContext.h index 0d805f0b..d7ec1e92 100644 --- a/src/kiwano/render/RenderContext.h +++ b/src/kiwano/render/RenderContext.h @@ -238,19 +238,28 @@ private: /// @brief 增加渲染图元数量 void IncreasePrimitivesCount(uint32_t increase = 1) const; -private: - bool antialias_; - bool fast_global_transform_; - float brush_opacity_; - TextAntialiasMode text_antialias_; - ComPtr text_renderer_; - ComPtr render_ctx_; - BrushPtr current_brush_; - Rect visible_size_; - Matrix3x2 global_transform_; + /// \~chinese + /// @brief 保存绘制状态 + void SaveDrawingState(); - mutable bool collecting_status_; - mutable Status status_; + /// \~chinese + /// @brief 恢复绘制状态 + void RestoreDrawingState(); + +private: + bool antialias_; + bool fast_global_transform_; + mutable bool collecting_status_; + float brush_opacity_; + TextAntialiasMode text_antialias_; + BrushPtr current_brush_; + Rect visible_size_; + Matrix3x2 global_transform_; + mutable Status status_; + + ComPtr text_renderer_; + ComPtr render_target_; + ComPtr drawing_state_; }; /// \~chinese @@ -296,8 +305,8 @@ inline RenderContext::Status const& RenderContext::GetStatus() const inline ComPtr RenderContext::GetRenderTarget() const { - KGE_ASSERT(render_ctx_); - return render_ctx_; + KGE_ASSERT(render_target_); + return render_target_; } inline ComPtr RenderContext::GetTextRenderer() const diff --git a/src/kiwano/render/Renderer.cpp b/src/kiwano/render/Renderer.cpp index 50163afd..c6cf4695 100644 --- a/src/kiwano/render/Renderer.cpp +++ b/src/kiwano/render/Renderer.cpp @@ -45,9 +45,8 @@ void Renderer::SetupComponent() target_window_ = Window::Instance().GetHandle(); output_size_ = Window::Instance().GetSize(); - d2d_res_ = nullptr; - d3d_res_ = nullptr; - drawing_state_block_ = nullptr; + d2d_res_ = nullptr; + d3d_res_ = nullptr; HRESULT hr = target_window_ ? S_OK : E_FAIL; @@ -61,16 +60,10 @@ void Renderer::SetupComponent() { hr = ID2DDeviceResources::Create(&d2d_res_, d3d_res_->GetDXGIDevice(), d3d_res_->GetDXGISwapChain()); - // DrawingStateBlock - if (SUCCEEDED(hr)) - { - hr = d2d_res_->GetFactory()->CreateDrawingStateBlock(&drawing_state_block_); - } - // Other device resources if (SUCCEEDED(hr)) { - hr = CreateDeviceResources(d2d_res_->GetFactory(), d2d_res_->GetDeviceContext()); + hr = render_ctx_.CreateDeviceResources(d2d_res_->GetFactory(), d2d_res_->GetDeviceContext()); } // FontFileLoader and FontCollectionLoader @@ -116,7 +109,7 @@ void Renderer::DestroyComponent() { KGE_SYS_LOG(L"Destroying device resources"); - DiscardDeviceResources(); + render_ctx_.DiscardDeviceResources(); d2d_res_->GetDWriteFactory()->UnregisterFontFileLoader(res_font_file_loader_.get()); res_font_file_loader_.reset(); @@ -124,34 +117,39 @@ void Renderer::DestroyComponent() d2d_res_->GetDWriteFactory()->UnregisterFontCollectionLoader(res_font_collection_loader_.get()); res_font_collection_loader_.reset(); - drawing_state_block_.reset(); d2d_res_.reset(); d3d_res_.reset(); ::CoUninitialize(); } -void Renderer::BeforeRender() +void Renderer::BeginDraw() { - KGE_ASSERT(d3d_res_ && IsValid()); + KGE_ASSERT(render_ctx_.IsValid()); + + render_ctx_.SaveDrawingState(); + render_ctx_.BeginDraw(); +} + +void Renderer::EndDraw() +{ + KGE_ASSERT(render_ctx_.IsValid()); + + render_ctx_.EndDraw(); + render_ctx_.RestoreDrawingState(); +} + +void Renderer::Clear() +{ + KGE_ASSERT(d3d_res_); HRESULT hr = d3d_res_->ClearRenderTarget(clear_color_); - - if (SUCCEEDED(hr)) - { - GetRenderTarget()->SaveDrawingState(drawing_state_block_.get()); - BeginDraw(); - } - win32::ThrowIfFailed(hr); } -void Renderer::AfterRender() +void Renderer::Present() { - KGE_ASSERT(d3d_res_ && IsValid()); - - EndDraw(); - GetRenderTarget()->RestoreDrawingState(drawing_state_block_.get()); + KGE_ASSERT(d3d_res_); HRESULT hr = d3d_res_->Present(vsync_); @@ -175,7 +173,7 @@ void Renderer::HandleEvent(Event* evt) HRESULT Renderer::HandleDeviceLost() { - KGE_ASSERT(d3d_res_ && d2d_res_ && render_ctx_); + KGE_ASSERT(d3d_res_ && d2d_res_ && render_ctx_.IsValid()); HRESULT hr = d3d_res_->HandleDeviceLost(); @@ -186,7 +184,7 @@ HRESULT Renderer::HandleDeviceLost() if (SUCCEEDED(hr)) { - hr = CreateDeviceResources(d2d_res_->GetFactory(), d2d_res_->GetDeviceContext()); + hr = render_ctx_.CreateDeviceResources(d2d_res_->GetFactory(), d2d_res_->GetDeviceContext()); } return hr; } @@ -939,7 +937,8 @@ void Renderer::ResizeTarget(uint32_t width, uint32_t height) { output_size_.x = static_cast(width); output_size_.y = static_cast(height); - hr = d3d_res_->SetLogicalSize(output_size_); + + hr = d3d_res_->SetLogicalSize(output_size_); } if (SUCCEEDED(hr)) @@ -949,7 +948,7 @@ void Renderer::ResizeTarget(uint32_t width, uint32_t height) if (SUCCEEDED(hr)) { - Resize(reinterpret_cast(GetRenderTarget()->GetSize())); + render_ctx_.Resize(output_size_); } win32::ThrowIfFailed(hr); diff --git a/src/kiwano/render/Renderer.h b/src/kiwano/render/Renderer.h index 42ccb3be..21275f84 100644 --- a/src/kiwano/render/Renderer.h +++ b/src/kiwano/render/Renderer.h @@ -58,9 +58,7 @@ typedef ID3D11DeviceResources ID3DDeviceResources; */ class KGE_API Renderer : public Singleton - , public RenderComponent , public EventComponent - , public RenderContext { friend Singleton; @@ -201,6 +199,26 @@ public: size_t dash_size, float dash_offset); public: + /// \~chinese + /// @brief 开始渲染 + void BeginDraw(); + + /// \~chinese + /// @brief 结束渲染 + void EndDraw(); + + /// \~chinese + /// @brief 清除绘制内容 + void Clear(); + + /// \~chinese + /// @brief 将绘制内容呈现至窗口 + void Present(); + + /// \~chinese + /// @brief 获取渲染上下文 + RenderContext& GetContext(); + /// \~chinese /// @brief 获取目标窗口 WindowHandle GetTargetWindow() const; @@ -222,10 +240,6 @@ public: void DestroyComponent() override; - void BeforeRender() override; - - void AfterRender() override; - void HandleEvent(Event* evt) override; private: @@ -238,14 +252,14 @@ private: void ResizeTarget(uint32_t width, uint32_t height); private: - bool vsync_; - WindowHandle target_window_; - Color clear_color_; - Size output_size_; + bool vsync_; + WindowHandle target_window_; + Color clear_color_; + Size output_size_; + RenderContext render_ctx_; ComPtr d2d_res_; ComPtr d3d_res_; - ComPtr drawing_state_block_; ComPtr font_collection_loader_; ComPtr res_font_file_loader_; ComPtr res_font_collection_loader_; @@ -268,6 +282,11 @@ inline Color const& Renderer::GetClearColor() const return clear_color_; } +inline RenderContext& Renderer::GetContext() +{ + return render_ctx_; +} + inline ID2DDeviceResources* Renderer::GetD2DDeviceResources() { KGE_ASSERT(d2d_res_);