Remove PerformanceMonitor strings
[chromium-blink-merge.git] / ui / accelerated_widget_mac / display_link_mac.cc
blob3013efb58e9469864717da37468c9117d2854ded
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 "ui/accelerated_widget_mac/display_link_mac.h"
7 #include "base/logging.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/trace_event/trace_event.h"
11 namespace base {
13 template<>
14 struct ScopedTypeRefTraits<CVDisplayLinkRef> {
15 static void Retain(CVDisplayLinkRef object) {
16 CVDisplayLinkRetain(object);
18 static void Release(CVDisplayLinkRef object) {
19 CVDisplayLinkRelease(object);
23 } // namespace base
25 namespace ui {
27 // static
28 scoped_refptr<DisplayLinkMac> DisplayLinkMac::GetForDisplay(
29 CGDirectDisplayID display_id) {
30 if (!display_id)
31 return nullptr;
33 // Return the existing display link for this display, if it exists.
34 DisplayMap::iterator found = display_map_.Get().find(display_id);
35 if (found != display_map_.Get().end()) {
36 return found->second;
39 CVReturn ret = kCVReturnSuccess;
41 base::ScopedTypeRef<CVDisplayLinkRef> display_link;
42 ret = CVDisplayLinkCreateWithCGDisplay(
43 display_id,
44 display_link.InitializeInto());
45 if (ret != kCVReturnSuccess) {
46 LOG(ERROR) << "CVDisplayLinkCreateWithActiveCGDisplays failed: " << ret;
47 return NULL;
50 scoped_refptr<DisplayLinkMac> display_link_mac;
51 display_link_mac = new DisplayLinkMac(display_id, display_link);
52 ret = CVDisplayLinkSetOutputCallback(
53 display_link_mac->display_link_,
54 &DisplayLinkCallback,
55 display_link_mac.get());
56 if (ret != kCVReturnSuccess) {
57 LOG(ERROR) << "CVDisplayLinkSetOutputCallback failed: " << ret;
58 return NULL;
61 return display_link_mac;
64 DisplayLinkMac::DisplayLinkMac(
65 CGDirectDisplayID display_id,
66 base::ScopedTypeRef<CVDisplayLinkRef> display_link)
67 : main_thread_task_runner_(
68 base::MessageLoop::current()->task_runner()),
69 display_id_(display_id),
70 display_link_(display_link),
71 timebase_and_interval_valid_(false) {
72 DCHECK(display_map_.Get().find(display_id) == display_map_.Get().end());
73 if (display_map_.Get().empty()) {
74 CGError register_error = CGDisplayRegisterReconfigurationCallback(
75 DisplayReconfigurationCallBack, nullptr);
76 DPLOG_IF(ERROR, register_error != kCGErrorSuccess)
77 << "CGDisplayRegisterReconfigurationCallback: "
78 << register_error;
80 display_map_.Get().insert(std::make_pair(display_id_, this));
83 DisplayLinkMac::~DisplayLinkMac() {
84 StopDisplayLink();
86 DisplayMap::iterator found = display_map_.Get().find(display_id_);
87 DCHECK(found != display_map_.Get().end());
88 DCHECK(found->second == this);
89 display_map_.Get().erase(found);
90 if (display_map_.Get().empty()) {
91 CGError remove_error = CGDisplayRemoveReconfigurationCallback(
92 DisplayReconfigurationCallBack, nullptr);
93 DPLOG_IF(ERROR, remove_error != kCGErrorSuccess)
94 << "CGDisplayRemoveReconfigurationCallback: "
95 << remove_error;
99 bool DisplayLinkMac::GetVSyncParameters(
100 base::TimeTicks* timebase, base::TimeDelta* interval) {
101 if (!timebase_and_interval_valid_) {
102 StartOrContinueDisplayLink();
103 return false;
106 *timebase = timebase_;
107 *interval = interval_;
108 return true;
111 base::TimeTicks DisplayLinkMac::GetNextVSyncTimeAfter(
112 const base::TimeTicks& from, double interval_fraction) {
113 if (!timebase_and_interval_valid_) {
114 StartOrContinueDisplayLink();
115 return from;
118 // Compute the previous vsync time.
119 base::TimeTicks previous_vsync =
120 interval_ * ((from - timebase_remainder_) / interval_) +
121 timebase_remainder_;
123 // Return |interval_fraction| through the next vsync.
124 return previous_vsync + (1 + interval_fraction) * interval_;
127 void DisplayLinkMac::Tick(const CVTimeStamp& cv_time) {
128 TRACE_EVENT0("ui", "DisplayLinkMac::Tick");
130 // Verify that videoRefreshPeriod is 32 bits.
131 DCHECK((cv_time.videoRefreshPeriod & ~0xffffFFFFull) == 0ull);
133 // Verify that the numerator and denominator make some sense.
134 uint32 numerator = static_cast<uint32>(cv_time.videoRefreshPeriod);
135 uint32 denominator = cv_time.videoTimeScale;
136 if (numerator <= 0 || denominator <= 0) {
137 LOG(WARNING) << "Unexpected numerator or denominator, bailing.";
138 return;
141 timebase_ = base::TimeTicks::FromInternalValue(
142 cv_time.hostTime / 1000);
143 interval_ = base::TimeDelta::FromMicroseconds(
144 1000000 * static_cast<int64>(numerator) / denominator);
145 // Compute |timebase_remainder_| to be the first vsync after time zero.
146 timebase_remainder_ =
147 timebase_ - interval_ * ((timebase_ - base::TimeTicks()) / interval_);
148 timebase_and_interval_valid_ = true;
150 StopDisplayLink();
153 void DisplayLinkMac::StartOrContinueDisplayLink() {
154 if (CVDisplayLinkIsRunning(display_link_))
155 return;
157 CVReturn ret = CVDisplayLinkStart(display_link_);
158 if (ret != kCVReturnSuccess) {
159 LOG(ERROR) << "CVDisplayLinkStart failed: " << ret;
163 void DisplayLinkMac::StopDisplayLink() {
164 if (!CVDisplayLinkIsRunning(display_link_))
165 return;
167 CVReturn ret = CVDisplayLinkStop(display_link_);
168 if (ret != kCVReturnSuccess) {
169 LOG(ERROR) << "CVDisplayLinkStop failed: " << ret;
173 // static
174 CVReturn DisplayLinkMac::DisplayLinkCallback(
175 CVDisplayLinkRef display_link,
176 const CVTimeStamp* now,
177 const CVTimeStamp* output_time,
178 CVOptionFlags flags_in,
179 CVOptionFlags* flags_out,
180 void* context) {
181 TRACE_EVENT0("ui", "DisplayLinkMac::DisplayLinkCallback");
182 DisplayLinkMac* display_link_mac = static_cast<DisplayLinkMac*>(context);
183 display_link_mac->main_thread_task_runner_->PostTask(
184 FROM_HERE,
185 base::Bind(&DisplayLinkMac::Tick, display_link_mac, *output_time));
186 return kCVReturnSuccess;
189 // static
190 void DisplayLinkMac::DisplayReconfigurationCallBack(
191 CGDirectDisplayID display,
192 CGDisplayChangeSummaryFlags flags,
193 void* user_info) {
194 DisplayMap::iterator found = display_map_.Get().find(display);
195 if (found == display_map_.Get().end())
196 return;
197 DisplayLinkMac* display_link_mac = found->second;
198 display_link_mac->timebase_and_interval_valid_ = false;
201 // static
202 base::LazyInstance<DisplayLinkMac::DisplayMap>
203 DisplayLinkMac::display_map_ = LAZY_INSTANCE_INITIALIZER;
205 } // ui