blob: 89f9274cf9842b4d7918f16a0b9356d1f309d0ad [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CC_PAINT_PAINT_CACHE_H_
#define CC_PAINT_PAINT_CACHE_H_
#include <map>
#include <set>
#include "base/containers/mru_cache.h"
#include "base/containers/stack_container.h"
#include "cc/paint/paint_export.h"
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkTextBlob.h"
namespace cc {
// PaintCache is used to cache high frequency small paint data types, like
// SkTextBlob and SkPath in the GPU service. The ClientPaintCache budgets and
// controls the cache state in the ServicePaintCache, regularly purging old
// entries returned in ClientPaintCache::Purge from the service side cache. In
// addition to this, the complete cache is cleared during the raster context
// idle cleanup. This effectively means that the cache budget is used as working
// memory that is only kept while we are actively rasterizing.
//
// The entries are serialized by the caller during paint op serialization, and
// the cache assumes the deserialization and purging to be done in order for
// accurately tracking the service side state in ServicePaintCache.
//
// Note that while TransferCache should be used for large data types that would
// benefit from a shared cache budgeted across all clients, using a client
// controlled PaintCache with a tighter budget is better for these data types
// since it avoids the need for cross-process ref-counting required by the
// TransferCache.
using PaintCacheId = uint32_t;
using PaintCacheIds = std::vector<PaintCacheId>;
enum class PaintCacheDataType : uint32_t { kTextBlob, kPath, kLast = kPath };
enum class PaintCacheEntryState : uint32_t {
kEmpty,
kCached,
kInlined,
kLast = kInlined
};
constexpr size_t PaintCacheDataTypeCount =
static_cast<uint32_t>(PaintCacheDataType::kLast) + 1u;
class CC_PAINT_EXPORT ClientPaintCache {
public:
explicit ClientPaintCache(size_t max_budget_bytes);
ClientPaintCache(const ClientPaintCache&) = delete;
~ClientPaintCache();
ClientPaintCache& operator=(const ClientPaintCache&) = delete;
bool Get(PaintCacheDataType type, PaintCacheId id);
void Put(PaintCacheDataType type, PaintCacheId id, size_t size);
// Populates |purged_data| with the list of ids which should be purged from
// the ServicePaintCache.
using PurgedData = PaintCacheIds[PaintCacheDataTypeCount];
void Purge(PurgedData* purged_data);
// Finalize the state of pending entries, which were sent to the service-side
// cache.
void FinalizePendingEntries();
// Notifies that the pending entries were not sent to the service-side cache
// and should be discarded.
void AbortPendingEntries();
// Notifies that all entries should be purged from the ServicePaintCache.
// Returns true if any entries were evicted from this call.
bool PurgeAll();
size_t bytes_used() const { return bytes_used_; }
private:
using CacheKey = std::pair<PaintCacheDataType, PaintCacheId>;
using CacheMap = base::MRUCache<CacheKey, size_t>;
template <typename Iterator>
void EraseFromMap(Iterator it);
CacheMap cache_map_;
const size_t max_budget_;
size_t bytes_used_ = 0u;
// List of entries added to the map but not committed since we might fail to
// send them to the service-side cache. This is necessary to ensure we
// maintain an accurate mirror of the service-side state.
base::StackVector<CacheKey, 1> pending_entries_;
};
class CC_PAINT_EXPORT ServicePaintCache {
public:
ServicePaintCache();
~ServicePaintCache();
// Stores the |blob| received from the client in the cache.
void PutTextBlob(PaintCacheId id, sk_sp<SkTextBlob> blob);
// Retrieves an entry for |id| stored in the cache. Or nullptr if the entry
// is not found.
sk_sp<SkTextBlob> GetTextBlob(PaintCacheId id) const;
// Stores |path| received from the client in the cache.
void PutPath(PaintCacheId, SkPath path);
// Retrieves an entry for |id| stored in the cache. The path data is stored in
// |path| pointed memory. Returns false, if the entry is not found.
bool GetPath(PaintCacheId id, SkPath* path) const;
void Purge(PaintCacheDataType type,
size_t n,
const volatile PaintCacheId* ids);
void PurgeAll();
bool empty() const { return cached_blobs_.empty() && cached_paths_.empty(); }
private:
using BlobMap = std::map<PaintCacheId, sk_sp<SkTextBlob>>;
BlobMap cached_blobs_;
using PathMap = std::map<PaintCacheId, SkPath>;
PathMap cached_paths_;
};
} // namespace cc
#endif // CC_PAINT_PAINT_CACHE_H_