diff --git a/examples/DemoRunner/Builds/Android/app/CMakeLists.txt b/examples/DemoRunner/Builds/Android/app/CMakeLists.txt
index 17fdff48fb..029f667b62 100644
--- a/examples/DemoRunner/Builds/Android/app/CMakeLists.txt
+++ b/examples/DemoRunner/Builds/Android/app/CMakeLists.txt
@@ -1982,6 +1982,7 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_graphics/native/juce_CoreGraphicsHelpers_mac.h"
"../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContext_windows.cpp"
"../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContext_windows.h"
+ "../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContextImpl_windows.cpp"
"../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContextImpl_windows.h"
"../../../../../modules/juce_graphics/native/juce_Direct2DImage_windows.cpp"
"../../../../../modules/juce_graphics/native/juce_Direct2DImage_windows.h"
@@ -4637,6 +4638,7 @@ set_source_files_properties(
"../../../../../modules/juce_graphics/native/juce_CoreGraphicsHelpers_mac.h"
"../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContext_windows.cpp"
"../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContext_windows.h"
+ "../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContextImpl_windows.cpp"
"../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContextImpl_windows.h"
"../../../../../modules/juce_graphics/native/juce_Direct2DImage_windows.cpp"
"../../../../../modules/juce_graphics/native/juce_Direct2DImage_windows.h"
diff --git a/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj b/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj
index 389dcbbfc4..463945211a 100644
--- a/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj
+++ b/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj
@@ -2406,6 +2406,9 @@
true
+
+ true
+
true
diff --git a/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj.filters b/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj.filters
index 3dc2be9f82..dec6bf36c3 100644
--- a/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj.filters
+++ b/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj.filters
@@ -3184,6 +3184,9 @@
JUCE Modules\juce_graphics\native
+
+ JUCE Modules\juce_graphics\native
+
JUCE Modules\juce_graphics\native
diff --git a/examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj b/examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj
index a584739c91..cdda016df4 100644
--- a/examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj
+++ b/examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj
@@ -2406,6 +2406,9 @@
true
+
+ true
+
true
diff --git a/examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj.filters b/examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj.filters
index bfd7177362..629f3ddc6f 100644
--- a/examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj.filters
+++ b/examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj.filters
@@ -3184,6 +3184,9 @@
JUCE Modules\juce_graphics\native
+
+ JUCE Modules\juce_graphics\native
+
JUCE Modules\juce_graphics\native
diff --git a/extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt b/extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt
index de5dbfa690..85eeaabcc1 100644
--- a/extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt
+++ b/extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt
@@ -1744,6 +1744,7 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_graphics/native/juce_CoreGraphicsHelpers_mac.h"
"../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContext_windows.cpp"
"../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContext_windows.h"
+ "../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContextImpl_windows.cpp"
"../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContextImpl_windows.h"
"../../../../../modules/juce_graphics/native/juce_Direct2DImage_windows.cpp"
"../../../../../modules/juce_graphics/native/juce_Direct2DImage_windows.h"
@@ -4013,6 +4014,7 @@ set_source_files_properties(
"../../../../../modules/juce_graphics/native/juce_CoreGraphicsHelpers_mac.h"
"../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContext_windows.cpp"
"../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContext_windows.h"
+ "../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContextImpl_windows.cpp"
"../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContextImpl_windows.h"
"../../../../../modules/juce_graphics/native/juce_Direct2DImage_windows.cpp"
"../../../../../modules/juce_graphics/native/juce_Direct2DImage_windows.h"
diff --git a/extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj b/extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj
index 5fa0947f26..3f1965ef79 100644
--- a/extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj
+++ b/extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj
@@ -2097,6 +2097,9 @@
true
+
+ true
+
true
diff --git a/extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj.filters b/extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj.filters
index c59991b45c..5f3f20abb3 100644
--- a/extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj.filters
+++ b/extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj.filters
@@ -2692,6 +2692,9 @@
JUCE Modules\juce_graphics\native
+
+ JUCE Modules\juce_graphics\native
+
JUCE Modules\juce_graphics\native
diff --git a/extras/AudioPluginHost/Builds/Android/app/CMakeLists.txt b/extras/AudioPluginHost/Builds/Android/app/CMakeLists.txt
index 2f132d11bb..8ac5f5b64a 100644
--- a/extras/AudioPluginHost/Builds/Android/app/CMakeLists.txt
+++ b/extras/AudioPluginHost/Builds/Android/app/CMakeLists.txt
@@ -1874,6 +1874,7 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_graphics/native/juce_CoreGraphicsHelpers_mac.h"
"../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContext_windows.cpp"
"../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContext_windows.h"
+ "../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContextImpl_windows.cpp"
"../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContextImpl_windows.h"
"../../../../../modules/juce_graphics/native/juce_Direct2DImage_windows.cpp"
"../../../../../modules/juce_graphics/native/juce_Direct2DImage_windows.h"
@@ -4296,6 +4297,7 @@ set_source_files_properties(
"../../../../../modules/juce_graphics/native/juce_CoreGraphicsHelpers_mac.h"
"../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContext_windows.cpp"
"../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContext_windows.h"
+ "../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContextImpl_windows.cpp"
"../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContextImpl_windows.h"
"../../../../../modules/juce_graphics/native/juce_Direct2DImage_windows.cpp"
"../../../../../modules/juce_graphics/native/juce_Direct2DImage_windows.h"
diff --git a/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj b/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj
index 21504e547e..b34c80cb2d 100644
--- a/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj
+++ b/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj
@@ -2231,6 +2231,9 @@
true
+
+ true
+
true
diff --git a/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj.filters b/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj.filters
index 205a49d177..5b98dd4f4c 100644
--- a/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj.filters
+++ b/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj.filters
@@ -2899,6 +2899,9 @@
JUCE Modules\juce_graphics\native
+
+ JUCE Modules\juce_graphics\native
+
JUCE Modules\juce_graphics\native
diff --git a/extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj b/extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj
index 1790e6aceb..0196bd9f3d 100644
--- a/extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj
+++ b/extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj
@@ -2231,6 +2231,9 @@
true
+
+ true
+
true
diff --git a/extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj.filters b/extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj.filters
index 41635442a1..aa47ad15a3 100644
--- a/extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj.filters
+++ b/extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj.filters
@@ -2899,6 +2899,9 @@
JUCE Modules\juce_graphics\native
+
+ JUCE Modules\juce_graphics\native
+
JUCE Modules\juce_graphics\native
diff --git a/extras/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt b/extras/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt
index 55c4f4104e..88cd727775 100644
--- a/extras/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt
+++ b/extras/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt
@@ -1763,6 +1763,7 @@ add_library( ${BINARY_NAME}
"../../../../../modules/juce_graphics/native/juce_CoreGraphicsHelpers_mac.h"
"../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContext_windows.cpp"
"../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContext_windows.h"
+ "../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContextImpl_windows.cpp"
"../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContextImpl_windows.h"
"../../../../../modules/juce_graphics/native/juce_Direct2DImage_windows.cpp"
"../../../../../modules/juce_graphics/native/juce_Direct2DImage_windows.h"
@@ -4112,6 +4113,7 @@ set_source_files_properties(
"../../../../../modules/juce_graphics/native/juce_CoreGraphicsHelpers_mac.h"
"../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContext_windows.cpp"
"../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContext_windows.h"
+ "../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContextImpl_windows.cpp"
"../../../../../modules/juce_graphics/native/juce_Direct2DGraphicsContextImpl_windows.h"
"../../../../../modules/juce_graphics/native/juce_Direct2DImage_windows.cpp"
"../../../../../modules/juce_graphics/native/juce_Direct2DImage_windows.h"
diff --git a/extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj b/extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj
index 95bea5dcb4..870c6182f8 100644
--- a/extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj
+++ b/extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj
@@ -2118,6 +2118,9 @@
true
+
+ true
+
true
diff --git a/extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj.filters b/extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj.filters
index 39217dba1e..c3db5dc64a 100644
--- a/extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj.filters
+++ b/extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj.filters
@@ -2746,6 +2746,9 @@
JUCE Modules\juce_graphics\native
+
+ JUCE Modules\juce_graphics\native
+
JUCE Modules\juce_graphics\native
diff --git a/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj b/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj
index 5421661e1a..13875b50ac 100644
--- a/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj
+++ b/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj
@@ -1260,6 +1260,9 @@
true
+
+ true
+
true
diff --git a/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj.filters
index 8f33150987..93f0ea36b1 100644
--- a/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj.filters
+++ b/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj.filters
@@ -1585,6 +1585,9 @@
JUCE Modules\juce_graphics\native
+
+ JUCE Modules\juce_graphics\native
+
JUCE Modules\juce_graphics\native
diff --git a/extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj b/extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj
index d1854b1428..fa7f1b6b61 100644
--- a/extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj
+++ b/extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj
@@ -1260,6 +1260,9 @@
true
+
+ true
+
true
diff --git a/extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj.filters
index 516194f1a1..7f68454775 100644
--- a/extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj.filters
+++ b/extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj.filters
@@ -1585,6 +1585,9 @@
JUCE Modules\juce_graphics\native
+
+ JUCE Modules\juce_graphics\native
+
JUCE Modules\juce_graphics\native
diff --git a/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj b/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj
index 9155e420bf..3346d55ba0 100644
--- a/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj
+++ b/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj
@@ -2239,6 +2239,9 @@
true
+
+ true
+
true
diff --git a/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj.filters b/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj.filters
index 27f050e2e5..982a6a149f 100644
--- a/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj.filters
+++ b/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj.filters
@@ -2947,6 +2947,9 @@
JUCE Modules\juce_graphics\native
+
+ JUCE Modules\juce_graphics\native
+
JUCE Modules\juce_graphics\native
diff --git a/extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj b/extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj
index 00969388f6..0ad82e37d4 100644
--- a/extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj
+++ b/extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj
@@ -2239,6 +2239,9 @@
true
+
+ true
+
true
diff --git a/extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj.filters b/extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj.filters
index 031a976ede..c56b183ef9 100644
--- a/extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj.filters
+++ b/extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj.filters
@@ -2947,6 +2947,9 @@
JUCE Modules\juce_graphics\native
+
+ JUCE Modules\juce_graphics\native
+
JUCE Modules\juce_graphics\native
diff --git a/extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_DynamicLibrary.vcxproj b/extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_DynamicLibrary.vcxproj
index cf92a7d5b9..52c5e2fe73 100644
--- a/extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_DynamicLibrary.vcxproj
+++ b/extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_DynamicLibrary.vcxproj
@@ -2117,6 +2117,9 @@
true
+
+ true
+
true
diff --git a/extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_DynamicLibrary.vcxproj.filters b/extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_DynamicLibrary.vcxproj.filters
index 52ca71fc8e..0512ee58ff 100644
--- a/extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_DynamicLibrary.vcxproj.filters
+++ b/extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_DynamicLibrary.vcxproj.filters
@@ -2743,6 +2743,9 @@
JUCE Modules\juce_graphics\native
+
+ JUCE Modules\juce_graphics\native
+
JUCE Modules\juce_graphics\native
diff --git a/modules/juce_graphics/juce_graphics.cpp b/modules/juce_graphics/juce_graphics.cpp
index f0c775358d..fd984f2be0 100644
--- a/modules/juce_graphics/juce_graphics.cpp
+++ b/modules/juce_graphics/juce_graphics.cpp
@@ -231,6 +231,7 @@ extern "C"
#include "native/juce_DirectX_windows.cpp"
#include "native/juce_DirectWriteTypeface_windows.cpp"
#include "native/juce_IconHelpers_windows.cpp"
+ #include "native/juce_Direct2DGraphicsContextImpl_windows.cpp"
#include "native/juce_Direct2DGraphicsContext_windows.cpp"
#include "native/juce_Direct2DImageContext_windows.cpp"
#include "native/juce_Direct2DImage_windows.cpp"
diff --git a/modules/juce_graphics/native/juce_Direct2DGraphicsContextImpl_windows.cpp b/modules/juce_graphics/native/juce_Direct2DGraphicsContextImpl_windows.cpp
new file mode 100644
index 0000000000..7f4dc2e7b1
--- /dev/null
+++ b/modules/juce_graphics/native/juce_Direct2DGraphicsContextImpl_windows.cpp
@@ -0,0 +1,290 @@
+/*
+ ==============================================================================
+
+ This file is part of the JUCE framework.
+ Copyright (c) Raw Material Software Limited
+
+ JUCE is an open source framework subject to commercial or open source
+ licensing.
+
+ By downloading, installing, or using the JUCE framework, or combining the
+ JUCE framework with any other source code, object code, content or any other
+ copyrightable work, you agree to the terms of the JUCE End User Licence
+ Agreement, and all incorporated terms including the JUCE Privacy Policy and
+ the JUCE Website Terms of Service, as applicable, which will bind you. If you
+ do not agree to the terms of these agreements, we will not license the JUCE
+ framework to you, and you must discontinue the installation or download
+ process and cease use of the JUCE framework.
+
+ JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
+ JUCE Privacy Policy: https://juce.com/juce-privacy-policy
+ JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
+
+ Or:
+
+ You may also use this code under the terms of the AGPLv3:
+ https://www.gnu.org/licenses/agpl-3.0.en.html
+
+ THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
+ WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
+
+ ==============================================================================
+*/
+
+namespace juce
+{
+
+bool Direct2DGraphicsContext::Pimpl::prepare()
+{
+ if (! deviceResources.has_value())
+ deviceResources = Direct2DDeviceResources::create (getDeviceContext());
+
+ return deviceResources.has_value();
+}
+
+void Direct2DGraphicsContext::Pimpl::teardown()
+{
+ deviceResources.reset();
+}
+
+bool Direct2DGraphicsContext::Pimpl::checkPaintReady()
+{
+ return deviceResources.has_value();
+}
+
+Direct2DGraphicsContext::Pimpl::Pimpl (Direct2DGraphicsContext& ownerIn)
+ : owner (ownerIn)
+{
+ directX->adapters.addListener (*this);
+}
+
+Direct2DGraphicsContext::Pimpl::~Pimpl()
+{
+ directX->adapters.removeListener (*this);
+
+ popAllSavedStates();
+}
+
+auto Direct2DGraphicsContext::Pimpl::startFrame() -> SavedState*
+{
+ prepare();
+
+ // Anything to paint?
+ const auto paintAreas = getPaintAreas();
+ const auto paintBounds = paintAreas.getBounds();
+
+ if (! getFrameSize().intersects (paintBounds) || paintBounds.isEmpty() || paintAreas.isEmpty())
+ return nullptr;
+
+ // Is Direct2D ready to paint?
+ if (! checkPaintReady())
+ return nullptr;
+
+ #if JUCE_DIRECT2D_METRICS
+ owner.metrics->startFrame();
+ #endif
+
+ JUCE_TRACE_EVENT_INT_RECT_LIST (etw::startD2DFrame, etw::direct2dKeyword, owner.getFrameId(), paintAreas);
+
+ const auto deviceContext = getDeviceContext();
+
+ // Init device context transform
+ resetTransform (deviceContext);
+
+ // Start drawing
+ deviceContext->SetTarget (getDeviceContextTarget());
+ deviceContext->BeginDraw();
+
+ // Init the save state stack and return the first saved state
+ return pushFirstSavedState (paintBounds);
+}
+
+HRESULT Direct2DGraphicsContext::Pimpl::finishFrame()
+{
+ // Fully pop the state stack
+ popAllSavedStates();
+
+ // Finish drawing
+ // SetTarget(nullptr) so the device context doesn't hold a reference to the swap chain buffer
+ HRESULT hr = S_OK;
+ {
+ JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (owner.metrics, endDrawDuration)
+ JUCE_SCOPED_TRACE_EVENT_FRAME (etw::endDraw, etw::direct2dKeyword, owner.getFrameId());
+
+ const auto deviceContext = getDeviceContext();
+ hr = deviceContext->EndDraw();
+ deviceContext->SetTarget (nullptr);
+ }
+
+ jassert (SUCCEEDED (hr));
+
+ if (FAILED (hr))
+ teardown();
+
+ #if JUCE_DIRECT2D_METRICS
+ owner.metrics->finishFrame();
+ #endif
+
+ return hr;
+}
+
+auto Direct2DGraphicsContext::Pimpl::getCurrentSavedState() const -> SavedState*
+{
+ return ! savedClientStates.empty() ? savedClientStates.back().get() : nullptr;
+}
+
+auto Direct2DGraphicsContext::Pimpl::pushFirstSavedState (Rectangle initialClipRegion) -> SavedState*
+{
+ jassert (savedClientStates.empty());
+
+ savedClientStates.push_back (std::make_unique (owner,
+ initialClipRegion,
+ getDeviceContext(),
+ deviceResources->colourBrush,
+ *deviceResources));
+
+ return getCurrentSavedState();
+}
+
+auto Direct2DGraphicsContext::Pimpl::pushSavedState() -> SavedState*
+{
+ jassert (! savedClientStates.empty());
+
+ savedClientStates.push_back (std::make_unique (*savedClientStates.back()));
+
+ return getCurrentSavedState();
+}
+
+auto Direct2DGraphicsContext::Pimpl::popSavedState() -> SavedState*
+{
+ savedClientStates.back()->popLayers();
+ savedClientStates.pop_back();
+
+ return getCurrentSavedState();
+}
+
+void Direct2DGraphicsContext::Pimpl::popAllSavedStates()
+{
+ while (! savedClientStates.empty())
+ popSavedState();
+}
+
+void Direct2DGraphicsContext::Pimpl::setDeviceContextTransform (AffineTransform transform)
+{
+ setTransform (getDeviceContext(), transform);
+}
+
+void Direct2DGraphicsContext::Pimpl::resetDeviceContextTransform()
+{
+ resetTransform (getDeviceContext());
+}
+
+bool Direct2DGraphicsContext::Pimpl::fillSpriteBatch (const RectangleList& list)
+{
+ if (! owner.currentState->fillType.isColour())
+ return false;
+
+ auto* rectangleListSpriteBatch = deviceResources->rectangleListSpriteBatch.get();
+
+ if (rectangleListSpriteBatch == nullptr)
+ return false;
+
+ const auto deviceContext = getDeviceContext();
+
+ if (deviceContext == nullptr)
+ return false;
+
+ owner.applyPendingClipList();
+
+ const auto& transform = owner.currentState->currentTransform;
+
+ if (transform.isOnlyTranslated)
+ {
+ auto translateRectangle = [&] (const Rectangle& r) -> Rectangle
+ {
+ return transform.translated (r);
+ };
+
+ return rectangleListSpriteBatch->fillRectangles (deviceContext,
+ list,
+ owner.currentState->fillType.colour,
+ translateRectangle,
+ owner.metrics.get());
+ }
+
+ if (owner.currentState->isCurrentTransformAxisAligned())
+ {
+ auto transformRectangle = [&] (const Rectangle& r) -> Rectangle
+ {
+ return transform.boundsAfterTransform (r);
+ };
+
+ return rectangleListSpriteBatch->fillRectangles (deviceContext,
+ list,
+ owner.currentState->fillType.colour,
+ transformRectangle,
+ owner.metrics.get());
+ }
+
+ auto checkRectangleWithoutTransforming = [&] (const Rectangle& r) -> Rectangle
+ {
+ return r;
+ };
+
+ ScopedTransform scopedTransform { *this, owner.currentState };
+ return rectangleListSpriteBatch->fillRectangles (deviceContext,
+ list,
+ owner.currentState->fillType.colour,
+ checkRectangleWithoutTransforming,
+ owner.metrics.get());
+}
+
+Line Direct2DGraphicsContext::Pimpl::offsetShape (Line a, Point b)
+{
+ return Line { a.getStart() + b, a.getEnd() + b };
+}
+
+Rectangle Direct2DGraphicsContext::Pimpl::offsetShape (Rectangle a, Point b)
+{
+ return a + b;
+}
+
+RectangleList Direct2DGraphicsContext::Pimpl::offsetShape (RectangleList a, Point b)
+{
+ a.offsetAll (b);
+ return a;
+}
+
+void Direct2DGraphicsContext::Pimpl::resetTransform (ID2D1DeviceContext1* context)
+{
+ context->SetTransform (D2D1::IdentityMatrix());
+}
+
+void Direct2DGraphicsContext::Pimpl::setTransform (ID2D1DeviceContext1* context, AffineTransform newTransform)
+{
+ context->SetTransform (D2DUtilities::transformToMatrix (newTransform));
+}
+
+DxgiAdapter::Ptr Direct2DGraphicsContext::Pimpl::findAdapter() const
+{
+ return Direct2DDeviceResources::findAdapter (directX->adapters, getDeviceContext());
+}
+
+void Direct2DGraphicsContext::Pimpl::adapterCreated (DxgiAdapter::Ptr newAdapter)
+{
+ const auto adapter = findAdapter();
+
+ if (adapter == nullptr || ! adapter->uniqueIDMatches (newAdapter))
+ teardown();
+}
+
+void Direct2DGraphicsContext::Pimpl::adapterRemoved (DxgiAdapter::Ptr expiringAdapter)
+{
+ const auto adapter = findAdapter();
+
+ if (adapter != nullptr && adapter->uniqueIDMatches (expiringAdapter))
+ teardown();
+}
+
+} // namespace juce
diff --git a/modules/juce_graphics/native/juce_Direct2DGraphicsContextImpl_windows.h b/modules/juce_graphics/native/juce_Direct2DGraphicsContextImpl_windows.h
index a6f89a22bf..68ac26d35a 100644
--- a/modules/juce_graphics/native/juce_Direct2DGraphicsContextImpl_windows.h
+++ b/modules/juce_graphics/native/juce_Direct2DGraphicsContextImpl_windows.h
@@ -566,156 +566,32 @@ protected:
std::vector> savedClientStates;
- virtual bool prepare()
- {
- if (! deviceResources.has_value())
- deviceResources = Direct2DDeviceResources::create (getDeviceContext());
-
- return deviceResources.has_value();
- }
-
- virtual void teardown()
- {
- deviceResources.reset();
- }
-
- virtual bool checkPaintReady()
- {
- return deviceResources.has_value();
- }
+ virtual bool prepare();
+ virtual void teardown();
+ virtual bool checkPaintReady();
public:
- explicit Pimpl (Direct2DGraphicsContext& ownerIn)
- : owner (ownerIn)
- {
- directX->adapters.addListener (*this);
- }
+ explicit Pimpl (Direct2DGraphicsContext& ownerIn);
+ ~Pimpl() override;
- ~Pimpl() override
- {
- directX->adapters.removeListener (*this);
+ virtual SavedState* startFrame();
+ virtual HRESULT finishFrame();
- popAllSavedStates();
- }
+ SavedState* getCurrentSavedState() const;
+ SavedState* pushFirstSavedState (Rectangle initialClipRegion);
- virtual SavedState* startFrame()
- {
- prepare();
+ SavedState* pushSavedState();
+ SavedState* popSavedState();
- // Anything to paint?
- const auto paintAreas = getPaintAreas();
- const auto paintBounds = paintAreas.getBounds();
-
- if (! getFrameSize().intersects (paintBounds) || paintBounds.isEmpty() || paintAreas.isEmpty())
- return nullptr;
-
- // Is Direct2D ready to paint?
- if (! checkPaintReady())
- return nullptr;
-
- #if JUCE_DIRECT2D_METRICS
- owner.metrics->startFrame();
- #endif
-
- JUCE_TRACE_EVENT_INT_RECT_LIST (etw::startD2DFrame, etw::direct2dKeyword, owner.getFrameId(), paintAreas);
-
- const auto deviceContext = getDeviceContext();
-
- // Init device context transform
- resetTransform (deviceContext);
-
- // Start drawing
- deviceContext->SetTarget (getDeviceContextTarget());
- deviceContext->BeginDraw();
-
- // Init the save state stack and return the first saved state
- return pushFirstSavedState (paintBounds);
- }
-
- virtual HRESULT finishFrame()
- {
- // Fully pop the state stack
- popAllSavedStates();
-
- // Finish drawing
- // SetTarget(nullptr) so the device context doesn't hold a reference to the swap chain buffer
- HRESULT hr = S_OK;
- {
- JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (owner.metrics, endDrawDuration)
- JUCE_SCOPED_TRACE_EVENT_FRAME (etw::endDraw, etw::direct2dKeyword, owner.getFrameId());
-
- const auto deviceContext = getDeviceContext();
- hr = deviceContext->EndDraw();
- deviceContext->SetTarget (nullptr);
- }
-
- jassert (SUCCEEDED (hr));
-
- if (FAILED (hr))
- teardown();
-
- #if JUCE_DIRECT2D_METRICS
- owner.metrics->finishFrame();
- #endif
-
- return hr;
- }
-
- SavedState* getCurrentSavedState() const
- {
- return ! savedClientStates.empty() ? savedClientStates.back().get() : nullptr;
- }
-
- SavedState* pushFirstSavedState (Rectangle initialClipRegion)
- {
- jassert (savedClientStates.empty());
-
- savedClientStates.push_back (std::make_unique (owner,
- initialClipRegion,
- getDeviceContext(),
- deviceResources->colourBrush,
- *deviceResources));
-
- return getCurrentSavedState();
- }
-
- SavedState* pushSavedState()
- {
- jassert (! savedClientStates.empty());
-
- savedClientStates.push_back (std::make_unique (*savedClientStates.back()));
-
- return getCurrentSavedState();
- }
-
- SavedState* popSavedState()
- {
- savedClientStates.back()->popLayers();
- savedClientStates.pop_back();
-
- return getCurrentSavedState();
- }
-
- void popAllSavedStates()
- {
- while (! savedClientStates.empty())
- popSavedState();
- }
+ void popAllSavedStates();
virtual RectangleList getPaintAreas() const = 0;
virtual Rectangle getFrameSize() const = 0;
virtual ComSmartPtr getDeviceContext() const = 0;
virtual ComSmartPtr getDeviceContextTarget() const = 0;
- void setDeviceContextTransform (AffineTransform transform)
- {
- setTransform (getDeviceContext(), transform);
- }
-
- void resetDeviceContextTransform()
- {
- resetTransform (getDeviceContext());
- }
+ void setDeviceContextTransform (AffineTransform transform);
+ void resetDeviceContextTransform();
auto getDirect2DFactory()
{
@@ -737,81 +613,11 @@ public:
return directWrite->getFonts();
}
- bool fillSpriteBatch (const RectangleList& list)
- {
- if (! owner.currentState->fillType.isColour())
- return false;
+ bool fillSpriteBatch (const RectangleList& list);
- auto* rectangleListSpriteBatch = deviceResources->rectangleListSpriteBatch.get();
-
- if (rectangleListSpriteBatch == nullptr)
- return false;
-
- const auto deviceContext = getDeviceContext();
-
- if (deviceContext == nullptr)
- return false;
-
- owner.applyPendingClipList();
-
- const auto& transform = owner.currentState->currentTransform;
-
- if (transform.isOnlyTranslated)
- {
- auto translateRectangle = [&] (const Rectangle& r) -> Rectangle
- {
- return transform.translated (r);
- };
-
- return rectangleListSpriteBatch->fillRectangles (deviceContext,
- list,
- owner.currentState->fillType.colour,
- translateRectangle,
- owner.metrics.get());
- }
-
- if (owner.currentState->isCurrentTransformAxisAligned())
- {
- auto transformRectangle = [&] (const Rectangle& r) -> Rectangle
- {
- return transform.boundsAfterTransform (r);
- };
-
- return rectangleListSpriteBatch->fillRectangles (deviceContext,
- list,
- owner.currentState->fillType.colour,
- transformRectangle,
- owner.metrics.get());
- }
-
- auto checkRectangleWithoutTransforming = [&] (const Rectangle& r) -> Rectangle
- {
- return r;
- };
-
- ScopedTransform scopedTransform { *this, owner.currentState };
- return rectangleListSpriteBatch->fillRectangles (deviceContext,
- list,
- owner.currentState->fillType.colour,
- checkRectangleWithoutTransforming,
- owner.metrics.get());
- }
-
- static Line offsetShape (Line a, Point b)
- {
- return Line { a.getStart() + b, a.getEnd() + b };
- }
-
- static Rectangle offsetShape (Rectangle a, Point b)
- {
- return a + b;
- }
-
- static RectangleList offsetShape (RectangleList a, Point b)
- {
- a.offsetAll (b);
- return a;
- }
+ static Line offsetShape (Line a, Point b);
+ static Rectangle offsetShape (Rectangle a, Point b);
+ static RectangleList offsetShape (RectangleList a, Point b);
template
void paintPrimitive (const Shape& shape, Fn&& primitiveOp)
@@ -848,36 +654,13 @@ public:
DirectWriteGlyphRun glyphRun;
private:
- static void resetTransform (ID2D1DeviceContext1* context)
- {
- context->SetTransform (D2D1::IdentityMatrix());
- }
+ static void resetTransform (ID2D1DeviceContext1* context);
+ static void setTransform (ID2D1DeviceContext1* context, AffineTransform newTransform);
- static void setTransform (ID2D1DeviceContext1* context, AffineTransform newTransform)
- {
- context->SetTransform (D2DUtilities::transformToMatrix (newTransform));
- }
+ DxgiAdapter::Ptr findAdapter() const;
- DxgiAdapter::Ptr findAdapter() const
- {
- return Direct2DDeviceResources::findAdapter (directX->adapters, getDeviceContext());
- }
-
- void adapterCreated (DxgiAdapter::Ptr newAdapter) override
- {
- const auto adapter = findAdapter();
-
- if (adapter == nullptr || ! adapter->uniqueIDMatches (newAdapter))
- teardown();
- }
-
- void adapterRemoved (DxgiAdapter::Ptr expiringAdapter) override
- {
- const auto adapter = findAdapter();
-
- if (adapter != nullptr && adapter->uniqueIDMatches (expiringAdapter))
- teardown();
- }
+ void adapterCreated (DxgiAdapter::Ptr newAdapter) override;
+ void adapterRemoved (DxgiAdapter::Ptr expiringAdapter) override;
HWND hwnd = nullptr;