1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef CC_TILES_IMAGE_CONTROLLER_H_
6 #define CC_TILES_IMAGE_CONTROLLER_H_
12 #include "base/callback.h"
13 #include "base/containers/flat_map.h"
14 #include "base/memory/raw_ptr.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/synchronization/lock.h"
18 #include "base/task/sequenced_task_runner.h"
19 #include "base/thread_annotations.h"
20 #include "cc/base/unique_notifier.h"
21 #include "cc/cc_export.h"
22 #include "cc/paint/draw_image.h"
23 #include "cc/raster/tile_task.h"
24 #include "cc/tiles/image_decode_cache.h"
28 class CC_EXPORT ImageController {
30 enum class ImageDecodeResult { SUCCESS, DECODE_NOT_REQUIRED, FAILURE };
32 using ImageDecodeRequestId = uint64_t;
33 using ImageDecodedCallback =
34 base::OnceCallback<void(ImageDecodeRequestId, ImageDecodeResult)>;
35 explicit ImageController(
36 scoped_refptr<base::SequencedTaskRunner> origin_task_runner,
37 scoped_refptr<base::SequencedTaskRunner> worker_task_runner);
38 ImageController(const ImageController&) = delete;
39 virtual ~ImageController();
41 ImageController& operator=(const ImageController&) = delete;
43 void SetImageDecodeCache(ImageDecodeCache* cache);
44 // Build tile tasks for synchronously decoded images.
45 // |sync_decoded_images| is the input. These are the images from a particular
46 // tile, retrieved by the DiscardableImageMap. Images can be removed from the
47 // vector under certain conditions.
48 // |tasks| is an output, which are the built tile tasks.
49 // |has_at_raster_images| is an output parameter.
50 // |has_hardware_accelerated_jpeg_candidates| and
51 // |has_hardware_accelerated_webp_candidates| are output parameters that
52 // indicate if there are images in |sync_decoded_images| that could be decoded
53 // using hardware decode acceleration.
54 // |tracing_info| is used in tracing or UMA only.
55 void ConvertImagesToTasks(std::vector<DrawImage>* sync_decoded_images,
56 std::vector<scoped_refptr<TileTask>>* tasks,
57 bool* has_at_raster_images,
58 bool* has_hardware_accelerated_jpeg_candidates,
59 bool* has_hardware_accelerated_webp_candidates,
60 const ImageDecodeCache::TracingInfo& tracing_info);
61 void UnrefImages(const std::vector<DrawImage>& images);
62 void ReduceMemoryUsage();
63 std::vector<scoped_refptr<TileTask>> SetPredecodeImages(
64 std::vector<DrawImage> predecode_images,
65 const ImageDecodeCache::TracingInfo& tracing_info);
67 // Virtual for testing.
68 virtual void UnlockImageDecode(ImageDecodeRequestId id);
70 // This function requests that the given image be decoded and locked. Once the
71 // callback has been issued, it is passed an ID, which should be used to
72 // unlock this image. It is up to the caller to ensure that the image is later
73 // unlocked using UnlockImageDecode.
74 // Virtual for testing.
75 virtual ImageDecodeRequestId QueueImageDecode(const DrawImage& draw_image,
76 ImageDecodedCallback callback);
77 size_t image_cache_max_limit_bytes() const {
78 return image_cache_max_limit_bytes_;
81 void SetMaxImageCacheLimitBytesForTesting(size_t bytes) {
82 image_cache_max_limit_bytes_ = bytes;
85 ImageDecodeCache* cache() const { return cache_; }
88 scoped_refptr<base::SequencedTaskRunner> worker_task_runner_;
91 struct ImageDecodeRequest {
93 ImageDecodeRequest(ImageDecodeRequestId id,
94 const DrawImage& draw_image,
95 ImageDecodedCallback callback,
96 scoped_refptr<TileTask> task,
98 ImageDecodeRequest(ImageDecodeRequest&& other);
99 ~ImageDecodeRequest();
101 ImageDecodeRequest& operator=(ImageDecodeRequest&& other);
103 ImageDecodeRequestId id;
104 DrawImage draw_image;
105 ImageDecodedCallback callback;
106 scoped_refptr<TileTask> task;
110 enum class WorkerTaskState {
116 // State accessible from the worker thread. Held in a isolated struct so it
117 // can be deleted asynchronously on the worker thread after the
118 // ImageController is deleted.
120 WorkerState(scoped_refptr<base::SequencedTaskRunner> origin_task_runner,
121 base::WeakPtr<ImageController> weak_ptr);
125 std::map<ImageDecodeRequestId, ImageDecodeRequest> image_decode_queue
127 std::map<ImageDecodeRequestId, ImageDecodeRequest>
128 requests_needing_completion GUARDED_BY(lock);
129 WorkerTaskState task_state GUARDED_BY(lock) = WorkerTaskState::kNoTask;
130 bool abort_task GUARDED_BY(lock) = false;
132 const scoped_refptr<base::SequencedTaskRunner> origin_task_runner;
133 const base::WeakPtr<ImageController> weak_ptr;
136 void StopWorkerTasks();
138 static void ProcessNextImageDecodeOnWorkerThread(WorkerState* worker_state);
140 void ImageDecodeCompleted(ImageDecodeRequestId id);
141 void GenerateTasksForOrphanedRequests();
143 void ScheduleImageDecodeOnWorkerIfNeeded()
144 EXCLUSIVE_LOCKS_REQUIRED(worker_state_->lock);
146 raw_ptr<ImageDecodeCache> cache_ = nullptr;
147 std::vector<DrawImage> predecode_locked_images_;
149 static ImageDecodeRequestId s_next_image_decode_queue_id_;
150 base::flat_map<ImageDecodeRequestId, DrawImage> requested_locked_images_;
151 size_t image_cache_max_limit_bytes_ = 0u;
153 std::unique_ptr<WorkerState> worker_state_;
155 // Orphaned requests are requests that were either in queue or needed a
156 // completion callback when we set the decode cache to be nullptr. When a new
157 // decode cache is set, these requests are re-enqueued again with tasks
158 // generated by the new cache. Note that when the cache is set, then aside
159 // from generating new tasks, this vector should be empty.
160 std::vector<ImageDecodeRequest> orphaned_decode_requests_;
162 base::WeakPtrFactory<ImageController> weak_ptr_factory_{this};
167 #endif // CC_TILES_IMAGE_CONTROLLER_H_