#pragma once #ifndef NOMINMAX #define NOMINMAX #endif #include "D3D12WindowRenderer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace XCEngine::UI::Editor::Host { class NativeRenderer : public ::XCEngine::UI::Editor::UIEditorTextMeasurer { public: bool Initialize(HWND hwnd); void Shutdown(); void SetDpiScale(float dpiScale); float GetDpiScale() const; void Resize(UINT width, UINT height); bool AttachWindowRenderer(D3D12WindowRenderer& windowRenderer); void DetachWindowRenderer(); void ReleaseWindowRendererBackBufferTargets(); bool RebuildWindowRendererBackBufferTargets(); bool HasAttachedWindowRenderer() const; bool Render(const ::XCEngine::UI::UIDrawData& drawData); bool RenderToWindowRenderer(const ::XCEngine::UI::UIDrawData& drawData); const std::string& GetLastRenderError() const; bool LoadTextureFromFile( const std::filesystem::path& path, ::XCEngine::UI::UITextureHandle& outTexture, std::string& outError); void ReleaseTexture(::XCEngine::UI::UITextureHandle& texture); float MeasureTextWidth( const ::XCEngine::UI::Editor::UIEditorTextMeasureRequest& request) const override; bool CaptureToPng( const ::XCEngine::UI::UIDrawData& drawData, UINT width, UINT height, const std::filesystem::path& outputPath, std::string& outError); private: struct NativeTextureResource { std::vector pixels = {}; Microsoft::WRL::ComPtr cachedBitmap = {}; const ID2D1RenderTarget* cachedTarget = nullptr; UINT width = 0u; UINT height = 0u; }; struct D3D12BackBufferInteropTarget { Microsoft::WRL::ComPtr wrappedResource = {}; Microsoft::WRL::ComPtr targetBitmap = {}; }; struct D3D12SourceTextureInteropResource { std::uintptr_t key = 0u; Microsoft::WRL::ComPtr wrappedResource = {}; Microsoft::WRL::ComPtr bitmap = {}; }; bool EnsureRenderTarget(); bool EnsureWindowRendererInterop(); bool EnsureWicFactory(std::string& outError); void DiscardRenderTarget(); bool CreateDeviceResources(); void ReleaseWindowRendererInterop(); bool RebuildBackBufferInteropTargets(); void ClearActiveInteropSourceTextures(); bool PrepareActiveInteropSourceTextures(const ::XCEngine::UI::UIDrawData& drawData); void InvalidateCachedTextureBitmaps(const ID2D1RenderTarget* renderTarget); bool RenderToTarget( ID2D1RenderTarget& renderTarget, ID2D1SolidColorBrush& solidBrush, const ::XCEngine::UI::UIDrawData& drawData); bool DecodeTextureFile( const std::filesystem::path& path, NativeTextureResource& outTexture, std::string& outError); bool ResolveTextureBitmap( ID2D1RenderTarget& renderTarget, NativeTextureResource& texture, Microsoft::WRL::ComPtr& outBitmap); bool ResolveInteropBitmap( const ::XCEngine::UI::UITextureHandle& texture, Microsoft::WRL::ComPtr& outBitmap) const; void RenderCommand( ID2D1RenderTarget& renderTarget, ID2D1SolidColorBrush& solidBrush, const ::XCEngine::UI::UIDrawCommand& command, std::vector& clipStack); IDWriteTextFormat* GetTextFormat(float fontSize) const; static D2D1_COLOR_F ToD2DColor(const ::XCEngine::UI::UIColor& color); static std::wstring Utf8ToWide(std::string_view text); HWND m_hwnd = nullptr; D3D12WindowRenderer* m_windowRenderer = nullptr; Microsoft::WRL::ComPtr m_d2dFactory; Microsoft::WRL::ComPtr m_dwriteFactory; Microsoft::WRL::ComPtr m_wicFactory; Microsoft::WRL::ComPtr m_d3d11Device; Microsoft::WRL::ComPtr m_d3d11DeviceContext; Microsoft::WRL::ComPtr m_d3d11On12Device; Microsoft::WRL::ComPtr m_d2dDevice; Microsoft::WRL::ComPtr m_d2dDeviceContext; Microsoft::WRL::ComPtr m_renderTarget; Microsoft::WRL::ComPtr m_solidBrush; Microsoft::WRL::ComPtr m_interopBrush; std::vector m_backBufferInteropTargets = {}; std::vector m_activeInteropSourceTextures = {}; std::unordered_map> m_activeInteropBitmaps; mutable std::unordered_map> m_textFormats; std::unordered_set m_liveTextures; std::string m_lastRenderError = {}; bool m_wicComInitialized = false; float m_dpiScale = 1.0f; }; } // namespace XCEngine::UI::Editor::Host