Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions display_list/display_list.cc
Original file line number Diff line number Diff line change
Expand Up @@ -294,9 +294,7 @@ static bool CompareOps(uint8_t* ptrA,
return true;
}

void DisplayList::RenderTo(DisplayListBuilder* builder,
SkScalar opacity) const {
// TODO(100983): Opacity is not respected and attributes are not reset.
void DisplayList::RenderTo(DisplayListBuilder* builder) const {
if (!builder) {
return;
}
Expand All @@ -308,6 +306,7 @@ void DisplayList::RenderTo(DisplayListBuilder* builder,
}

void DisplayList::RenderTo(SkCanvas* canvas, SkScalar opacity) const {
FML_DCHECK(can_apply_group_opacity() || opacity >= SK_Scalar1);
DisplayListCanvasDispatcher dispatcher(canvas, opacity);
if (has_rtree()) {
Dispatch(dispatcher, canvas->getLocalClipBounds());
Expand Down
3 changes: 1 addition & 2 deletions display_list/display_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,7 @@ class DisplayList : public SkRefCnt {
void Dispatch(Dispatcher& ctx) const;
void Dispatch(Dispatcher& ctx, const SkRect& cull_rect) const;

void RenderTo(DisplayListBuilder* builder,
SkScalar opacity = SK_Scalar1) const;
void RenderTo(DisplayListBuilder* builder) const;

void RenderTo(SkCanvas* canvas, SkScalar opacity = SK_Scalar1) const;

Expand Down
67 changes: 67 additions & 0 deletions flow/layers/display_list_layer_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "flutter/flow/layers/display_list_layer.h"

#include "flutter/display_list/display_list_builder.h"
#include "flutter/flow/layers/layer_tree.h"
#include "flutter/flow/testing/diff_context_test.h"
#include "flutter/flow/testing/skia_gpu_object_layer_test.h"
#include "flutter/fml/macros.h"
Expand Down Expand Up @@ -249,6 +250,8 @@ TEST_F(DisplayListLayerTest, CachedIncompatibleDisplayListOpacityInheritance) {
display_list_layer->Preroll(preroll_context());
display_list_layer->Preroll(preroll_context());
display_list_layer->Preroll(preroll_context());
LayerTree::TryToRasterCache(*preroll_context()->raster_cached_entries,
&paint_context(), false);

int opacity_alpha = 0x7F;
SkPoint opacity_offset = SkPoint::Make(10, 10);
Expand Down Expand Up @@ -516,5 +519,69 @@ TEST_F(DisplayListLayerTest, DisplayListAccessCountDependsOnVisibility) {
ASSERT_TRUE(raster_cache_item->Draw(paint_context(), nullptr));
}

TEST_F(DisplayListLayerTest, OverflowCachedDisplayListOpacityInheritance) {
use_mock_raster_cache();
PrerollContext* context = preroll_context();
int per_frame =
RasterCacheUtil::kDefaultPictureAndDispLayListCacheLimitPerFrame;
int layer_count = per_frame + 1;
SkPoint opacity_offset = {10, 10};
auto opacity_layer = std::make_shared<OpacityLayer>(0.5f, opacity_offset);
std::shared_ptr<DisplayListLayer> layers[layer_count];
for (int i = 0; i < layer_count; i++) {
DisplayListBuilder builder(false);
builder.drawRect({0, 0, 100, 100});
builder.drawRect({50, 50, 100, 100});
auto display_list = builder.Build();
ASSERT_FALSE(display_list->can_apply_group_opacity());
SkPoint offset = {i * 200.0f, 0};

layers[i] = std::make_shared<DisplayListLayer>(
offset, SkiaGPUObject(display_list, unref_queue()), true, false);
opacity_layer->Add(layers[i]);
}
for (size_t j = 0; j < context->raster_cache->access_threshold(); j++) {
context->raster_cache->BeginFrame();
for (int i = 0; i < layer_count; i++) {
context->renderable_state_flags = 0;
layers[i]->Preroll(context);
ASSERT_EQ(context->renderable_state_flags, 0) << "pass " << (j + 1);
}
}
opacity_layer->Preroll(context);
ASSERT_FALSE(opacity_layer->children_can_accept_opacity());
LayerTree::TryToRasterCache(*context->raster_cached_entries, &paint_context(),
false);
context->raster_cached_entries->clear();
context->raster_cache->BeginFrame();
for (int i = 0; i < per_frame; i++) {
context->renderable_state_flags = 0;
layers[i]->Preroll(context);
ASSERT_EQ(context->renderable_state_flags,
LayerStateStack::kCallerCanApplyOpacity)
<< "layer " << (i + 1);
}
for (int i = per_frame; i < layer_count; i++) {
context->renderable_state_flags = 0;
layers[i]->Preroll(context);
ASSERT_EQ(context->renderable_state_flags, 0) << "layer " << (i + 1);
}
opacity_layer->Preroll(context);
ASSERT_FALSE(opacity_layer->children_can_accept_opacity());
LayerTree::TryToRasterCache(*context->raster_cached_entries, &paint_context(),
false);
context->raster_cached_entries->clear();
context->raster_cache->BeginFrame();
for (int i = 0; i < layer_count; i++) {
context->renderable_state_flags = 0;
layers[i]->Preroll(context);
ASSERT_EQ(context->renderable_state_flags,
LayerStateStack::kCallerCanApplyOpacity)
<< "layer " << (i + 1);
}
opacity_layer->Preroll(context);
ASSERT_TRUE(opacity_layer->children_can_accept_opacity());
}

} // namespace testing
} // namespace flutter
11 changes: 8 additions & 3 deletions flow/layers/display_list_raster_cache_item.cc
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,16 @@ void DisplayListRasterCacheItem::PrerollFinalize(PrerollContext* context,
auto* raster_cache = context->raster_cache;
SkRect bounds = display_list_->bounds().makeOffset(offset_.x(), offset_.y());
bool visible = !context->state_stack.content_culled(bounds);
int accesses = raster_cache->MarkSeen(key_id_, matrix, visible);
if (!visible || accesses <= raster_cache->access_threshold()) {
RasterCache::CacheInfo cache_info =
raster_cache->MarkSeen(key_id_, matrix, visible);
if (!visible ||
cache_info.accesses_since_visible <= raster_cache->access_threshold()) {
cache_state_ = kNone;
} else {
context->renderable_state_flags |= LayerStateStack::kCallerCanApplyOpacity;
if (cache_info.has_image) {
context->renderable_state_flags |=
LayerStateStack::kCallerCanApplyOpacity;
}
cache_state_ = kCurrent;
}
return;
Expand Down
8 changes: 4 additions & 4 deletions flow/raster_cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -110,17 +110,17 @@ bool RasterCache::UpdateCacheEntry(
return entry.image != nullptr;
}

int RasterCache::MarkSeen(const RasterCacheKeyID& id,
const SkMatrix& matrix,
bool visible) const {
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;
return {entry.accesses_since_visible, entry.image != nullptr};
}

int RasterCache::GetAccessCount(const RasterCacheKeyID& id,
Expand Down
12 changes: 8 additions & 4 deletions flow/raster_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ class RasterCache {
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,
Expand Down Expand Up @@ -203,7 +207,7 @@ class RasterCache {
* 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.
*/
int access_threshold() const { return access_threshold_; }
size_t access_threshold() const { return access_threshold_; }

bool GenerateNewCacheInThisFrame() const {
// Disabling caching when access_threshold is zero is historic behavior.
Expand All @@ -221,9 +225,9 @@ class RasterCache {
* @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.
*/
int MarkSeen(const RasterCacheKeyID& id,
const SkMatrix& matrix,
bool visible) const;
CacheInfo MarkSeen(const RasterCacheKeyID& id,
const SkMatrix& matrix,
bool visible) const;

/**
* Returns the access count (i.e. accesses_since_visible) for the given
Expand Down
2 changes: 1 addition & 1 deletion flow/testing/mock_raster_cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ void MockRasterCache::AddMockPicture(int width, int height) {

DisplayListRasterCacheItem display_list_item(display_list.get(), SkPoint(),
true, false);
for (int i = 0; i < access_threshold(); i++) {
for (size_t i = 0; i < access_threshold(); i++) {
AutoCache(&display_list_item, &preroll_context_, ctm);
}
RasterCache::Context r_context = {
Expand Down