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 197 198 199 200 201 202 203 204 205 206
|
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CC_TILES_IMAGE_DECODE_CACHE_H_
#define CC_TILES_IMAGE_DECODE_CACHE_H_
#include <atomic>
#include "base/memory/ref_counted.h"
#include "base/notreached.h"
#include "cc/base/devtools_instrumentation.h"
#include "cc/cc_export.h"
#include "cc/paint/decoded_draw_image.h"
#include "cc/paint/draw_image.h"
#include "cc/raster/tile_task.h"
#include "cc/tiles/image_decode_cache_utils.h"
#include "cc/tiles/tile_priority.h"
namespace cc {
// ImageDecodeCache is responsible for generating decode tasks, decoding
// images, storing images in cache, and being able to return the decoded images
// when requested.
// ImageDecodeCache is responsible for the following things:
// 1. Given a DrawImage, it can return an TileTask which when run will
// decode and cache the resulting image. If the image does not need a task to
// be decoded, then nullptr will be returned. The return value of the
// function indicates whether the image was or is going to be locked, so an
// unlock will be required.
// 2. Given a cache key and a DrawImage, it can decode the image and store it in
// the cache. Note that it is important that this function is only accessed
// via an image decode task.
// 3. Given a DrawImage, it can return a DecodedDrawImage, which represented the
// decoded version of the image. Note that if the image is not in the cache
// and it needs to be scaled/decoded, then this decode will happen as part of
// getting the image. As such, this should only be accessed from a raster
// thread.
class CC_EXPORT ImageDecodeCache {
public:
enum class TaskType { kInRaster, kOutOfRaster };
// See GenerateClientId.
using ClientId = uint32_t;
// This information should be used strictly in tracing, UMA, and any other
// reporting systems.
struct TracingInfo {
TracingInfo(uint64_t prepare_tiles_id,
TilePriority::PriorityBin requesting_tile_bin)
: prepare_tiles_id(prepare_tiles_id),
requesting_tile_bin(requesting_tile_bin) {}
TracingInfo() = default;
// ID for the current prepare tiles call.
const uint64_t prepare_tiles_id = 0;
// The bin of the tile that caused this image to be requested.
const TilePriority::PriorityBin requesting_tile_bin = TilePriority::NOW;
};
static devtools_instrumentation::ScopedImageDecodeTask::TaskType
ToScopedTaskType(TaskType task_type) {
using ScopedTaskType =
devtools_instrumentation::ScopedImageDecodeTask::TaskType;
switch (task_type) {
case TaskType::kInRaster:
return ScopedTaskType::kInRaster;
case TaskType::kOutOfRaster:
return ScopedTaskType::kOutOfRaster;
}
NOTREACHED();
}
static devtools_instrumentation::ScopedImageDecodeTask::ImageType
ToScopedImageType(ImageType image_type) {
using ScopedImageType =
devtools_instrumentation::ScopedImageDecodeTask::ImageType;
switch (image_type) {
case ImageType::kAVIF:
return ScopedImageType::kAvif;
case ImageType::kBMP:
return ScopedImageType::kBmp;
case ImageType::kGIF:
return ScopedImageType::kGif;
case ImageType::kICO:
return ScopedImageType::kIco;
case ImageType::kJPEG:
return ScopedImageType::kJpeg;
case ImageType::kPNG:
return ScopedImageType::kPng;
case ImageType::kWEBP:
return ScopedImageType::kWebP;
case ImageType::kInvalid:
return ScopedImageType::kOther;
}
}
virtual ~ImageDecodeCache() {}
struct CC_EXPORT TaskResult {
explicit TaskResult(bool need_unref,
bool is_at_raster_decode,
bool can_do_hardware_accelerated_decode);
explicit TaskResult(scoped_refptr<TileTask> task,
bool can_do_hardware_accelerated_decode);
TaskResult(const TaskResult& result);
~TaskResult();
scoped_refptr<TileTask> task;
bool need_unref = false;
bool is_at_raster_decode = false;
bool can_do_hardware_accelerated_decode = false;
};
// Fill in an TileTask which will decode the given image when run. In
// case the image is already cached, fills in nullptr. Returns true if the
// image needs to be unreffed when the caller is finished with it. |client_id|
// helps to identify a client that requests a task if the cache is shared
// between multiple clients. Returns the same task iff an image task for the
// the |client_id| already exists. The way multiple image tasks for the same
// image from different clients are managed is an implementation detail of the
// cache instance. The clients shouldn't worry about the ordering between
// these tasks. The |client_id| is an id that must be generated by calling
// |GenerateClientId| to avoid any collisions.
//
// This is called by the tile manager (on the compositor thread) when creating
// a raster task.
virtual TaskResult GetTaskForImageAndRef(ClientId client_id,
const DrawImage& image,
const TracingInfo& tracing_info) = 0;
// Similar to GetTaskForImageAndRef (including the |client_id|), except that
// it returns tasks that are not meant to be run as part of raster. That is,
// this is part of a predecode API. Note that this should only return a task
// responsible for decoding (and not uploading), since it will be run on a
// worker thread which may not have the right GPU context for upload.
virtual TaskResult GetOutOfRasterDecodeTaskForImageAndRef(
ClientId client_id,
const DrawImage& image,
bool speculative = false) = 0;
// Unrefs an image. When the tile is finished, this should be called for every
// GetTaskForImageAndRef call that returned true.
virtual void UnrefImage(const DrawImage& image) = 0;
// Returns a decoded draw image. This may cause a decode if the image was not
// predecoded.
//
// This is called by a raster task (on a worker thread) when an image is
// required.
//
// TODO(khushalsagar/vmpstr): Since the cache knows if it's a video frame, it
// should discard any frames from the same source not in use in the
// compositor.
virtual DecodedDrawImage GetDecodedImageForDraw(const DrawImage& image) = 0;
// Unrefs an image. This should be called for every GetDecodedImageForDraw
// when the draw with the image is finished.
virtual void DrawWithImageFinished(const DrawImage& image,
const DecodedDrawImage& decoded_image) = 0;
// This function informs the cache that now is a good time to clean up
// memory. This is called periodically from the compositor thread.
virtual void ReduceCacheUsage() = 0;
// This function informs the cache that we are hidden and should not be
// retaining cached resources longer than needed. If |context_lock_acquired|
// is true, the caller has already acquired the context lock.
virtual void SetShouldAggressivelyFreeResources(
bool aggressively_free_resources) = 0;
// Clears all elements from the cache.
virtual void ClearCache() = 0;
// Returns the maximum amount of memory we would be able to lock. This ignores
// any temporary states, such as throttled, and return the maximum possible
// memory. It is used as an esimate of whether an image can fit into the
// locked budget before creating a task.
virtual size_t GetMaximumMemoryLimitBytes() const = 0;
// Returns true if the cache should be used for |image|. In certain cases the
// image can directly be used for raster (for instance bitmaps in a software
// draw).
virtual bool UseCacheForDrawImage(const DrawImage& image) const = 0;
// Should be called periodically to record statistics about cache use and
// performance.
virtual void RecordStats() = 0;
// Returns a unique id that can be used to request upload/decode tasks for
// images' uploading/decoding. This can be optionally used by ImageDecodeCache
// instance to manage decode/upload tasks. Implementations may override this
// to add additional logic. However, they should eventually use this to have a
// new client id generated.
virtual ClientId GenerateClientId();
protected:
static const ClientId kDefaultClientId;
private:
// A next available id for a client identification.
std::atomic<ClientId> next_available_id_ = 0;
};
} // namespace cc
#endif // CC_TILES_IMAGE_DECODE_CACHE_H_
|