1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
|
// 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.
#ifndef COMPONENTS_VIZ_COMMON_FRAME_SINKS_BEGIN_FRAME_ARGS_H_
#define COMPONENTS_VIZ_COMMON_FRAME_SINKS_BEGIN_FRAME_ARGS_H_
#include <stdint.h>
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "base/location.h"
#include "base/time/time.h"
#include "components/viz/common/viz_common_export.h"
namespace perfetto {
class EventContext;
namespace protos {
namespace pbzero {
class BeginFrameArgsV2;
}
} // namespace protos
} // namespace perfetto
namespace base {
namespace trace_event {
class ConvertableToTraceFormat;
class TracedValue;
} // namespace trace_event
} // namespace base
/**
* In debug builds we trace the creation origin of BeginFrameArgs objects. We
* reuse the base::Location system to do that.
*
* However, in release builds we don't want this as it doubles the size of the
* BeginFrameArgs object. As well it adds a number of largish strings to the
* binary. Despite the argument being unused, most compilers are unable to
* optimise it away even when unused. Instead we use the BEGINFRAME_FROM_HERE
* macro to prevent the data even getting referenced.
*/
#ifdef NDEBUG
#define BEGINFRAME_FROM_HERE nullptr
#else
#define BEGINFRAME_FROM_HERE FROM_HERE
#endif
namespace viz {
struct VIZ_COMMON_EXPORT BeginFrameId {
// |source_id| and |sequence_number| identify a BeginFrame. These are set by
// the original BeginFrameSource that created the BeginFrameArgs. When
// |source_id| of consecutive BeginFrameArgs changes, observers should expect
// the continuity of |sequence_number| to break.
uint64_t source_id = 0;
uint64_t sequence_number = 0;
// Creates an invalid set of values.
BeginFrameId();
BeginFrameId(const BeginFrameId& id);
BeginFrameId& operator=(const BeginFrameId& id);
BeginFrameId(uint64_t source_id, uint64_t sequence_number);
friend std::strong_ordering operator<=>(const BeginFrameId&,
const BeginFrameId&) = default;
bool IsNextInSequenceTo(const BeginFrameId& previous) const;
bool IsSequenceValid() const;
std::string ToString() const;
};
struct VIZ_COMMON_EXPORT PossibleDeadline {
PossibleDeadline(int64_t vsync_id,
base::TimeDelta latch_delta,
base::TimeDelta present_delta);
~PossibleDeadline();
// Out-of-line copy and assignment operators.
PossibleDeadline(const PossibleDeadline& other);
PossibleDeadline(PossibleDeadline&& other);
PossibleDeadline& operator=(const PossibleDeadline& other);
PossibleDeadline& operator=(PossibleDeadline&& other);
// Passed during swap to select the deadline.
int64_t vsync_id;
// Time delta from `BeginFrameArgs::frame_time` when the receiving pipeline
// stage starts to do its work. All viz CPU and GPU work need to be complete
// by this time to not miss a frame.
base::TimeDelta latch_delta;
// Time delta from `BeginFrameArgs::frame_time` when the frame is expected to
// be presented to the user. This would be the present time if viz finished
// its work before `latch_delta` and subsequent stages were also on time.
base::TimeDelta present_delta;
};
struct VIZ_COMMON_EXPORT PossibleDeadlines {
explicit PossibleDeadlines(size_t preferred_index);
~PossibleDeadlines();
// Out-of-line copy and assignment operators.
PossibleDeadlines(const PossibleDeadlines& other);
PossibleDeadlines(PossibleDeadlines&& other);
PossibleDeadlines& operator=(const PossibleDeadlines& other);
PossibleDeadlines& operator=(PossibleDeadlines&& other);
const PossibleDeadline& GetPreferredDeadline() const;
// Index into to `deadlines` vector picked by the OS as the default.
size_t preferred_index;
std::vector<PossibleDeadline> deadlines;
};
struct VIZ_COMMON_EXPORT BeginFrameArgs {
enum BeginFrameArgsType {
INVALID,
NORMAL,
MISSED,
};
static const char* TypeToString(BeginFrameArgsType type);
static constexpr uint64_t kStartingSourceId = 0;
// |source_id| for BeginFrameArgs not created by a BeginFrameSource. Used to
// avoid sequence number conflicts of BeginFrameArgs manually fed to an
// observer with those fed to the observer by the its BeginFrameSource.
static constexpr uint64_t kManualSourceId = UINT32_MAX;
static constexpr uint64_t kInvalidFrameNumber = 0;
static constexpr uint64_t kStartingFrameNumber = 1;
// Creates an invalid set of values.
BeginFrameArgs();
~BeginFrameArgs();
BeginFrameArgs(const BeginFrameArgs& args);
BeginFrameArgs& operator=(const BeginFrameArgs& args);
#ifdef NDEBUG
typedef const void* CreationLocation;
#else
typedef const base::Location& CreationLocation;
base::Location created_from;
#endif
// You should be able to find all instances where a BeginFrame has been
// created by searching for "BeginFrameArgs::Create".
// The location argument should **always** be BEGINFRAME_FROM_HERE macro.
static BeginFrameArgs Create(CreationLocation location,
uint64_t source_id,
uint64_t sequence_number,
base::TimeTicks frame_time,
base::TimeTicks deadline,
base::TimeDelta interval,
BeginFrameArgsType type);
// This is the default interval assuming 60Hz to use to avoid sprinkling the
// code with magic numbers.
static constexpr base::TimeDelta DefaultInterval() {
return base::Seconds(1) / 60;
}
// This is the preferred interval to use when the producer can animate at the
// max interval supported by the Display.
static constexpr base::TimeDelta MinInterval() { return base::Seconds(0); }
// This is a hard-coded deadline adjustment used by the display compositor.
// Using 1/3 of the vsync as the default adjustment gives the display
// compositor the last 1/3 of a frame to produce output, the client impl
// thread the middle 1/3 of a frame to produce output, and the client's main
// thread the first 1/3 of a frame to produce output.
static constexpr float kDefaultEstimatedDisplayDrawTimeRatio = 1.f / 3;
// Returns how much time the display should reserve for draw and swap if the
// BeginFrame interval is |interval|.
static base::TimeDelta DefaultEstimatedDisplayDrawTime(
base::TimeDelta interval) {
return interval * kDefaultEstimatedDisplayDrawTimeRatio;
}
bool IsValid() const { return interval >= base::TimeDelta(); }
// TODO(nuskos): Once we have a protozero -> String utility function remove
// these base::trace_event json dictionary functions.
std::unique_ptr<base::trace_event::ConvertableToTraceFormat> AsValue() const;
void AsValueInto(base::trace_event::TracedValue* dict) const;
void AsProtozeroInto(perfetto::EventContext& ctx,
perfetto::protos::pbzero::BeginFrameArgsV2* args) const;
std::string ToString() const;
// The time at which the frame started. Used, for example, by animations to
// decide to slow down or skip ahead.
base::TimeTicks frame_time;
// The time by which the receiving pipeline stage should do its work.
base::TimeTicks deadline;
// The inverse of the desired frame rate.
base::TimeDelta interval;
BeginFrameId frame_id;
// |trace_id| is used as the id for the trace-events associated with this
// begin-frame. The trace-id is set by the service, and can be used by both
// the client and service as the id for trace-events.
int64_t trace_id = -1;
// The time when viz dispatched this to a client.
base::TimeTicks dispatch_time;
// For clients to denote when they received this being dispatched.
base::TimeTicks client_arrival_time;
BeginFrameArgsType type = INVALID;
bool on_critical_path = true;
// If true, observers of this BeginFrame should not produce a new
// CompositorFrame, but instead only run the (web-visible) side effects of the
// BeginFrame, such as updating animations and layout. Such a BeginFrame
// effectively advances an observer's view of frame time, which in turn may
// trigger side effects such as loading of new resources.
//
// Observers have to explicitly opt-in to receiving animate_only
// BeginFrames via BeginFrameObserver::WantsAnimateOnlyBeginFrames.
//
// Designed for use in headless, in conjunction with
// --disable-threaded-animation, --disable-threaded-scrolling, and
// --disable-checker-imaging, see bit.ly/headless-rendering.
bool animate_only = false;
// Number of frames being skipped during throttling since last BeginFrame
// sent.
uint64_t frames_throttled_since_last = 0;
// This is not serialized for mojo as it should only be used internal to viz.
// Note `deadline` is not yet updated to one of these deadline since some
// code still assumes `deadline` is a multiple of `interval` from
// `frame_time`.
std::optional<PossibleDeadlines> possible_deadlines;
private:
BeginFrameArgs(uint64_t source_id,
uint64_t sequence_number,
base::TimeTicks frame_time,
base::TimeTicks deadline,
base::TimeDelta interval,
BeginFrameArgsType type);
};
// Sent by a BeginFrameObserver as acknowledgment of completing a BeginFrame.
struct VIZ_COMMON_EXPORT BeginFrameAck {
BeginFrameAck() = default;
// Constructs an instance as a response to the specified BeginFrameArgs.
BeginFrameAck(const BeginFrameArgs& args, bool has_damage);
BeginFrameAck(uint64_t source_id,
uint64_t sequence_number,
bool has_damage,
int64_t trace_id = -1);
BeginFrameAck(const BeginFrameAck& other) = default;
BeginFrameAck& operator=(const BeginFrameAck& other) = default;
// Creates a BeginFrameAck for a manual BeginFrame. Used when clients produce
// a CompositorFrame without prior BeginFrame, e.g. for synchronous drawing.
static BeginFrameAck CreateManualAckWithDamage();
// Source identifier and Sequence number of the BeginFrame that is
// acknowledged. The BeginFrameSource that receives the acknowledgment uses
// this to discard BeginFrameAcks for BeginFrames sent by a different source.
// Such a situation may occur when the BeginFrameSource of the observer
// changes while a BeginFrame from the old source is still in flight.
BeginFrameId frame_id;
// The |trace_id| of the BeginFrame that is acknowledged.
int64_t trace_id = -1;
// |true| if the observer has produced damage (e.g. sent a CompositorFrame or
// damaged a surface) as part of responding to the BeginFrame.
bool has_damage = false;
};
} // namespace viz
#endif // COMPONENTS_VIZ_COMMON_FRAME_SINKS_BEGIN_FRAME_ARGS_H_
|