diff --git a/modules/juce_graphics/native/juce_Direct2DHwndContext_windows.cpp b/modules/juce_graphics/native/juce_Direct2DHwndContext_windows.cpp index 30804a10c6..cede792977 100644 --- a/modules/juce_graphics/native/juce_Direct2DHwndContext_windows.cpp +++ b/modules/juce_graphics/native/juce_Direct2DHwndContext_windows.cpp @@ -36,10 +36,13 @@ namespace juce { //============================================================================== -class Presentation +class alignas (MEMORY_ALLOCATION_ALIGNMENT) Presentation { public: - SLIST_ENTRY& getListEntry() { return listEntry; } + SLIST_ENTRY& getListEntry() + { + return listEntry; + } auto getPresentationBitmap() const { @@ -90,13 +93,47 @@ public: } private: - JUCE_ALIGN (MEMORY_ALLOCATION_ALIGNMENT) SLIST_ENTRY listEntry; ComSmartPtr presentationBitmap; RectangleList paintAreas; HRESULT hr = S_OK; }; +class SList +{ +public: + void push (SLIST_ENTRY& item) + { + jassert ((reinterpret_cast (&item) % MEMORY_ALLOCATION_ALIGNMENT) == 0); + InterlockedPushEntrySList (head.get(), &item); + } + + auto* pop() + { + return InterlockedPopEntrySList (head.get()); + } + +private: + struct Destructor + { + void operator() (void* ptr) const + { + _aligned_free (ptr); + } + }; + + std::unique_ptr head { []() -> SLIST_HEADER* + { + auto* result = static_cast (_aligned_malloc (sizeof (SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT)); + + if (result == nullptr) + return nullptr; + + InitializeSListHead (result); + return result; + }() }; +}; + struct Direct2DHwndContext::HwndPimpl : public Direct2DGraphicsContext::Pimpl { private: @@ -108,39 +145,33 @@ private: multithread (multithreadIn), swapChainEventHandle (ownerIn.swap.swapChainEvent->getHandle()) { - InitializeSListHead (&paintedPresentations); - InitializeSListHead (&retiredPresentations); - for (auto& p : presentations) - InterlockedPushEntrySList (&retiredPresentations, &p.getListEntry()); + retired.push (p.getListEntry()); } ~SwapChainThread() { SetEvent (quitEvent.getHandle()); thread.join(); - - InterlockedFlushSList (&paintedPresentations); - InterlockedFlushSList (&retiredPresentations); } Presentation* getFreshPresentation() { - if (auto listEntry = InterlockedPopEntrySList (&retiredPresentations)) - return reinterpret_cast (listEntry); + if (auto* listEntry = reinterpret_cast (retired.pop())) + return listEntry; return nullptr; } void pushPaintedPresentation (Presentation* presentationIn) { - InterlockedPushEntrySList (&paintedPresentations, &presentationIn->getListEntry()); + painted.push (presentationIn->getListEntry()); SetEvent (wakeEvent.getHandle()); } void retirePresentation (Presentation* presentationIn) { - InterlockedPushEntrySList (&retiredPresentations, &presentationIn->getListEntry()); + retired.push (presentationIn->getListEntry()); } void notify() @@ -149,35 +180,10 @@ private: } private: - void serviceSwapChain() - { - if (swapChainReady) - { - if (auto listEntry = InterlockedPopEntrySList (&paintedPresentations)) - { - JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (owner.owner.metrics, swapChainThreadTime); - - auto filledPresentation = reinterpret_cast (listEntry); - - { - ScopedMultithread scopedMultithread { multithread }; - owner.present (filledPresentation, 0); - } - - swapChainReady = false; - InterlockedPushEntrySList (&retiredPresentations, listEntry); - } - } - } - - JUCE_ALIGN (MEMORY_ALLOCATION_ALIGNMENT) - SLIST_HEADER paintedPresentations; - JUCE_ALIGN (MEMORY_ALLOCATION_ALIGNMENT) - SLIST_HEADER retiredPresentations; + SList painted, retired; Direct2DHwndContext::HwndPimpl& owner; ComSmartPtr multithread; HANDLE swapChainEventHandle = nullptr; - bool swapChainReady = false; std::vector presentations = std::vector (2); WindowsScopedEvent wakeEvent; @@ -186,7 +192,30 @@ private: void threadLoop() { - Thread::setCurrentThreadName ("swapChainThread"); + Thread::setCurrentThreadName ("JUCE D2D swap chain thread"); + + bool swapChainReady = false; + + const auto serviceSwapChain = [&] + { + if (! swapChainReady) + return; + + auto* listEntry = reinterpret_cast (painted.pop()); + + if (listEntry == nullptr) + return; + + JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME (owner.owner.metrics, swapChainThreadTime); + + { + ScopedMultithread scopedMultithread { multithread }; + owner.present (listEntry, 0); + } + + retired.push (listEntry->getListEntry()); + swapChainReady = false; + }; for (;;) { diff --git a/modules/juce_graphics/native/juce_Direct2DResources_windows.cpp b/modules/juce_graphics/native/juce_Direct2DResources_windows.cpp index 8616e910f7..414f72022a 100644 --- a/modules/juce_graphics/native/juce_Direct2DResources_windows.cpp +++ b/modules/juce_graphics/native/juce_Direct2DResources_windows.cpp @@ -482,8 +482,8 @@ public: swapChainDescription.Height = (UINT) size.getHeight(); swapChainDescription.SampleDesc.Count = 1; swapChainDescription.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - swapChainDescription.BufferCount = bufferCount; - swapChainDescription.SwapEffect = swapEffect; + swapChainDescription.BufferCount = 2; + swapChainDescription.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; swapChainDescription.Flags = swapChainFlags; swapChainDescription.Scaling = DXGI_SCALING_STRETCH; @@ -587,11 +587,9 @@ public: return { (int) size.width, (int) size.height }; } - DXGI_SWAP_EFFECT const swapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; - UINT const bufferCount = 2; - uint32 const swapChainFlags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; - uint32 const presentSyncInterval = 1; - uint32 const presentFlags = 0; + static constexpr uint32 swapChainFlags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; + static constexpr uint32 presentSyncInterval = 1; + static constexpr uint32 presentFlags = 0; ComSmartPtr chain; ComSmartPtr buffer; std::optional swapChainEvent;