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

Submitted by Yuri Benditovich on Feb. 12, 2017, 1:09 p.m.

Details

Message ID 1486904994-169784-4-git-send-email-yuri.benditovich@daynix.com
State New
Headers show
Series "Changes for Win10 HLK test" ( rev: 1 ) in Spice

Not browsing as part of any series.

Commit Message

Yuri Benditovich Feb. 12, 2017, 1:09 p.m.
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@daynix.com>
---
 qxldod/QxlDod.cpp | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 qxldod/QxlDod.h   |  7 ++++++
 2 files changed, 71 insertions(+)

Patch hide | download patch | download mbox

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