> On Thu, Feb 16, 2017 at 5:54 PM, Frediano Ziglio < fzig...@redhat.com > > wrote:
> > > > > > > In case the driver supports VSync control feature, it > > > > maintains timer for VSync interrupt indication. > > > > In further commits this timer will be started upon > > > > class driver request. The interrupt notification and > > > > related DPC do not access device registers. > > > > > > > > Signed-off-by: Yuri Benditovich < yuri.benditov...@daynix.com > > > > > --- > > > > qxldod/QxlDod.cpp | 82 > > > > +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > > > > qxldod/QxlDod.h | 14 ++++++++++ > > > > 2 files changed, 96 insertions(+) > > > > > > > > diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp > > > > index cd22446..9175300 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; > > > > } > > > > > > > > @@ -518,6 +525,7 @@ NTSTATUS QxlDod::QueryAdapterInfo(_In_ CONST > > > > DXGKARG_QUERYADAPTERINFO* pQueryAda > > > > pDriverCaps->PointerCaps.Color = 1; > > > > > > > > pDriverCaps->SupportNonVGA = m_pHWDevice->IsBIOSCompatible(); > > > > + pDriverCaps->SchedulingCaps.VSyncPowerSaveAware = > > > > g_bSupportVSync; > > > > > > > I think we could set this to TRUE. If OS supports VSync will deactivate > > > if not should do nothing or try to deactivate. > > > Could be if set to FALSE that OS still expect VSync coming or don't > > > enable some energy saving policy. > > Setting it to TRUE when VSync is not supported may create some side-effect in > Windows, > as this combination is not expected. Setting it to FALSE when VSync is > supported also does > not make too much sense as then the driver will send indications also when > the system > is completely inactive. So, only meaningful choice for us is to keep it equal > to VSync control. > > > DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s 1\n", __FUNCTION__)); > > > > return STATUS_SUCCESS; > > > > @@ -4813,6 +4821,14 @@ BOOLEAN QxlDevice::InterruptRoutine(_In_ > > > > PDXGKRNL_INTERFACE pDxgkInterface, _In_ > > > > } > > > > > > > > QXL_NON_PAGED > > > > +VOID QxlDevice::VSyncInterruptPostProcess(_In_ PDXGKRNL_INTERFACE > > > > pDxgkInterface) > > > > +{ > > > > + if (!pDxgkInterface->DxgkCbQueueDpc(pDxgkInterface->DeviceHandle)) { > > > > + DbgPrint(TRACE_LEVEL_WARNING, ("---> %s can't enqueue DPC, pending > > > > interrupts %X\n", __FUNCTION__, m_Pending)); > > > > + } > > > > +} > > > > + > > > > +QXL_NON_PAGED > > > > VOID QxlDevice::DpcRoutine(PVOID) > > > > { > > > > LONG intStatus = InterlockedExchange(&m_Pending, 0); > > > > @@ -4914,3 +4930,69 @@ NTSTATUS > > > > HwDeviceInterface::AcquireDisplayInfo(DXGK_DISPLAY_INFORMATION& DispInf > > > > } > > > > return Status; > > > > } > > > > + > > > > +// Vga device does not generate interrupts > > > > +QXL_NON_PAGED VOID VgaDevice::VSyncInterruptPostProcess(_In_ > > > > PDXGKRNL_INTERFACE pxface) > > > > +{ > > > > + pxface->DxgkCbQueueDpc(pxface->DeviceHandle); > > > > +} > > > > + > > > > +QXL_NON_PAGED VOID QxlDod::IndicateVSyncInterrupt() > > > > +{ > > > Maybe is more flexible if this function returns BOOLEAN. > > > > + DXGKARGCB_NOTIFY_INTERRUPT_DATA data = {}; > > > > + data.InterruptType = DXGK_INTERRUPT_DISPLAYONLY_VSYNC; > > > > + m_DxgkInterface.DxgkCbNotifyInterrupt(m_DxgkInterface.DeviceHandle, > > > > &data); > > > > + m_pHWDevice->VSyncInterruptPostProcess(&m_DxgkInterface); > > > > +} > > > > + > > > > +QXL_NON_PAGED BOOLEAN QxlDod::VsyncTimerSynchRoutine(PVOID context) > > > > +{ > > > > + QxlDod* pQxl = reinterpret_cast<QxlDod*>(context); > > > > + pQxl->IndicateVSyncInterrupt(); > > > > + return FALSE; > > > Here would be > > > return pQxl->IndicateVSyncInterrupt(); > > > so we could handle the return value from the member function (if needed > > > in the future). > > This procedure currently returns boolean just because Windows > synch routine prototype defined such a way without any reason. > There is no meaningful information that we can pass back on this boolean. > When synch procedure needs to return something little bigger than boolean, > local context passed to the routine does the job. > > > +} > > > > + > > > > +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, > > > > + VsyncTimerSynchRoutine, > > > > + this, > > > > + 0, > > > > + &bDummy > > > > + ); > > > > + INCREMENT_VSYNC_COUNTER(&m_VsyncFiredCounter); > > > > + } > > > > +} > > > > + > > > > +VOID QxlDod::EnableVsync(BOOLEAN bEnable) > > > > +{ > > > > + PAGED_CODE(); > > > > + if (g_bSupportVSync) > > > > + { > > > > + m_bVsyncEnabled = bEnable; > > > > + if (!m_bVsyncEnabled) > > > > + { > > > > + DbgPrint(TRACE_LEVEL_WARNING, ("Disabled VSync(fired %d)\n", > > > > InterlockedExchange(&m_VsyncFiredCounter, 0))); > > > > + 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 53724e8..9cfb6de 100755 > > > > --- a/qxldod/QxlDod.h > > > > +++ b/qxldod/QxlDod.h > > > > @@ -239,6 +239,7 @@ public: > > > > QXL_NON_PAGED virtual BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE > > > > pDxgkInterface, _In_ ULONG MessageNumber) = 0; > > > > QXL_NON_PAGED virtual VOID DpcRoutine(PVOID) = 0; > > > > QXL_NON_PAGED virtual VOID ResetDevice(void) = 0; > > > > + QXL_NON_PAGED virtual VOID VSyncInterruptPostProcess(_In_ > > > > PDXGKRNL_INTERFACE) = 0; > > > > virtual NTSTATUS AcquireFrameBuffer(CURRENT_BDD_MODE* pCurrentBddMode) { > > > > return STATUS_SUCCESS; } > > > > virtual NTSTATUS ReleaseFrameBuffer(CURRENT_BDD_MODE* pCurrentBddMode) { > > > > return STATUS_SUCCESS; } > > > > > > > > @@ -306,6 +307,7 @@ public: > > > > QXL_NON_PAGED BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE > > > > pDxgkInterface, _In_ ULONG MessageNumber); > > > > QXL_NON_PAGED VOID DpcRoutine(PVOID); > > > > QXL_NON_PAGED VOID ResetDevice(VOID); > > > > + QXL_NON_PAGED VOID VSyncInterruptPostProcess(_In_ PDXGKRNL_INTERFACE); > > > > NTSTATUS AcquireFrameBuffer(CURRENT_BDD_MODE* pCurrentBddMode); > > > > NTSTATUS ReleaseFrameBuffer(CURRENT_BDD_MODE* pCurrentBddMode); > > > > NTSTATUS SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* > > > > pSetPointerShape); > > > > @@ -358,8 +360,10 @@ enum { > > > > > > > > #ifdef DBG > > > > #define RESOURCE_TYPE(res, val) do { res->type = val; } while (0) > > > > +#define INCREMENT_VSYNC_COUNTER(counter) InterlockedIncrement(counter) > > > > #else > > > > #define RESOURCE_TYPE(res, val) > > > > +#define INCREMENT_VSYNC_COUNTER(counter) > > > > #endif > > > > > > > > typedef struct Resource Resource; > > > > @@ -480,6 +484,7 @@ public: > > > > QXL_NON_PAGED BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE > > > > pDxgkInterface, _In_ ULONG MessageNumber); > > > > QXL_NON_PAGED VOID DpcRoutine(PVOID); > > > > QXL_NON_PAGED VOID ResetDevice(VOID); > > > > + QXL_NON_PAGED VOID VSyncInterruptPostProcess(_In_ PDXGKRNL_INTERFACE); > > > > NTSTATUS SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* > > > > pSetPointerShape); > > > > NTSTATUS SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* > > > > pSetPointerPosition); > > > > NTSTATUS Escape(_In_ CONST DXGKARG_ESCAPE* pEscap); > > > > @@ -622,6 +627,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); > > > > @@ -719,6 +728,7 @@ public: > > > > { > > > > return > > > > m_DxgkInterface.DxgkCbAcquirePostDisplayOwnership(m_DxgkInterface.DeviceHandle, > > > > &DispInfo); > > > > } > > > > + VOID EnableVsync(BOOLEAN bEnable); > > > > private: > > > > VOID CleanUp(VOID); > > > > NTSTATUS CheckHardware(); > > > > @@ -744,6 +754,10 @@ 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); > > > > + QXL_NON_PAGED VOID IndicateVSyncInterrupt(); > > > > + static QXL_NON_PAGED BOOLEAN VsyncTimerSynchRoutine(PVOID context); > > > > }; > > > > > > > > NTSTATUS > > > Otherwise looks good. > Acked-by: Frediano Ziglio <fzig...@redhat.com> Frediano
_______________________________________________ Spice-devel mailing list Spice-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/spice-devel