1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/renderer_host/display_link_mac.h"
7 #include "base/debug/trace_event.h"
8 #include "base/logging.h"
13 struct ScopedTypeRefTraits<CVDisplayLinkRef> {
14 static void Retain(CVDisplayLinkRef object) {
15 CVDisplayLinkRetain(object);
17 static void Release(CVDisplayLinkRef object) {
18 CVDisplayLinkRelease(object);
27 scoped_refptr<DisplayLinkMac> DisplayLinkMac::Create() {
28 CVReturn ret = kCVReturnSuccess;
30 base::ScopedTypeRef<CVDisplayLinkRef> display_link;
31 ret = CVDisplayLinkCreateWithActiveCGDisplays(display_link.InitializeInto());
32 if (ret != kCVReturnSuccess) {
33 LOG(ERROR) << "CVDisplayLinkCreateWithActiveCGDisplays failed: " << ret;
37 scoped_refptr<DisplayLinkMac> display_link_mac;
38 display_link_mac = new DisplayLinkMac(display_link);
40 ret = CVDisplayLinkSetOutputCallback(
41 display_link_mac->display_link_,
43 display_link_mac.get());
44 if (ret != kCVReturnSuccess) {
45 LOG(ERROR) << "CVDisplayLinkSetOutputCallback failed: " << ret;
49 return display_link_mac;
52 DisplayLinkMac::DisplayLinkMac(
53 base::ScopedTypeRef<CVDisplayLinkRef> display_link)
54 : display_link_(display_link),
56 FROM_HERE, base::TimeDelta::FromSeconds(1),
57 this, &DisplayLinkMac::StopDisplayLink),
58 timebase_and_interval_valid_(false) {
61 DisplayLinkMac::~DisplayLinkMac() {
62 if (CVDisplayLinkIsRunning(display_link_))
63 CVDisplayLinkStop(display_link_);
66 bool DisplayLinkMac::GetVSyncParameters(
67 base::TimeTicks* timebase, base::TimeDelta* interval) {
68 StartOrContinueDisplayLink();
70 base::AutoLock lock(lock_);
71 if (!timebase_and_interval_valid_)
74 *timebase = timebase_;
75 *interval = interval_;
79 void DisplayLinkMac::Tick(const CVTimeStamp* cv_time) {
80 TRACE_EVENT0("browser", "DisplayLinkMac::GetVSyncParameters");
81 base::AutoLock lock(lock_);
83 // Verify that videoRefreshPeriod is 32 bits.
84 DCHECK((cv_time->videoRefreshPeriod & ~0xffffFFFFull) == 0ull);
86 // Verify that the numerator and denominator make some sense.
87 uint32 numerator = static_cast<uint32>(cv_time->videoRefreshPeriod);
88 uint32 denominator = cv_time->videoTimeScale;
89 if (numerator <= 0 || denominator <= 0) {
90 LOG(WARNING) << "Unexpected numerator or denominator, bailing.";
94 timebase_ = base::TimeTicks::FromInternalValue(
95 cv_time->hostTime / 1000);
96 interval_ = base::TimeDelta::FromMicroseconds(
97 1000000 * static_cast<int64>(numerator) / denominator);
98 timebase_and_interval_valid_ = true;
101 void DisplayLinkMac::StartOrContinueDisplayLink() {
102 // Reset the timer, so that the display link won't be turned off for another
106 if (CVDisplayLinkIsRunning(display_link_))
109 CVReturn ret = CVDisplayLinkStart(display_link_);
110 if (ret != kCVReturnSuccess) {
111 LOG(ERROR) << "CVDisplayLinkStart failed: " << ret;
115 void DisplayLinkMac::StopDisplayLink() {
116 if (!CVDisplayLinkIsRunning(display_link_))
119 CVReturn ret = CVDisplayLinkStop(display_link_);
120 if (ret != kCVReturnSuccess) {
121 LOG(ERROR) << "CVDisplayLinkStop failed: " << ret;
125 CVReturn DisplayLinkMac::DisplayLinkCallback(
126 CVDisplayLinkRef display_link,
127 const CVTimeStamp* now,
128 const CVTimeStamp* output_time,
129 CVOptionFlags flags_in,
130 CVOptionFlags* flags_out,
132 DisplayLinkMac* display_link_mac = static_cast<DisplayLinkMac*>(context);
133 display_link_mac->Tick(output_time);
134 return kCVReturnSuccess;