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

Direct2D: Correctly recreate ID2D1DeviceContext when moving transparent windows between devices

This commit is contained in:
reuk 2024-08-29 16:14:51 +01:00
parent 14d52769dc
commit 25e2fa44ff
No known key found for this signature in database
GPG key ID: FCB43929F012EE5C
4 changed files with 73 additions and 67 deletions

View file

@ -255,9 +255,11 @@ public:
// Constructor for first stack entry
SavedState (Direct2DGraphicsContext& ownerIn,
Rectangle<int> frameSizeIn,
ComSmartPtr<ID2D1DeviceContext1> deviceContext,
ComSmartPtr<ID2D1SolidColorBrush>& colourBrushIn,
Direct2DDeviceResources& deviceResourcesIn)
: owner (ownerIn),
context (deviceContext),
currentBrush (colourBrushIn),
colourBrush (colourBrushIn),
deviceResources (deviceResourcesIn),
@ -267,7 +269,7 @@ public:
void pushLayer (const D2D1_LAYER_PARAMETERS1& layerParameters)
{
layers.push (deviceResources.deviceContext, layerParameters);
layers.push (context, layerParameters);
}
void pushGeometryClipLayer (ComSmartPtr<ID2D1Geometry> geometry)
@ -290,7 +292,7 @@ public:
{
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (owner.metrics, pushAliasedAxisAlignedLayerTime)
layers.push (deviceResources.deviceContext, r);
layers.push (context, r);
}
void pushTransparencyLayer (float opacity)
@ -301,12 +303,12 @@ public:
void popLayers()
{
while (! layers.isEmpty())
layers.popOne (deviceResources.deviceContext);
layers.popOne (context);
}
void popTopLayer()
{
layers.popOne (deviceResources.deviceContext);
layers.popOne (context);
}
void setFont (const Font& newFont)
@ -349,17 +351,17 @@ public:
JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (Direct2DMetricsHub::getInstance()->imageContextMetrics, createBitmapTime);
return Direct2DBitmap::toBitmap (fillType.image, deviceResources.deviceContext, Image::ARGB);
return Direct2DBitmap::toBitmap (fillType.image, context, Image::ARGB);
}();
if (d2d1Bitmap != nullptr)
{
D2D1_BRUSH_PROPERTIES brushProps { fillType.getOpacity(), D2DUtilities::transformToMatrix (fillType.transform) };
auto bmProps = D2D1::BitmapBrushProperties (D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_WRAP);
if (const auto hr = deviceResources.deviceContext->CreateBitmapBrush (d2d1Bitmap,
bmProps,
brushProps,
bitmapBrush.resetAndGetPointerAddress()); SUCCEEDED (hr))
if (const auto hr = context->CreateBitmapBrush (d2d1Bitmap,
bmProps,
brushProps,
bitmapBrush.resetAndGetPointerAddress()); SUCCEEDED (hr))
{
currentBrush = bitmapBrush;
}
@ -369,12 +371,12 @@ public:
{
if (fillType.gradient->isRadial)
{
radialGradient = deviceResources.radialGradientCache.get (*fillType.gradient, deviceResources.deviceContext, owner.metrics.get());
radialGradient = deviceResources.radialGradientCache.get (*fillType.gradient, context, owner.metrics.get());
currentBrush = radialGradient;
}
else
{
linearGradient = deviceResources.linearGradientCache.get (*fillType.gradient, deviceResources.deviceContext, owner.metrics.get());
linearGradient = deviceResources.linearGradientCache.get (*fillType.gradient, context, owner.metrics.get());
currentBrush = linearGradient;
}
}
@ -509,7 +511,8 @@ public:
Direct2DGraphicsContext& owner;
ComSmartPtr<ID2D1Brush> currentBrush = nullptr;
ComSmartPtr<ID2D1DeviceContext1> context;
ComSmartPtr<ID2D1Brush> currentBrush;
ComSmartPtr<ID2D1SolidColorBrush>& colourBrush; // reference to shared colour brush
ComSmartPtr<ID2D1BitmapBrush> bitmapBrush;
ComSmartPtr<ID2D1LinearGradientBrush> linearGradient;
@ -520,7 +523,7 @@ public:
Direct2DDeviceResources& deviceResources;
RectangleList<float> deviceSpaceClipList;
Font font { FontOptions {} };
Font font { FontOptions{} };
FillType fillType;
@ -552,12 +555,12 @@ protected:
std::vector<std::unique_ptr<Direct2DGraphicsContext::SavedState>> savedClientStates;
virtual HRESULT prepare()
virtual bool prepare()
{
if (! deviceResources.has_value())
deviceResources = Direct2DDeviceResources::create (directX->adapters.getDefaultAdapter());
deviceResources = Direct2DDeviceResources::create (getDeviceContext());
return deviceResources.has_value() ? S_OK : E_FAIL;
return deviceResources.has_value();
}
virtual void teardown()
@ -565,8 +568,6 @@ protected:
deviceResources.reset();
}
virtual ComSmartPtr<ID2D1Image> getDeviceContextTarget() const = 0;
virtual bool checkPaintReady()
{
return deviceResources.has_value();
@ -607,15 +608,17 @@ public:
JUCE_TRACE_EVENT_INT_RECT_LIST (etw::startD2DFrame, etw::direct2dKeyword, owner.getFrameId(), paintAreas);
const auto deviceContext = getDeviceContext();
// Init device context transform
resetTransform (deviceResources->deviceContext);
resetTransform (deviceContext);
const auto effectiveDpi = USER_DEFAULT_SCREEN_DPI * dpiScale;
deviceResources->deviceContext->SetDpi (effectiveDpi, effectiveDpi);
deviceContext->SetDpi (effectiveDpi, effectiveDpi);
// Start drawing
deviceResources->deviceContext->SetTarget (getDeviceContextTarget());
deviceResources->deviceContext->BeginDraw();
deviceContext->SetTarget (getDeviceContextTarget());
deviceContext->BeginDraw();
// Init the save state stack and return the first saved state
return pushFirstSavedState (paintBounds);
@ -633,8 +636,9 @@ 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);
const auto deviceContext = getDeviceContext();
hr = deviceContext->EndDraw();
deviceContext->SetTarget (nullptr);
}
jassert (SUCCEEDED (hr));
@ -660,6 +664,7 @@ public:
savedClientStates.push_back (std::make_unique<SavedState> (owner,
initialClipRegion,
getDeviceContext(),
deviceResources->colourBrush,
*deviceResources));
@ -689,22 +694,19 @@ public:
popSavedState();
}
ComSmartPtr<ID2D1DeviceContext1> getDeviceContext() const noexcept
{
return deviceResources->deviceContext;
}
virtual RectangleList<int> getPaintAreas() const = 0;
virtual Rectangle<int> getFrameSize() const = 0;
virtual ComSmartPtr<ID2D1DeviceContext1> getDeviceContext() const = 0;
virtual ComSmartPtr<ID2D1Image> getDeviceContextTarget() const = 0;
void setDeviceContextTransform (AffineTransform transform)
{
setTransform (deviceResources->deviceContext, transform);
setTransform (getDeviceContext(), transform);
}
void resetDeviceContextTransform()
{
resetTransform (deviceResources->deviceContext);
resetTransform (getDeviceContext());
}
auto getDirect2DFactory()
@ -737,7 +739,7 @@ public:
if (rectangleListSpriteBatch == nullptr)
return false;
auto deviceContext = getDeviceContext();
const auto deviceContext = getDeviceContext();
if (deviceContext == nullptr)
return false;
@ -798,7 +800,7 @@ public:
owner.applyPendingClipList();
auto deviceContext = deviceResources->deviceContext;
auto deviceContext = getDeviceContext();
if (deviceContext == nullptr)
return;
@ -838,10 +840,7 @@ private:
DxgiAdapter::Ptr findAdapter() const
{
if (! deviceResources.has_value())
return {};
return deviceResources->findAdapter (directX->adapters);
return Direct2DDeviceResources::findAdapter (directX->adapters, getDeviceContext());
}
void adapterCreated (DxgiAdapter::Ptr newAdapter) override