blob: d249aaf1809e805bc5bd6249c1ce0d688fb54526 [file] [log] [blame]
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include <utility>
#include "base/trace_event/interned_args_helper.h"
#include "base/trace_event/traced_value.h"
#include "base/tracing/protos/chrome_track_event.pbzero.h"
#include "third_party/perfetto/protos/perfetto/trace/track_event/source_location.pbzero.h"
namespace viz {
const char* BeginFrameArgs::TypeToString(BeginFrameArgsType type) {
switch (type) {
case BeginFrameArgs::INVALID:
return "INVALID";
case BeginFrameArgs::NORMAL:
return "NORMAL";
case BeginFrameArgs::MISSED:
return "MISSED";
}
NOTREACHED();
}
namespace {
perfetto::protos::pbzero::BeginFrameArgsV2::BeginFrameArgsType
TypeToProtozeroEnum(BeginFrameArgs::BeginFrameArgsType type) {
using pbzeroType = perfetto::protos::pbzero::BeginFrameArgsV2;
switch (type) {
case BeginFrameArgs::INVALID:
return pbzeroType::BEGIN_FRAME_ARGS_TYPE_INVALID;
case BeginFrameArgs::NORMAL:
return pbzeroType::BEGIN_FRAME_ARGS_TYPE_NORMAL;
case BeginFrameArgs::MISSED:
return pbzeroType::BEGIN_FRAME_ARGS_TYPE_MISSED;
}
NOTREACHED();
}
} // namespace
constexpr uint64_t BeginFrameArgs::kInvalidFrameNumber;
constexpr uint64_t BeginFrameArgs::kStartingFrameNumber;
BeginFrameId::BeginFrameId()
: source_id(0), sequence_number(BeginFrameArgs::kInvalidFrameNumber) {}
BeginFrameId::BeginFrameId(const BeginFrameId& id) = default;
BeginFrameId& BeginFrameId::operator=(const BeginFrameId& id) = default;
BeginFrameId::BeginFrameId(uint64_t source_id, uint64_t sequence_number)
: source_id(source_id), sequence_number(sequence_number) {}
bool BeginFrameId::IsNextInSequenceTo(const BeginFrameId& previous) const {
return (source_id == previous.source_id &&
sequence_number > previous.sequence_number);
}
bool BeginFrameId::IsSequenceValid() const {
return (BeginFrameArgs::kInvalidFrameNumber != sequence_number);
}
std::string BeginFrameId::ToString() const {
base::trace_event::TracedValueJSON value;
value.SetInteger("source_id", source_id);
value.SetInteger("sequence_number", sequence_number);
return value.ToJSON();
}
PossibleDeadline::PossibleDeadline(int64_t vsync_id,
base::TimeDelta latch_delta,
base::TimeDelta present_delta)
: vsync_id(vsync_id),
latch_delta(latch_delta),
present_delta(present_delta) {}
PossibleDeadline::PossibleDeadline(const PossibleDeadline& other) = default;
PossibleDeadline::PossibleDeadline(PossibleDeadline&& other) = default;
PossibleDeadline::~PossibleDeadline() = default;
PossibleDeadline& PossibleDeadline::operator=(const PossibleDeadline& other) =
default;
PossibleDeadline& PossibleDeadline::operator=(PossibleDeadline&& other) =
default;
PossibleDeadlines::PossibleDeadlines(size_t preferred_index)
: preferred_index(preferred_index) {}
PossibleDeadlines::PossibleDeadlines(const PossibleDeadlines& other) = default;
PossibleDeadlines::PossibleDeadlines(PossibleDeadlines&& other) = default;
PossibleDeadlines::~PossibleDeadlines() = default;
PossibleDeadlines& PossibleDeadlines::operator=(
const PossibleDeadlines& other) = default;
PossibleDeadlines& PossibleDeadlines::operator=(PossibleDeadlines&& other) =
default;
const PossibleDeadline& PossibleDeadlines::GetPreferredDeadline() const {
return deadlines[preferred_index];
}
BeginFrameArgs::BeginFrameArgs()
: frame_time(base::TimeTicks::Min()),
deadline(base::TimeTicks::Min()),
interval(base::Microseconds(-1)),
frame_id(BeginFrameId(0, kInvalidFrameNumber)) {}
BeginFrameArgs::~BeginFrameArgs() = default;
BeginFrameArgs::BeginFrameArgs(uint64_t source_id,
uint64_t sequence_number,
base::TimeTicks frame_time,
base::TimeTicks deadline,
base::TimeDelta interval,
BeginFrameArgs::BeginFrameArgsType type)
: frame_time(frame_time),
deadline(deadline),
interval(interval),
frame_id(BeginFrameId(source_id, sequence_number)),
type(type) {
DCHECK_LE(kStartingFrameNumber, sequence_number);
}
BeginFrameArgs::BeginFrameArgs(const BeginFrameArgs& args) = default;
BeginFrameArgs& BeginFrameArgs::operator=(const BeginFrameArgs& args) = default;
BeginFrameArgs BeginFrameArgs::Create(BeginFrameArgs::CreationLocation location,
uint64_t source_id,
uint64_t sequence_number,
base::TimeTicks frame_time,
base::TimeTicks deadline,
base::TimeDelta interval,
BeginFrameArgs::BeginFrameArgsType type) {
DCHECK_NE(type, BeginFrameArgs::INVALID);
#ifdef NDEBUG
return BeginFrameArgs(source_id, sequence_number, frame_time, deadline,
interval, type);
#else
BeginFrameArgs args = BeginFrameArgs(source_id, sequence_number, frame_time,
deadline, interval, type);
args.created_from = location;
return args;
#endif
}
std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
BeginFrameArgs::AsValue() const {
std::unique_ptr<base::trace_event::TracedValue> state(
new base::trace_event::TracedValue());
AsValueInto(state.get());
return std::move(state);
}
void BeginFrameArgs::AsValueInto(base::trace_event::TracedValue* state) const {
state->SetString("type", "BeginFrameArgs");
state->SetString("subtype", TypeToString(type));
state->SetInteger("source_id", frame_id.source_id);
state->SetInteger("sequence_number", frame_id.sequence_number);
state->SetInteger("frames_throttled_since_last", frames_throttled_since_last);
state->SetDouble("frame_time_us",
frame_time.since_origin().InMicrosecondsF());
state->SetDouble("deadline_us", deadline.since_origin().InMicrosecondsF());
state->SetDouble("interval_us", interval.InMicrosecondsF());
#ifndef NDEBUG
state->SetString("created_from", created_from.ToString());
#endif
state->SetBoolean("on_critical_path", on_critical_path);
state->SetBoolean("animate_only", animate_only);
state->SetBoolean("has_possible_deadlines", !!possible_deadlines);
}
void BeginFrameArgs::AsProtozeroInto(
perfetto::EventContext& ctx,
perfetto::protos::pbzero::BeginFrameArgsV2* state) const {
state->set_type(TypeToProtozeroEnum(type));
state->set_source_id(frame_id.source_id);
state->set_sequence_number(frame_id.sequence_number);
state->set_frames_throttled_since_last(frames_throttled_since_last);
state->set_frame_time_us(frame_time.since_origin().InMicroseconds());
state->set_deadline_us(deadline.since_origin().InMicroseconds());
state->set_interval_delta_us(interval.InMicroseconds());
state->set_on_critical_path(on_critical_path);
state->set_animate_only(animate_only);
#ifndef NDEBUG
state->set_source_location_iid(
base::trace_event::InternedSourceLocation::Get(&ctx, created_from));
#endif
}
std::string BeginFrameArgs::ToString() const {
base::trace_event::TracedValueJSON value;
AsValueInto(&value);
return value.ToJSON();
}
BeginFrameAck::BeginFrameAck(const BeginFrameArgs& args, bool has_damage)
: frame_id(args.frame_id),
trace_id(args.trace_id),
has_damage(has_damage) {}
BeginFrameAck::BeginFrameAck(uint64_t source_id,
uint64_t sequence_number,
bool has_damage,
int64_t trace_id)
: frame_id(BeginFrameId(source_id, sequence_number)),
trace_id(trace_id),
has_damage(has_damage) {
DCHECK(frame_id.IsSequenceValid());
}
// static
BeginFrameAck BeginFrameAck::CreateManualAckWithDamage() {
return BeginFrameAck(BeginFrameArgs::kManualSourceId,
BeginFrameArgs::kStartingFrameNumber, true);
}
void BeginFrameAck::AsValueInto(base::trace_event::TracedValue* dict) const {
dict->SetInteger("source_id", static_cast<int>(frame_id.source_id));
dict->SetInteger("sequence_number",
static_cast<int>(frame_id.sequence_number));
dict->SetBoolean("has_damage", has_damage);
dict->SetInteger("trace_id", static_cast<int>(trace_id));
}
} // namespace viz