[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
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

View File

@ -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();

View File

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

View File

@ -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: ";
{

View File

@ -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)

View File

@ -234,7 +234,8 @@ HRESULT D2DDeviceResources::CreateDeviceResources(_In_ ComPtr<IDXGIDevice> dxgi_
// Create the Direct2D device object and a corresponding context.
ComPtr<ID2D1Device> 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<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))
{
@ -342,7 +344,8 @@ HRESULT D2DDeviceResources::CreateBitmapFromConverter(_Out_ ComPtr<ID2D1Bitmap>&
return E_UNEXPECTED;
ComPtr<ID2D1Bitmap> 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<IWICBitmapD
return E_UNEXPECTED;
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);
if (SUCCEEDED(hr))

View File

@ -42,11 +42,11 @@ HRESULT RenderContext::CreateDeviceResources(ComPtr<ID2D1Factory> 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<ID2D1Factory> factory, ComPt
Resize(reinterpret_cast<const Size&>(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<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;
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<uint32_t> 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<ID2D1Layer> 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
//

View File

@ -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<ITextRenderer> text_renderer_;
ComPtr<ID2D1RenderTarget> 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<ITextRenderer> text_renderer_;
ComPtr<ID2D1RenderTarget> render_target_;
ComPtr<ID2D1DrawingStateBlock> drawing_state_;
};
/// \~chinese
@ -296,8 +305,8 @@ inline RenderContext::Status const& RenderContext::GetStatus() const
inline ComPtr<ID2D1RenderTarget> RenderContext::GetRenderTarget() const
{
KGE_ASSERT(render_ctx_);
return render_ctx_;
KGE_ASSERT(render_target_);
return render_target_;
}
inline ComPtr<ITextRenderer> RenderContext::GetTextRenderer() const

View File

@ -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<float>(width);
output_size_.y = static_cast<float>(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<const Size&>(GetRenderTarget()->GetSize()));
render_ctx_.Resize(output_size_);
}
win32::ThrowIfFailed(hr);

View File

@ -58,9 +58,7 @@ typedef ID3D11DeviceResources ID3DDeviceResources;
*/
class KGE_API Renderer
: public Singleton<Renderer>
, public RenderComponent
, public EventComponent
, public RenderContext
{
friend Singleton<Renderer>;
@ -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<ID2DDeviceResources> d2d_res_;
ComPtr<ID3DDeviceResources> d3d_res_;
ComPtr<ID2D1DrawingStateBlock> drawing_state_block_;
ComPtr<IFontCollectionLoader> font_collection_loader_;
ComPtr<IResourceFontFileLoader> res_font_file_loader_;
ComPtr<IResourceFontCollectionLoader> 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_);