#include "NativeRendererInternal.h" namespace XCEngine::UI::Editor::Host { using namespace NativeRendererInternal; bool NativeRenderer::Render(const ::XCEngine::UI::UIDrawData& drawData) { if (!EnsureRenderTarget()) { if (m_lastRenderError.empty()) { m_lastRenderError = "EnsureRenderTarget failed."; } return false; } const bool rendered = RenderToTarget(*m_renderTarget.Get(), *m_solidBrush.Get(), drawData); const HRESULT hr = m_renderTarget->EndDraw(); if (hr == D2DERR_RECREATE_TARGET) { m_lastRenderError = HrToString("ID2D1HwndRenderTarget::EndDraw", hr); DiscardRenderTarget(); return false; } if (!rendered || FAILED(hr)) { m_lastRenderError = HrToString("ID2D1HwndRenderTarget::EndDraw", hr); return false; } m_lastRenderError.clear(); return true; } bool NativeRenderer::RenderToWindowRenderer(const ::XCEngine::UI::UIDrawData& drawData) { if (!EnsureWindowRendererInterop()) { if (m_lastRenderError.empty()) { m_lastRenderError = "Window renderer interop is not available."; } return false; } if (!m_windowInterop.HasBackBufferTargets() && !m_windowInterop.RebuildBackBufferTargets()) { if (m_lastRenderError.empty()) { m_lastRenderError = "Window renderer back buffer interop targets are unavailable."; } return false; } ID3D11On12Device* d3d11On12Device = m_windowInterop.GetD3D11On12Device(); ID3D11DeviceContext* d3d11DeviceContext = m_windowInterop.GetD3D11DeviceContext(); ID2D1DeviceContext* d2dDeviceContext = m_windowInterop.GetD2DDeviceContext(); ID2D1SolidColorBrush* interopBrush = m_windowInterop.GetInteropBrush(); if (d3d11On12Device == nullptr || d3d11DeviceContext == nullptr || d2dDeviceContext == nullptr || interopBrush == nullptr) { m_lastRenderError = "Window renderer interop resources are incomplete."; return false; } const std::uint32_t backBufferIndex = m_windowInterop.GetCurrentBackBufferIndex(); if (m_windowInterop.GetWrappedBackBufferResource(backBufferIndex) == nullptr || m_windowInterop.GetBackBufferTargetBitmap(backBufferIndex) == nullptr) { m_lastRenderError = "Back buffer interop target index is out of range."; return false; } if (!m_windowRenderer->PreparePresentSurface()) { m_lastRenderError = "Failed to prepare the D3D12 present surface: " + m_windowRenderer->GetLastError(); return false; } if (!m_windowRenderer->SubmitFrame(false)) { m_lastRenderError = "Failed to submit the D3D12 frame before UI composition."; return false; } if (!m_windowInterop.PrepareSourceTextures(drawData)) { ID3D11Resource* backBufferResource = m_windowInterop.GetWrappedBackBufferResource(backBufferIndex); if (backBufferResource != nullptr) { d3d11On12Device->AcquireWrappedResources(&backBufferResource, 1u); d3d11On12Device->ReleaseWrappedResources(&backBufferResource, 1u); } d3d11DeviceContext->Flush(); m_windowInterop.ClearSourceTextures(); const bool signaled = m_windowRenderer->SignalFrameCompletion(); ReleaseWindowRendererInterop(); if (!signaled) { m_lastRenderError = "Failed to signal D3D12 frame completion after interop preparation failed."; } return false; } std::vector acquiredResources = {}; m_windowInterop.BuildAcquiredResources(backBufferIndex, acquiredResources); if (acquiredResources.empty()) { m_lastRenderError = "No wrapped interop resources were prepared for UI composition."; return false; } d3d11On12Device->AcquireWrappedResources( acquiredResources.data(), static_cast(acquiredResources.size())); d2dDeviceContext->SetTarget(m_windowInterop.GetBackBufferTargetBitmap(backBufferIndex)); const bool rendered = RenderToTarget(*d2dDeviceContext, *interopBrush, drawData); const HRESULT hr = d2dDeviceContext->EndDraw(); d3d11On12Device->ReleaseWrappedResources( acquiredResources.data(), static_cast(acquiredResources.size())); d3d11DeviceContext->Flush(); d2dDeviceContext->SetTarget(nullptr); m_windowInterop.ClearSourceTextures(); if (!rendered || FAILED(hr)) { m_lastRenderError = FAILED(hr) ? HrToString("ID2D1DeviceContext::EndDraw", hr) : "RenderToTarget failed during D3D11On12 composition."; const bool signaled = m_windowRenderer->SignalFrameCompletion(); if (hr == D2DERR_RECREATE_TARGET) { ReleaseWindowRendererBackBufferTargets(); } else { ReleaseWindowRendererInterop(); } if (!signaled) { m_lastRenderError = "Failed to signal D3D12 frame completion after UI composition failed."; } return false; } if (!m_windowRenderer->SignalFrameCompletion()) { m_lastRenderError = "Failed to signal D3D12 frame completion after UI composition."; ReleaseWindowRendererInterop(); return false; } if (!m_windowRenderer->PresentFrame()) { m_lastRenderError = "Failed to present the D3D12 swap chain."; ReleaseWindowRendererInterop(); return false; } m_lastRenderError.clear(); return true; } } // namespace XCEngine::UI::Editor::Host