[Spice-devel] [RFC qxl-wddm-dod 2/3] Implement rendering state machine
Yuri Benditovich
yuri.benditovich at daynix.com
Sun Apr 16 19:43:02 UTC 2017
Preparation for synchronization of changing display mode and
sending drawable objects to the host.
Signed-off-by: Yuri Benditovich <yuri.benditovich at daynix.com>
---
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
More information about the Spice-devel
mailing list