vmpstr | 64cdba3 | 2016-03-03 00:38:40 | [diff] [blame] | 1 | // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef CC_TILES_GPU_IMAGE_DECODE_CONTROLLER_H_ |
| 6 | #define CC_TILES_GPU_IMAGE_DECODE_CONTROLLER_H_ |
| 7 | |
ericrk | d2ff2a13 | 2016-04-11 22:16:00 | [diff] [blame] | 8 | #include <memory> |
vmpstr | 64cdba3 | 2016-03-03 00:38:40 | [diff] [blame] | 9 | #include <unordered_map> |
ericrk | d2ff2a13 | 2016-04-11 22:16:00 | [diff] [blame] | 10 | #include <vector> |
vmpstr | 64cdba3 | 2016-03-03 00:38:40 | [diff] [blame] | 11 | |
ericrk | d2ff2a13 | 2016-04-11 22:16:00 | [diff] [blame] | 12 | #include "base/containers/mru_cache.h" |
| 13 | #include "base/memory/discardable_memory.h" |
vmpstr | 64cdba3 | 2016-03-03 00:38:40 | [diff] [blame] | 14 | #include "base/synchronization/lock.h" |
ericrk | d2ff2a13 | 2016-04-11 22:16:00 | [diff] [blame] | 15 | #include "base/trace_event/memory_dump_provider.h" |
vmpstr | 64cdba3 | 2016-03-03 00:38:40 | [diff] [blame] | 16 | #include "cc/base/cc_export.h" |
ericrk | d2ff2a13 | 2016-04-11 22:16:00 | [diff] [blame] | 17 | #include "cc/resources/resource_format.h" |
vmpstr | 64cdba3 | 2016-03-03 00:38:40 | [diff] [blame] | 18 | #include "cc/tiles/image_decode_controller.h" |
ericrk | d2ff2a13 | 2016-04-11 22:16:00 | [diff] [blame] | 19 | #include "skia/ext/refptr.h" |
| 20 | |
| 21 | class SkImageTextureData; |
vmpstr | 64cdba3 | 2016-03-03 00:38:40 | [diff] [blame] | 22 | |
| 23 | namespace cc { |
| 24 | |
ericrk | d2ff2a13 | 2016-04-11 22:16:00 | [diff] [blame] | 25 | class ContextProvider; |
| 26 | |
| 27 | // GpuImageDecodeController handles the decode and upload of images that will |
| 28 | // be used by Skia's GPU raster path. It also maintains a cache of these |
| 29 | // decoded/uploaded images for later re-use. |
| 30 | // |
| 31 | // Generally, when an image is required for raster, GpuImageDecodeController |
| 32 | // creates two tasks, one to decode the image, and one to upload the image to |
| 33 | // the GPU. These tasks are completed before the raster task which depends on |
| 34 | // the image. We need to seperate decode and upload tasks, as decode can occur |
| 35 | // simultaneously on multiple threads, while upload requires the GL context |
| 36 | // lock must happen on our non-concurrent raster thread. |
| 37 | // |
| 38 | // Decoded and Uploaded image data share a single cache entry. Depending on how |
| 39 | // far we've progressed, this cache entry may contain CPU-side decoded data, |
| 40 | // GPU-side uploaded data, or both. Because CPU-side decoded data is stored in |
| 41 | // discardable memory, and is only locked for short periods of time (until the |
| 42 | // upload completes), this memory is not counted against our sized cache |
| 43 | // limits. Uploaded GPU memory, being non-discardable, always counts against |
| 44 | // our limits. |
| 45 | // |
| 46 | // In cases where the number of images needed exceeds our cache limits, we |
| 47 | // operate in an "at-raster" mode. In this mode, there are no decode/upload |
| 48 | // tasks, and images are decoded/uploaded as needed, immediately before being |
| 49 | // used in raster. Cache entries for at-raster tasks are marked as such, which |
| 50 | // prevents future tasks from taking a dependency on them and extending their |
| 51 | // lifetime longer than is necessary. |
vmpstr | 64cdba3 | 2016-03-03 00:38:40 | [diff] [blame] | 52 | class CC_EXPORT GpuImageDecodeController : public ImageDecodeController { |
| 53 | public: |
ericrk | d2ff2a13 | 2016-04-11 22:16:00 | [diff] [blame] | 54 | explicit GpuImageDecodeController(ContextProvider* context, |
| 55 | ResourceFormat decode_format); |
vmpstr | 64cdba3 | 2016-03-03 00:38:40 | [diff] [blame] | 56 | ~GpuImageDecodeController() override; |
| 57 | |
| 58 | // ImageDecodeController overrides. |
ericrk | d2ff2a13 | 2016-04-11 22:16:00 | [diff] [blame] | 59 | |
| 60 | // Finds the existing uploaded image for the provided DrawImage. Creates an |
| 61 | // upload task to upload the image if an exsiting image does not exist. |
vmpstr | 64cdba3 | 2016-03-03 00:38:40 | [diff] [blame] | 62 | bool GetTaskForImageAndRef(const DrawImage& image, |
| 63 | uint64_t prepare_tiles_id, |
prashant.n | 49b3e6465 | 2016-04-19 07:04:49 | [diff] [blame^] | 64 | scoped_refptr<TileTask>* task) override; |
vmpstr | 64cdba3 | 2016-03-03 00:38:40 | [diff] [blame] | 65 | void UnrefImage(const DrawImage& image) override; |
| 66 | DecodedDrawImage GetDecodedImageForDraw(const DrawImage& draw_image) override; |
| 67 | void DrawWithImageFinished(const DrawImage& image, |
| 68 | const DecodedDrawImage& decoded_image) override; |
| 69 | void ReduceCacheUsage() override; |
ericrk | d2ff2a13 | 2016-04-11 22:16:00 | [diff] [blame] | 70 | void SetShouldAggressivelyFreeResources( |
| 71 | bool aggressively_free_resources) override; |
vmpstr | 64cdba3 | 2016-03-03 00:38:40 | [diff] [blame] | 72 | |
ericrk | d2ff2a13 | 2016-04-11 22:16:00 | [diff] [blame] | 73 | // Called by Decode / Upload tasks. |
vmpstr | 64cdba3 | 2016-03-03 00:38:40 | [diff] [blame] | 74 | void DecodeImage(const DrawImage& image); |
ericrk | d2ff2a13 | 2016-04-11 22:16:00 | [diff] [blame] | 75 | void UploadImage(const DrawImage& image); |
| 76 | void DecodeTaskCompleted(const DrawImage& image); |
| 77 | void UploadTaskCompleted(const DrawImage& image); |
vmpstr | 64cdba3 | 2016-03-03 00:38:40 | [diff] [blame] | 78 | |
ericrk | d2ff2a13 | 2016-04-11 22:16:00 | [diff] [blame] | 79 | // For testing only. |
| 80 | void SetCachedItemLimitForTesting(size_t limit) { |
| 81 | cached_items_limit_ = limit; |
| 82 | } |
| 83 | void SetCachedBytesLimitForTesting(size_t limit) { |
| 84 | cached_bytes_limit_ = limit; |
| 85 | } |
| 86 | size_t GetBytesUsedForTesting() const { return bytes_used_; } |
vmpstr | 64cdba3 | 2016-03-03 00:38:40 | [diff] [blame] | 87 | |
| 88 | private: |
ericrk | d2ff2a13 | 2016-04-11 22:16:00 | [diff] [blame] | 89 | enum class DecodedDataMode { GPU, CPU }; |
| 90 | |
| 91 | // Stores the CPU-side decoded bits of an image and supporting fields. |
| 92 | struct DecodedImageData { |
| 93 | DecodedImageData(); |
| 94 | ~DecodedImageData(); |
| 95 | |
| 96 | // May be null if image not yet decoded. |
| 97 | std::unique_ptr<base::DiscardableMemory> data; |
| 98 | uint32_t ref_count; |
| 99 | bool is_locked; |
| 100 | |
| 101 | // Set to true if the image was corrupt and could not be decoded. |
| 102 | bool decode_failure; |
| 103 | }; |
| 104 | |
| 105 | // Stores the GPU-side image and supporting fields. |
| 106 | struct UploadedImageData { |
| 107 | UploadedImageData(); |
| 108 | ~UploadedImageData(); |
| 109 | |
| 110 | // May be null if image not yet uploaded / prepared. |
| 111 | skia::RefPtr<SkImage> image; |
| 112 | // True if the image is counting against our memory limits. |
| 113 | bool budgeted; |
| 114 | uint32_t ref_count; |
| 115 | }; |
| 116 | |
| 117 | struct ImageData { |
| 118 | ImageData(DecodedDataMode mode, size_t size); |
| 119 | ~ImageData(); |
| 120 | |
| 121 | const DecodedDataMode mode; |
| 122 | const size_t size; |
| 123 | bool is_at_raster; |
| 124 | |
| 125 | DecodedImageData decode; |
| 126 | UploadedImageData upload; |
| 127 | }; |
| 128 | |
| 129 | using ImageDataMRUCache = |
| 130 | base::MRUCache<uint32_t, std::unique_ptr<ImageData>>; |
| 131 | |
| 132 | // All private functions should only be called while holding |lock_|. Some |
| 133 | // functions also require the |context_| lock. These are indicated by |
| 134 | // additional comments. |
| 135 | |
| 136 | // Similar to GetTaskForImageAndRef, but gets the dependent decode task |
| 137 | // rather than the upload task, if necessary. |
prashant.n | 49b3e6465 | 2016-04-19 07:04:49 | [diff] [blame^] | 138 | scoped_refptr<TileTask> GetImageDecodeTaskAndRef(const DrawImage& image, |
| 139 | uint64_t prepare_tiles_id); |
ericrk | d2ff2a13 | 2016-04-11 22:16:00 | [diff] [blame] | 140 | |
| 141 | void RefImageDecode(const DrawImage& draw_image); |
| 142 | void UnrefImageDecode(const DrawImage& draw_image); |
| 143 | void RefImage(const DrawImage& draw_image); |
| 144 | void UnrefImageInternal(const DrawImage& draw_image); |
| 145 | void RefCountChanged(ImageData* image_data); |
| 146 | |
| 147 | // Ensures that the cache can hold an element of |required_size|, freeing |
| 148 | // unreferenced cache entries if necessary to make room. |
| 149 | bool EnsureCapacity(size_t required_size); |
| 150 | bool CanFitSize(size_t size) const; |
| 151 | bool ExceedsPreferredCount() const; |
| 152 | |
| 153 | void DecodeImageIfNecessary(const DrawImage& draw_image, |
| 154 | ImageData* image_data); |
| 155 | |
| 156 | std::unique_ptr<GpuImageDecodeController::ImageData> CreateImageData( |
| 157 | const DrawImage& image); |
| 158 | SkImageInfo CreateImageInfoForDrawImage(const DrawImage& draw_image) const; |
| 159 | |
| 160 | // The following two functions also require the |context_| lock to be held. |
| 161 | void UploadImageIfNecessary(const DrawImage& draw_image, |
| 162 | ImageData* image_data); |
| 163 | void DeletePendingImages(); |
| 164 | |
| 165 | const ResourceFormat format_; |
| 166 | ContextProvider* context_; |
| 167 | skia::RefPtr<GrContextThreadSafeProxy> context_threadsafe_proxy_; |
| 168 | |
| 169 | // All members below this point must only be accessed while holding |lock_|. |
vmpstr | 64cdba3 | 2016-03-03 00:38:40 | [diff] [blame] | 170 | base::Lock lock_; |
| 171 | |
prashant.n | 49b3e6465 | 2016-04-19 07:04:49 | [diff] [blame^] | 172 | std::unordered_map<uint32_t, scoped_refptr<TileTask>> |
ericrk | d2ff2a13 | 2016-04-11 22:16:00 | [diff] [blame] | 173 | pending_image_upload_tasks_; |
prashant.n | 49b3e6465 | 2016-04-19 07:04:49 | [diff] [blame^] | 174 | std::unordered_map<uint32_t, scoped_refptr<TileTask>> |
ericrk | d2ff2a13 | 2016-04-11 22:16:00 | [diff] [blame] | 175 | pending_image_decode_tasks_; |
| 176 | |
| 177 | ImageDataMRUCache image_data_; |
| 178 | |
| 179 | size_t cached_items_limit_; |
| 180 | size_t cached_bytes_limit_; |
| 181 | size_t bytes_used_; |
| 182 | |
| 183 | // We can't release GPU backed SkImages without holding the context lock, |
| 184 | // so we add them to this list and defer deletion until the next time the lock |
| 185 | // is held. |
| 186 | std::vector<skia::RefPtr<SkImage>> images_pending_deletion_; |
vmpstr | 64cdba3 | 2016-03-03 00:38:40 | [diff] [blame] | 187 | }; |
| 188 | |
| 189 | } // namespace cc |
| 190 | |
| 191 | #endif // CC_TILES_GPU_IMAGE_DECODE_CONTROLLER_H_ |