blob: 5274d5bdf1c9841a08ef7eef921ec80908d0840a [file] [log] [blame]
// Copyright 2019 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 "cc/trees/presentation_time_callback_buffer.h"
#include <utility>
#include <vector>
namespace cc {
PresentationTimeCallbackBuffer::PresentationTimeCallbackBuffer() = default;
PresentationTimeCallbackBuffer::PresentationTimeCallbackBuffer(
PresentationTimeCallbackBuffer&& other)
: frame_token_infos_(std::move(other.frame_token_infos_)) {}
PresentationTimeCallbackBuffer& PresentationTimeCallbackBuffer::operator=(
PresentationTimeCallbackBuffer&& other) {
if (this != &other) {
frame_token_infos_ = std::move(other.frame_token_infos_);
}
return *this;
}
PresentationTimeCallbackBuffer::~PresentationTimeCallbackBuffer() = default;
PresentationTimeCallbackBuffer::FrameTokenInfo::FrameTokenInfo(uint32_t token)
: token(token) {}
PresentationTimeCallbackBuffer::FrameTokenInfo::FrameTokenInfo(
FrameTokenInfo&&) = default;
PresentationTimeCallbackBuffer::FrameTokenInfo&
PresentationTimeCallbackBuffer::FrameTokenInfo::operator=(FrameTokenInfo&&) =
default;
PresentationTimeCallbackBuffer::FrameTokenInfo::~FrameTokenInfo() = default;
void PresentationTimeCallbackBuffer::RegisterMainThreadPresentationCallbacks(
uint32_t frame_token,
std::vector<CallbackType> callbacks) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
FrameTokenInfo& frame_info = GetOrMakeRegistration(frame_token);
// Splice the given |callbacks| onto the vector of existing callbacks.
auto& sink = frame_info.main_thread_callbacks;
sink.reserve(sink.size() + callbacks.size());
std::move(callbacks.begin(), callbacks.end(), std::back_inserter(sink));
DCHECK_LE(frame_token_infos_.size(), 25u);
}
void PresentationTimeCallbackBuffer::RegisterFrameTime(
uint32_t frame_token,
base::TimeTicks frame_time) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
FrameTokenInfo& frame_info = GetOrMakeRegistration(frame_token);
// Protect against clobbering previously registered frame times.
DCHECK(frame_info.frame_time.is_null() ||
frame_info.frame_time == frame_time);
frame_info.frame_time = frame_time;
DCHECK_LE(frame_token_infos_.size(), 25u);
}
PresentationTimeCallbackBuffer::PendingCallbacks::PendingCallbacks() = default;
PresentationTimeCallbackBuffer::PendingCallbacks::PendingCallbacks(
PendingCallbacks&&) = default;
PresentationTimeCallbackBuffer::PendingCallbacks&
PresentationTimeCallbackBuffer::PendingCallbacks::operator=(
PendingCallbacks&&) = default;
PresentationTimeCallbackBuffer::PendingCallbacks::~PendingCallbacks() = default;
PresentationTimeCallbackBuffer::PendingCallbacks
PresentationTimeCallbackBuffer::PopPendingCallbacks(uint32_t frame_token) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
PendingCallbacks result;
while (!frame_token_infos_.empty()) {
auto info = frame_token_infos_.begin();
if (viz::FrameTokenGT(info->token, frame_token))
break;
// Forward compositor frame timings on exact frame token matches. These
// timings correspond to frames that caused on-screen damage.
if (info->token == frame_token && !info->frame_time.is_null())
result.frame_time = info->frame_time;
// Collect the main-thread callbacks. It's the caller's job to post them to
// the main thread.
std::move(info->main_thread_callbacks.begin(),
info->main_thread_callbacks.end(),
std::back_inserter(result.main_thread_callbacks));
frame_token_infos_.erase(info);
}
return result;
}
PresentationTimeCallbackBuffer::FrameTokenInfo&
PresentationTimeCallbackBuffer::GetOrMakeRegistration(uint32_t frame_token) {
// If the freshest registration is for an earlier frame token, add a new
// entry to the queue.
if (frame_token_infos_.empty() ||
viz::FrameTokenGT(frame_token, frame_token_infos_.back().token)) {
frame_token_infos_.emplace_back(frame_token);
}
// Registrations should use monotonically increasing frame tokens.
DCHECK_EQ(frame_token_infos_.back().token, frame_token);
return frame_token_infos_.back();
}
} // namespace cc