summaryrefslogtreecommitdiffstats
path: root/chromium/content/browser/renderer_host/display_link_mac.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/content/browser/renderer_host/display_link_mac.cc')
-rw-r--r--chromium/content/browser/renderer_host/display_link_mac.cc160
1 files changed, 160 insertions, 0 deletions
diff --git a/chromium/content/browser/renderer_host/display_link_mac.cc b/chromium/content/browser/renderer_host/display_link_mac.cc
new file mode 100644
index 00000000000..b4592a9f3b7
--- /dev/null
+++ b/chromium/content/browser/renderer_host/display_link_mac.cc
@@ -0,0 +1,160 @@
+// 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 base {
+
+template<>
+struct ScopedTypeRefTraits<CVDisplayLinkRef> {
+ static void Retain(CVDisplayLinkRef object) {
+ CVDisplayLinkRetain(object);
+ }
+ static void Release(CVDisplayLinkRef object) {
+ CVDisplayLinkRelease(object);
+ }
+};
+
+} // namespace base
+
+namespace content {
+
+// static
+scoped_refptr<DisplayLinkMac> DisplayLinkMac::GetForDisplay(
+ CGDirectDisplayID display_id) {
+ // Return the existing display link for this display, if it exists.
+ DisplayMap::iterator found = display_map_.Get().find(display_id);
+ if (found != display_map_.Get().end()) {
+ return found->second;
+ }
+
+ CVReturn ret = kCVReturnSuccess;
+
+ base::ScopedTypeRef<CVDisplayLinkRef> display_link;
+ ret = CVDisplayLinkCreateWithCGDisplay(
+ display_id,
+ display_link.InitializeInto());
+ if (ret != kCVReturnSuccess) {
+ LOG(ERROR) << "CVDisplayLinkCreateWithActiveCGDisplays failed: " << ret;
+ return NULL;
+ }
+
+ scoped_refptr<DisplayLinkMac> display_link_mac;
+ display_link_mac = new DisplayLinkMac(display_id, 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(
+ CGDirectDisplayID display_id,
+ base::ScopedTypeRef<CVDisplayLinkRef> display_link)
+ : display_id_(display_id),
+ display_link_(display_link),
+ stop_timer_(
+ FROM_HERE, base::TimeDelta::FromSeconds(1),
+ this, &DisplayLinkMac::StopDisplayLink),
+ timebase_and_interval_valid_(false) {
+ DCHECK(display_map_.Get().find(display_id) == display_map_.Get().end());
+ display_map_.Get().insert(std::make_pair(display_id_, this));
+}
+
+DisplayLinkMac::~DisplayLinkMac() {
+ if (CVDisplayLinkIsRunning(display_link_))
+ CVDisplayLinkStop(display_link_);
+
+ DisplayMap::iterator found = display_map_.Get().find(display_id_);
+ DCHECK(found != display_map_.Get().end());
+ DCHECK(found->second == this);
+ display_map_.Get().erase(found);
+}
+
+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;
+}
+
+// static
+base::LazyInstance<DisplayLinkMac::DisplayMap>
+ DisplayLinkMac::display_map_ = LAZY_INSTANCE_INITIALIZER;
+
+} // content
+