From 68441e07262c0ab3e2abddabea7c3d3c998a70e7 Mon Sep 17 00:00:00 2001 From: reuk Date: Mon, 12 Aug 2024 18:36:33 +0100 Subject: [PATCH] Direct2D: Refactor DeviceResources helper --- .../juce_Direct2DGraphicsContext_windows.cpp | 41 +++--- .../juce_Direct2DHwndContext_windows.cpp | 20 +-- .../native/juce_Direct2DResources_windows.cpp | 127 ++++++++++++++---- 3 files changed, 128 insertions(+), 60 deletions(-) diff --git a/modules/juce_graphics/native/juce_Direct2DGraphicsContext_windows.cpp b/modules/juce_graphics/native/juce_Direct2DGraphicsContext_windows.cpp index 8f715d0016..319df6aba3 100644 --- a/modules/juce_graphics/native/juce_Direct2DGraphicsContext_windows.cpp +++ b/modules/juce_graphics/native/juce_Direct2DGraphicsContext_windows.cpp @@ -553,24 +553,21 @@ protected: RectangleList paintAreas; DxgiAdapter::Ptr adapter; - Direct2DDeviceResources deviceResources; + std::optional deviceResources; std::vector> savedClientStates; virtual HRESULT prepare() { - if (! deviceResources.canPaint (adapter)) - { - if (auto hr = deviceResources.create (adapter); FAILED (hr)) - return hr; - } + if (! deviceResources.has_value()) + deviceResources = Direct2DDeviceResources::create (adapter); - return S_OK; + return deviceResources.has_value() ? S_OK : E_FAIL; } virtual void teardown() { - deviceResources.release(); + deviceResources.reset(); } virtual ComSmartPtr getDeviceContextTarget() const = 0; @@ -579,7 +576,7 @@ protected: virtual bool checkPaintReady() { - return deviceResources.canPaint (adapter); + return deviceResources.has_value(); } public: @@ -626,14 +623,14 @@ public: JUCE_TRACE_EVENT_INT_RECT_LIST (etw::startD2DFrame, etw::direct2dKeyword, owner.getFrameId(), paintAreas); // Init device context transform - resetTransform (deviceResources.deviceContext); + resetTransform (deviceResources->deviceContext); const auto effectiveDpi = USER_DEFAULT_SCREEN_DPI * dpiScale; - deviceResources.deviceContext->SetDpi (effectiveDpi, effectiveDpi); + deviceResources->deviceContext->SetDpi (effectiveDpi, effectiveDpi); // Start drawing - deviceResources.deviceContext->SetTarget (getDeviceContextTarget()); - deviceResources.deviceContext->BeginDraw(); + deviceResources->deviceContext->SetTarget (getDeviceContextTarget()); + deviceResources->deviceContext->BeginDraw(); // Init the save state stack and return the first saved state return pushFirstSavedState (paintBounds); @@ -651,8 +648,8 @@ public: JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (owner.metrics, endDrawDuration) JUCE_SCOPED_TRACE_EVENT_FRAME (etw::endDraw, etw::direct2dKeyword, owner.getFrameId()); - hr = deviceResources.deviceContext->EndDraw(); - deviceResources.deviceContext->SetTarget (nullptr); + hr = deviceResources->deviceContext->EndDraw(); + deviceResources->deviceContext->SetTarget (nullptr); } jassert (SUCCEEDED (hr)); @@ -678,9 +675,9 @@ public: savedClientStates.push_back (std::make_unique (owner, initialClipRegion, - deviceResources.colourBrush, + deviceResources->colourBrush, adapter, - deviceResources)); + *deviceResources)); return getCurrentSavedState(); } @@ -715,7 +712,7 @@ public: ComSmartPtr getDeviceContext() const noexcept { - return deviceResources.deviceContext; + return deviceResources->deviceContext; } const auto& getPaintAreas() const noexcept @@ -727,12 +724,12 @@ public: void setDeviceContextTransform (AffineTransform transform) { - setTransform (deviceResources.deviceContext, transform); + setTransform (deviceResources->deviceContext, transform); } void resetDeviceContextTransform() { - resetTransform (deviceResources.deviceContext); + resetTransform (deviceResources->deviceContext); } auto getDirect2DFactory() @@ -760,7 +757,7 @@ public: if (! owner.currentState->fillType.isColour()) return false; - auto* rectangleListSpriteBatch = deviceResources.rectangleListSpriteBatch.get(); + auto* rectangleListSpriteBatch = deviceResources->rectangleListSpriteBatch.get(); if (rectangleListSpriteBatch == nullptr) return false; @@ -826,7 +823,7 @@ public: owner.applyPendingClipList(); - auto deviceContext = deviceResources.deviceContext; + auto deviceContext = deviceResources->deviceContext; if (deviceContext == nullptr) return; diff --git a/modules/juce_graphics/native/juce_Direct2DHwndContext_windows.cpp b/modules/juce_graphics/native/juce_Direct2DHwndContext_windows.cpp index 689c211f04..8a5f434136 100644 --- a/modules/juce_graphics/native/juce_Direct2DHwndContext_windows.cpp +++ b/modules/juce_graphics/native/juce_Direct2DHwndContext_windows.cpp @@ -332,11 +332,11 @@ private: return E_FAIL; } - if (! deviceResources.canPaint (adapter)) - { - if (auto hr = deviceResources.create (adapter); FAILED (hr)) - return hr; - } + if (! deviceResources.has_value()) + deviceResources = Direct2DDeviceResources::create (adapter); + + if (! deviceResources.has_value()) + return E_FAIL; if (! hwnd || frameSize.isEmpty()) return E_FAIL; @@ -346,7 +346,7 @@ private: if (auto hr = swap.create (hwnd, frameSize, adapter); FAILED (hr)) return hr; - if (auto hr = swap.createBuffer (deviceResources.deviceContext); FAILED (hr)) + if (auto hr = swap.createBuffer (deviceResources->deviceContext); FAILED (hr)) return hr; } @@ -450,7 +450,7 @@ public: ComSmartPtr getDeviceContextTarget() const override { if (auto* p = presentation.getPresentation()) - return p->getPresentationBitmap (swap.getSize(), deviceResources.deviceContext); + return p->getPresentationBitmap (swap.getSize(), deviceResources->deviceContext); return {}; } @@ -478,7 +478,7 @@ public: // Resize/scale the swap chain prepare(); - if (auto deviceContext = deviceResources.deviceContext) + if (auto deviceContext = deviceResources->deviceContext) { ScopedMultithread scopedMultithread { directX->getD2DMultithread() }; @@ -630,7 +630,7 @@ public: Image createSnapshot() const { - if (frameSize.isEmpty() || deviceResources.deviceContext == nullptr || swap.buffer == nullptr) + if (frameSize.isEmpty() || deviceResources->deviceContext == nullptr || swap.buffer == nullptr) return {}; // Create the bitmap to receive the snapshot @@ -643,7 +643,7 @@ public: ComSmartPtr snapshot; - if (const auto hr = deviceResources.deviceContext->CreateBitmap (size, nullptr, 0, bitmapProperties, snapshot.resetAndGetPointerAddress()); FAILED (hr)) + if (const auto hr = deviceResources->deviceContext->CreateBitmap (size, nullptr, 0, bitmapProperties, snapshot.resetAndGetPointerAddress()); FAILED (hr)) return {}; const ScopedMultithread scope { directX->getD2DMultithread() }; diff --git a/modules/juce_graphics/native/juce_Direct2DResources_windows.cpp b/modules/juce_graphics/native/juce_Direct2DResources_windows.cpp index f06ba87fee..58e7091dcf 100644 --- a/modules/juce_graphics/native/juce_Direct2DResources_windows.cpp +++ b/modules/juce_graphics/native/juce_Direct2DResources_windows.cpp @@ -254,45 +254,113 @@ private: class Direct2DDeviceResources { public: - Direct2DDeviceResources() = default; - - // Create a Direct2D device context for a DXGI adapter - HRESULT create (DxgiAdapter::Ptr adapter) + static DxgiAdapter::Ptr findAdapter (const DxgiAdapters& adapters, ID2D1Bitmap1* bitmap) { - jassert (adapter); + if (bitmap == nullptr) + return {}; - if (deviceContext == nullptr) - deviceContext = Direct2DDeviceContext::create (adapter); + ComSmartPtr surface; + bitmap->GetSurface (surface.resetAndGetPointerAddress()); - if (colourBrush == nullptr) + if (surface == nullptr) + return {}; + + ComSmartPtr device; + JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wlanguage-extension-token") + surface->GetDevice (__uuidof (device), (void**) device.resetAndGetPointerAddress()); + JUCE_END_IGNORE_WARNINGS_GCC_LIKE + + return findAdapter (adapters, device); + } + + static DxgiAdapter::Ptr findAdapter (const DxgiAdapters& dxgiAdapters, IDXGIDevice* dxgiDevice) + { + if (dxgiDevice == nullptr) + return {}; + + ComSmartPtr adapter; + dxgiDevice->GetAdapter (adapter.resetAndGetPointerAddress()); + + if (adapter == nullptr) + return {}; + + ComSmartPtr adapter1; + adapter.QueryInterface (adapter1); + + if (adapter1 == nullptr) + return {}; + + const auto adapterLuid = getLUID (adapter1); + + const auto& adapters = dxgiAdapters.getAdapterArray(); + + const auto it = std::find_if (adapters.begin(), adapters.end(), [&] (DxgiAdapter::Ptr ptr) { - if (const auto hr = deviceContext->CreateSolidColorBrush (D2D1::ColorF (0.0f, 0.0f, 0.0f, 1.0f), - colourBrush.resetAndGetPointerAddress()); + const auto tie = [] (const LUID& x) { return std::tie (x.LowPart, x.HighPart); }; + + const auto thisLuid = getLUID (ptr->dxgiAdapter); + return tie (thisLuid) == tie (adapterLuid); + }); + + if (it == adapters.end()) + return {}; + + return *it; + } + + static DxgiAdapter::Ptr findAdapter (const DxgiAdapters& dxgiAdapters, ID2D1DeviceContext1* context) + { + if (context == nullptr) + return {}; + + ComSmartPtr device; + context->GetDevice (device.resetAndGetPointerAddress()); + + if (device == nullptr) + return {}; + + ComSmartPtr dxgiDevice; + device.QueryInterface (dxgiDevice); + + return findAdapter (dxgiAdapters, dxgiDevice); + } + + static LUID getLUID (ComSmartPtr adapter) + { + DXGI_ADAPTER_DESC1 desc{}; + adapter->GetDesc1 (&desc); + return desc.AdapterLuid; + } + + static std::optional create (DxgiAdapter::Ptr adapter) + { + return create (Direct2DDeviceContext::create (adapter)); + } + + static std::optional create (ComSmartPtr context) + { + if (context == nullptr) + return {}; + + Direct2DDeviceResources result; + result.deviceContext = context; + + if (const auto hr = result.deviceContext->CreateSolidColorBrush (D2D1::ColorF (0.0f, 0.0f, 0.0f, 1.0f), + result.colourBrush.resetAndGetPointerAddress()); FAILED (hr)) - { - jassertfalse; - return hr; - } + { + jassertfalse; + return {}; } - if (rectangleListSpriteBatch == nullptr) - rectangleListSpriteBatch = std::make_unique(); + result.rectangleListSpriteBatch = std::make_unique(); - return S_OK; + return result; } - void release() + DxgiAdapter::Ptr findAdapter (const DxgiAdapters& adapters) const { - rectangleListSpriteBatch = nullptr; - linearGradientCache = {}; - radialGradientCache = {}; - colourBrush = nullptr; - deviceContext = nullptr; - } - - bool canPaint (DxgiAdapter::Ptr adapter) const - { - return adapter->direct2DDevice != nullptr && deviceContext != nullptr && colourBrush != nullptr; + return findAdapter (adapters, deviceContext); } ComSmartPtr deviceContext; @@ -300,6 +368,9 @@ public: LinearGradientCache linearGradientCache; RadialGradientCache radialGradientCache; std::unique_ptr rectangleListSpriteBatch; + +private: + Direct2DDeviceResources() = default; }; class SwapChain