Move the framebuffer update to the start of the display cycle to reduce tearing.
Stabilize the IPS calculation.


svn path=/trunk/; revision=72477
This commit is contained in:
Aleksandar Andrejevic 2016-08-27 21:55:34 +00:00
parent e5bc9e5062
commit 4966051e96
3 changed files with 29 additions and 37 deletions

View file

@ -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");

View file

@ -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);

View file

@ -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();
}
}