blob: 69ae12acc042b1e5469c3991edb05ee4e832d72c [file] [log] [blame]
// Copyright 2022 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_COMBINATION_CACHE_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_OVERLAY_COMBINATION_CACHE_H_
#include <array>
#include <bitset>
#include <map>
#include <memory>
#include <utility>
#include <vector>
#include "base/containers/span.h"
#include "components/viz/common/display/overlay_strategy.h"
#include "components/viz/service/display/overlay_candidate.h"
#include "components/viz/service/display/overlay_proposed_candidate.h"
#include "components/viz/service/viz_service_export.h"
#include "ui/gfx/geometry/rect_f.h"
namespace viz {
// Uniquely identifies OverlayProposedCandidates as it will be stored in the
// OverlayCombinationCache. An overlay with the same strategy and the same
// rounded display_rect are considered identical.
struct OverlayCacheKey {
explicit OverlayCacheKey(const OverlayProposedCandidate& candidate);
bool operator<(const OverlayCacheKey& other) const {
if (other.strategy != strategy) {
return strategy < other.strategy;
} else {
return display_rect < other.display_rect;
}
}
// The candidate's rounded display_rect.
gfx::Rect display_rect;
// The strategy that proposed this candidate.
OverlayStrategy strategy;
};
// A vector of proposed candidates to try and promote to overlays, as determined
// by the OverlayCombinationCache. There is also a flag that indicates that this
// entire combination has been successfully promoted to overlays the last time
// it was tested.
struct VIZ_SERVICE_EXPORT OverlayCombinationToTest {
OverlayCombinationToTest();
~OverlayCombinationToTest();
OverlayCombinationToTest(OverlayCombinationToTest&& other);
OverlayCombinationToTest& operator=(OverlayCombinationToTest&& other);
// The candidates that should be promoted to overlays.
std::vector<OverlayProposedCandidate> candidates_to_test;
// True iff this combination of candidates were successfully promoted to
// overlays the last time they were tested.
bool previously_succeeded = false;
};
class CombinationIdMapper;
// Attempts to determine the optimal combination of candidates that we should
// attempt to promote to overlays each frame, based on total expected relative
// power gain, and past success/failure of these combinations being promoted.
class VIZ_SERVICE_EXPORT OverlayCombinationCache {
public:
// The maximum number of candidates this cache can track.
static constexpr size_t kMaxTrackedCandidates = 8;
// The invalid candidate id.
static constexpr size_t kInvalidCandidateId = kMaxTrackedCandidates;
// We track all 2^N combinations of the max N tracked overlay candidates.
static constexpr size_t kMaxTrackedCombinations = 1 << kMaxTrackedCandidates;
// Represents a set of CandidateIds.
using CandidateCombination = std::bitset<kMaxTrackedCandidates>;
// Represents a bit index used in a CandidateCombination.
// This may also represent `kInvalidCandidateId`.
// Valid CandidateIds are in the range [0, kMaxTrackedCandidates).
using CandidateId = size_t;
OverlayCombinationCache();
~OverlayCombinationCache();
// Given proposed candidates that are sorted by power gain, and the maximum
// number of overlays you'd like to try and promote, determines the best
// combination of overlays to try promoting this frame.
OverlayCombinationToTest GetOverlayCombinationToTest(
base::span<OverlayProposedCandidate const> sorted_candidates,
int max_overlays_considered);
// Records the success/failure of each candidate we attempted to promote to an
// overlay. This should be called after testing the combination returned by
// GetOverlayCombinationToTest() each frame.
// NOTE: The OverlayProposedCandidate.candidate.overlay_handled field should
// be true iff that candidate was promoted this frame.
void DeclarePromotedCandidates(
base::span<OverlayProposedCandidate const> attempted_candidates);
// Clears all caches. This includes CandidateIds and CombinationResults.
void ClearCache();
private:
friend class OverlayCombinationCacheTest;
// The result of attempting to promote a CandidateCombination to overlays, or
// unknown.
enum class CombinationResult : uint8_t { kUnknown, kPromoted, kFailed };
// Get the first max_overlays_possible candidates (if there are that many)
// that represent unique quads. If there are multiple candidates for a single
// quad, only the first one will be used.
std::vector<OverlayProposedCandidate> GetConsideredCandidates(
base::span<OverlayProposedCandidate const> sorted_candidates,
size_t max_overlays_possible);
// Gets the CandidateIds for each considered candidate. Reuses cached ids if
// they exist, or maps new ids. All ids returned will be valid.
// Any candidates that were considered last frame but are not this frame are
// considered stale, and will have their CandidateIds and CombinationResults
// cleared.
std::vector<CandidateId> GetIds(
const std::vector<OverlayProposedCandidate>& considered_candidates);
// Generates all (2^N - 1) possible combinations of considered_candidates
// (ignoring the empty set), and calculates the sum of their relative power
// gains. Returns a vector of all of these CandidateCombination and total
// power gain pairs.
std::vector<std::pair<CandidateCombination, int>> GetPowerSortedCombinations(
const std::vector<OverlayProposedCandidate>& considered_candidates,
const std::vector<CandidateId>& considered_ids);
// Reset the cached CombinationResult to kUnknown for any combination
// containing any of the candidates in stale_candidates.
void RemoveStaleCombinations(const CandidateCombination& stale_candidates);
// Maps OverlayProposedCandidates to CandidateIds.
std::unique_ptr<CombinationIdMapper> id_mapper_;
// The test result, if known, for every possible CandidateCombination.
std::array<CombinationResult, kMaxTrackedCombinations> combo_results_;
};
// Manages the mapping from OverlayProposedCandidates to CandidateIds ids based
// on their OverlayCacheKey. There are a fixed number of available ids, based on
// the maximum size of a CandidateCombination.
class VIZ_SERVICE_EXPORT CombinationIdMapper {
public:
CombinationIdMapper();
~CombinationIdMapper();
// Gets a CandidateId for a given OverlayProposedCandidate.
// Returns the cached id for this candidate if it exists, otherwise it
// attempts to map the candidate to new id. If the cache is full (more than
// kMaxTrackedCandidates in the cache), then kInvalidCandidateId is returned.
//
// NOTE: Callers need to check for kInvalidCandidateId before using it to
// access a CandidateCombination.
OverlayCombinationCache::CandidateId GetCandidateId(
const OverlayProposedCandidate& candidate);
// Returns a CandidateCombination of all the ids currently claimed.
OverlayCombinationCache::CandidateCombination GetClaimedIds() {
return claimed_ids_;
}
// Remove all ids in stale_candidates from the cache.
void RemoveStaleIds(
const OverlayCombinationCache::CandidateCombination& stale_candidates);
// Clear all cached ids.
void ClearIds();
private:
// Maps up to (kMaxTrackedCandidates) OverlayCacheKeys to unique CandidateIds.
std::map<OverlayCacheKey, OverlayCombinationCache::CandidateId>
candidate_ids_;
// A set containing all ids that have been claimed.
OverlayCombinationCache::CandidateCombination claimed_ids_;
};
} // namespace viz
#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_OVERLAY_COMBINATION_CACHE_H_