1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

Direct2D: Refactor DeviceResources helper

This commit is contained in:
reuk 2024-08-12 18:36:33 +01:00
parent 58c267106f
commit 68441e0726
No known key found for this signature in database
GPG key ID: FCB43929F012EE5C
3 changed files with 128 additions and 60 deletions

View file

@ -553,24 +553,21 @@ protected:
RectangleList<int> paintAreas; RectangleList<int> paintAreas;
DxgiAdapter::Ptr adapter; DxgiAdapter::Ptr adapter;
Direct2DDeviceResources deviceResources; std::optional<Direct2DDeviceResources> deviceResources;
std::vector<std::unique_ptr<Direct2DGraphicsContext::SavedState>> savedClientStates; std::vector<std::unique_ptr<Direct2DGraphicsContext::SavedState>> savedClientStates;
virtual HRESULT prepare() virtual HRESULT prepare()
{ {
if (! deviceResources.canPaint (adapter)) if (! deviceResources.has_value())
{ deviceResources = Direct2DDeviceResources::create (adapter);
if (auto hr = deviceResources.create (adapter); FAILED (hr))
return hr;
}
return S_OK; return deviceResources.has_value() ? S_OK : E_FAIL;
} }
virtual void teardown() virtual void teardown()
{ {
deviceResources.release(); deviceResources.reset();
} }
virtual ComSmartPtr<ID2D1Image> getDeviceContextTarget() const = 0; virtual ComSmartPtr<ID2D1Image> getDeviceContextTarget() const = 0;
@ -579,7 +576,7 @@ protected:
virtual bool checkPaintReady() virtual bool checkPaintReady()
{ {
return deviceResources.canPaint (adapter); return deviceResources.has_value();
} }
public: public:
@ -626,14 +623,14 @@ public:
JUCE_TRACE_EVENT_INT_RECT_LIST (etw::startD2DFrame, etw::direct2dKeyword, owner.getFrameId(), paintAreas); JUCE_TRACE_EVENT_INT_RECT_LIST (etw::startD2DFrame, etw::direct2dKeyword, owner.getFrameId(), paintAreas);
// Init device context transform // Init device context transform
resetTransform (deviceResources.deviceContext); resetTransform (deviceResources->deviceContext);
const auto effectiveDpi = USER_DEFAULT_SCREEN_DPI * dpiScale; const auto effectiveDpi = USER_DEFAULT_SCREEN_DPI * dpiScale;
deviceResources.deviceContext->SetDpi (effectiveDpi, effectiveDpi); deviceResources->deviceContext->SetDpi (effectiveDpi, effectiveDpi);
// Start drawing // Start drawing
deviceResources.deviceContext->SetTarget (getDeviceContextTarget()); deviceResources->deviceContext->SetTarget (getDeviceContextTarget());
deviceResources.deviceContext->BeginDraw(); deviceResources->deviceContext->BeginDraw();
// Init the save state stack and return the first saved state // Init the save state stack and return the first saved state
return pushFirstSavedState (paintBounds); return pushFirstSavedState (paintBounds);
@ -651,8 +648,8 @@ public:
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (owner.metrics, endDrawDuration) JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (owner.metrics, endDrawDuration)
JUCE_SCOPED_TRACE_EVENT_FRAME (etw::endDraw, etw::direct2dKeyword, owner.getFrameId()); JUCE_SCOPED_TRACE_EVENT_FRAME (etw::endDraw, etw::direct2dKeyword, owner.getFrameId());
hr = deviceResources.deviceContext->EndDraw(); hr = deviceResources->deviceContext->EndDraw();
deviceResources.deviceContext->SetTarget (nullptr); deviceResources->deviceContext->SetTarget (nullptr);
} }
jassert (SUCCEEDED (hr)); jassert (SUCCEEDED (hr));
@ -678,9 +675,9 @@ public:
savedClientStates.push_back (std::make_unique<SavedState> (owner, savedClientStates.push_back (std::make_unique<SavedState> (owner,
initialClipRegion, initialClipRegion,
deviceResources.colourBrush, deviceResources->colourBrush,
adapter, adapter,
deviceResources)); *deviceResources));
return getCurrentSavedState(); return getCurrentSavedState();
} }
@ -715,7 +712,7 @@ public:
ComSmartPtr<ID2D1DeviceContext1> getDeviceContext() const noexcept ComSmartPtr<ID2D1DeviceContext1> getDeviceContext() const noexcept
{ {
return deviceResources.deviceContext; return deviceResources->deviceContext;
} }
const auto& getPaintAreas() const noexcept const auto& getPaintAreas() const noexcept
@ -727,12 +724,12 @@ public:
void setDeviceContextTransform (AffineTransform transform) void setDeviceContextTransform (AffineTransform transform)
{ {
setTransform (deviceResources.deviceContext, transform); setTransform (deviceResources->deviceContext, transform);
} }
void resetDeviceContextTransform() void resetDeviceContextTransform()
{ {
resetTransform (deviceResources.deviceContext); resetTransform (deviceResources->deviceContext);
} }
auto getDirect2DFactory() auto getDirect2DFactory()
@ -760,7 +757,7 @@ public:
if (! owner.currentState->fillType.isColour()) if (! owner.currentState->fillType.isColour())
return false; return false;
auto* rectangleListSpriteBatch = deviceResources.rectangleListSpriteBatch.get(); auto* rectangleListSpriteBatch = deviceResources->rectangleListSpriteBatch.get();
if (rectangleListSpriteBatch == nullptr) if (rectangleListSpriteBatch == nullptr)
return false; return false;
@ -826,7 +823,7 @@ public:
owner.applyPendingClipList(); owner.applyPendingClipList();
auto deviceContext = deviceResources.deviceContext; auto deviceContext = deviceResources->deviceContext;
if (deviceContext == nullptr) if (deviceContext == nullptr)
return; return;

View file

@ -332,11 +332,11 @@ private:
return E_FAIL; return E_FAIL;
} }
if (! deviceResources.canPaint (adapter)) if (! deviceResources.has_value())
{ deviceResources = Direct2DDeviceResources::create (adapter);
if (auto hr = deviceResources.create (adapter); FAILED (hr))
return hr; if (! deviceResources.has_value())
} return E_FAIL;
if (! hwnd || frameSize.isEmpty()) if (! hwnd || frameSize.isEmpty())
return E_FAIL; return E_FAIL;
@ -346,7 +346,7 @@ private:
if (auto hr = swap.create (hwnd, frameSize, adapter); FAILED (hr)) if (auto hr = swap.create (hwnd, frameSize, adapter); FAILED (hr))
return hr; return hr;
if (auto hr = swap.createBuffer (deviceResources.deviceContext); FAILED (hr)) if (auto hr = swap.createBuffer (deviceResources->deviceContext); FAILED (hr))
return hr; return hr;
} }
@ -450,7 +450,7 @@ public:
ComSmartPtr<ID2D1Image> getDeviceContextTarget() const override ComSmartPtr<ID2D1Image> getDeviceContextTarget() const override
{ {
if (auto* p = presentation.getPresentation()) if (auto* p = presentation.getPresentation())
return p->getPresentationBitmap (swap.getSize(), deviceResources.deviceContext); return p->getPresentationBitmap (swap.getSize(), deviceResources->deviceContext);
return {}; return {};
} }
@ -478,7 +478,7 @@ public:
// Resize/scale the swap chain // Resize/scale the swap chain
prepare(); prepare();
if (auto deviceContext = deviceResources.deviceContext) if (auto deviceContext = deviceResources->deviceContext)
{ {
ScopedMultithread scopedMultithread { directX->getD2DMultithread() }; ScopedMultithread scopedMultithread { directX->getD2DMultithread() };
@ -630,7 +630,7 @@ public:
Image createSnapshot() const Image createSnapshot() const
{ {
if (frameSize.isEmpty() || deviceResources.deviceContext == nullptr || swap.buffer == nullptr) if (frameSize.isEmpty() || deviceResources->deviceContext == nullptr || swap.buffer == nullptr)
return {}; return {};
// Create the bitmap to receive the snapshot // Create the bitmap to receive the snapshot
@ -643,7 +643,7 @@ public:
ComSmartPtr<ID2D1Bitmap1> snapshot; ComSmartPtr<ID2D1Bitmap1> 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 {}; return {};
const ScopedMultithread scope { directX->getD2DMultithread() }; const ScopedMultithread scope { directX->getD2DMultithread() };

View file

@ -254,45 +254,113 @@ private:
class Direct2DDeviceResources class Direct2DDeviceResources
{ {
public: public:
Direct2DDeviceResources() = default; static DxgiAdapter::Ptr findAdapter (const DxgiAdapters& adapters, ID2D1Bitmap1* bitmap)
// Create a Direct2D device context for a DXGI adapter
HRESULT create (DxgiAdapter::Ptr adapter)
{ {
jassert (adapter); if (bitmap == nullptr)
return {};
if (deviceContext == nullptr) ComSmartPtr<IDXGISurface> surface;
deviceContext = Direct2DDeviceContext::create (adapter); bitmap->GetSurface (surface.resetAndGetPointerAddress());
if (colourBrush == nullptr) if (surface == nullptr)
return {};
ComSmartPtr<IDXGIDevice> 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<IDXGIAdapter> adapter;
dxgiDevice->GetAdapter (adapter.resetAndGetPointerAddress());
if (adapter == nullptr)
return {};
ComSmartPtr<IDXGIAdapter1> 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), const auto tie = [] (const LUID& x) { return std::tie (x.LowPart, x.HighPart); };
colourBrush.resetAndGetPointerAddress());
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<ID2D1Device> device;
context->GetDevice (device.resetAndGetPointerAddress());
if (device == nullptr)
return {};
ComSmartPtr<IDXGIDevice> dxgiDevice;
device.QueryInterface (dxgiDevice);
return findAdapter (dxgiAdapters, dxgiDevice);
}
static LUID getLUID (ComSmartPtr<IDXGIAdapter1> adapter)
{
DXGI_ADAPTER_DESC1 desc{};
adapter->GetDesc1 (&desc);
return desc.AdapterLuid;
}
static std::optional<Direct2DDeviceResources> create (DxgiAdapter::Ptr adapter)
{
return create (Direct2DDeviceContext::create (adapter));
}
static std::optional<Direct2DDeviceResources> create (ComSmartPtr<ID2D1DeviceContext1> 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)) FAILED (hr))
{ {
jassertfalse; jassertfalse;
return hr; return {};
}
} }
if (rectangleListSpriteBatch == nullptr) result.rectangleListSpriteBatch = std::make_unique<RectangleListSpriteBatch>();
rectangleListSpriteBatch = std::make_unique<RectangleListSpriteBatch>();
return S_OK; return result;
} }
void release() DxgiAdapter::Ptr findAdapter (const DxgiAdapters& adapters) const
{ {
rectangleListSpriteBatch = nullptr; return findAdapter (adapters, deviceContext);
linearGradientCache = {};
radialGradientCache = {};
colourBrush = nullptr;
deviceContext = nullptr;
}
bool canPaint (DxgiAdapter::Ptr adapter) const
{
return adapter->direct2DDevice != nullptr && deviceContext != nullptr && colourBrush != nullptr;
} }
ComSmartPtr<ID2D1DeviceContext1> deviceContext; ComSmartPtr<ID2D1DeviceContext1> deviceContext;
@ -300,6 +368,9 @@ public:
LinearGradientCache linearGradientCache; LinearGradientCache linearGradientCache;
RadialGradientCache radialGradientCache; RadialGradientCache radialGradientCache;
std::unique_ptr<RectangleListSpriteBatch> rectangleListSpriteBatch; std::unique_ptr<RectangleListSpriteBatch> rectangleListSpriteBatch;
private:
Direct2DDeviceResources() = default;
}; };
class SwapChain class SwapChain