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
|
// Copyright 2020 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_OVERLAY_CANDIDATE_TEMPORAL_TRACKER_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_OVERLAY_CANDIDATE_TEMPORAL_TRACKER_H_
#include "components/viz/common/resources/resource_id.h"
#include "components/viz/service/viz_service_export.h"
namespace viz {
// Overlay selection is extremely important for optimal power and performance.
// The |OverlayCandidateTemporalTracker| class provides a way to temporally
// track overlay candidate properties and to categorize them. This tracker
// operates on highly opaque input; it only understands resource id (changes)
// and damage ratios. The hysteresis in categorization is intentional and its
// purpose is to temporally stabilize the result.
class VIZ_SERVICE_EXPORT OverlayCandidateTemporalTracker {
public:
// The |Config| contains values that are derived as part of a heuristic. This
// |Config| allows for the potential of platform specific variations or
// experiments.
struct VIZ_SERVICE_EXPORT Config {
// This is the only heuristic input constant to our power model. It
// effectively determines the threshold for positive power gain.
float damage_rate_threshold = 0.3f;
// |max_num_frames_avg| is the number of frames that are averaged before
// exponential averaging starts.
// https://en.wikipedia.org/wiki/Exponential_smoothing It is also the frame
// count cutoff for when an unchanging candidate is considered to be
// inactive. see 'IsActivelyChanging()'
int max_num_frames_avg = 100;
// Hysteresis range used to update |ratio_rate_category_|.
float damage_rate_hysteresis_range = 0.1f;
};
explicit OverlayCandidateTemporalTracker(const Config& config)
: config_(config) {}
// This function returns an opaque but comparable value representing the
// power improvement by promoting the tracked candidate to an overlay.
// Negative values indicate that the model suggests a power degradation if the
// candidate is promoted to overlay.
int GetModeledPowerGain(uint64_t curr_frame,
int display_area,
bool is_fullscreen) const;
// This function returns true when the time since the |resource_id| changed
// exceeds a specific threshold.
bool IsActivelyChanging(uint64_t curr_frame) const;
// This function adds a new record to the tracker if the |resource_id| has
// changed since last update.
// The |force_resource_update| flag has been added for the case when the
// resource has been updated but the |resource_id| has not changed. The case
// for when this occurs is a low latency surface (ink). Fortunately, we can
// use surface damage to ascertain when these surfaces have changed despite
// the |resource_id| remaining constant.
void AddRecord(uint64_t curr_frame,
float damage_area_ratio,
ResourceId resource_id,
bool force_resource_update = false);
// This function returns true when this tracker's 'AddRecord' was not called
// in the previous frame. We require this behavior in order to know when an
// overlay candidate is no longer present since we are tracking across frames.
bool IsAbsent();
// Clear the number of samples used for averaging damage ratio rate.
void ResetForTesting();
// Return the number of samples we currently use for sampling.
int GetNumSamplesForTesting() const { return num_samples_; }
// The functions and data below are used internally but also can be used for
// diagnosis and testing.
float MeanFrameRatioRate() const { return damage_record_avg_; }
float GetDamageRatioRate() const { return ratio_rate_category_; }
uint64_t LastChangeFrameCount(uint64_t curr_frame) const;
private:
void CategorizeDamageRatioRate(uint64_t curr_frame);
ResourceId prev_resource_id_ = kInvalidResourceId;
float ratio_rate_category_ = 0.0f;
const Config config_;
// The state of this absent bool is as follows:
// In the normal flow 'IsAbsent()' is tested which sets |absent| = true. Then
// the 'AddRecord() sets it false again in the same frame.
// When this tracker no longer corresponds to an overlay candidate the
// 'IsAbsent()' is tested which sets |absent| = true but on the next frame
// 'IsAbsent()' returns true because |absent| was never reset to false. This
// indicating this tracker should be removed.
bool absent_ = false;
uint64_t frame_record_prev_ = 0;
float damage_record_avg_ = 0.f;
int num_samples_ = 0;
};
} // namespace viz
#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_OVERLAY_CANDIDATE_TEMPORAL_TRACKER_H_
|