mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
The size of the LTO build of the engine with the dylib compressed is as follows: ```sh $ du -k libFlutter* 5236 libFlutter.dylib.tar.gz 4324 libFlutterSlimpeller.dylib.tar.gz ``` Sizes are in KiB. This represents a binary size reduction of 17.41% of the compressed artifacts. The compression ratios will likely differ based on the compression scheme. Uncompressed, the sizes are: ```sh $ du -k libFlutter* 16920 libFlutter.dylib 14044 libFlutterSlimpeller.dylib ``` This represents a binary size reduction of 16.99% which is in the same ballpark. The really mucky bit was backing out the raster cache and persistent cache. I want to clean that up in a later patch so that those TUs are part of a separate submodule. Opting out of Impeller will lead to a fatal log at startup saying the opt-out is disallowed. Fixes https://github.com/flutter/flutter/issues/126606
286 lines
9.1 KiB
C++
286 lines
9.1 KiB
C++
// Copyright 2013 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef FLUTTER_FLOW_RASTER_CACHE_H_
|
|
#define FLUTTER_FLOW_RASTER_CACHE_H_
|
|
|
|
#if !SLIMPELLER
|
|
|
|
#include <memory>
|
|
#include <unordered_map>
|
|
|
|
#include "flutter/display_list/dl_canvas.h"
|
|
#include "flutter/flow/raster_cache_key.h"
|
|
#include "flutter/flow/raster_cache_util.h"
|
|
#include "flutter/fml/macros.h"
|
|
#include "flutter/fml/memory/weak_ptr.h"
|
|
#include "flutter/fml/trace_event.h"
|
|
#include "third_party/skia/include/core/SkMatrix.h"
|
|
#include "third_party/skia/include/core/SkRect.h"
|
|
|
|
class GrDirectContext;
|
|
class SkColorSpace;
|
|
|
|
namespace flutter {
|
|
|
|
enum class RasterCacheLayerStrategy { kLayer, kLayerChildren };
|
|
|
|
class RasterCacheResult {
|
|
public:
|
|
RasterCacheResult(sk_sp<DlImage> image,
|
|
const SkRect& logical_rect,
|
|
const char* type,
|
|
sk_sp<const DlRTree> rtree = nullptr);
|
|
|
|
virtual ~RasterCacheResult() = default;
|
|
|
|
virtual void draw(DlCanvas& canvas,
|
|
const DlPaint* paint,
|
|
bool preserve_rtree) const;
|
|
|
|
virtual SkISize image_dimensions() const {
|
|
return image_ ? image_->dimensions() : SkISize::Make(0, 0);
|
|
};
|
|
|
|
virtual int64_t image_bytes() const {
|
|
return image_ ? image_->GetApproximateByteSize() : 0;
|
|
};
|
|
|
|
private:
|
|
sk_sp<DlImage> image_;
|
|
SkRect logical_rect_;
|
|
fml::tracing::TraceFlow flow_;
|
|
sk_sp<const DlRTree> rtree_;
|
|
};
|
|
|
|
class Layer;
|
|
class RasterCacheItem;
|
|
struct PrerollContext;
|
|
struct PaintContext;
|
|
|
|
struct RasterCacheMetrics {
|
|
/**
|
|
* The number of cache entries with images evicted in this frame.
|
|
*/
|
|
size_t eviction_count = 0;
|
|
|
|
/**
|
|
* The size of all of the images evicted in this frame.
|
|
*/
|
|
size_t eviction_bytes = 0;
|
|
|
|
/**
|
|
* The number of cache entries with images used in this frame.
|
|
*/
|
|
size_t in_use_count = 0;
|
|
|
|
/**
|
|
* The size of all of the images used in this frame.
|
|
*/
|
|
size_t in_use_bytes = 0;
|
|
|
|
/**
|
|
* The total cache entries that had images during this frame.
|
|
*/
|
|
size_t total_count() const { return in_use_count; }
|
|
|
|
/**
|
|
* The size of all of the cached images during this frame.
|
|
*/
|
|
size_t total_bytes() const { return in_use_bytes; }
|
|
};
|
|
|
|
/**
|
|
* RasterCache is used to cache rasterized layers or display lists to improve
|
|
* performance.
|
|
*
|
|
* Life cycle of RasterCache methods:
|
|
* - Preroll stage
|
|
* - LayerTree::Preroll - for each Layer in the tree:
|
|
* - RasterCacheItem::PrerollSetup
|
|
* At the start of each layer's preroll, add cache items to
|
|
* `PrerollContext::raster_cached_entries`.
|
|
* - RasterCacheItem::PrerollFinalize
|
|
* At the end of each layer's preroll, may mark cache entries as
|
|
* encountered by the current frame.
|
|
* - Paint stage
|
|
* - RasterCache::EvictUnusedCacheEntries
|
|
* Evict cached images that are no longer used.
|
|
* - LayerTree::TryToPrepareRasterCache
|
|
* Create cache image for each cache entry if it does not exist.
|
|
* - LayerTree::Paint - for each layer in the tree:
|
|
* If layers or display lists are cached as cached images, the method
|
|
* `RasterCache::Draw` will be used to draw those cache images.
|
|
* - RasterCache::EndFrame:
|
|
* Computes used counts and memory then reports cache metrics.
|
|
*/
|
|
class RasterCache {
|
|
public:
|
|
struct Context {
|
|
GrDirectContext* gr_context;
|
|
const sk_sp<SkColorSpace> dst_color_space;
|
|
const SkMatrix& matrix;
|
|
const SkRect& logical_rect;
|
|
const char* flow_type;
|
|
};
|
|
struct CacheInfo {
|
|
const size_t accesses_since_visible;
|
|
const bool has_image;
|
|
};
|
|
|
|
std::unique_ptr<RasterCacheResult> Rasterize(
|
|
const RasterCache::Context& context,
|
|
sk_sp<const DlRTree> rtree,
|
|
const std::function<void(DlCanvas*)>& draw_function,
|
|
const std::function<void(DlCanvas*, const SkRect& rect)>&
|
|
draw_checkerboard) const;
|
|
|
|
explicit RasterCache(
|
|
size_t access_threshold = 3,
|
|
size_t picture_and_display_list_cache_limit_per_frame =
|
|
RasterCacheUtil::kDefaultPictureAndDisplayListCacheLimitPerFrame);
|
|
|
|
virtual ~RasterCache() = default;
|
|
|
|
// Draws this item if it should be rendered from the cache and returns
|
|
// true iff it was successfully drawn. Typically this should only fail
|
|
// if the item was disabled due to conditions discovered during |Preroll|
|
|
// or if the attempt to populate the entry failed due to bounds overflow
|
|
// conditions.
|
|
// If |preserve_rtree| is true, the raster cache will preserve the original
|
|
// RTree of cached content by blitting individual rectangles from the cached
|
|
// image to the canvas according to the original layer R-Tree (if present).
|
|
// This is to ensure that the target surface R-Tree will not be clobbered with
|
|
// one large blit as it can affect platform view overlays and hit testing.
|
|
bool Draw(const RasterCacheKeyID& id,
|
|
DlCanvas& canvas,
|
|
const DlPaint* paint,
|
|
bool preserve_rtree = false) const;
|
|
|
|
bool HasEntry(const RasterCacheKeyID& id, const SkMatrix&) const;
|
|
|
|
void BeginFrame();
|
|
|
|
void EvictUnusedCacheEntries();
|
|
|
|
void EndFrame();
|
|
|
|
void Clear();
|
|
|
|
const RasterCacheMetrics& picture_metrics() const { return picture_metrics_; }
|
|
const RasterCacheMetrics& layer_metrics() const { return layer_metrics_; }
|
|
|
|
size_t GetCachedEntriesCount() const;
|
|
|
|
/**
|
|
* Return the number of map entries in the layer cache regardless of whether
|
|
* the entries have been populated with an image.
|
|
*/
|
|
size_t GetLayerCachedEntriesCount() const;
|
|
|
|
/**
|
|
* Return the number of map entries in the picture (DisplayList) cache
|
|
* regardless of whether the entries have been populated with an image.
|
|
*/
|
|
size_t GetPictureCachedEntriesCount() const;
|
|
|
|
/**
|
|
* @brief Estimate how much memory is used by picture raster cache entries in
|
|
* bytes.
|
|
*
|
|
* Only SkImage's memory usage is counted as other objects are often much
|
|
* smaller compared to SkImage. SkImageInfo::computeMinByteSize is used to
|
|
* estimate the SkImage memory usage.
|
|
*/
|
|
size_t EstimatePictureCacheByteSize() const;
|
|
|
|
/**
|
|
* @brief Estimate how much memory is used by layer raster cache entries in
|
|
* bytes.
|
|
*
|
|
* Only SkImage's memory usage is counted as other objects are often much
|
|
* smaller compared to SkImage. SkImageInfo::computeMinByteSize is used to
|
|
* estimate the SkImage memory usage.
|
|
*/
|
|
size_t EstimateLayerCacheByteSize() const;
|
|
|
|
/**
|
|
* @brief Return the number of frames that a picture must be prepared
|
|
* before it will be cached. If the number is 0, then no picture will
|
|
* ever be cached.
|
|
*
|
|
* If the number is one, then it must be prepared and drawn on 1 frame
|
|
* and it will then be cached on the next frame if it is prepared.
|
|
*/
|
|
size_t access_threshold() const { return access_threshold_; }
|
|
|
|
bool GenerateNewCacheInThisFrame() const {
|
|
// Disabling caching when access_threshold is zero is historic behavior.
|
|
return access_threshold_ != 0 && display_list_cached_this_frame_ <
|
|
display_list_cache_limit_per_frame_;
|
|
}
|
|
|
|
/**
|
|
* @brief The entry whose RasterCacheKey is generated by RasterCacheKeyID
|
|
* and matrix is marked as encountered by the current frame. The entry
|
|
* will be created if it does not exist. Optionally the entry will be marked
|
|
* as visible in the current frame if the caller determines that it
|
|
* intersects the cull rect. The access_count of the entry will be
|
|
* increased if it is visible, or if it was ever visible.
|
|
* @return the number of times the entry has been hit since it was created.
|
|
* For a new entry that will be 1 if it is visible, or zero if non-visible.
|
|
*/
|
|
CacheInfo MarkSeen(const RasterCacheKeyID& id,
|
|
const SkMatrix& matrix,
|
|
bool visible) const;
|
|
|
|
/**
|
|
* Returns the access count (i.e. accesses_since_visible) for the given
|
|
* entry in the cache, or -1 if no such entry exists.
|
|
*/
|
|
int GetAccessCount(const RasterCacheKeyID& id, const SkMatrix& matrix) const;
|
|
|
|
bool UpdateCacheEntry(const RasterCacheKeyID& id,
|
|
const Context& raster_cache_context,
|
|
const std::function<void(DlCanvas*)>& render_function,
|
|
sk_sp<const DlRTree> rtree = nullptr) const;
|
|
|
|
private:
|
|
struct Entry {
|
|
bool encountered_this_frame = false;
|
|
bool visible_this_frame = false;
|
|
size_t accesses_since_visible = 0;
|
|
std::unique_ptr<RasterCacheResult> image;
|
|
};
|
|
|
|
void UpdateMetrics();
|
|
|
|
RasterCacheMetrics& GetMetricsForKind(RasterCacheKeyKind kind);
|
|
|
|
const size_t access_threshold_;
|
|
const size_t display_list_cache_limit_per_frame_;
|
|
mutable size_t display_list_cached_this_frame_ = 0;
|
|
RasterCacheMetrics layer_metrics_;
|
|
RasterCacheMetrics picture_metrics_;
|
|
mutable RasterCacheKey::Map<Entry> cache_;
|
|
bool checkerboard_images_ = false;
|
|
|
|
void TraceStatsToTimeline() const;
|
|
|
|
friend class RasterCacheItem;
|
|
friend class LayerRasterCacheItem;
|
|
|
|
FML_DISALLOW_COPY_AND_ASSIGN(RasterCache);
|
|
};
|
|
|
|
} // namespace flutter
|
|
|
|
#else // !SLIMPELLER
|
|
|
|
class RasterCache;
|
|
|
|
#endif // !SLIMPELLER
|
|
|
|
#endif // FLUTTER_FLOW_RASTER_CACHE_H_
|