Preparation for synchronization of changing display mode and sending drawable objects to the host. Signed-off-by: Yuri Benditovich <yuri.benditovich@xxxxxxxxxx> --- qxldod/QxlDod.h | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index b524577..63cb3d7 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -506,6 +506,106 @@ typedef struct DpcCbContext { #define MAX(x, y) (((x) >= (y)) ? (x) : (y)) #define ALIGN(a, b) (((a) + ((b) - 1)) & ~((b) - 1)) +class RenderingStateMachine +{ +public: + void Start() + { + PAGED_CODE(); + QXL_ASSERT(m_State == FlowState::Stopped); + InterlockedIncrement(&m_Counter); + m_State = FlowState::Running; + InterlockedAnd(&m_Counter, ~StoppedMask); + } + + void Stop() + { + PAGED_CODE(); + QXL_ASSERT(m_State == FlowState::Running); + m_State = FlowState::Stopping; + KeClearEvent(&m_NoOutstandingItems); + InterlockedOr(&m_Counter, StoppedMask); + UnregisterOutstandingItem(__FUNCTION__); + WaitForObject(&m_NoOutstandingItems, NULL); + } + + bool RegisterOutstandingItem() + { + PAGED_CODE(); + auto value = InterlockedIncrement(&m_Counter); + if (value & StoppedMask) + { + value = InterlockedDecrement(&m_Counter); + if (value == StoppedMask) + { + CompleteStopping(__FUNCTION__); + } + return false; + } + return true; + } + + void UnregisterOutstandingItem(LPCSTR from) + { + PAGED_CODE(); + QXL_ASSERT(m_State != FlowState::Stopped); + LONG value = InterlockedDecrement(&m_Counter); + if (value == StoppedMask) + { + CompleteStopping(from); + } + else if (value) + { + // common case, one or more drawables pushed, StoppedMask not set + // also pushing not last drawable during mode set (StoppedMask set) + } + else + { + // illegal case + QXL_ASSERT(value != 0); + } + } + + RenderingStateMachine() + { + PAGED_CODE(); + m_Counter = 1; + KeInitializeMutex(&m_CompleteStoppingMutex, 0); + KeInitializeEvent(&m_NoOutstandingItems, SynchronizationEvent, FALSE); + } + ~RenderingStateMachine() = default; + RenderingStateMachine(const RenderingStateMachine&) = delete; + RenderingStateMachine& operator= (const RenderingStateMachine&) = delete; + +private: + void CompleteStopping(LPCSTR from) + { + PAGED_CODE(); + WaitForObject(&m_CompleteStoppingMutex, NULL); + if (m_State == FlowState::Stopping) + { + DbgPrint(TRACE_LEVEL_WARNING, ("%s: from %s\n", __FUNCTION__, from)); + m_State = FlowState::Stopped; + KeSetEvent(&m_NoOutstandingItems, IO_NO_INCREMENT, FALSE); + } + ReleaseMutex(&m_CompleteStoppingMutex, TRUE); + } + + enum { StoppedMask = 0x40000000 }; + + using FlowState = enum + { + Running, + Stopping, + Stopped + }; + + LONG m_Counter; + FlowState m_State = FlowState::Running; + KEVENT m_NoOutstandingItems; + KMUTEX m_CompleteStoppingMutex; +}; + #include "start-packed.h" SPICE_RING_DECLARE(QXLPresentOnlyRing, QXLDrawable**, 1024); #include "end-packed.h" -- 2.7.0.windows.1 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel