[deploy] Separating Renderer from the RenderContext

This commit is contained in:
Nomango 2020-02-03 14:15:30 +08:00
parent dff97d8249
commit 9ea6781f0e
10 changed files with 196 additions and 143 deletions

View File

@ -56,7 +56,10 @@ EXCLUDE = src/3rd-party \
ENABLE_PREPROCESSING = YES ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES MACRO_EXPANSION = YES
PREDEFINED = KGE_API= \ 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 # 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 # contain include files that are not input files but should be processed by the

View File

@ -90,12 +90,23 @@ void ImGuiModule::OnUpdate(Duration dt)
void ImGuiModule::BeforeRender() 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() void ImGuiModule::AfterRender()
{ {
Render(); ImGui::Render();
ImGui_Impl_RenderDrawData(ImGui::GetDrawData());
} }
void ImGuiModule::HandleEvent(Event* evt) 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() void ImGuiModule::UpdateMousePos()
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();

View File

@ -54,10 +54,6 @@ public:
void OnUpdate(Duration dt) override; void OnUpdate(Duration dt) override;
private: private:
void NewFrame();
void Render();
void UpdateMousePos(); void UpdateMousePos();
void UpdateMouseCursor(); void UpdateMouseCursor();

View File

@ -104,10 +104,11 @@ void DebugActor::OnUpdate(Duration dt)
} }
#endif #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() ss << "Render: " << status.duration.Milliseconds() << "ms" << std::endl;
<< std::endl;
ss << "Primitives / sec: " << std::fixed << status.primitives * frame_time_.size() << std::endl;
ss << "Memory: "; ss << "Memory: ";
{ {

View File

@ -62,7 +62,7 @@ void Application::Run(bool debug)
if (debug) if (debug)
{ {
Director::Instance().ShowDebugInfo(true); Director::Instance().ShowDebugInfo(true);
Renderer::Instance().SetCollectingStatus(true); Renderer::Instance().GetContext().SetCollectingStatus(true);
} }
// Everything is ready // Everything is ready
@ -185,6 +185,9 @@ void Application::Update()
void Application::Render() void Application::Render()
{ {
Renderer& renderer = Renderer::Instance();
renderer.Clear();
// Before render // Before render
for (auto c : render_comps_) for (auto c : render_comps_)
{ {
@ -192,17 +195,20 @@ void Application::Render()
} }
// Rendering // Rendering
Renderer& renderer = Renderer::Instance(); renderer.BeginDraw();
for (auto c : render_comps_) for (auto c : render_comps_)
{ {
c->OnRender(renderer); c->OnRender(renderer.GetContext());
} }
renderer.EndDraw();
// After render // After render
for (auto rit = render_comps_.rbegin(); rit != render_comps_.rend(); ++rit) for (auto rit = render_comps_.rbegin(); rit != render_comps_.rend(); ++rit)
{ {
(*rit)->AfterRender(); (*rit)->AfterRender();
} }
renderer.Present();
} }
void Application::DispatchEvent(Event* evt) void Application::DispatchEvent(Event* evt)

View File

@ -234,7 +234,8 @@ HRESULT D2DDeviceResources::CreateDeviceResources(_In_ ComPtr<IDXGIDevice> dxgi_
// Create the Direct2D device object and a corresponding context. // Create the Direct2D device object and a corresponding context.
ComPtr<ID2D1Device> device; ComPtr<ID2D1Device> device;
HRESULT hr = factory_->CreateDevice(dxgi_device.get(), &device);
HRESULT hr = factory_->CreateDevice(dxgi_device.get(), &device);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
@ -261,7 +262,8 @@ HRESULT D2DDeviceResources::CreateWindowSizeDependentResources()
// Create a Direct2D target bitmap associated with the // Create a Direct2D target bitmap associated with the
// swap chain back buffer and set it as the current target. // swap chain back buffer and set it as the current target.
ComPtr<IDXGISurface> dxgi_back_buffer; ComPtr<IDXGISurface> 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)) if (SUCCEEDED(hr))
{ {
@ -342,7 +344,8 @@ HRESULT D2DDeviceResources::CreateBitmapFromConverter(_Out_ ComPtr<ID2D1Bitmap>&
return E_UNEXPECTED; return E_UNEXPECTED;
ComPtr<ID2D1Bitmap> output; ComPtr<ID2D1Bitmap> output;
HRESULT hr = device_context_->CreateBitmapFromWicBitmap(converter.get(), properties, &output);
HRESULT hr = device_context_->CreateBitmapFromWicBitmap(converter.get(), properties, &output);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
@ -358,7 +361,8 @@ HRESULT D2DDeviceResources::CreateBitmapDecoderFromFile(_Out_ ComPtr<IWICBitmapD
return E_UNEXPECTED; return E_UNEXPECTED;
ComPtr<IWICBitmapDecoder> decoder_output; ComPtr<IWICBitmapDecoder> 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); WICDecodeMetadataCacheOnLoad, &decoder_output);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))

View File

@ -42,11 +42,11 @@ HRESULT RenderContext::CreateDeviceResources(ComPtr<ID2D1Factory> factory, ComPt
if (!factory || !ctx) if (!factory || !ctx)
return E_INVALIDARG; return E_INVALIDARG;
render_ctx_ = ctx; render_target_ = ctx;
text_renderer_.reset(); text_renderer_.reset();
current_brush_.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)) if (SUCCEEDED(hr))
{ {
@ -56,19 +56,25 @@ HRESULT RenderContext::CreateDeviceResources(ComPtr<ID2D1Factory> factory, ComPt
Resize(reinterpret_cast<const Size&>(GetRenderTarget()->GetSize())); Resize(reinterpret_cast<const Size&>(GetRenderTarget()->GetSize()));
} }
// DrawingStateBlock
if (SUCCEEDED(hr))
{
hr = factory->CreateDrawingStateBlock(&drawing_state_);
}
return hr; return hr;
} }
void RenderContext::DiscardDeviceResources() void RenderContext::DiscardDeviceResources()
{ {
text_renderer_.reset(); text_renderer_.reset();
render_ctx_.reset(); render_target_.reset();
current_brush_.reset(); current_brush_.reset();
} }
bool RenderContext::IsValid() const bool RenderContext::IsValid() const
{ {
return render_ctx_ != nullptr; return render_target_ != nullptr;
} }
void RenderContext::BeginDraw() void RenderContext::BeginDraw()
@ -79,15 +85,15 @@ void RenderContext::BeginDraw()
status_.primitives = 0; status_.primitives = 0;
} }
if (render_ctx_) if (render_target_)
{ {
render_ctx_->BeginDraw(); render_target_->BeginDraw();
} }
} }
void RenderContext::EndDraw() void RenderContext::EndDraw()
{ {
win32::ThrowIfFailed(render_ctx_->EndDraw()); win32::ThrowIfFailed(render_target_->EndDraw());
if (collecting_status_) if (collecting_status_)
{ {
@ -97,12 +103,12 @@ void RenderContext::EndDraw()
void RenderContext::DrawGeometry(Geometry const& geometry, float stroke_width, const StrokeStyle& stroke) 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!"); KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
if (geometry.IsValid()) 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()); stroke.GetStrokeStyle().get());
IncreasePrimitivesCount(); IncreasePrimitivesCount();
@ -111,12 +117,12 @@ void RenderContext::DrawGeometry(Geometry const& geometry, float stroke_width, c
void RenderContext::FillGeometry(Geometry const& geometry) 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!"); KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
if (geometry.IsValid()) if (geometry.IsValid())
{ {
render_ctx_->FillGeometry(geometry.GetGeometry().get(), current_brush_->GetBrush().get()); render_target_->FillGeometry(geometry.GetGeometry().get(), current_brush_->GetBrush().get());
IncreasePrimitivesCount(); 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) 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!"); 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()); stroke_width, stroke.GetStrokeStyle().get());
IncreasePrimitivesCount(); 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) 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!"); 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()); stroke.GetStrokeStyle().get());
IncreasePrimitivesCount(); IncreasePrimitivesCount();
@ -146,10 +152,10 @@ void RenderContext::DrawRectangle(Rect const& rect, float stroke_width, const St
void RenderContext::FillRectangle(Rect const& rect) 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!"); 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(); IncreasePrimitivesCount();
} }
@ -157,10 +163,10 @@ void RenderContext::FillRectangle(Rect const& rect)
void RenderContext::DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, float stroke_width, void RenderContext::DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, float stroke_width,
const StrokeStyle& stroke) 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!"); 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()); current_brush_->GetBrush().get(), stroke_width, stroke.GetStrokeStyle().get());
IncreasePrimitivesCount(); IncreasePrimitivesCount();
@ -168,10 +174,10 @@ void RenderContext::DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, f
void RenderContext::FillRoundedRectangle(Rect const& rect, Vec2 const& radius) 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!"); 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()); current_brush_->GetBrush().get());
IncreasePrimitivesCount(); 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) 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!"); 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()); current_brush_->GetBrush().get(), stroke_width, stroke.GetStrokeStyle().get());
IncreasePrimitivesCount(); 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) 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!"); 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()); current_brush_->GetBrush().get());
IncreasePrimitivesCount(); 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) 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()) 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_LINEAR
: D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR; : 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); brush_opacity_, mode, src_rect ? &DX::ConvertToRectF(*src_rect) : nullptr);
IncreasePrimitivesCount(); IncreasePrimitivesCount();
@ -260,10 +266,10 @@ void RenderContext::DrawTextLayout(TextLayout const& layout, Point const& offset
void RenderContext::CreateTexture(Texture& texture, math::Vec2T<uint32_t> size, D2D1_PIXEL_FORMAT format) void RenderContext::CreateTexture(Texture& texture, math::Vec2T<uint32_t> 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<ID2D1Bitmap> saved_bitmap; ComPtr<ID2D1Bitmap> 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)) if (SUCCEEDED(hr))
{ {
@ -277,24 +283,24 @@ void RenderContext::CreateTexture(Texture& texture, math::Vec2T<uint32_t> size,
void RenderContext::PushClipRect(Rect const& clip_rect) void RenderContext::PushClipRect(Rect const& clip_rect)
{ {
KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); KGE_ASSERT(render_target_ && "Render target has not been initialized!");
render_ctx_->PushAxisAlignedClip(DX::ConvertToRectF(clip_rect), render_target_->PushAxisAlignedClip(DX::ConvertToRectF(clip_rect),
antialias_ ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED); antialias_ ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED);
} }
void RenderContext::PopClipRect() void RenderContext::PopClipRect()
{ {
KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); KGE_ASSERT(render_target_ && "Render target has not been initialized!");
render_ctx_->PopAxisAlignedClip(); render_target_->PopAxisAlignedClip();
} }
void RenderContext::PushLayer(LayerArea& layer) 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()) if (!layer.IsValid())
{ {
ComPtr<ID2D1Layer> output; ComPtr<ID2D1Layer> output;
HRESULT hr = render_ctx_->CreateLayer(&output); HRESULT hr = render_target_->CreateLayer(&output);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
@ -308,7 +314,7 @@ void RenderContext::PushLayer(LayerArea& layer)
if (layer.IsValid()) if (layer.IsValid())
{ {
render_ctx_->PushLayer( render_target_->PushLayer(
D2D1::LayerParameters(DX::ConvertToRectF(layer.GetAreaRect()), layer.GetMaskGeometry().GetGeometry().get(), D2D1::LayerParameters(DX::ConvertToRectF(layer.GetAreaRect()), layer.GetMaskGeometry().GetGeometry().get(),
antialias_ ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED, antialias_ ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED,
DX::ConvertToMatrix3x2F(layer.GetMaskTransform()), layer.GetOpacity(), nullptr, DX::ConvertToMatrix3x2F(layer.GetMaskTransform()), layer.GetOpacity(), nullptr,
@ -319,34 +325,34 @@ void RenderContext::PushLayer(LayerArea& layer)
void RenderContext::PopLayer() void RenderContext::PopLayer()
{ {
KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); KGE_ASSERT(render_target_ && "Render target has not been initialized!");
render_ctx_->PopLayer(); render_target_->PopLayer();
} }
void RenderContext::Clear() void RenderContext::Clear()
{ {
KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); KGE_ASSERT(render_target_ && "Render target has not been initialized!");
render_ctx_->Clear(); render_target_->Clear();
} }
void RenderContext::Clear(Color const& clear_color) void RenderContext::Clear(Color const& clear_color)
{ {
KGE_ASSERT(render_ctx_ && "Render target has not been initialized!"); KGE_ASSERT(render_target_ && "Render target has not been initialized!");
render_ctx_->Clear(DX::ConvertToColorF(clear_color)); render_target_->Clear(DX::ConvertToColorF(clear_color));
} }
void RenderContext::SetTransform(const Matrix3x2& matrix) 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_) if (fast_global_transform_)
{ {
render_ctx_->SetTransform(DX::ConvertToMatrix3x2F(&matrix)); render_target_->SetTransform(DX::ConvertToMatrix3x2F(&matrix));
} }
else else
{ {
Matrix3x2 result = matrix * global_transform_; 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) 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; antialias_ = enabled;
} }
void RenderContext::SetTextAntialiasMode(TextAntialiasMode mode) 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; D2D1_TEXT_ANTIALIAS_MODE antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
switch (mode) switch (mode)
@ -395,12 +401,12 @@ void RenderContext::SetTextAntialiasMode(TextAntialiasMode mode)
} }
text_antialias_ = mode; text_antialias_ = mode;
render_ctx_->SetTextAntialiasMode(antialias_mode); render_target_->SetTextAntialiasMode(antialias_mode);
} }
bool RenderContext::CheckVisibility(Rect const& bounds, Matrix3x2 const& transform) 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_) 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 // TextureRenderContext
// //

View File

@ -238,19 +238,28 @@ private:
/// @brief 增加渲染图元数量 /// @brief 增加渲染图元数量
void IncreasePrimitivesCount(uint32_t increase = 1) const; void IncreasePrimitivesCount(uint32_t increase = 1) const;
private: /// \~chinese
bool antialias_; /// @brief 保存绘制状态
bool fast_global_transform_; void SaveDrawingState();
float brush_opacity_;
TextAntialiasMode text_antialias_;
ComPtr<ITextRenderer> text_renderer_;
ComPtr<ID2D1RenderTarget> render_ctx_;
BrushPtr current_brush_;
Rect visible_size_;
Matrix3x2 global_transform_;
mutable bool collecting_status_; /// \~chinese
mutable Status status_; /// @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<ITextRenderer> text_renderer_;
ComPtr<ID2D1RenderTarget> render_target_;
ComPtr<ID2D1DrawingStateBlock> drawing_state_;
}; };
/// \~chinese /// \~chinese
@ -296,8 +305,8 @@ inline RenderContext::Status const& RenderContext::GetStatus() const
inline ComPtr<ID2D1RenderTarget> RenderContext::GetRenderTarget() const inline ComPtr<ID2D1RenderTarget> RenderContext::GetRenderTarget() const
{ {
KGE_ASSERT(render_ctx_); KGE_ASSERT(render_target_);
return render_ctx_; return render_target_;
} }
inline ComPtr<ITextRenderer> RenderContext::GetTextRenderer() const inline ComPtr<ITextRenderer> RenderContext::GetTextRenderer() const

View File

@ -45,9 +45,8 @@ void Renderer::SetupComponent()
target_window_ = Window::Instance().GetHandle(); target_window_ = Window::Instance().GetHandle();
output_size_ = Window::Instance().GetSize(); output_size_ = Window::Instance().GetSize();
d2d_res_ = nullptr; d2d_res_ = nullptr;
d3d_res_ = nullptr; d3d_res_ = nullptr;
drawing_state_block_ = nullptr;
HRESULT hr = target_window_ ? S_OK : E_FAIL; 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()); 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 // Other device resources
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = CreateDeviceResources(d2d_res_->GetFactory(), d2d_res_->GetDeviceContext()); hr = render_ctx_.CreateDeviceResources(d2d_res_->GetFactory(), d2d_res_->GetDeviceContext());
} }
// FontFileLoader and FontCollectionLoader // FontFileLoader and FontCollectionLoader
@ -116,7 +109,7 @@ void Renderer::DestroyComponent()
{ {
KGE_SYS_LOG(L"Destroying device resources"); KGE_SYS_LOG(L"Destroying device resources");
DiscardDeviceResources(); render_ctx_.DiscardDeviceResources();
d2d_res_->GetDWriteFactory()->UnregisterFontFileLoader(res_font_file_loader_.get()); d2d_res_->GetDWriteFactory()->UnregisterFontFileLoader(res_font_file_loader_.get());
res_font_file_loader_.reset(); res_font_file_loader_.reset();
@ -124,34 +117,39 @@ void Renderer::DestroyComponent()
d2d_res_->GetDWriteFactory()->UnregisterFontCollectionLoader(res_font_collection_loader_.get()); d2d_res_->GetDWriteFactory()->UnregisterFontCollectionLoader(res_font_collection_loader_.get());
res_font_collection_loader_.reset(); res_font_collection_loader_.reset();
drawing_state_block_.reset();
d2d_res_.reset(); d2d_res_.reset();
d3d_res_.reset(); d3d_res_.reset();
::CoUninitialize(); ::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_); HRESULT hr = d3d_res_->ClearRenderTarget(clear_color_);
if (SUCCEEDED(hr))
{
GetRenderTarget()->SaveDrawingState(drawing_state_block_.get());
BeginDraw();
}
win32::ThrowIfFailed(hr); win32::ThrowIfFailed(hr);
} }
void Renderer::AfterRender() void Renderer::Present()
{ {
KGE_ASSERT(d3d_res_ && IsValid()); KGE_ASSERT(d3d_res_);
EndDraw();
GetRenderTarget()->RestoreDrawingState(drawing_state_block_.get());
HRESULT hr = d3d_res_->Present(vsync_); HRESULT hr = d3d_res_->Present(vsync_);
@ -175,7 +173,7 @@ void Renderer::HandleEvent(Event* evt)
HRESULT Renderer::HandleDeviceLost() 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(); HRESULT hr = d3d_res_->HandleDeviceLost();
@ -186,7 +184,7 @@ HRESULT Renderer::HandleDeviceLost()
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = CreateDeviceResources(d2d_res_->GetFactory(), d2d_res_->GetDeviceContext()); hr = render_ctx_.CreateDeviceResources(d2d_res_->GetFactory(), d2d_res_->GetDeviceContext());
} }
return hr; return hr;
} }
@ -939,7 +937,8 @@ void Renderer::ResizeTarget(uint32_t width, uint32_t height)
{ {
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);
hr = d3d_res_->SetLogicalSize(output_size_);
hr = d3d_res_->SetLogicalSize(output_size_);
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
@ -949,7 +948,7 @@ void Renderer::ResizeTarget(uint32_t width, uint32_t height)
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
Resize(reinterpret_cast<const Size&>(GetRenderTarget()->GetSize())); render_ctx_.Resize(output_size_);
} }
win32::ThrowIfFailed(hr); win32::ThrowIfFailed(hr);

View File

@ -58,9 +58,7 @@ typedef ID3D11DeviceResources ID3DDeviceResources;
*/ */
class KGE_API Renderer class KGE_API Renderer
: public Singleton<Renderer> : public Singleton<Renderer>
, public RenderComponent
, public EventComponent , public EventComponent
, public RenderContext
{ {
friend Singleton<Renderer>; friend Singleton<Renderer>;
@ -201,6 +199,26 @@ public:
size_t dash_size, float dash_offset); size_t dash_size, float dash_offset);
public: public:
/// \~chinese
/// @brief 开始渲染
void BeginDraw();
/// \~chinese
/// @brief 结束渲染
void EndDraw();
/// \~chinese
/// @brief 清除绘制内容
void Clear();
/// \~chinese
/// @brief 将绘制内容呈现至窗口
void Present();
/// \~chinese
/// @brief 获取渲染上下文
RenderContext& GetContext();
/// \~chinese /// \~chinese
/// @brief »ñȡĿ±ê´°¿Ú /// @brief »ñȡĿ±ê´°¿Ú
WindowHandle GetTargetWindow() const; WindowHandle GetTargetWindow() const;
@ -222,10 +240,6 @@ public:
void DestroyComponent() override; void DestroyComponent() override;
void BeforeRender() override;
void AfterRender() override;
void HandleEvent(Event* evt) override; void HandleEvent(Event* evt) override;
private: private:
@ -238,14 +252,14 @@ private:
void ResizeTarget(uint32_t width, uint32_t height); void ResizeTarget(uint32_t width, uint32_t height);
private: private:
bool vsync_; bool vsync_;
WindowHandle target_window_; WindowHandle target_window_;
Color clear_color_; Color clear_color_;
Size output_size_; Size output_size_;
RenderContext render_ctx_;
ComPtr<ID2DDeviceResources> d2d_res_; ComPtr<ID2DDeviceResources> d2d_res_;
ComPtr<ID3DDeviceResources> d3d_res_; ComPtr<ID3DDeviceResources> d3d_res_;
ComPtr<ID2D1DrawingStateBlock> drawing_state_block_;
ComPtr<IFontCollectionLoader> font_collection_loader_; ComPtr<IFontCollectionLoader> font_collection_loader_;
ComPtr<IResourceFontFileLoader> res_font_file_loader_; ComPtr<IResourceFontFileLoader> res_font_file_loader_;
ComPtr<IResourceFontCollectionLoader> res_font_collection_loader_; ComPtr<IResourceFontCollectionLoader> res_font_collection_loader_;
@ -268,6 +282,11 @@ inline Color const& Renderer::GetClearColor() const
return clear_color_; return clear_color_;
} }
inline RenderContext& Renderer::GetContext()
{
return render_ctx_;
}
inline ID2DDeviceResources* Renderer::GetD2DDeviceResources() inline ID2DDeviceResources* Renderer::GetD2DDeviceResources()
{ {
KGE_ASSERT(d2d_res_); KGE_ASSERT(d2d_res_);