| // 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_ |