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
|
// Copyright 2024 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_SERVICE_DISPLAY_FRAME_INTERVAL_MATCHERS_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_FRAME_INTERVAL_MATCHERS_H_
#include <optional>
#include <string>
#include <variant>
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ref.h"
#include "base/time/time.h"
#include "components/viz/common/constants.h"
#include "components/viz/common/quads/frame_interval_inputs.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/service/viz_service_export.h"
#include "third_party/perfetto/include/perfetto/tracing/traced_value_forward.h"
namespace viz {
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class FrameIntervalMatcherType {
kNone = 0,
kInputBoost = 1,
kOnlyVideo = 2,
kVideoConference = 3,
kOnlyAnimatingImage = 4,
kOnlyScrollBarFadeOut = 5,
kUserInputBoost = 6,
kSlowScrollThrottle = 7,
kMaxValue = kSlowScrollThrottle,
};
// Works with `FrameIntervalDecider` to compute the ideal frame interval.
// Matchers are independent and each matcher matches a specific scenario. Note
// however matcher order is important.
// Matchers should generally be stateless as they can be recreated at run time,
// and any input or state should be stored in `FrameIntervalDecider`.
// Matcher should generally not be platform-specific.
class VIZ_SERVICE_EXPORT FrameIntervalMatcher {
public:
// Result can either be an interval class or a specific frame interval,
// depending on setting and the inputs.
enum class FrameIntervalClass {
// These are ordered from lowest frame interval to highest.
kBoost, // Used for latency or smoothness sensitive situation such as
// scrolling.
kDefault, // Used if nothing matched.
};
enum class ResultIntervalType {
kExact,
kAtLeast,
};
struct ResultInterval {
base::TimeDelta interval;
ResultIntervalType type = ResultIntervalType::kExact;
bool operator==(const ResultInterval& other) const;
};
using Result = std::variant<FrameIntervalClass, ResultInterval>;
using ResultCallback =
base::RepeatingCallback<void(Result, FrameIntervalMatcherType)>;
// Settings for configuration where display supports a fixed set of discrete
// frame intervals.
struct VIZ_SERVICE_EXPORT FixedIntervalSettings {
FixedIntervalSettings();
FixedIntervalSettings(const FixedIntervalSettings&);
~FixedIntervalSettings();
base::TimeDelta default_interval; // Used for FrameIntervalClass::kDefault.
base::flat_set<base::TimeDelta> supported_intervals; // Cannot be empty.
};
// Settings for configuration where display supports a continuous range of
// frame intervals.
struct VIZ_SERVICE_EXPORT ContinuousRangeSettings {
ContinuousRangeSettings();
ContinuousRangeSettings(const ContinuousRangeSettings&);
~ContinuousRangeSettings();
base::TimeDelta default_interval; // Used for FrameIntervalClass::kDefault.
base::TimeDelta min_interval;
base::TimeDelta max_interval;
};
struct VIZ_SERVICE_EXPORT Settings {
Settings();
~Settings();
Settings(const Settings& other);
Settings& operator=(const Settings& other);
Settings(Settings&& other);
Settings& operator=(Settings&& other);
// Called with desired display frame interval Result. Must remain valid to
// call for the lifetime of FrameIntervalDecider.
ResultCallback result_callback;
// Settings for what intervals are supported by the display. If this is
// provided, then `FrameIntervalDecider` matchers should never return a
// FrameIntervalClass result, and instead should pick one of the
// supported intervals. If this is set to `monostate`, then
// `FrameIntervalClass` as well as any frame interval can be returned.
std::variant<std::monostate, FixedIntervalSettings, ContinuousRangeSettings>
interval_settings;
// Timeout to wait for when increasing frame interval, to avoid blip when
// rapidly switching frame intervals..
base::TimeDelta increase_frame_interval_timeout = base::Milliseconds(100);
// For matchers where relevant, frame sinks that has not updated in this
// time will be assumed to be static and ignored for computation.
base::TimeDelta ignore_frame_sink_timeout = base::Milliseconds(250);
// Used for time delta equality comparisons.
base::TimeDelta epsilon = base::Milliseconds(0.5);
// Passed into `media::VideoCadenceEstimator::HasSimpleCadence` to compute
// ideal frame interval.
base::TimeDelta max_time_until_next_glitch = kMaxTimeUntilNextGlitch;
};
struct VIZ_SERVICE_EXPORT Inputs {
Inputs(const Settings& settings, uint64_t frame_id);
~Inputs();
Inputs(const Inputs& other);
Inputs& operator=(const Inputs& other);
// Serializes this struct into a trace.
void WriteIntoTrace(perfetto::TracedValue trace_context) const;
base::raw_ref<const Settings> settings;
// Increasing id for each viz frame.
uint64_t frame_id;
base::TimeTicks aggregated_frame_time;
base::flat_map<FrameSinkId, FrameIntervalInputs> inputs_map;
};
static std::string ResultToString(const Result& result);
static std::string MatcherTypeToString(FrameIntervalMatcherType type);
static bool AreAlmostEqual(base::TimeDelta a,
base::TimeDelta b,
base::TimeDelta epsilon);
virtual ~FrameIntervalMatcher() = default;
FrameIntervalMatcherType type() const { return type_; }
virtual std::optional<Result> Match(const Inputs& matcher_inputs) = 0;
protected:
explicit FrameIntervalMatcher(FrameIntervalMatcherType type);
private:
const FrameIntervalMatcherType type_;
};
#define DECLARE_SIMPLE_FRAME_INTERVAL_MATCHER(ClassName) \
class VIZ_SERVICE_EXPORT ClassName : public FrameIntervalMatcher { \
public: \
ClassName(); \
~ClassName() override; \
std::optional<Result> Match(const Inputs& matcher_inputs) override; \
}
DECLARE_SIMPLE_FRAME_INTERVAL_MATCHER(InputBoostMatcher);
DECLARE_SIMPLE_FRAME_INTERVAL_MATCHER(OnlyVideoMatcher);
DECLARE_SIMPLE_FRAME_INTERVAL_MATCHER(VideoConferenceMatcher);
DECLARE_SIMPLE_FRAME_INTERVAL_MATCHER(OnlyAnimatingImageMatcher);
DECLARE_SIMPLE_FRAME_INTERVAL_MATCHER(OnlyScrollBarFadeOutAnimationMatcher);
DECLARE_SIMPLE_FRAME_INTERVAL_MATCHER(UserInputBoostMatcher);
#undef DECLARE_SIMPLE_FRAME_INTERVAL_MATCHER
class VIZ_SERVICE_EXPORT SlowScrollThrottleMatcher
: public FrameIntervalMatcher {
public:
explicit SlowScrollThrottleMatcher(float device_scale_factor);
~SlowScrollThrottleMatcher() override;
std::optional<Result> Match(const Inputs& matcher_inputs) override;
private:
const float device_scale_factor_;
uint64_t last_frame_id_matched_without_extra_update_ = 0u;
};
} // namespace viz
#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_FRAME_INTERVAL_MATCHERS_H_
|