| OLD | NEW | 
|---|
|  | (Empty) | 
| 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_SOFTWARE_IMAGE_DECODE_CONTROLLER_H_ |  | 
| 6 #define CC_TILES_SOFTWARE_IMAGE_DECODE_CONTROLLER_H_ |  | 
| 7 |  | 
| 8 #include <stdint.h> |  | 
| 9 |  | 
| 10 #include <memory> |  | 
| 11 #include <unordered_map> |  | 
| 12 #include <unordered_set> |  | 
| 13 |  | 
| 14 #include "base/atomic_sequence_num.h" |  | 
| 15 #include "base/containers/mru_cache.h" |  | 
| 16 #include "base/hash.h" |  | 
| 17 #include "base/memory/discardable_memory_allocator.h" |  | 
| 18 #include "base/memory/memory_coordinator_client.h" |  | 
| 19 #include "base/memory/ref_counted.h" |  | 
| 20 #include "base/numerics/safe_math.h" |  | 
| 21 #include "base/threading/thread_checker.h" |  | 
| 22 #include "base/trace_event/memory_dump_provider.h" |  | 
| 23 #include "cc/base/cc_export.h" |  | 
| 24 #include "cc/playback/decoded_draw_image.h" |  | 
| 25 #include "cc/playback/draw_image.h" |  | 
| 26 #include "cc/resources/resource_format.h" |  | 
| 27 #include "cc/tiles/image_decode_controller.h" |  | 
| 28 #include "third_party/skia/include/core/SkRefCnt.h" |  | 
| 29 #include "ui/gfx/geometry/rect.h" |  | 
| 30 |  | 
| 31 namespace cc { |  | 
| 32 |  | 
| 33 // ImageDecodeControllerKey is a class that gets a cache key out of a given draw |  | 
| 34 // image. That is, this key uniquely identifies an image in the cache. Note that |  | 
| 35 // it's insufficient to use SkImage's unique id, since the same image can appear |  | 
| 36 // in the cache multiple times at different scales and filter qualities. |  | 
| 37 class CC_EXPORT ImageDecodeControllerKey { |  | 
| 38  public: |  | 
| 39   static ImageDecodeControllerKey FromDrawImage(const DrawImage& image); |  | 
| 40 |  | 
| 41   ImageDecodeControllerKey(const ImageDecodeControllerKey& other); |  | 
| 42 |  | 
| 43   bool operator==(const ImageDecodeControllerKey& other) const { |  | 
| 44     // The image_id always has to be the same. However, after that all original |  | 
| 45     // decodes are the same, so if we can use the original decode, return true. |  | 
| 46     // If not, then we have to compare every field. |  | 
| 47     return image_id_ == other.image_id_ && |  | 
| 48            can_use_original_decode_ == other.can_use_original_decode_ && |  | 
| 49            (can_use_original_decode_ || |  | 
| 50             (src_rect_ == other.src_rect_ && |  | 
| 51              target_size_ == other.target_size_ && |  | 
| 52              filter_quality_ == other.filter_quality_)); |  | 
| 53   } |  | 
| 54 |  | 
| 55   bool operator!=(const ImageDecodeControllerKey& other) const { |  | 
| 56     return !(*this == other); |  | 
| 57   } |  | 
| 58 |  | 
| 59   uint32_t image_id() const { return image_id_; } |  | 
| 60   SkFilterQuality filter_quality() const { return filter_quality_; } |  | 
| 61   gfx::Rect src_rect() const { return src_rect_; } |  | 
| 62   gfx::Size target_size() const { return target_size_; } |  | 
| 63 |  | 
| 64   bool can_use_original_decode() const { return can_use_original_decode_; } |  | 
| 65   bool should_use_subrect() const { return should_use_subrect_; } |  | 
| 66   size_t get_hash() const { return hash_; } |  | 
| 67 |  | 
| 68   // Helper to figure out how much memory the locked image represented by this |  | 
| 69   // key would take. |  | 
| 70   size_t locked_bytes() const { |  | 
| 71     // TODO(vmpstr): Handle formats other than RGBA. |  | 
| 72     base::CheckedNumeric<size_t> result = 4; |  | 
| 73     result *= target_size_.width(); |  | 
| 74     result *= target_size_.height(); |  | 
| 75     return result.ValueOrDefault(std::numeric_limits<size_t>::max()); |  | 
| 76   } |  | 
| 77 |  | 
| 78   std::string ToString() const; |  | 
| 79 |  | 
| 80  private: |  | 
| 81   ImageDecodeControllerKey(uint32_t image_id, |  | 
| 82                            const gfx::Rect& src_rect, |  | 
| 83                            const gfx::Size& size, |  | 
| 84                            SkFilterQuality filter_quality, |  | 
| 85                            bool can_use_original_decode, |  | 
| 86                            bool should_use_subrect); |  | 
| 87 |  | 
| 88   uint32_t image_id_; |  | 
| 89   gfx::Rect src_rect_; |  | 
| 90   gfx::Size target_size_; |  | 
| 91   SkFilterQuality filter_quality_; |  | 
| 92   bool can_use_original_decode_; |  | 
| 93   bool should_use_subrect_; |  | 
| 94   size_t hash_; |  | 
| 95 }; |  | 
| 96 |  | 
| 97 // Hash function for the above ImageDecodeControllerKey. |  | 
| 98 struct ImageDecodeControllerKeyHash { |  | 
| 99   size_t operator()(const ImageDecodeControllerKey& key) const { |  | 
| 100     return key.get_hash(); |  | 
| 101   } |  | 
| 102 }; |  | 
| 103 |  | 
| 104 class CC_EXPORT SoftwareImageDecodeController |  | 
| 105     : public ImageDecodeController, |  | 
| 106       public base::trace_event::MemoryDumpProvider, |  | 
| 107       public base::MemoryCoordinatorClient { |  | 
| 108  public: |  | 
| 109   using ImageKey = ImageDecodeControllerKey; |  | 
| 110   using ImageKeyHash = ImageDecodeControllerKeyHash; |  | 
| 111 |  | 
| 112   SoftwareImageDecodeController(ResourceFormat format, |  | 
| 113                                 size_t locked_memory_limit_bytes); |  | 
| 114   ~SoftwareImageDecodeController() override; |  | 
| 115 |  | 
| 116   // ImageDecodeController overrides. |  | 
| 117   bool GetTaskForImageAndRef(const DrawImage& image, |  | 
| 118                              const TracingInfo& tracing_info, |  | 
| 119                              scoped_refptr<TileTask>* task) override; |  | 
| 120   void UnrefImage(const DrawImage& image) override; |  | 
| 121   DecodedDrawImage GetDecodedImageForDraw(const DrawImage& image) override; |  | 
| 122   void DrawWithImageFinished(const DrawImage& image, |  | 
| 123                              const DecodedDrawImage& decoded_image) override; |  | 
| 124   void ReduceCacheUsage() override; |  | 
| 125   // Software doesn't keep outstanding images pinned, so this is a no-op. |  | 
| 126   void SetShouldAggressivelyFreeResources( |  | 
| 127       bool aggressively_free_resources) override {} |  | 
| 128 |  | 
| 129   // Decode the given image and store it in the cache. This is only called by an |  | 
| 130   // image decode task from a worker thread. |  | 
| 131   void DecodeImage(const ImageKey& key, const DrawImage& image); |  | 
| 132 |  | 
| 133   void RemovePendingTask(const ImageKey& key); |  | 
| 134 |  | 
| 135   // MemoryDumpProvider overrides. |  | 
| 136   bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, |  | 
| 137                     base::trace_event::ProcessMemoryDump* pmd) override; |  | 
| 138 |  | 
| 139  private: |  | 
| 140   // DecodedImage is a convenience storage for discardable memory. It can also |  | 
| 141   // construct an image out of SkImageInfo and stored discardable memory. |  | 
| 142   class DecodedImage { |  | 
| 143    public: |  | 
| 144     DecodedImage(const SkImageInfo& info, |  | 
| 145                  std::unique_ptr<base::DiscardableMemory> memory, |  | 
| 146                  const SkSize& src_rect_offset, |  | 
| 147                  uint64_t tracing_id); |  | 
| 148     ~DecodedImage(); |  | 
| 149 |  | 
| 150     const sk_sp<SkImage>& image() const { |  | 
| 151       DCHECK(locked_); |  | 
| 152       return image_; |  | 
| 153     } |  | 
| 154 |  | 
| 155     const SkSize& src_rect_offset() const { return src_rect_offset_; } |  | 
| 156 |  | 
| 157     bool is_locked() const { return locked_; } |  | 
| 158     bool Lock(); |  | 
| 159     void Unlock(); |  | 
| 160 |  | 
| 161     const base::DiscardableMemory* memory() const { return memory_.get(); } |  | 
| 162 |  | 
| 163     // An ID which uniquely identifies this DecodedImage within the image decode |  | 
| 164     // controller. Used in memory tracing. |  | 
| 165     uint64_t tracing_id() const { return tracing_id_; } |  | 
| 166     // Mark this image as being used in either a draw or as a source for a |  | 
| 167     // scaled image. Either case represents this decode as being valuable and |  | 
| 168     // not wasted. |  | 
| 169     void mark_used() { usage_stats_.used = true; } |  | 
| 170 |  | 
| 171    private: |  | 
| 172     struct UsageStats { |  | 
| 173       // We can only create a decoded image in a locked state, so the initial |  | 
| 174       // lock count is 1. |  | 
| 175       int lock_count = 1; |  | 
| 176       bool used = false; |  | 
| 177       bool last_lock_failed = false; |  | 
| 178       bool first_lock_wasted = false; |  | 
| 179     }; |  | 
| 180 |  | 
| 181     bool locked_; |  | 
| 182     SkImageInfo image_info_; |  | 
| 183     std::unique_ptr<base::DiscardableMemory> memory_; |  | 
| 184     sk_sp<SkImage> image_; |  | 
| 185     SkSize src_rect_offset_; |  | 
| 186     uint64_t tracing_id_; |  | 
| 187     UsageStats usage_stats_; |  | 
| 188   }; |  | 
| 189 |  | 
| 190   // MemoryBudget is a convenience class for memory bookkeeping and ensuring |  | 
| 191   // that we don't go over the limit when pre-decoding. |  | 
| 192   class MemoryBudget { |  | 
| 193    public: |  | 
| 194     explicit MemoryBudget(size_t limit_bytes); |  | 
| 195 |  | 
| 196     size_t AvailableMemoryBytes() const; |  | 
| 197     void AddUsage(size_t usage); |  | 
| 198     void SubtractUsage(size_t usage); |  | 
| 199     void ResetUsage(); |  | 
| 200     size_t total_limit_bytes() const { return limit_bytes_; } |  | 
| 201     size_t GetCurrentUsageSafe() const; |  | 
| 202 |  | 
| 203    private: |  | 
| 204     size_t limit_bytes_; |  | 
| 205     base::CheckedNumeric<size_t> current_usage_bytes_; |  | 
| 206   }; |  | 
| 207 |  | 
| 208   using ImageMRUCache = base::HashingMRUCache<ImageKey, |  | 
| 209                                               std::unique_ptr<DecodedImage>, |  | 
| 210                                               ImageKeyHash>; |  | 
| 211 |  | 
| 212   // Looks for the key in the cache and returns true if it was found and was |  | 
| 213   // successfully locked (or if it was already locked). Note that if this |  | 
| 214   // function returns true, then a ref count is increased for the image. |  | 
| 215   bool LockDecodedImageIfPossibleAndRef(const ImageKey& key); |  | 
| 216 |  | 
| 217   // Actually decode the image. Note that this function can (and should) be |  | 
| 218   // called with no lock acquired, since it can do a lot of work. Note that it |  | 
| 219   // can also return nullptr to indicate the decode failed. |  | 
| 220   std::unique_ptr<DecodedImage> DecodeImageInternal( |  | 
| 221       const ImageKey& key, |  | 
| 222       const DrawImage& draw_image); |  | 
| 223 |  | 
| 224   // Get the decoded draw image for the given key and draw_image. Note that this |  | 
| 225   // function has to be called with no lock acquired, since it will acquire its |  | 
| 226   // own locks and might call DecodeImageInternal above. Also note that this |  | 
| 227   // function will use the provided key, even if |  | 
| 228   // ImageKey::FromDrawImage(draw_image) would return a different key. |  | 
| 229   // Note that when used internally, we still require that |  | 
| 230   // DrawWithImageFinished() is called afterwards. |  | 
| 231   DecodedDrawImage GetDecodedImageForDrawInternal(const ImageKey& key, |  | 
| 232                                                   const DrawImage& draw_image); |  | 
| 233 |  | 
| 234   // GetOriginalImageDecode is called by DecodeImageInternal when the quality |  | 
| 235   // does not scale the image. Like DecodeImageInternal, it should be called |  | 
| 236   // with no lock acquired and it returns nullptr if the decoding failed. |  | 
| 237   std::unique_ptr<DecodedImage> GetOriginalImageDecode( |  | 
| 238       sk_sp<const SkImage> image); |  | 
| 239 |  | 
| 240   // GetSubrectImageDecode is similar to GetOriginalImageDecode in that no scale |  | 
| 241   // is performed on the image. However, we extract a subrect (copy it out) and |  | 
| 242   // only return this subrect in order to cache a smaller amount of memory. Note |  | 
| 243   // that this uses GetOriginalImageDecode to get the initial data, which |  | 
| 244   // ensures that we cache an unlocked version of the original image in case we |  | 
| 245   // need to extract multiple subrects (as would be the case in an atlas). |  | 
| 246   std::unique_ptr<DecodedImage> GetSubrectImageDecode( |  | 
| 247       const ImageKey& key, |  | 
| 248       sk_sp<const SkImage> image); |  | 
| 249 |  | 
| 250   // GetScaledImageDecode is called by DecodeImageInternal when the quality |  | 
| 251   // requires the image be scaled. Like DecodeImageInternal, it should be |  | 
| 252   // called with no lock acquired and it returns nullptr if the decoding or |  | 
| 253   // scaling failed. |  | 
| 254   std::unique_ptr<DecodedImage> GetScaledImageDecode( |  | 
| 255       const ImageKey& key, |  | 
| 256       sk_sp<const SkImage> image); |  | 
| 257 |  | 
| 258   void SanityCheckState(int line, bool lock_acquired); |  | 
| 259   void RefImage(const ImageKey& key); |  | 
| 260   void RefAtRasterImage(const ImageKey& key); |  | 
| 261   void UnrefAtRasterImage(const ImageKey& key); |  | 
| 262 |  | 
| 263   // Helper function which dumps all images in a specific ImageMRUCache. |  | 
| 264   void DumpImageMemoryForCache(const ImageMRUCache& cache, |  | 
| 265                                const char* cache_name, |  | 
| 266                                base::trace_event::ProcessMemoryDump* pmd) const; |  | 
| 267 |  | 
| 268   // Overriden from base::MemoryCoordinatorClient. |  | 
| 269   void OnMemoryStateChange(base::MemoryState state) override; |  | 
| 270 |  | 
| 271   std::unordered_map<ImageKey, scoped_refptr<TileTask>, ImageKeyHash> |  | 
| 272       pending_image_tasks_; |  | 
| 273 |  | 
| 274   // The members below this comment can only be accessed if the lock is held to |  | 
| 275   // ensure that they are safe to access on multiple threads. |  | 
| 276   base::Lock lock_; |  | 
| 277 |  | 
| 278   // Decoded images and ref counts (predecode path). |  | 
| 279   ImageMRUCache decoded_images_; |  | 
| 280   std::unordered_map<ImageKey, int, ImageKeyHash> decoded_images_ref_counts_; |  | 
| 281 |  | 
| 282   // Decoded image and ref counts (at-raster decode path). |  | 
| 283   ImageMRUCache at_raster_decoded_images_; |  | 
| 284   std::unordered_map<ImageKey, int, ImageKeyHash> |  | 
| 285       at_raster_decoded_images_ref_counts_; |  | 
| 286 |  | 
| 287   MemoryBudget locked_images_budget_; |  | 
| 288 |  | 
| 289   ResourceFormat format_; |  | 
| 290   size_t max_items_in_cache_; |  | 
| 291 |  | 
| 292   // Used to uniquely identify DecodedImages for memory traces. |  | 
| 293   base::AtomicSequenceNumber next_tracing_id_; |  | 
| 294 }; |  | 
| 295 |  | 
| 296 }  // namespace cc |  | 
| 297 |  | 
| 298 #endif  // CC_TILES_SOFTWARE_IMAGE_DECODE_CONTROLLER_H_ |  | 
| OLD | NEW | 
|---|