Flutter Engine
 
Loading...
Searching...
No Matches
image_filter_layer.cc
Go to the documentation of this file.
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
6
10
11namespace flutter {
12
13ImageFilterLayer::ImageFilterLayer(const std::shared_ptr<DlImageFilter>& filter,
14 const DlPoint& offset)
16 RasterCacheUtil::kMinimumRendersBeforeCachingFilterLayer),
17 offset_(offset),
18 filter_(filter),
19 transformed_filter_(nullptr) {}
20
21void ImageFilterLayer::Diff(DiffContext* context, const Layer* old_layer) {
22 DiffContext::AutoSubtreeRestore subtree(context);
23 auto* prev = static_cast<const ImageFilterLayer*>(old_layer);
24 if (!context->IsSubtreeDirty()) {
25 FML_DCHECK(prev);
26 if (NotEquals(filter_, prev->filter_) || offset_ != prev->offset_) {
27 context->MarkSubtreeDirty(context->GetOldLayerPaintRegion(old_layer));
28 }
29 }
30
32 if (context->has_raster_cache()) {
34 }
35
36 if (filter_) {
37 auto filter = filter_->makeWithLocalMatrix(context->GetMatrix());
38 if (filter) {
39 // This transform will be applied to every child rect in the subtree
40 context->PushFilterBoundsAdjustment([filter](DlRect rect) {
41 DlIRect filter_out_bounds;
42 filter->map_device_bounds(DlIRect::RoundOut(rect), DlMatrix(),
43 filter_out_bounds);
44 return DlRect::Make(filter_out_bounds);
45 });
46 }
47 }
48 DiffChildren(context, prev);
49 context->SetLayerPaintRegion(this, context->CurrentSubtreeRegion());
50}
51
53 auto mutator = context->state_stack.save();
54 mutator.translate(offset_);
55
58
59#if !SLIMPELLER
60 AutoCache cache = AutoCache(layer_raster_cache_item_.get(), context,
61 context->state_stack.matrix());
62#endif // !SLIMPELLER
63
64 DlRect child_bounds;
65
66 PrerollChildren(context, &child_bounds);
67
68 if (!filter_) {
69 child_bounds = child_bounds.Shift(offset_);
70 set_paint_bounds(child_bounds);
71 return;
72 }
73
74 // Our saveLayer would apply any outstanding opacity or any outstanding
75 // color filter after it applies our image filter. So we can apply either
76 // of those attributes with our saveLayer.
77 context->renderable_state_flags =
80
81 const DlIRect filter_in_bounds = DlIRect::RoundOut(child_bounds);
82 DlIRect filter_out_bounds;
83 filter_->map_device_bounds(filter_in_bounds, DlMatrix(), filter_out_bounds);
84 child_bounds = DlRect::Make(filter_out_bounds).Shift(offset_);
85
86 set_paint_bounds(child_bounds);
87
88#if !SLIMPELLER
89 // CacheChildren only when the transformed_filter_ doesn't equal null.
90 // So in here we reset the LayerRasterCacheItem cache state.
91 layer_raster_cache_item_->MarkNotCacheChildren();
92#endif // !SLIMPELLER
93
94 transformed_filter_ =
95 filter_->makeWithLocalMatrix(context->state_stack.matrix());
96
97#if !SLIMPELLER
98 if (transformed_filter_) {
99 layer_raster_cache_item_->MarkCacheChildren();
100 }
101#endif // !SLIMPELLER
102}
103
105 FML_DCHECK(needs_painting(context));
106
107 auto mutator = context.state_stack.save();
108
109#if !SLIMPELLER
110 if (context.raster_cache) {
111 // Try drawing the layer cache item from the cache before applying the
112 // image filter if it was cached with the filter applied.
113 if (!layer_raster_cache_item_->IsCacheChildren()) {
114 DlPaint paint;
115 if (layer_raster_cache_item_->Draw(context,
116 context.state_stack.fill(paint))) {
117 return;
118 }
119 }
120 }
121#endif // !SLIMPELLER
122
123 // Only apply the offset if not being raster-cached to avoid the offset being
124 // applied twice.
125 mutator.translate(offset_);
126
127#if !SLIMPELLER
128 if (context.raster_cache) {
129 mutator.integralTransform();
130 }
131
132 if (context.raster_cache && layer_raster_cache_item_->IsCacheChildren()) {
133 // If we render the children from cache then we need the special
134 // transformed version of the filter so we must process it into the
135 // cache paint object manually.
136 FML_DCHECK(transformed_filter_ != nullptr);
137 DlPaint paint;
138 context.state_stack.fill(paint);
139 paint.setImageFilter(transformed_filter_);
140 if (layer_raster_cache_item_->Draw(context, &paint)) {
141 return;
142 }
143 }
144#endif // !SLIMPELLER
145
146 // Now apply the image filter and then try rendering the children.
147 mutator.applyImageFilter(child_paint_bounds(), filter_);
148
149 PaintChildren(context);
150}
151
152} // namespace flutter
std::unique_ptr< LayerRasterCacheItem > layer_raster_cache_item_
const DlRect & child_paint_bounds() const
void PrerollChildren(PrerollContext *context, DlRect *child_paint_bounds)
void PaintChildren(PaintContext &context) const override
virtual void DiffChildren(DiffContext *context, const ContainerLayer *old_layer)
void WillPaintWithIntegralTransform()
void SetLayerPaintRegion(const Layer *layer, const PaintRegion &region)
void MarkSubtreeDirty(const PaintRegion &previous_paint_region=PaintRegion())
PaintRegion CurrentSubtreeRegion() const
void PushFilterBoundsAdjustment(const FilterBoundsAdjustment &filter)
bool has_raster_cache() const
PaintRegion GetOldLayerPaintRegion(const Layer *layer) const
const DlMatrix & GetMatrix() const
bool IsSubtreeDirty() const
void PushTransform(const DlMatrix &transform)
DlPaint & setImageFilter(std::nullptr_t filter)
Definition dl_paint.h:167
void Diff(DiffContext *context, const Layer *old_layer) override
void Paint(PaintContext &context) const override
void Preroll(PrerollContext *context) override
ImageFilterLayer(const std::shared_ptr< DlImageFilter > &filter, const DlPoint &offset=DlPoint())
static AutoPrerollSaveLayerState Create(PrerollContext *preroll_context, bool save_layer_is_active=true, bool layer_itself_performs_readback=false)
Definition layer.cc:37
void set_paint_bounds(const DlRect &paint_bounds)
Definition layer.h:209
bool needs_painting(PaintContext &context) const
Definition layer.h:218
void translate(DlScalar tx, DlScalar ty)
void fill(MutatorsStack *mutators)
static constexpr int kCallerCanApplyColorFilter
const DlMatrix matrix() const
static constexpr int kCallerCanApplyOpacity
#define FML_DCHECK(condition)
Definition logging.h:122
impeller::Matrix DlMatrix
bool NotEquals(const T *a, const U *b)
LayerStateStack & state_stack
Definition layer.h:91
LayerStateStack & state_stack
Definition layer.h:49
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition matrix.h:95
static constexpr std::enable_if_t< std::is_floating_point_v< FT >, TRect > Make(const TRect< U > &rect)
Definition rect.h:157
RoundOut(const TRect< U > &r)
Definition rect.h:679
constexpr TRect< T > Shift(T dx, T dy) const
Returns a new rectangle translated by the given offset.
Definition rect.h:602