mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Direct2D: Use PostMessage for swapchain events
Co-authored-by: Matt Gonzalez <matt@echoaudio.com>
This commit is contained in:
parent
16326d13d3
commit
44d304b468
3 changed files with 65 additions and 19 deletions
|
|
@ -38,17 +38,18 @@ namespace juce
|
|||
struct Direct2DHwndContext::HwndPimpl : public Direct2DGraphicsContext::Pimpl
|
||||
{
|
||||
private:
|
||||
struct SwapChainThread : private AsyncUpdater
|
||||
struct SwapChainThread
|
||||
{
|
||||
SwapChainThread (Direct2DHwndContext::HwndPimpl& ownerIn, HANDLE swapHandle)
|
||||
: owner (ownerIn),
|
||||
swapChainEventHandle (swapHandle)
|
||||
{
|
||||
SetWindowSubclass (owner.hwnd, subclassWindowProc, (UINT_PTR) this, (DWORD_PTR) this);
|
||||
}
|
||||
|
||||
~SwapChainThread() override
|
||||
~SwapChainThread()
|
||||
{
|
||||
cancelPendingUpdate();
|
||||
RemoveWindowSubclass (owner.hwnd, subclassWindowProc, (UINT_PTR) this);
|
||||
SetEvent (quitEvent.getHandle());
|
||||
thread.join();
|
||||
}
|
||||
|
|
@ -62,10 +63,32 @@ private:
|
|||
WindowsScopedEvent quitEvent;
|
||||
std::thread thread { [&] { threadLoop(); } };
|
||||
|
||||
void handleAsyncUpdate() override
|
||||
static constexpr uint32_t swapchainReadyMessageID = WM_USER + 124;
|
||||
|
||||
bool handleWindowProcMessage (UINT message)
|
||||
{
|
||||
owner.swapEventReceived = true;
|
||||
owner.present();
|
||||
if (message == swapchainReadyMessageID)
|
||||
{
|
||||
owner.onSwapchainEvent();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK subclassWindowProc (HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam,
|
||||
UINT_PTR,
|
||||
DWORD_PTR referenceData)
|
||||
{
|
||||
auto* that = reinterpret_cast<SwapChainThread*> (referenceData);
|
||||
|
||||
if (that != nullptr && that->handleWindowProcMessage (message))
|
||||
return 0;
|
||||
|
||||
return DefSubclassProc (hwnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
void threadLoop()
|
||||
|
|
@ -82,7 +105,7 @@ private:
|
|||
{
|
||||
case WAIT_OBJECT_0:
|
||||
{
|
||||
triggerAsyncUpdate();
|
||||
PostMessage (owner.hwnd, swapchainReadyMessageID, 0, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -98,10 +121,12 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
HWND hwnd;
|
||||
SwapChain swap;
|
||||
ComSmartPtr<ID2D1DeviceContext1> deviceContext;
|
||||
std::unique_ptr<SwapChainThread> swapChainThread;
|
||||
std::optional<CompositionTree> compositionTree;
|
||||
SwapchainDelegate& delegate;
|
||||
|
||||
// Areas that must be repainted during the next paint call, between startFrame/endFrame
|
||||
RectangleList<int> deferredRepaints;
|
||||
|
|
@ -111,12 +136,17 @@ private:
|
|||
|
||||
std::vector<RECT> dirtyRectangles;
|
||||
int64 lastFinishFrameTicks = 0;
|
||||
HWND hwnd = nullptr;
|
||||
|
||||
// Set to true after the swap event is signalled, indicating that we're allowed to try presenting
|
||||
// a new frame.
|
||||
bool swapEventReceived = false;
|
||||
|
||||
void onSwapchainEvent()
|
||||
{
|
||||
swapEventReceived = true;
|
||||
delegate.onSwapchainEvent();
|
||||
}
|
||||
|
||||
bool prepare() override
|
||||
{
|
||||
const auto adapter = directX->adapters.getAdapterForHwnd (hwnd);
|
||||
|
|
@ -182,6 +212,7 @@ private:
|
|||
bool ready = Pimpl::checkPaintReady();
|
||||
ready &= swap.canPaint();
|
||||
ready &= compositionTree.has_value();
|
||||
ready &= swapEventReceived;
|
||||
|
||||
return ready;
|
||||
}
|
||||
|
|
@ -189,9 +220,10 @@ private:
|
|||
JUCE_DECLARE_WEAK_REFERENCEABLE (HwndPimpl)
|
||||
|
||||
public:
|
||||
HwndPimpl (Direct2DHwndContext& ownerIn, HWND hwndIn)
|
||||
HwndPimpl (Direct2DHwndContext& ownerIn, HWND hwndIn, SwapchainDelegate& swapDelegate)
|
||||
: Pimpl (ownerIn),
|
||||
hwnd (hwndIn)
|
||||
hwnd (hwndIn),
|
||||
delegate (swapDelegate)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -375,7 +407,7 @@ public:
|
|||
};
|
||||
|
||||
//==============================================================================
|
||||
Direct2DHwndContext::Direct2DHwndContext (HWND windowHandle)
|
||||
Direct2DHwndContext::Direct2DHwndContext (HWND windowHandle, SwapchainDelegate& swapDelegate)
|
||||
{
|
||||
#if JUCE_DIRECT2D_METRICS
|
||||
metrics = new Direct2DMetrics { Direct2DMetricsHub::getInstance()->lock,
|
||||
|
|
@ -384,7 +416,7 @@ Direct2DHwndContext::Direct2DHwndContext (HWND windowHandle)
|
|||
Direct2DMetricsHub::getInstance()->add (metrics);
|
||||
#endif
|
||||
|
||||
pimpl = std::make_unique<HwndPimpl> (*this, windowHandle);
|
||||
pimpl = std::make_unique<HwndPimpl> (*this, windowHandle, swapDelegate);
|
||||
}
|
||||
|
||||
Direct2DHwndContext::~Direct2DHwndContext()
|
||||
|
|
|
|||
|
|
@ -38,7 +38,13 @@ namespace juce
|
|||
class Direct2DHwndContext : public Direct2DGraphicsContext
|
||||
{
|
||||
public:
|
||||
explicit Direct2DHwndContext (HWND windowHandle);
|
||||
struct SwapchainDelegate
|
||||
{
|
||||
virtual ~SwapchainDelegate() = default;
|
||||
virtual void onSwapchainEvent() = 0;
|
||||
};
|
||||
|
||||
Direct2DHwndContext (HWND windowHandle, SwapchainDelegate& swapDelegate);
|
||||
~Direct2DHwndContext() override;
|
||||
|
||||
void handleShowWindow();
|
||||
|
|
|
|||
|
|
@ -5061,7 +5061,8 @@ private:
|
|||
RectangleList<int> deferredRepaints;
|
||||
};
|
||||
|
||||
class D2DRenderContext : public RenderContext
|
||||
class D2DRenderContext : public RenderContext,
|
||||
private Direct2DHwndContext::SwapchainDelegate
|
||||
{
|
||||
public:
|
||||
static constexpr auto name = "Direct2D";
|
||||
|
|
@ -5080,7 +5081,7 @@ public:
|
|||
if (transparent != direct2DContext->supportsTransparency())
|
||||
{
|
||||
direct2DContext.reset();
|
||||
direct2DContext = getContextForPeer (peer);
|
||||
direct2DContext = getContextForPeer (peer, *this);
|
||||
}
|
||||
|
||||
if (direct2DContext->supportsTransparency())
|
||||
|
|
@ -5129,6 +5130,11 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
void onSwapchainEvent() override
|
||||
{
|
||||
handleDirect2DPaint();
|
||||
}
|
||||
|
||||
struct WrappedD2DHwndContextBase
|
||||
{
|
||||
virtual ~WrappedD2DHwndContextBase() = default;
|
||||
|
|
@ -5159,7 +5165,8 @@ private:
|
|||
class WrappedD2DHwndContext : public WrappedD2DHwndContextBase
|
||||
{
|
||||
public:
|
||||
explicit WrappedD2DHwndContext (HWND hwnd) : ctx (hwnd) {}
|
||||
WrappedD2DHwndContext (HWND hwnd, SwapchainDelegate& swapDelegate)
|
||||
: ctx (hwnd, swapDelegate) {}
|
||||
|
||||
void addDeferredRepaint (Rectangle<int> area) override
|
||||
{
|
||||
|
|
@ -5475,17 +5482,18 @@ private:
|
|||
#endif
|
||||
}
|
||||
|
||||
static std::unique_ptr<WrappedD2DHwndContextBase> getContextForPeer (HWNDComponentPeer& peer)
|
||||
static std::unique_ptr<WrappedD2DHwndContextBase> getContextForPeer (HWNDComponentPeer& peer,
|
||||
SwapchainDelegate& delegate)
|
||||
{
|
||||
if (peer.getTransparencyKind() != HWNDComponentPeer::TransparencyKind::opaque)
|
||||
return std::make_unique<WrappedD2DHwndContextTransparent> (peer);
|
||||
|
||||
return std::make_unique<WrappedD2DHwndContext> (peer.getHWND());
|
||||
return std::make_unique<WrappedD2DHwndContext> (peer.getHWND(), delegate);
|
||||
}
|
||||
|
||||
HWNDComponentPeer& peer;
|
||||
|
||||
std::unique_ptr<WrappedD2DHwndContextBase> direct2DContext = getContextForPeer (peer);
|
||||
std::unique_ptr<WrappedD2DHwndContextBase> direct2DContext = getContextForPeer (peer, *this);
|
||||
UpdateRegion updateRegion;
|
||||
|
||||
#if JUCE_ETW_TRACELOGGING
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue