mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-11 08:30:55 +00:00
Starts towards an implementation of time warping.
This commit is contained in:
parent
e1cbad0b6d
commit
14d976eecb
@ -153,7 +153,9 @@ struct ActivityObserver: public Activity::Observer {
|
|||||||
|
|
||||||
CSHighPrecisionTimer *_timer;
|
CSHighPrecisionTimer *_timer;
|
||||||
CGSize _pixelSize;
|
CGSize _pixelSize;
|
||||||
std::atomic_flag is_updating;
|
std::atomic_flag _isUpdating;
|
||||||
|
int64_t _syncTime;
|
||||||
|
double _refreshPeriod;
|
||||||
|
|
||||||
std::unique_ptr<Outputs::Display::OpenGL::ScanTarget> _scanTarget;
|
std::unique_ptr<Outputs::Display::OpenGL::ScanTarget> _scanTarget;
|
||||||
}
|
}
|
||||||
@ -207,7 +209,7 @@ struct ActivityObserver: public Activity::Observer {
|
|||||||
_speakerDelegate.machineAccessLock = _delegateMachineAccessLock;
|
_speakerDelegate.machineAccessLock = _delegateMachineAccessLock;
|
||||||
|
|
||||||
_joystickMachine = _machine->joystick_machine();
|
_joystickMachine = _machine->joystick_machine();
|
||||||
is_updating.clear();
|
_isUpdating.clear();
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@ -705,11 +707,14 @@ struct ActivityObserver: public Activity::Observer {
|
|||||||
#pragma mark - Timer
|
#pragma mark - Timer
|
||||||
|
|
||||||
- (void)openGLView:(CSOpenGLView *)view didUpdateDisplayLink:(CVDisplayLinkRef)displayLink {
|
- (void)openGLView:(CSOpenGLView *)view didUpdateDisplayLink:(CVDisplayLinkRef)displayLink {
|
||||||
|
_refreshPeriod = CVDisplayLinkGetActualOutputVideoRefreshPeriod(displayLink);
|
||||||
|
NSLog(@"Refresh period: %0.5f (%0.5f)", _refreshPeriod, 1.0 / _refreshPeriod);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)openGLViewDisplayLinkDidFire:(CSOpenGLView *)view {
|
- (void)openGLViewDisplayLinkDidFire:(CSOpenGLView *)view {
|
||||||
CGSize pixelSize = view.backingSize;
|
CGSize pixelSize = view.backingSize;
|
||||||
@synchronized(self) {
|
@synchronized(self) {
|
||||||
|
_syncTime = std::chrono::high_resolution_clock::now().time_since_epoch().count();
|
||||||
_pixelSize = pixelSize;
|
_pixelSize = pixelSize;
|
||||||
}
|
}
|
||||||
[self.view performWithGLContext:^{
|
[self.view performWithGLContext:^{
|
||||||
@ -725,22 +730,48 @@ struct ActivityObserver: public Activity::Observer {
|
|||||||
_timer = [[CSHighPrecisionTimer alloc] initWithTask:^{
|
_timer = [[CSHighPrecisionTimer alloc] initWithTask:^{
|
||||||
const auto timeNow = std::chrono::high_resolution_clock::now().time_since_epoch().count();
|
const auto timeNow = std::chrono::high_resolution_clock::now().time_since_epoch().count();
|
||||||
const auto duration = timeNow - lastTime;
|
const auto duration = timeNow - lastTime;
|
||||||
lastTime = timeNow;
|
|
||||||
|
|
||||||
CGSize pixelSize;
|
CGSize pixelSize;
|
||||||
|
int64_t syncTime;
|
||||||
@synchronized(self) {
|
@synchronized(self) {
|
||||||
|
syncTime = self->_syncTime;
|
||||||
|
|
||||||
|
// If this tick includes vsync then inspect the machine.
|
||||||
|
BOOL splitAndSync = NO;
|
||||||
|
if(timeNow >= self->_syncTime && lastTime < self->_syncTime) {
|
||||||
|
// Grab the scan status and check out the machine's current frame time.
|
||||||
|
// If it's stable and within 3% of a non-zero integer multiple of the
|
||||||
|
// display rate, consider an adjustment.
|
||||||
|
const auto scan_status = self->_machine->crt_machine()->get_scan_status();
|
||||||
|
if(scan_status.field_duration_gradient < 0.00001) {
|
||||||
|
auto ratio = self->_refreshPeriod / scan_status.field_duration;
|
||||||
|
if(ratio > 1.5) {
|
||||||
|
ratio = fmod(ratio, 1.0);
|
||||||
|
if(ratio < 0.5) ratio += 1.0;
|
||||||
|
}
|
||||||
|
splitAndSync = ratio <= 1.03 && ratio >= 0.97;
|
||||||
|
// if(splitAndSync) {
|
||||||
|
// NSLog(@"+: %0.3f %0.3f [%0.5f]", scan_status.field_duration / self->_refreshPeriod, ratio, scan_status.field_duration_gradient);
|
||||||
|
// } else {
|
||||||
|
// NSLog(@"-: %0.3f %0.3f [%0.5f]", scan_status.field_duration / self->_refreshPeriod, ratio, scan_status.field_duration_gradient);
|
||||||
|
// }
|
||||||
|
} // else NSLog(@"e");
|
||||||
|
}
|
||||||
|
|
||||||
self->_machine->crt_machine()->run_for((double)duration / 1e9);
|
self->_machine->crt_machine()->run_for((double)duration / 1e9);
|
||||||
pixelSize = self->_pixelSize;
|
pixelSize = self->_pixelSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!self->is_updating.test_and_set()) {
|
if(!self->_isUpdating.test_and_set()) {
|
||||||
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
|
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
|
||||||
[self.view performWithGLContext:^{
|
[self.view performWithGLContext:^{
|
||||||
self->_scanTarget->update((int)pixelSize.width, (int)pixelSize.height);
|
self->_scanTarget->update((int)pixelSize.width, (int)pixelSize.height);
|
||||||
} flushDrawable:NO];
|
} flushDrawable:NO];
|
||||||
self->is_updating.clear();
|
self->_isUpdating.clear();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lastTime = timeNow;
|
||||||
} interval:uint64_t(1000000000) / uint64_t(TICKS)];
|
} interval:uint64_t(1000000000) / uint64_t(TICKS)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user