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;
|
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;
|
||||||
|
|
|
||||||
|
|
@ -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() };
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue