[Spice-devel] [PATCH 3/7] qxl-wddm-dod: Timer-based VSync interrupt indication

Yuri Benditovich yuri.benditovich at daynix.com
Sun Feb 12 13:09:50 UTC 2017


In case the driver supports VSync control feature the driver
maintains timer for VSync interrupt indication.
In further commits this timer can be started upon class
driver request.

Signed-off-by: Yuri Benditovich <yuri.benditovich at daynix.com>
---
 qxldod/QxlDod.cpp | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 qxldod/QxlDod.h   |  7 ++++++
 2 files changed, 71 insertions(+)

diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp
index c956fd5..78d4340 100755
--- a/qxldod/QxlDod.cpp
+++ b/qxldod/QxlDod.cpp
@@ -82,6 +82,12 @@ QxlDod::QxlDod(_In_ DEVICE_OBJECT* pPhysicalDeviceObject) : m_pPhysicalDevice(pP
     RtlZeroMemory(m_CurrentModes, sizeof(m_CurrentModes));
     RtlZeroMemory(&m_PointerShape, sizeof(m_PointerShape));
     m_pHWDevice = NULL;
+
+    KeInitializeDpc(&m_VsyncTimerDpc, VsyncTimerProcGate, this);
+    KeInitializeTimer(&m_VsyncTimer);
+    m_VsyncFiredCounter = 0;
+    m_bVsyncEnabled = FALSE;
+
     DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__));
 }
 
@@ -198,6 +204,7 @@ NTSTATUS QxlDod::StopDevice(VOID)
 {
     PAGED_CODE();
     m_Flags.DriverStarted = FALSE;
+    EnableVsync(FALSE);
     return STATUS_SUCCESS;
 }
 
@@ -462,6 +469,7 @@ NTSTATUS QxlDod::QueryAdapterInfo(_In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAda
             pDriverCaps->PointerCaps.Color = 1;
 
             pDriverCaps->SupportNonVGA = m_pHWDevice->IsBIOSCompatible();
+            pDriverCaps->SchedulingCaps.VSyncPowerSaveAware = g_bSupportVSync;
 
             DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s 1\n", __FUNCTION__));
             return STATUS_SUCCESS;
@@ -4889,3 +4897,59 @@ NTSTATUS HwDeviceInterface::AcquireDisplayInfo(DXGK_DISPLAY_INFORMATION& DispInf
     }
     return Status;
 }
+
+QXL_NON_PAGED static BOOLEAN VSynchRoutine(PVOID context)
+{
+    DXGKRNL_INTERFACE *pxface = (DXGKRNL_INTERFACE *)context;
+    DXGKARGCB_NOTIFY_INTERRUPT_DATA data = {};
+    data.InterruptType = DXGK_INTERRUPT_DISPLAYONLY_VSYNC;
+    pxface->DxgkCbNotifyInterrupt(pxface->DeviceHandle, &data);
+    pxface->DxgkCbQueueDpc(pxface->DeviceHandle);
+    return 0;
+}
+
+QXL_NON_PAGED VOID QxlDod::VsyncTimerProc()
+{
+    BOOLEAN bDummy;
+    DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
+    if (m_bVsyncEnabled && m_AdapterPowerState == PowerDeviceD0)
+    {
+        m_DxgkInterface.DxgkCbSynchronizeExecution(
+            m_DxgkInterface.DeviceHandle,
+            VSynchRoutine,
+            &m_DxgkInterface,
+            0,
+            &bDummy
+        );
+        InterlockedIncrement(&m_VsyncFiredCounter);
+    }
+}
+
+VOID QxlDod::EnableVsync(BOOLEAN bEnable)
+{
+    PAGED_CODE();
+    if (g_bSupportVSync)
+    {
+        m_bVsyncEnabled = bEnable;
+        if (!m_bVsyncEnabled)
+        {
+            LONG counter = InterlockedExchange(&m_VsyncFiredCounter, 0);
+            DbgPrint(TRACE_LEVEL_WARNING, ("Disabled VSync(fired %d)\n", counter));
+            KeCancelTimer(&m_VsyncTimer);
+        }
+        else
+        {
+            LARGE_INTEGER li;
+            LONG period = 1000 / VSYNC_RATE;
+            DbgPrint(TRACE_LEVEL_WARNING, ("Enabled VSync(fired %d)\n", m_VsyncFiredCounter));
+            li.QuadPart = -10000000 / VSYNC_RATE;
+            KeSetTimerEx(&m_VsyncTimer, li, period, &m_VsyncTimerDpc);
+        }
+    }
+}
+
+QXL_NON_PAGED VOID QxlDod::VsyncTimerProcGate(_In_ _KDPC *dpc, _In_ PVOID context, _In_ PVOID arg1, _In_ PVOID arg2)
+{
+    QxlDod* pQxl = reinterpret_cast<QxlDod*>(context);
+    pQxl->VsyncTimerProc();
+}
diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h
index 4598718..005aaed 100755
--- a/qxldod/QxlDod.h
+++ b/qxldod/QxlDod.h
@@ -624,6 +624,10 @@ private:
     DXGKARG_SETPOINTERSHAPE m_PointerShape;
 
     HwDeviceInterface* m_pHWDevice;
+    KTIMER m_VsyncTimer;
+    KDPC   m_VsyncTimerDpc;
+    BOOLEAN m_bVsyncEnabled;
+    LONG m_VsyncFiredCounter;
 public:
     QxlDod(_In_ DEVICE_OBJECT* pPhysicalDeviceObject);
     ~QxlDod(void);
@@ -721,6 +725,7 @@ public:
     {
         return m_DxgkInterface.DxgkCbAcquirePostDisplayOwnership(m_DxgkInterface.DeviceHandle, &DispInfo);
     }
+    VOID EnableVsync(BOOLEAN bEnable);
 private:
     VOID CleanUp(VOID);
     NTSTATUS CheckHardware();
@@ -746,6 +751,8 @@ private:
     NTSTATUS IsVidPnSourceModeFieldsValid(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMode) const;
     NTSTATUS IsVidPnPathFieldsValid(CONST D3DKMDT_VIDPN_PRESENT_PATH* pPath) const;
     NTSTATUS RegisterHWInfo(_In_ ULONG Id);
+    QXL_NON_PAGED VOID VsyncTimerProc();
+    static QXL_NON_PAGED VOID VsyncTimerProcGate(_In_ _KDPC *dpc, _In_ PVOID context, _In_ PVOID arg1, _In_ PVOID arg2);
 };
 
 NTSTATUS
-- 
2.7.0.windows.1



More information about the Spice-devel mailing list