This source file includes following definitions.
- GetForDisplay
- timebase_and_interval_valid_
- GetVSyncParameters
- Tick
- StartOrContinueDisplayLink
- StopDisplayLink
- DisplayLinkCallback
#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 content {
scoped_refptr<DisplayLinkMac> DisplayLinkMac::GetForDisplay(
CGDirectDisplayID display_id) {
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_);
DCHECK((cv_time->videoRefreshPeriod & ~0xffffFFFFull) == 0ull);
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() {
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;
}
base::LazyInstance<DisplayLinkMac::DisplayMap>
DisplayLinkMac::display_map_ = LAZY_INSTANCE_INITIALIZER;
}