Kaylee Lubick ef050da2b8 Use moved Skia Ganesh header files (flutter/engine#54833)
In http://review.skia.org/892736 and http://review.skia.org/893856, Skia
moved its Ganesh headers to align with the Graphite ones. This updates
Flutter to use those moved files.

All changes are mechanical and there is no API difference between the
headers (indeed, the old ones simply `#include` the new ones).

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide] and the [C++,
Objective-C, Java style guides].
- [ ] I listed at least one issue that this PR fixes in the description
above.
- [x] I added new tests to check the change I am making or feature I am
adding, or the PR is [test-exempt]. See [testing the engine] for
instructions on writing and running engine tests.
- [ ] I updated/added relevant documentation (doc comments with `///`).
- [x] I signed the [CLA].
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#overview
[Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene
[test-exempt]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo
[C++, Objective-C, Java style guides]:
https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
[testing the engine]:
https://github.com/flutter/flutter/wiki/Testing-the-engine
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes
[Discord]: https://github.com/flutter/flutter/wiki/Chat
2024-09-04 07:09:51 -07:00

316 lines
10 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.
#if !SLIMPELLER
#include "flutter/flow/raster_cache.h"
#include <cstddef>
#include <vector>
#include "flutter/common/constants.h"
#include "flutter/display_list/skia/dl_sk_dispatcher.h"
#include "flutter/flow/layers/container_layer.h"
#include "flutter/flow/layers/layer.h"
#include "flutter/flow/paint_utils.h"
#include "flutter/flow/raster_cache_util.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/trace_event.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColorSpace.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/gpu/ganesh/GrDirectContext.h"
#include "third_party/skia/include/gpu/ganesh/SkSurfaceGanesh.h"
namespace flutter {
RasterCacheResult::RasterCacheResult(sk_sp<DlImage> image,
const SkRect& logical_rect,
const char* type,
sk_sp<const DlRTree> rtree)
: image_(std::move(image)),
logical_rect_(logical_rect),
flow_(type),
rtree_(std::move(rtree)) {}
void RasterCacheResult::draw(DlCanvas& canvas,
const DlPaint* paint,
bool preserve_rtree) const {
DlAutoCanvasRestore auto_restore(&canvas, true);
auto matrix = RasterCacheUtil::GetIntegralTransCTM(canvas.GetTransform());
SkRect bounds =
RasterCacheUtil::GetRoundedOutDeviceBounds(logical_rect_, matrix);
FML_DCHECK(std::abs(bounds.width() - image_->dimensions().width()) <= 1 &&
std::abs(bounds.height() - image_->dimensions().height()) <= 1);
canvas.TransformReset();
flow_.Step();
if (!preserve_rtree || !rtree_) {
canvas.DrawImage(image_, {bounds.fLeft, bounds.fTop},
DlImageSampling::kNearestNeighbor, paint);
} else {
// On some platforms RTree from overlay layers is used for unobstructed
// platform views and hit testing. To preserve the RTree raster cache must
// paint individual rects instead of the whole image.
auto rects = rtree_->region().getRects(true);
canvas.Translate(bounds.fLeft, bounds.fTop);
SkRect rtree_bounds =
RasterCacheUtil::GetRoundedOutDeviceBounds(rtree_->bounds(), matrix);
for (auto rect : rects) {
SkRect device_rect = RasterCacheUtil::GetRoundedOutDeviceBounds(
SkRect::Make(rect), matrix);
device_rect.offset(-rtree_bounds.fLeft, -rtree_bounds.fTop);
canvas.DrawImageRect(image_, device_rect, device_rect,
DlImageSampling::kNearestNeighbor, paint);
}
}
}
RasterCache::RasterCache(size_t access_threshold,
size_t display_list_cache_limit_per_frame)
: access_threshold_(access_threshold),
display_list_cache_limit_per_frame_(display_list_cache_limit_per_frame) {}
/// @note Procedure doesn't copy all closures.
std::unique_ptr<RasterCacheResult> RasterCache::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 {
auto matrix = RasterCacheUtil::GetIntegralTransCTM(context.matrix);
SkRect dest_rect =
RasterCacheUtil::GetRoundedOutDeviceBounds(context.logical_rect, matrix);
const SkImageInfo image_info = SkImageInfo::MakeN32Premul(
dest_rect.width(), dest_rect.height(), context.dst_color_space);
sk_sp<SkSurface> surface =
context.gr_context
? SkSurfaces::RenderTarget(context.gr_context, skgpu::Budgeted::kYes,
image_info)
: SkSurfaces::Raster(image_info);
if (!surface) {
return nullptr;
}
DlSkCanvasAdapter canvas(surface->getCanvas());
canvas.Clear(DlColor::kTransparent());
canvas.Translate(-dest_rect.left(), -dest_rect.top());
canvas.Transform(matrix);
draw_function(&canvas);
if (checkerboard_images_) {
draw_checkerboard(&canvas, context.logical_rect);
}
auto image = DlImage::Make(surface->makeImageSnapshot());
return std::make_unique<RasterCacheResult>(
image, context.logical_rect, context.flow_type, std::move(rtree));
}
bool RasterCache::UpdateCacheEntry(
const RasterCacheKeyID& id,
const Context& raster_cache_context,
const std::function<void(DlCanvas*)>& render_function,
sk_sp<const DlRTree> rtree) const {
RasterCacheKey key = RasterCacheKey(id, raster_cache_context.matrix);
Entry& entry = cache_[key];
if (!entry.image) {
void (*func)(DlCanvas*, const SkRect& rect) = DrawCheckerboard;
entry.image = Rasterize(raster_cache_context, std::move(rtree),
render_function, func);
if (entry.image != nullptr) {
switch (id.type()) {
case RasterCacheKeyType::kDisplayList: {
display_list_cached_this_frame_++;
break;
}
default:
break;
}
return true;
}
}
return entry.image != nullptr;
}
RasterCache::CacheInfo RasterCache::MarkSeen(const RasterCacheKeyID& id,
const SkMatrix& matrix,
bool visible) const {
RasterCacheKey key = RasterCacheKey(id, matrix);
Entry& entry = cache_[key];
entry.encountered_this_frame = true;
entry.visible_this_frame = visible;
if (visible || entry.accesses_since_visible > 0) {
entry.accesses_since_visible++;
}
return {entry.accesses_since_visible, entry.image != nullptr};
}
int RasterCache::GetAccessCount(const RasterCacheKeyID& id,
const SkMatrix& matrix) const {
RasterCacheKey key = RasterCacheKey(id, matrix);
auto entry = cache_.find(key);
if (entry != cache_.cend()) {
return entry->second.accesses_since_visible;
}
return -1;
}
bool RasterCache::HasEntry(const RasterCacheKeyID& id,
const SkMatrix& matrix) const {
RasterCacheKey key = RasterCacheKey(id, matrix);
if (cache_.find(key) != cache_.cend()) {
return true;
}
return false;
}
bool RasterCache::Draw(const RasterCacheKeyID& id,
DlCanvas& canvas,
const DlPaint* paint,
bool preserve_rtree) const {
auto it = cache_.find(RasterCacheKey(id, canvas.GetTransform()));
if (it == cache_.end()) {
return false;
}
Entry& entry = it->second;
if (entry.image) {
entry.image->draw(canvas, paint, preserve_rtree);
return true;
}
return false;
}
void RasterCache::BeginFrame() {
display_list_cached_this_frame_ = 0;
picture_metrics_ = {};
layer_metrics_ = {};
}
void RasterCache::UpdateMetrics() {
for (auto it = cache_.begin(); it != cache_.end(); ++it) {
Entry& entry = it->second;
FML_DCHECK(entry.encountered_this_frame);
if (entry.image) {
RasterCacheMetrics& metrics = GetMetricsForKind(it->first.kind());
metrics.in_use_count++;
metrics.in_use_bytes += entry.image->image_bytes();
}
entry.encountered_this_frame = false;
}
}
void RasterCache::EvictUnusedCacheEntries() {
std::vector<RasterCacheKey::Map<Entry>::iterator> dead;
for (auto it = cache_.begin(); it != cache_.end(); ++it) {
Entry& entry = it->second;
if (!entry.encountered_this_frame) {
dead.push_back(it);
}
}
for (auto it : dead) {
if (it->second.image) {
RasterCacheMetrics& metrics = GetMetricsForKind(it->first.kind());
metrics.eviction_count++;
metrics.eviction_bytes += it->second.image->image_bytes();
}
cache_.erase(it);
}
}
void RasterCache::EndFrame() {
UpdateMetrics();
TraceStatsToTimeline();
}
void RasterCache::Clear() {
cache_.clear();
picture_metrics_ = {};
layer_metrics_ = {};
}
size_t RasterCache::GetCachedEntriesCount() const {
return cache_.size();
}
size_t RasterCache::GetLayerCachedEntriesCount() const {
size_t layer_cached_entries_count = 0;
for (const auto& item : cache_) {
if (item.first.kind() == RasterCacheKeyKind::kLayerMetrics) {
layer_cached_entries_count++;
}
}
return layer_cached_entries_count;
}
size_t RasterCache::GetPictureCachedEntriesCount() const {
size_t display_list_cached_entries_count = 0;
for (const auto& item : cache_) {
if (item.first.kind() == RasterCacheKeyKind::kDisplayListMetrics) {
display_list_cached_entries_count++;
}
}
return display_list_cached_entries_count;
}
void RasterCache::TraceStatsToTimeline() const {
#if !FLUTTER_RELEASE
FML_TRACE_COUNTER(
"flutter", //
"RasterCache", reinterpret_cast<int64_t>(this), //
"LayerCount", layer_metrics_.total_count(), //
"LayerMBytes", layer_metrics_.total_bytes() / kMegaByteSizeInBytes, //
"PictureCount", picture_metrics_.total_count(), //
"PictureMBytes", picture_metrics_.total_bytes() / kMegaByteSizeInBytes);
#endif // !FLUTTER_RELEASE
}
size_t RasterCache::EstimateLayerCacheByteSize() const {
size_t layer_cache_bytes = 0;
for (const auto& item : cache_) {
if (item.first.kind() == RasterCacheKeyKind::kLayerMetrics &&
item.second.image) {
layer_cache_bytes += item.second.image->image_bytes();
}
}
return layer_cache_bytes;
}
size_t RasterCache::EstimatePictureCacheByteSize() const {
size_t picture_cache_bytes = 0;
for (const auto& item : cache_) {
if (item.first.kind() == RasterCacheKeyKind::kDisplayListMetrics &&
item.second.image) {
picture_cache_bytes += item.second.image->image_bytes();
}
}
return picture_cache_bytes;
}
RasterCacheMetrics& RasterCache::GetMetricsForKind(RasterCacheKeyKind kind) {
switch (kind) {
case RasterCacheKeyKind::kDisplayListMetrics:
return picture_metrics_;
case RasterCacheKeyKind::kLayerMetrics:
return layer_metrics_;
}
}
} // namespace flutter
#endif // !SLIMPELLER