mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
[NTVDM]
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:
parent
e5bc9e5062
commit
4966051e96
3 changed files with 29 additions and 37 deletions
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue