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:
parent
58c267106f
commit
68441e0726
3 changed files with 128 additions and 60 deletions
|
|
@ -553,24 +553,21 @@ protected:
|
|||
RectangleList<int> paintAreas;
|
||||
|
||||
DxgiAdapter::Ptr adapter;
|
||||
Direct2DDeviceResources deviceResources;
|
||||
std::optional<Direct2DDeviceResources> deviceResources;
|
||||
|
||||
std::vector<std::unique_ptr<Direct2DGraphicsContext::SavedState>> 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<ID2D1Image> 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<SavedState> (owner,
|
||||
initialClipRegion,
|
||||
deviceResources.colourBrush,
|
||||
deviceResources->colourBrush,
|
||||
adapter,
|
||||
deviceResources));
|
||||
*deviceResources));
|
||||
|
||||
return getCurrentSavedState();
|
||||
}
|
||||
|
|
@ -715,7 +712,7 @@ public:
|
|||
|
||||
ComSmartPtr<ID2D1DeviceContext1> 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;
|
||||
|
|
|
|||
|
|
@ -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<ID2D1Image> 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<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 {};
|
||||
|
||||
const ScopedMultithread scope { directX->getD2DMultithread() };
|
||||
|
|
|
|||
|
|
@ -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<IDXGISurface> surface;
|
||||
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),
|
||||
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<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))
|
||||
{
|
||||
jassertfalse;
|
||||
return hr;
|
||||
}
|
||||
{
|
||||
jassertfalse;
|
||||
return {};
|
||||
}
|
||||
|
||||
if (rectangleListSpriteBatch == nullptr)
|
||||
rectangleListSpriteBatch = std::make_unique<RectangleListSpriteBatch>();
|
||||
result.rectangleListSpriteBatch = std::make_unique<RectangleListSpriteBatch>();
|
||||
|
||||
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<ID2D1DeviceContext1> deviceContext;
|
||||
|
|
@ -300,6 +368,9 @@ public:
|
|||
LinearGradientCache linearGradientCache;
|
||||
RadialGradientCache radialGradientCache;
|
||||
std::unique_ptr<RectangleListSpriteBatch> rectangleListSpriteBatch;
|
||||
|
||||
private:
|
||||
Direct2DDeviceResources() = default;
|
||||
};
|
||||
|
||||
class SwapChain
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue