From 4966051e9643504bc58f519e97a468a54df2072e Mon Sep 17 00:00:00 2001 From: Aleksandar Andrejevic Date: Sat, 27 Aug 2016 21:55:34 +0000 Subject: [PATCH] [NTVDM] Move the framebuffer update to the start of the display cycle to reduce tearing. Stabilize the IPS calculation. svn path=/trunk/; revision=72477 --- reactos/subsystems/mvdm/ntvdm/clock.c | 33 +++++++++---------- reactos/subsystems/mvdm/ntvdm/clock.h | 7 ++-- .../mvdm/ntvdm/hardware/video/svga.c | 26 +++++---------- 3 files changed, 29 insertions(+), 37 deletions(-) diff --git a/reactos/subsystems/mvdm/ntvdm/clock.c b/reactos/subsystems/mvdm/ntvdm/clock.c index 84d63915e90..d38d4792f7a 100644 --- a/reactos/subsystems/mvdm/ntvdm/clock.c +++ b/reactos/subsystems/mvdm/ntvdm/clock.c @@ -38,8 +38,6 @@ /* VARIABLES ******************************************************************/ static LIST_ENTRY Timers; -static ULONGLONG Cycles = 0ULL; -static ULONGLONG CurrentIps = 20000000ULL; // 20 MIPS is a good estimate static LARGE_INTEGER StartPerfCount, Frequency; // static ULONG StartTickCount; static LARGE_INTEGER Counter; @@ -47,17 +45,28 @@ static ULONG CurrentTickCount; static ULONGLONG LastCycles = 0ULL; static PHARDWARE_TIMER IpsTimer; +ULONGLONG CurrentCycleCount = 0ULL; +ULONGLONG CurrentIps = 20000000ULL; // 20 MIPS is a good estimate + /* PRIVATE FUNCTIONS **********************************************************/ static VOID FASTCALL IpsCallback(ULONGLONG ElapsedTime) { - CurrentIps = (Cycles - LastCycles) / ElapsedTime; + static INT NumCalls = 0; + + ULONGLONG NewIps = 10ULL * (CurrentCycleCount - LastCycles) / ElapsedTime; + CurrentIps = (CurrentIps + NewIps) >> 1; #ifdef IPS_DISPLAY - DPRINT1("NTVDM: %I64u Instructions Per Second\n", CurrentIps); + NumCalls++; + if (NumCalls == 10) + { + DPRINT1("NTVDM: %I64u Instructions Per Second\n", CurrentIps); + NumCalls = 0; + } #endif - LastCycles = Cycles; + LastCycles = CurrentCycleCount; } /* PUBLIC FUNCTIONS ***********************************************************/ @@ -81,7 +90,7 @@ VOID ClockUpdate(VOID) for (i = 0; VdmRunning && CpuRunning && (i < STEPS_PER_CYCLE); i++) { CpuStep(); - ++Cycles; + ++CurrentCycleCount; } Entry = Timers.Flink; @@ -205,16 +214,6 @@ VOID DestroyHardwareTimer(PHARDWARE_TIMER Timer) } } -ULONGLONG GetCycleCount(VOID) -{ - return Cycles; -} - -ULONGLONG GetCycleSpeed(VOID) -{ - return CurrentIps; -} - BOOLEAN ClockInitialize(VOID) { InitializeListHead(&Timers); @@ -231,7 +230,7 @@ BOOLEAN ClockInitialize(VOID) /* Find the starting tick count */ // StartTickCount = GetTickCount(); - IpsTimer = CreateHardwareTimer(HARDWARE_TIMER_ENABLED, HZ_TO_NS(1), IpsCallback); + IpsTimer = CreateHardwareTimer(HARDWARE_TIMER_ENABLED, HZ_TO_NS(10), IpsCallback); if (IpsTimer == NULL) { wprintf(L"FATAL: Cannot create IPS timer.\n"); diff --git a/reactos/subsystems/mvdm/ntvdm/clock.h b/reactos/subsystems/mvdm/ntvdm/clock.h index f5d04e5e989..2a1f41586a8 100644 --- a/reactos/subsystems/mvdm/ntvdm/clock.h +++ b/reactos/subsystems/mvdm/ntvdm/clock.h @@ -33,20 +33,21 @@ typedef struct _HARDWARE_TIMER /* FUNCTIONS ******************************************************************/ +extern ULONGLONG CurrentCycleCount; +extern ULONGLONG CurrentIps; + PHARDWARE_TIMER CreateHardwareTimer ( ULONG Flags, ULONGLONG Delay, /* nanoseconds */ PHARDWARE_TIMER_PROC Callback ); + VOID EnableHardwareTimer(PHARDWARE_TIMER Timer); VOID DisableHardwareTimer(PHARDWARE_TIMER Timer); VOID SetHardwareTimerDelay(PHARDWARE_TIMER Timer, ULONGLONG NewDelay); VOID DestroyHardwareTimer(PHARDWARE_TIMER Timer); -ULONGLONG GetCycleCount(VOID); -ULONGLONG GetCycleSpeed(VOID); - VOID ClockUpdate(VOID); BOOLEAN ClockInitialize(VOID); diff --git a/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.c b/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.c index 754de9e9744..c88dc5dc02f 100644 --- a/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.c +++ b/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.c @@ -1104,8 +1104,8 @@ static BYTE WINAPI VgaReadPort(USHORT Port) { BYTE Result = 0; BOOLEAN Vsync, Hsync; - ULONGLONG Cycles = GetCycleCount(); - ULONG CyclesPerMicrosecond = (ULONG)((GetCycleSpeed() + 500000ULL) / 1000000ULL); + ULONGLONG Cycles = CurrentCycleCount; + ULONG CyclesPerMicrosecond = (ULONG)((CurrentIps + 500000ULL) / 1000000ULL); ULONG Dots = (VgaSeqRegisters[VGA_SEQ_CLOCK_REG] & 1) ? 9 : 8; ULONG Clock = VgaGetClockFrequency() / 1000000; ULONG HblankStart, HblankEnd; @@ -1624,38 +1624,29 @@ static VOID FASTCALL VgaHorizontalRetrace(ULONGLONG ElapsedTime) { ULONG VerticalTotal = VgaCrtcRegisters[VGA_CRTC_VERT_TOTAL_REG]; ULONG VerticalRetraceStart = VgaCrtcRegisters[VGA_CRTC_START_VERT_RETRACE_REG]; - ULONG VerticalRetraceEnd; - BOOLEAN BeforeVSyncStart, BeforeVSyncEnd; - ULONG CurrentCycleCount = GetCycleCount(); + BOOLEAN BeforeVSync; ULONG ElapsedCycles = CurrentCycleCount - HorizontalRetraceCycle; ULONG Dots = (VgaSeqRegisters[VGA_SEQ_CLOCK_REG] & 1) ? 9 : 8; ULONG HorizTotalDots = ((ULONG)VgaCrtcRegisters[VGA_CRTC_HORZ_TOTAL_REG] + 5) * Dots; ULONG HSyncsPerSecond = VgaGetClockFrequency() / HorizTotalDots; - ULONG HSyncs = (ElapsedCycles * HSyncsPerSecond) / GetCycleSpeed(); + ULONG HSyncs = (ElapsedCycles * HSyncsPerSecond + (CurrentIps >> 1)) / CurrentIps; UNREFERENCED_PARAMETER(ElapsedTime); if (HSyncs == 0) HSyncs = 1; - + VerticalTotal |= (VgaCrtcRegisters[VGA_CRTC_OVERFLOW_REG] & VGA_CRTC_OVERFLOW_VT8) << 8; VerticalTotal |= (VgaCrtcRegisters[VGA_CRTC_OVERFLOW_REG] & VGA_CRTC_OVERFLOW_VT9) << 4; VerticalRetraceStart |= (VgaCrtcRegisters[VGA_CRTC_OVERFLOW_REG] & VGA_CRTC_OVERFLOW_VRS8) << 6; VerticalRetraceStart |= (VgaCrtcRegisters[VGA_CRTC_OVERFLOW_REG] & VGA_CRTC_OVERFLOW_VRS9) << 2; - VerticalRetraceEnd = VerticalRetraceStart + (VgaCrtcRegisters[VGA_CRTC_END_VERT_RETRACE_REG] & 0x0F); - /* Set the cycle */ HorizontalRetraceCycle = CurrentCycleCount; /* Increment the scanline counter, but make sure we don't skip any part of the vertical retrace */ - BeforeVSyncStart = (ScanlineCounter < VerticalRetraceStart); - BeforeVSyncEnd = (ScanlineCounter < VerticalRetraceEnd); + BeforeVSync = (ScanlineCounter < VerticalRetraceStart); ScanlineCounter += HSyncs; - if (BeforeVSyncStart && ScanlineCounter >= VerticalRetraceStart) ScanlineCounter = VerticalRetraceStart; - else if (BeforeVSyncEnd && ScanlineCounter >= VerticalRetraceEnd) ScanlineCounter = VerticalRetraceEnd; - - /* The scanline counter wraps around */ - ScanlineCounter %= VerticalTotal; + if (BeforeVSync && ScanlineCounter >= VerticalRetraceStart) ScanlineCounter = VerticalRetraceStart; if (ScanlineCounter == VerticalRetraceStart) { @@ -1673,8 +1664,9 @@ static VOID FASTCALL VgaHorizontalRetrace(ULONGLONG ElapsedTime) + ((VgaCrtcRegisters[VGA_CRTC_PRESET_ROW_SCAN_REG] >> 5) & 3); } - if (ScanlineCounter == VerticalRetraceEnd) + if (ScanlineCounter > VerticalTotal) { + ScanlineCounter = 0; VgaVerticalRetrace(); } }