mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-28 07:29:45 +00:00
Moves drawing into the next timer tick after retrace if sync locked.
... which should mean it occurs within 1/600th of a second of announced retrace, which I assume always will be less than the retrace period. So: does the frame buffer update during retrace. This should completely eliminate tearing for machines that can be synced to the native output rate.
This commit is contained in:
parent
7c0f3bb237
commit
b76a5870b3
@ -67,7 +67,7 @@
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
buildConfiguration = "Release"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
enableASanStackUseAfterReturn = "YES"
|
||||
|
@ -157,6 +157,7 @@ struct ActivityObserver: public Activity::Observer {
|
||||
int64_t _syncTime;
|
||||
int64_t _timeDiff;
|
||||
double _refreshPeriod;
|
||||
BOOL _isSyncLocking;
|
||||
|
||||
std::unique_ptr<Outputs::Display::OpenGL::ScanTarget> _scanTarget;
|
||||
}
|
||||
@ -712,6 +713,7 @@ struct ActivityObserver: public Activity::Observer {
|
||||
const auto timeNow = std::chrono::high_resolution_clock::now().time_since_epoch().count();
|
||||
|
||||
CGSize pixelSize = view.backingSize;
|
||||
BOOL isSyncLocking;
|
||||
@synchronized(self) {
|
||||
// Store a means to map from CVTimeStamp.hostTime to std::chrono::high_resolution_clock;
|
||||
// there is an extremely dodgy assumption here that both are in the same units (and, below, that both as in ns).
|
||||
@ -727,12 +729,17 @@ struct ActivityObserver: public Activity::Observer {
|
||||
|
||||
// Set the current refresh period.
|
||||
_refreshPeriod = double(now->videoRefreshPeriod) / double(now->videoTimeScale);
|
||||
|
||||
// Determine where responsibility lies for drawing.
|
||||
isSyncLocking = _isSyncLocking;
|
||||
}
|
||||
|
||||
// Draw the current output. (TODO: do this within the timer if either raster racing or, at least, sync matching).
|
||||
[self.view performWithGLContext:^{
|
||||
self->_scanTarget->draw((int)pixelSize.width, (int)pixelSize.height);
|
||||
} flushDrawable:YES];
|
||||
if(!isSyncLocking) {
|
||||
[self.view performWithGLContext:^{
|
||||
self->_scanTarget->draw((int)pixelSize.width, (int)pixelSize.height);
|
||||
} flushDrawable:YES];
|
||||
}
|
||||
}
|
||||
|
||||
#define TICKS 600
|
||||
@ -766,6 +773,7 @@ struct ActivityObserver: public Activity::Observer {
|
||||
splitAndSync = ratio <= maximumAdjustment && ratio >= 1 / maximumAdjustment;
|
||||
}
|
||||
}
|
||||
self->_isSyncLocking = splitAndSync;
|
||||
|
||||
// If the time window is being split, run up to the split, then check out machine speed, possibly
|
||||
// adjusting multiplier, then run after the split.
|
||||
@ -804,19 +812,19 @@ struct ActivityObserver: public Activity::Observer {
|
||||
// a concluding draw. Implicit assumption here: whatever is left to be done in the final window
|
||||
// can be done within the retrace period.
|
||||
auto wasUpdating = self->_isUpdating.test_and_set();
|
||||
// if(wasUpdating && splitAndSync) {
|
||||
// while(self->_isUpdating.test_and_set());
|
||||
// wasUpdating = false;
|
||||
// }
|
||||
if(wasUpdating && splitAndSync) {
|
||||
while(self->_isUpdating.test_and_set());
|
||||
wasUpdating = false;
|
||||
}
|
||||
if(!wasUpdating) {
|
||||
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
|
||||
[self.view performWithGLContext:^{
|
||||
self->_scanTarget->update((int)pixelSize.width, (int)pixelSize.height);
|
||||
|
||||
// if(splitAndSync) {
|
||||
// self->_scanTarget->draw((int)pixelSize.width, (int)pixelSize.height);
|
||||
// }
|
||||
} flushDrawable:NO];
|
||||
if(splitAndSync) {
|
||||
self->_scanTarget->draw((int)pixelSize.width, (int)pixelSize.height);
|
||||
}
|
||||
} flushDrawable:splitAndSync];
|
||||
self->_isUpdating.clear();
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user