Fix and separate out VSync code on Mac
Sending VSync parameters to the renderer was deleted in r286038. This
adds that back (the impact of that was fairly limited because the browser's
back-pressure effectively causes the VSync).
This also pulls the computation out of CompositingIOSurfaceMac, and
into a separate DisplayLinkMac class which is hung off of each
CompositingIOSurface instance. This results in fewer total display links,
though, in practice, only the links for animating visible tabs are
running.
BUG=340133
Review URL: https://codereview.chromium.org/152373002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@249054 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/content/browser/renderer_host/display_link_mac.cc b/content/browser/renderer_host/display_link_mac.cc
new file mode 100644
index 0000000..843eb1a
--- /dev/null
+++ b/content/browser/renderer_host/display_link_mac.cc
@@ -0,0 +1,124 @@
+// Copyright 2014 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 "content/browser/renderer_host/display_link_mac.h"
+
+#include "base/debug/trace_event.h"
+#include "base/logging.h"
+
+namespace content {
+
+// static
+scoped_refptr<DisplayLinkMac> DisplayLinkMac::Create() {
+ CVReturn ret = kCVReturnSuccess;
+
+ scoped_refptr<DisplayLinkMac> display_link_mac;
+ {
+ CVDisplayLinkRef display_link = NULL;
+ ret = CVDisplayLinkCreateWithActiveCGDisplays(&display_link);
+ if (ret != kCVReturnSuccess) {
+ LOG(ERROR) << "CVDisplayLinkCreateWithActiveCGDisplays failed: " << ret;
+ return NULL;
+ }
+ display_link_mac = new DisplayLinkMac(display_link);
+ }
+
+ ret = CVDisplayLinkSetOutputCallback(
+ display_link_mac->display_link_,
+ &DisplayLinkCallback,
+ display_link_mac.get());
+ if (ret != kCVReturnSuccess) {
+ LOG(ERROR) << "CVDisplayLinkSetOutputCallback failed: " << ret;
+ return NULL;
+ }
+
+ return display_link_mac;
+}
+
+DisplayLinkMac::DisplayLinkMac(CVDisplayLinkRef display_link)
+ : display_link_(display_link),
+ stop_timer_(
+ FROM_HERE, base::TimeDelta::FromSeconds(1),
+ this, &DisplayLinkMac::StopDisplayLink),
+ timebase_and_interval_valid_(false) {
+}
+
+DisplayLinkMac::~DisplayLinkMac() {
+ if (CVDisplayLinkIsRunning(display_link_))
+ CVDisplayLinkStop(display_link_);
+}
+
+bool DisplayLinkMac::GetVSyncParameters(
+ base::TimeTicks* timebase, base::TimeDelta* interval) {
+ StartOrContinueDisplayLink();
+
+ base::AutoLock lock(lock_);
+ if (!timebase_and_interval_valid_)
+ return false;
+
+ *timebase = timebase_;
+ *interval = interval_;
+ return true;
+}
+
+void DisplayLinkMac::Tick(const CVTimeStamp* cv_time) {
+ TRACE_EVENT0("browser", "DisplayLinkMac::GetVSyncParameters");
+ base::AutoLock lock(lock_);
+
+ // Verify that videoRefreshPeriod is 32 bits.
+ DCHECK((cv_time->videoRefreshPeriod & ~0xffffFFFFull) == 0ull);
+
+ // Verify that the numerator and denominator make some sense.
+ uint32 numerator = static_cast<uint32>(cv_time->videoRefreshPeriod);
+ uint32 denominator = cv_time->videoTimeScale;
+ if (numerator <= 0 || denominator <= 0) {
+ LOG(WARNING) << "Unexpected numerator or denominator, bailing.";
+ return;
+ }
+
+ timebase_ = base::TimeTicks::FromInternalValue(
+ cv_time->hostTime / 1000);
+ interval_ = base::TimeDelta::FromMicroseconds(
+ 1000000 * static_cast<int64>(numerator) / denominator);
+ timebase_and_interval_valid_ = true;
+}
+
+void DisplayLinkMac::StartOrContinueDisplayLink() {
+ // Reset the timer, so that the display link won't be turned off for another
+ // second.
+ stop_timer_.Reset();
+
+ if (CVDisplayLinkIsRunning(display_link_))
+ return;
+
+ CVReturn ret = CVDisplayLinkStart(display_link_);
+ if (ret != kCVReturnSuccess) {
+ LOG(ERROR) << "CVDisplayLinkStart failed: " << ret;
+ }
+}
+
+void DisplayLinkMac::StopDisplayLink() {
+ if (!CVDisplayLinkIsRunning(display_link_))
+ return;
+
+ CVReturn ret = CVDisplayLinkStop(display_link_);
+ if (ret != kCVReturnSuccess) {
+ LOG(ERROR) << "CVDisplayLinkStop failed: " << ret;
+ }
+}
+
+CVReturn DisplayLinkMac::DisplayLinkCallback(
+ CVDisplayLinkRef display_link,
+ const CVTimeStamp* now,
+ const CVTimeStamp* output_time,
+ CVOptionFlags flags_in,
+ CVOptionFlags* flags_out,
+ void* context) {
+ DisplayLinkMac* display_link_mac = static_cast<DisplayLinkMac*>(context);
+ display_link_mac->Tick(output_time);
+ return kCVReturnSuccess;
+}
+
+} // content
+