1 // Copyright 2013 The Flutter 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 FLUTTER_FLOW_RASTER_CACHE_H_ 6 #define FLUTTER_FLOW_RASTER_CACHE_H_ 7 8 #include <memory> 9 #include <unordered_map> 10 11 #include "flutter/flow/instrumentation.h" 12 #include "flutter/flow/raster_cache_key.h" 13 #include "flutter/fml/macros.h" 14 #include "flutter/fml/memory/weak_ptr.h" 15 #include "third_party/skia/include/core/SkImage.h" 16 #include "third_party/skia/include/core/SkSize.h" 17 18 namespace flutter { 19 20 class RasterCacheResult { 21 public: 22 RasterCacheResult(); 23 24 RasterCacheResult(const RasterCacheResult& other); 25 26 ~RasterCacheResult(); 27 28 RasterCacheResult(sk_sp<SkImage> image, const SkRect& logical_rect); 29 30 operator bool() const { return static_cast<bool>(image_); } 31 is_valid()32 bool is_valid() const { return static_cast<bool>(image_); }; 33 34 void draw(SkCanvas& canvas, const SkPaint* paint = nullptr) const; 35 image_dimensions()36 SkISize image_dimensions() const { 37 return image_ ? image_->dimensions() : SkISize::Make(0, 0); 38 }; 39 40 private: 41 sk_sp<SkImage> image_; 42 SkRect logical_rect_; 43 }; 44 45 struct PrerollContext; 46 47 class RasterCache { 48 public: 49 // The default max number of picture raster caches to be generated per frame. 50 // Generating too many caches in one frame may cause jank on that frame. This 51 // limit allows us to throttle the cache and distribute the work across 52 // multiple frames. 53 static constexpr int kDefaultPictureCacheLimitPerFrame = 3; 54 55 explicit RasterCache( 56 size_t access_threshold = 3, 57 size_t picture_cache_limit_per_frame = kDefaultPictureCacheLimitPerFrame); 58 59 ~RasterCache(); 60 GetDeviceBounds(const SkRect & rect,const SkMatrix & ctm)61 static SkIRect GetDeviceBounds(const SkRect& rect, const SkMatrix& ctm) { 62 SkRect device_rect; 63 ctm.mapRect(&device_rect, rect); 64 SkIRect bounds; 65 device_rect.roundOut(&bounds); 66 return bounds; 67 } 68 GetIntegralTransCTM(const SkMatrix & ctm)69 static SkMatrix GetIntegralTransCTM(const SkMatrix& ctm) { 70 SkMatrix result = ctm; 71 result[SkMatrix::kMTransX] = SkScalarRoundToScalar(ctm.getTranslateX()); 72 result[SkMatrix::kMTransY] = SkScalarRoundToScalar(ctm.getTranslateY()); 73 return result; 74 } 75 76 // Return true if the cache is generated. 77 // 78 // We may return false and not generate the cache if 79 // 1. The picture is not worth rasterizing 80 // 2. The matrix is singular 81 // 3. The picture is accessed too few times 82 // 4. There are too many pictures to be cached in the current frame. 83 // (See also kDefaultPictureCacheLimitPerFrame.) 84 bool Prepare(GrContext* context, 85 SkPicture* picture, 86 const SkMatrix& transformation_matrix, 87 SkColorSpace* dst_color_space, 88 bool is_complex, 89 bool will_change); 90 91 void Prepare(PrerollContext* context, Layer* layer, const SkMatrix& ctm); 92 93 RasterCacheResult Get(const SkPicture& picture, const SkMatrix& ctm) const; 94 95 RasterCacheResult Get(Layer* layer, const SkMatrix& ctm) const; 96 97 void SweepAfterFrame(); 98 99 void Clear(); 100 101 void SetCheckboardCacheImages(bool checkerboard); 102 103 private: 104 struct Entry { 105 bool used_this_frame = false; 106 size_t access_count = 0; 107 RasterCacheResult image; 108 }; 109 110 template <class Cache, class Iterator> SweepOneCacheAfterFrame(Cache & cache)111 static void SweepOneCacheAfterFrame(Cache& cache) { 112 std::vector<Iterator> dead; 113 114 for (auto it = cache.begin(); it != cache.end(); ++it) { 115 Entry& entry = it->second; 116 if (!entry.used_this_frame) { 117 dead.push_back(it); 118 } 119 entry.used_this_frame = false; 120 } 121 122 for (auto it : dead) { 123 cache.erase(it); 124 } 125 } 126 127 const size_t access_threshold_; 128 const size_t picture_cache_limit_per_frame_; 129 size_t picture_cached_this_frame_ = 0; 130 PictureRasterCacheKey::Map<Entry> picture_cache_; 131 LayerRasterCacheKey::Map<Entry> layer_cache_; 132 bool checkerboard_images_; 133 fml::WeakPtrFactory<RasterCache> weak_factory_; 134 135 void TraceStatsToTimeline() const; 136 137 FML_DISALLOW_COPY_AND_ASSIGN(RasterCache); 138 }; 139 140 } // namespace flutter 141 142 #endif // FLUTTER_FLOW_RASTER_CACHE_H_ 143