Skip to content

Commit

Permalink
Use DlImageFilter for ImageFilterLayer (flutter#34837)
Browse files Browse the repository at this point in the history
  • Loading branch information
JsouLiang authored Aug 16, 2022
1 parent 8c7d896 commit c007c40
Show file tree
Hide file tree
Showing 8 changed files with 196 additions and 164 deletions.
2 changes: 1 addition & 1 deletion display_list/display_list_image_filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ std::shared_ptr<DlImageFilter> DlImageFilter::From(
}

std::shared_ptr<DlImageFilter> DlImageFilter::makeWithLocalMatrix(
const SkMatrix& matrix) {
const SkMatrix& matrix) const {
if (matrix.isIdentity()) {
return shared();
}
Expand Down
10 changes: 5 additions & 5 deletions display_list/display_list_image_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ class DlImageFilter
}

virtual std::shared_ptr<DlImageFilter> makeWithLocalMatrix(
const SkMatrix& matrix);
const SkMatrix& matrix) const;

// Return a DlComposeImageFilter pointer to this object iff it is a Compose
// type of ImageFilter, otherwise return nullptr.
Expand Down Expand Up @@ -634,7 +634,7 @@ class DlColorFilterImageFilter final : public DlImageFilter {
}

std::shared_ptr<DlImageFilter> makeWithLocalMatrix(
const SkMatrix& matrix) override {
const SkMatrix& matrix) const override {
return shared();
}

Expand Down Expand Up @@ -764,7 +764,7 @@ class DlUnknownImageFilter final : public DlImageFilter {

SkRect* map_local_bounds(const SkRect& input_bounds,
SkRect& output_bounds) const override {
if (modifies_transparent_black()) {
if (!sk_filter_ || modifies_transparent_black()) {
output_bounds = input_bounds;
return nullptr;
}
Expand All @@ -775,7 +775,7 @@ class DlUnknownImageFilter final : public DlImageFilter {
SkIRect* map_device_bounds(const SkIRect& input_bounds,
const SkMatrix& ctm,
SkIRect& output_bounds) const override {
if (modifies_transparent_black()) {
if (!sk_filter_ || modifies_transparent_black()) {
output_bounds = input_bounds;
return nullptr;
}
Expand All @@ -787,7 +787,7 @@ class DlUnknownImageFilter final : public DlImageFilter {
SkIRect* get_input_device_bounds(const SkIRect& output_bounds,
const SkMatrix& ctm,
SkIRect& input_bounds) const override {
if (modifies_transparent_black()) {
if (!sk_filter_ || modifies_transparent_black()) {
input_bounds = output_bounds;
return nullptr;
}
Expand Down
60 changes: 35 additions & 25 deletions flow/layers/image_filter_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
// found in the LICENSE file.

#include "flutter/flow/layers/image_filter_layer.h"
#include "flutter/display_list/display_list_comparable.h"
#include "flutter/flow/layers/layer.h"
#include "flutter/flow/raster_cache_util.h"

namespace flutter {

ImageFilterLayer::ImageFilterLayer(sk_sp<SkImageFilter> filter)
ImageFilterLayer::ImageFilterLayer(std::shared_ptr<const DlImageFilter> filter)
: CacheableContainerLayer(
RasterCacheUtil::kMinimumRendersBeforeCachingFilterLayer),
filter_(std::move(filter)),
Expand All @@ -19,7 +20,7 @@ void ImageFilterLayer::Diff(DiffContext* context, const Layer* old_layer) {
auto* prev = static_cast<const ImageFilterLayer*>(old_layer);
if (!context->IsSubtreeDirty()) {
FML_DCHECK(prev);
if (filter_ != prev->filter_) {
if (NotEquals(filter_, prev->filter_)) {
context->MarkSubtreeDirty(context->GetOldLayerPaintRegion(old_layer));
}
}
Expand All @@ -29,9 +30,10 @@ void ImageFilterLayer::Diff(DiffContext* context, const Layer* old_layer) {
if (filter) {
// This transform will be applied to every child rect in the subtree
context->PushFilterBoundsAdjustment([filter](SkRect rect) {
return SkRect::Make(
filter->filterBounds(rect.roundOut(), SkMatrix::I(),
SkImageFilter::kForward_MapDirection));
SkIRect filter_out_bounds;
filter->map_device_bounds(rect.roundOut(), SkMatrix::I(),
filter_out_bounds);
return SkRect::Make(filter_out_bounds);
});
}
}
Expand All @@ -50,7 +52,6 @@ void ImageFilterLayer::Preroll(PrerollContext* context,

SkRect child_bounds = SkRect::MakeEmpty();
PrerollChildren(context, matrix, &child_bounds);
context->subtree_can_inherit_opacity = true;

// We always paint with a saveLayer (or a cached rendering),
// so we can always apply opacity in any of those cases.
Expand All @@ -61,10 +62,11 @@ void ImageFilterLayer::Preroll(PrerollContext* context,
return;
}

const SkIRect filter_input_bounds = child_bounds.roundOut();
SkIRect filter_output_bounds = filter_->filterBounds(
filter_input_bounds, SkMatrix::I(), SkImageFilter::kForward_MapDirection);
child_bounds = SkRect::Make(filter_output_bounds);
const SkIRect filter_in_bounds = child_bounds.roundOut();
SkIRect filter_out_bounds;
filter_->map_device_bounds(filter_in_bounds, SkMatrix::I(),
filter_out_bounds);
child_bounds = SkRect::Make(filter_out_bounds);

set_paint_bounds(child_bounds);

Expand All @@ -83,23 +85,31 @@ void ImageFilterLayer::Paint(PaintContext& context) const {
FML_DCHECK(needs_painting(context));

AutoCachePaint cache_paint(context);

if (layer_raster_cache_item_->IsCacheChildren()) {
cache_paint.setImageFilter(transformed_filter_);
}
if (layer_raster_cache_item_->Draw(context, cache_paint.sk_paint())) {
return;
if (context.raster_cache) {
if (layer_raster_cache_item_->IsCacheChildren()) {
cache_paint.setImageFilter(transformed_filter_.get());
}
if (layer_raster_cache_item_->Draw(context, cache_paint.sk_paint())) {
return;
}
}

cache_paint.setImageFilter(filter_);

// Normally a save_layer is sized to the current layer bounds, but in this
// case the bounds of the child may not be the same as the filtered version
// so we use the bounds of the child container which do not include any
// modifications that the filter might apply.
Layer::AutoSaveLayer save_layer = Layer::AutoSaveLayer::Create(
context, child_paint_bounds(), cache_paint.sk_paint());
PaintChildren(context);
cache_paint.setImageFilter(filter_.get());
if (context.leaf_nodes_builder) {
FML_DCHECK(context.builder_multiplexer);
context.builder_multiplexer->saveLayer(&child_paint_bounds(),
cache_paint.dl_paint());
PaintChildren(context);
context.builder_multiplexer->restore();
} else {
// Normally a save_layer is sized to the current layer bounds, but in this
// case the bounds of the child may not be the same as the filtered version
// so we use the bounds of the child container which do not include any
// modifications that the filter might apply.
Layer::AutoSaveLayer save_layer = Layer::AutoSaveLayer::Create(
context, child_paint_bounds(), cache_paint.sk_paint());
PaintChildren(context);
}
}

} // namespace flutter
8 changes: 5 additions & 3 deletions flow/layers/image_filter_layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@
#ifndef FLUTTER_FLOW_LAYERS_IMAGE_FILTER_LAYER_H_
#define FLUTTER_FLOW_LAYERS_IMAGE_FILTER_LAYER_H_

#include <memory>
#include "flutter/flow/layers/cacheable_layer.h"
#include "flutter/flow/layers/layer.h"
#include "include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkImageFilter.h"

namespace flutter {

class ImageFilterLayer : public CacheableContainerLayer {
public:
explicit ImageFilterLayer(sk_sp<SkImageFilter> filter);
explicit ImageFilterLayer(std::shared_ptr<const DlImageFilter> filter);

void Diff(DiffContext* context, const Layer* old_layer) override;

Expand All @@ -22,8 +24,8 @@ class ImageFilterLayer : public CacheableContainerLayer {
void Paint(PaintContext& context) const override;

private:
sk_sp<SkImageFilter> filter_;
sk_sp<SkImageFilter> transformed_filter_;
std::shared_ptr<const DlImageFilter> filter_;
std::shared_ptr<const DlImageFilter> transformed_filter_;

FML_DISALLOW_COPY_AND_ASSIGN(ImageFilterLayer);
};
Expand Down
Loading

0 comments on commit c007c40

Please sign in to comment.