blob: b47876156730e733b694160cd2981b8921355fc3 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "sky/services/vsync/ios/vsync_provider_impl.h"
#include <Foundation/Foundation.h>
#include <QuartzCore/CADisplayLink.h>
#include <mach/mach_time.h>
@interface VSyncClient : NSObject
@end
static inline uint64_t CurrentTimeMicrosSeconds() {
static mach_timebase_info_data_t timebase = {0};
if (timebase.denom == 0) {
(void)mach_timebase_info(&timebase);
}
return (mach_absolute_time() * 1e-3 * timebase.numer) / timebase.denom;
}
@implementation VSyncClient {
CADisplayLink* _displayLink;
::vsync::VSyncProvider::AwaitVSyncCallback _pendingCallback;
}
- (instancetype)init {
self = [super init];
if (self) {
_displayLink = [[CADisplayLink
displayLinkWithTarget:self
selector:@selector(onDisplayLink:)] retain];
_displayLink.paused = YES;
[_displayLink addToRunLoop:[NSRunLoop currentRunLoop]
forMode:NSRunLoopCommonModes];
}
return self;
}
- (void)await:(::vsync::VSyncProvider::AwaitVSyncCallback)callback {
_pendingCallback = callback;
_displayLink.paused = NO;
}
- (void)onDisplayLink:(CADisplayLink*)link {
_displayLink.paused = YES;
_pendingCallback.Run(CurrentTimeMicrosSeconds());
}
- (void)dealloc {
[_displayLink invalidate];
[_displayLink release];
[super dealloc];
}
@end
namespace sky {
namespace services {
namespace vsync {
VsyncProviderImpl::VsyncProviderImpl(
mojo::InterfaceRequest<::vsync::VSyncProvider> request)
: binding_(this, request.Pass()), client_([[VSyncClient alloc] init]) {}
VsyncProviderImpl::~VsyncProviderImpl() {
[client_ release];
}
void VsyncProviderImpl::AwaitVSync(const AwaitVSyncCallback& callback) {
[client_ await:callback];
}
void VSyncProviderFactory::Create(
mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<::vsync::VSyncProvider> request) {
new VsyncProviderImpl(request.Pass());
}
} // namespace vsync
} // namespace services
} // namespace sky