#include "XCUIBackend/NativeWindowUICompositor.h" #include #include #include #include #include #include namespace XCEngine { namespace Editor { namespace XCUIBackend { namespace { bool PrepareSwapChainRender( ::XCEngine::Editor::Platform::D3D12WindowRenderer& windowRenderer, const float clearColor[4], ::XCEngine::Rendering::RenderContext& outRenderContext, const ::XCEngine::Rendering::RenderSurface*& outRenderSurface, ::XCEngine::RHI::RHIResourceView*& outRenderTargetView) { outRenderContext = windowRenderer.GetRenderContext(); outRenderSurface = windowRenderer.GetCurrentRenderSurface(); outRenderTargetView = nullptr; if (!outRenderContext.IsValid() || outRenderSurface == nullptr || outRenderContext.commandList == nullptr || windowRenderer.GetSwapChain() == nullptr) { return false; } const auto& colorAttachments = outRenderSurface->GetColorAttachments(); if (colorAttachments.empty() || colorAttachments[0] == nullptr) { return false; } outRenderTargetView = colorAttachments[0]; outRenderContext.commandList->TransitionBarrier( outRenderTargetView, ::XCEngine::RHI::ResourceStates::Present, ::XCEngine::RHI::ResourceStates::RenderTarget); outRenderContext.commandList->SetRenderTargets(1, &outRenderTargetView, nullptr); outRenderContext.commandList->ClearRenderTarget(outRenderTargetView, clearColor); return true; } void RebindSwapChainRenderTarget( ::XCEngine::Rendering::RenderContext& renderContext, ::XCEngine::RHI::RHIResourceView* renderTargetView) { if (renderContext.commandList == nullptr || renderTargetView == nullptr) { return; } renderContext.commandList->SetRenderTargets(1, &renderTargetView, nullptr); } void PresentSwapChainRender( ::XCEngine::Editor::Platform::D3D12WindowRenderer& windowRenderer, ::XCEngine::Rendering::RenderContext& renderContext, ::XCEngine::RHI::RHIResourceView* renderTargetView) { if (renderContext.commandList == nullptr || renderContext.commandQueue == nullptr || renderTargetView == nullptr || windowRenderer.GetSwapChain() == nullptr) { return; } renderContext.commandList->TransitionBarrier( renderTargetView, ::XCEngine::RHI::ResourceStates::RenderTarget, ::XCEngine::RHI::ResourceStates::Present); renderContext.commandList->Close(); void* commandLists[] = { renderContext.commandList }; renderContext.commandQueue->ExecuteCommandLists(1, commandLists); windowRenderer.GetSwapChain()->Present(1, 0); } } // namespace bool NativeWindowUICompositor::Initialize( HWND hwnd, ::XCEngine::Editor::Platform::D3D12WindowRenderer& windowRenderer, const ConfigureFontsCallback& configureFonts) { (void)configureFonts; m_hwnd = hwnd; m_windowRenderer = hwnd != nullptr ? &windowRenderer : nullptr; m_renderBackend.Shutdown(); m_renderBackend.ResetStats(); m_pendingRenderPacket.Clear(); m_lastPresentStats = {}; return m_windowRenderer != nullptr; } void NativeWindowUICompositor::Shutdown() { m_renderBackend.Shutdown(); m_pendingRenderPacket.Clear(); m_lastPresentStats = {}; m_windowRenderer = nullptr; m_hwnd = nullptr; } bool NativeWindowUICompositor::HandleWindowMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { (void)hwnd; (void)message; (void)wParam; (void)lParam; return false; } void NativeWindowUICompositor::RenderFrame( const float clearColor[4], const UiRenderCallback& renderUi, const RenderCallback& beforeUiRender, const RenderCallback& afterUiRender) { (void)renderUi; m_lastPresentStats = {}; if (m_windowRenderer == nullptr) { return; } ::XCEngine::Rendering::RenderContext renderContext = {}; const ::XCEngine::Rendering::RenderSurface* renderSurface = nullptr; ::XCEngine::RHI::RHIResourceView* renderTargetView = nullptr; if (!PrepareSwapChainRender( *m_windowRenderer, clearColor, renderContext, renderSurface, renderTargetView)) { return; } if (beforeUiRender) { beforeUiRender(renderContext, *renderSurface); RebindSwapChainRenderTarget(renderContext, renderTargetView); } m_lastPresentStats.hadPendingPacket = m_pendingRenderPacket.HasDrawData(); m_lastPresentStats.submittedDrawListCount = m_pendingRenderPacket.drawData.GetDrawListCount(); m_lastPresentStats.submittedCommandCount = m_pendingRenderPacket.drawData.GetTotalCommandCount(); if (m_pendingRenderPacket.textAtlasProvider != nullptr) { m_renderBackend.SetTextAtlasProvider(m_pendingRenderPacket.textAtlasProvider); } else { m_renderBackend.SetTextAtlasProvider(nullptr); } if (m_lastPresentStats.hadPendingPacket) { m_lastPresentStats.renderedNativeOverlay = m_renderBackend.Render(renderContext, *renderSurface, m_pendingRenderPacket.drawData); m_lastPresentStats.overlayStats = m_renderBackend.GetLastOverlayStats(); } else { m_renderBackend.ResetStats(); m_lastPresentStats.overlayStats = m_renderBackend.GetLastOverlayStats(); } m_pendingRenderPacket.Clear(); if (afterUiRender) { RebindSwapChainRenderTarget(renderContext, renderTargetView); afterUiRender(renderContext, *renderSurface); } PresentSwapChainRender(*m_windowRenderer, renderContext, renderTargetView); } bool NativeWindowUICompositor::CreateTextureDescriptor( ::XCEngine::RHI::RHIDevice* device, ::XCEngine::RHI::RHITexture* texture, UITextureRegistration& outRegistration) { (void)device; (void)texture; outRegistration = {}; return false; } void NativeWindowUICompositor::FreeTextureDescriptor(const UITextureRegistration& registration) { (void)registration; } void NativeWindowUICompositor::SubmitRenderPacket(const XCUINativeWindowRenderPacket& packet) { m_pendingRenderPacket = packet; } void NativeWindowUICompositor::SubmitRenderPacket( const ::XCEngine::UI::UIDrawData& drawData, const IXCUITextAtlasProvider* textAtlasProvider) { m_pendingRenderPacket.drawData = drawData; m_pendingRenderPacket.textAtlasProvider = textAtlasProvider; } void NativeWindowUICompositor::ClearPendingRenderPacket() { m_pendingRenderPacket.Clear(); } bool NativeWindowUICompositor::HasPendingRenderPacket() const { return m_pendingRenderPacket.HasDrawData(); } const XCUINativeWindowRenderPacket& NativeWindowUICompositor::GetPendingRenderPacket() const { return m_pendingRenderPacket; } const XCUINativeWindowPresentStats& NativeWindowUICompositor::GetLastPresentStats() const { return m_lastPresentStats; } std::unique_ptr CreateNativeWindowUICompositor() { return std::make_unique(); } } // namespace XCUIBackend } // namespace Editor } // namespace XCEngine