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
|
// Copyright 2016 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_CONTROLLER_H_
#define CC_TILES_IMAGE_CONTROLLER_H_
#include <map>
#include <memory>
#include <vector>
#include "base/containers/flat_map.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr_exclusion.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
#include "base/task/sequenced_task_runner.h"
#include "base/thread_annotations.h"
#include "cc/base/unique_notifier.h"
#include "cc/cc_export.h"
#include "cc/paint/draw_image.h"
#include "cc/raster/tile_task.h"
#include "cc/tiles/image_decode_cache.h"
namespace cc {
class CC_EXPORT ImageController {
public:
enum class ImageDecodeResult { SUCCESS, DECODE_NOT_REQUIRED, FAILURE };
using ImageDecodeRequestId = uint64_t;
using ImageDecodedCallback =
base::OnceCallback<void(ImageDecodeRequestId, ImageDecodeResult)>;
explicit ImageController(
scoped_refptr<base::SequencedTaskRunner> origin_task_runner,
scoped_refptr<base::SequencedTaskRunner> worker_task_runner,
base::RepeatingCallback<void(scoped_refptr<TileTask>)>
notify_external_dependent);
ImageController(const ImageController&) = delete;
virtual ~ImageController();
ImageController& operator=(const ImageController&) = delete;
void SetImageDecodeCache(ImageDecodeCache* cache);
// Build tile tasks for synchronously decoded images.
// |sync_decoded_images| is the input. These are the images from a particular
// tile, retrieved by the DiscardableImageMap. Images can be removed from the
// vector under certain conditions.
// |tasks| is an output, which are the built tile tasks.
// |has_at_raster_images| is an output parameter.
// |has_hardware_accelerated_jpeg_candidates| and
// |has_hardware_accelerated_webp_candidates| are output parameters that
// indicate if there are images in |sync_decoded_images| that could be decoded
// using hardware decode acceleration.
// |tracing_info| is used in tracing or UMA only.
void ConvertImagesToTasks(std::vector<DrawImage>* sync_decoded_images,
std::vector<scoped_refptr<TileTask>>* tasks,
bool* has_at_raster_images,
bool* has_hardware_accelerated_jpeg_candidates,
bool* has_hardware_accelerated_webp_candidates,
const ImageDecodeCache::TracingInfo& tracing_info);
void UnrefImages(const std::vector<DrawImage>& images);
void ReduceMemoryUsage();
std::vector<scoped_refptr<TileTask>> SetPredecodeImages(
std::vector<DrawImage> predecode_images,
const ImageDecodeCache::TracingInfo& tracing_info);
// Virtual for testing.
virtual void UnlockImageDecode(ImageDecodeRequestId id);
// This function requests that the given image be decoded and locked. Once the
// callback has been issued, it is passed an ID, which should be used to
// unlock this image. It is up to the caller to ensure that the image is later
// unlocked using UnlockImageDecode.
// Virtual for testing.
virtual ImageDecodeRequestId QueueImageDecode(const DrawImage& draw_image,
ImageDecodedCallback callback,
bool speculative);
// Signals that an external dependency of `task` has completed.
void ExternalDependencyCompletedForTask(scoped_refptr<TileTask> task);
size_t image_cache_max_limit_bytes() const {
return image_cache_max_limit_bytes_;
}
void SetMaxImageCacheLimitBytesForTesting(size_t bytes) {
image_cache_max_limit_bytes_ = bytes;
}
bool HasReadyToRunTaskForTesting() const;
void FlushDecodeTasksForTesting();
ImageDecodeCache* cache() const { return cache_; }
protected:
scoped_refptr<base::SequencedTaskRunner> worker_task_runner_;
private:
struct ImageDecodeRequest {
ImageDecodeRequest();
ImageDecodeRequest(ImageDecodeRequestId id,
const DrawImage& draw_image,
ImageDecodedCallback callback,
scoped_refptr<TileTask> task,
bool need_unref,
bool has_external_dependency);
ImageDecodeRequest(ImageDecodeRequest&& other);
~ImageDecodeRequest();
ImageDecodeRequest& operator=(ImageDecodeRequest&& other);
ImageDecodeRequestId id;
DrawImage draw_image;
ImageDecodedCallback callback;
scoped_refptr<TileTask> task;
bool need_unref;
bool has_external_dependency;
};
enum class WorkerTaskState {
kNoTask,
kQueuedTask,
kRunningTask,
};
// State accessible from the worker thread. Held in a isolated struct so it
// can be deleted asynchronously on the worker thread after the
// ImageController is deleted.
struct WorkerState {
WorkerState(scoped_refptr<base::SequencedTaskRunner> origin_task_runner,
base::WeakPtr<ImageController> weak_ptr);
~WorkerState();
base::Lock lock;
std::map<ImageDecodeRequestId, ImageDecodeRequest> image_decode_queue
GUARDED_BY(lock);
std::map<ImageDecodeRequestId, ImageDecodeRequest>
requests_needing_completion GUARDED_BY(lock);
WorkerTaskState task_state GUARDED_BY(lock) = WorkerTaskState::kNoTask;
const scoped_refptr<base::SequencedTaskRunner> origin_task_runner;
const base::WeakPtr<ImageController> weak_ptr;
};
void ForEachDecodeRequest(base::FunctionRef<void(ImageDecodeRequest&)>);
void StopWorkerTasks();
bool HasReadyToRunTask() const;
static void ProcessNextImageDecodeOnWorkerThread(WorkerState* worker_state);
static void ProcessNextImageDecodeWithLock(WorkerState* worker_state);
void ImageDecodeCompleted(ImageDecodeRequestId id);
ImageDecodeResult CompleteTaskForRequest(ImageDecodeRequest& request);
void GenerateTasksForOrphanedRequests();
void ScheduleImageDecodeOnWorkerIfNeeded()
EXCLUSIVE_LOCKS_REQUIRED(worker_state_->lock);
// RAW_PTR_EXCLUSION: ImageDecodeCache is marked as not supported by raw_ptr.
// See raw_ptr.h for more information.
RAW_PTR_EXCLUSION ImageDecodeCache* cache_ = nullptr;
std::vector<DrawImage> predecode_locked_images_;
static ImageDecodeRequestId s_next_image_decode_queue_id_;
base::flat_map<ImageDecodeRequestId, DrawImage> requested_locked_images_;
size_t image_cache_max_limit_bytes_ = 0u;
std::unique_ptr<WorkerState> worker_state_;
base::RepeatingClosure worker_task_;
const base::RepeatingCallback<void(scoped_refptr<TileTask>)>
notify_external_dependent_;
// Orphaned requests are requests that were either in queue or needed a
// completion callback when we set the decode cache to be nullptr. When a new
// decode cache is set, these requests are re-enqueued again with tasks
// generated by the new cache. Note that when the cache is set, then aside
// from generating new tasks, this vector should be empty.
std::vector<ImageDecodeRequest> orphaned_decode_requests_;
// The id generated by ImageDecodeCache instance to identify this client
// instance when requesting image tasks.
ImageDecodeCache::ClientId image_cache_client_id_ = 0;
base::WeakPtrFactory<ImageController> weak_ptr_factory_{this};
};
} // namespace cc
#endif // CC_TILES_IMAGE_CONTROLLER_H_
|