Skip to content

Commit

Permalink
Displaylist ColorFilter objects (#31491)
Browse files Browse the repository at this point in the history
  • Loading branch information
flar authored Feb 17, 2022
1 parent 01ac6cf commit 70c1173
Show file tree
Hide file tree
Showing 20 changed files with 861 additions and 124 deletions.
2 changes: 1 addition & 1 deletion DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ deps = {
'src': 'https://github.com/flutter/buildroot.git' + '@' + '79643299bd052c53631b8b200bb582e8badb2708',

'src/flutter/impeller':
Var('github_git') + '/flutter/impeller' + '@' + 'c55014e747541b9a2cca15e6b2cb1b1ef9123da3',
Var('github_git') + '/flutter/impeller' + '@' + '78bc2a026c554c444b2e67b36fd44cd548341a51',

# Fuchsia compatibility
#
Expand Down
3 changes: 3 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ FILE: ../../../flutter/display_list/display_list_canvas_dispatcher.h
FILE: ../../../flutter/display_list/display_list_canvas_recorder.cc
FILE: ../../../flutter/display_list/display_list_canvas_recorder.h
FILE: ../../../flutter/display_list/display_list_canvas_unittests.cc
FILE: ../../../flutter/display_list/display_list_color_filter.cc
FILE: ../../../flutter/display_list/display_list_color_filter.h
FILE: ../../../flutter/display_list/display_list_color_filter_unittests.cc
FILE: ../../../flutter/display_list/display_list_complexity.cc
FILE: ../../../flutter/display_list/display_list_complexity.h
FILE: ../../../flutter/display_list/display_list_dispatcher.cc
Expand Down
3 changes: 3 additions & 0 deletions display_list/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ source_set("display_list") {
"display_list_canvas_dispatcher.h",
"display_list_canvas_recorder.cc",
"display_list_canvas_recorder.h",
"display_list_color_filter.cc",
"display_list_color_filter.h",
"display_list_complexity.cc",
"display_list_complexity.h",
"display_list_dispatcher.cc",
Expand All @@ -40,6 +42,7 @@ source_set("unittests") {

sources = [
"display_list_canvas_unittests.cc",
"display_list_color_filter_unittests.cc",
"display_list_unittests.cc",
]

Expand Down
12 changes: 7 additions & 5 deletions display_list/display_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef FLUTTER_FLOW_DISPLAY_LIST_H_
#define FLUTTER_FLOW_DISPLAY_LIST_H_
#ifndef FLUTTER_DISPLAY_LIST_DISPLAY_LIST_H_
#define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_H_

#include <optional>

Expand Down Expand Up @@ -76,13 +76,15 @@ namespace flutter {
V(ClearBlender) \
V(SetShader) \
V(ClearShader) \
V(SetColorFilter) \
V(ClearColorFilter) \
V(SetImageFilter) \
V(ClearImageFilter) \
V(SetPathEffect) \
V(ClearPathEffect) \
\
V(ClearColorFilter) \
V(SetColorFilter) \
V(SetSkColorFilter) \
\
V(ClearMaskFilter) \
V(SetMaskFilter) \
V(SetMaskBlurFilterNormal) \
Expand Down Expand Up @@ -278,4 +280,4 @@ class DisplayList : public SkRefCnt {

} // namespace flutter

#endif // FLUTTER_FLOW_DISPLAY_LIST_H_
#endif // FLUTTER_DISPLAY_LIST_DISPLAY_LIST_H_
55 changes: 50 additions & 5 deletions display_list/display_list_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,50 @@ void DisplayListBuilder::onSetImageFilter(sk_sp<SkImageFilter> filter) {
? Push<SetImageFilterOp>(0, 0, std::move(filter))
: Push<ClearImageFilterOp>(0, 0);
}
void DisplayListBuilder::onSetColorFilter(sk_sp<SkColorFilter> filter) {
(current_color_filter_ = filter) //
? Push<SetColorFilterOp>(0, 0, std::move(filter))
: Push<ClearColorFilterOp>(0, 0);
void DisplayListBuilder::onSetColorFilter(const DlColorFilter* filter) {
if (filter == nullptr) {
if (!current_color_filter_) {
return;
}
current_color_filter_ = nullptr;
Push<ClearColorFilterOp>(0, 0);
} else {
if (current_color_filter_ && *current_color_filter_ == *filter) {
return;
}
current_color_filter_ = filter->shared();
switch (filter->type()) {
case DlColorFilter::kBlend: {
const DlBlendColorFilter* blend_filter = filter->asBlend();
FML_DCHECK(blend_filter);
void* pod = Push<SetColorFilterOp>(blend_filter->size(), 0);
new (pod) DlBlendColorFilter(blend_filter);
break;
}
case DlColorFilter::kMatrix: {
const DlMatrixColorFilter* matrix_filter = filter->asMatrix();
FML_DCHECK(matrix_filter);
void* pod = Push<SetColorFilterOp>(matrix_filter->size(), 0);
new (pod) DlMatrixColorFilter(matrix_filter);
break;
}
case DlColorFilter::kSrgbToLinearGamma: {
void* pod = Push<SetColorFilterOp>(filter->size(), 0);
new (pod) DlSrgbToLinearGammaColorFilter();
break;
}
case DlColorFilter::kLinearToSrgbGamma: {
void* pod = Push<SetColorFilterOp>(filter->size(), 0);
new (pod) DlLinearToSrgbGammaColorFilter();
break;
}
case DlColorFilter::kUnknown: {
const sk_sp<SkColorFilter> sk_filter = filter->sk_filter();
Push<SetSkColorFilterOp>(0, 0, sk_filter);
break;
}
}
}
UpdateCurrentOpacityCompatibility();
}
void DisplayListBuilder::onSetPathEffect(sk_sp<SkPathEffect> effect) {
Expand Down Expand Up @@ -211,7 +251,12 @@ void DisplayListBuilder::setAttributesFromPaint(
// we must clear it because it is a second potential color filter
// that is composed with the paint's color filter.
setInvertColors(false);
setColorFilter(sk_ref_sp(paint.getColorFilter()));
SkColorFilter* color_filter = paint.getColorFilter();
if (color_filter) {
setColorFilter(DlColorFilter::From(color_filter).get());
} else {
setColorFilter(nullptr);
}
}
if (flags.applies_image_filter()) {
setImageFilter(sk_ref_sp(paint.getImageFilter()));
Expand Down
15 changes: 8 additions & 7 deletions display_list/display_list_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,9 @@ class DisplayListBuilder final : public virtual Dispatcher,
onSetImageFilter(std::move(filter));
}
}
void setColorFilter(sk_sp<SkColorFilter> filter) override {
if (current_color_filter_ != filter) {
onSetColorFilter(std::move(filter));
}
void setColorFilter(const DlColorFilter* filter) override {
// onSetColorFilter will deal with whether the filter is new
onSetColorFilter(filter);
}
void setPathEffect(sk_sp<SkPathEffect> effect) override {
if (current_path_effect_ != effect) {
Expand Down Expand Up @@ -128,7 +127,9 @@ class DisplayListBuilder final : public virtual Dispatcher,
SkPaint::Cap getStrokeCap() const { return current_stroke_cap_; }
SkPaint::Join getStrokeJoin() const { return current_stroke_join_; }
sk_sp<SkShader> getShader() const { return current_shader_; }
sk_sp<SkColorFilter> getColorFilter() const { return current_color_filter_; }
sk_sp<SkColorFilter> getColorFilter() const {
return current_color_filter_->sk_filter();
}
bool isInvertColors() const { return current_invert_colors_; }
std::optional<SkBlendMode> getBlendMode() const {
if (current_blender_) {
Expand Down Expand Up @@ -390,7 +391,7 @@ class DisplayListBuilder final : public virtual Dispatcher,
void onSetBlender(sk_sp<SkBlender> blender);
void onSetShader(sk_sp<SkShader> shader);
void onSetImageFilter(sk_sp<SkImageFilter> filter);
void onSetColorFilter(sk_sp<SkColorFilter> filter);
void onSetColorFilter(const DlColorFilter* filter);
void onSetPathEffect(sk_sp<SkPathEffect> effect);
void onSetMaskFilter(sk_sp<SkMaskFilter> filter);
void onSetMaskBlurFilter(SkBlurStyle style, SkScalar sigma);
Expand All @@ -409,7 +410,7 @@ class DisplayListBuilder final : public virtual Dispatcher,
SkBlendMode current_blend_mode_ = SkBlendMode::kSrcOver;
sk_sp<SkBlender> current_blender_;
sk_sp<SkShader> current_shader_;
sk_sp<SkColorFilter> current_color_filter_;
std::shared_ptr<const DlColorFilter> current_color_filter_;
sk_sp<SkImageFilter> current_image_filter_;
sk_sp<SkPathEffect> current_path_effect_;
sk_sp<SkMaskFilter> current_mask_filter_;
Expand Down
27 changes: 10 additions & 17 deletions display_list/display_list_canvas_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -836,48 +836,43 @@ class CanvasCompareTester {
0, 0, 0, 0.5, 0,
};
// clang-format on
sk_sp<SkColorFilter> filter =
SkColorFilters::Matrix(rotate_alpha_color_matrix);
DlMatrixColorFilter filter(rotate_alpha_color_matrix);
{
RenderWith(testP, env, tolerance,
CaseParameters(
"saveLayer ColorFilter, no bounds",
[=](SkCanvas* cv, SkPaint& p) {
SkPaint save_p;
save_p.setColorFilter(filter);
save_p.setColorFilter(filter.sk_filter());
cv->saveLayer(nullptr, &save_p);
p.setStrokeWidth(5.0);
},
[=](DisplayListBuilder& b) {
b.setColorFilter(filter);
b.setColorFilter(&filter);
b.saveLayer(nullptr, true);
b.setColorFilter(nullptr);
b.setStrokeWidth(5.0);
})
.with_restore(cv_safe_restore, dl_safe_restore, true));
}
EXPECT_TRUE(filter->unique())
<< "saveLayer ColorFilter, no bounds Cleanup";
{
RenderWith(testP, env, tolerance,
CaseParameters(
"saveLayer ColorFilter and bounds",
[=](SkCanvas* cv, SkPaint& p) {
SkPaint save_p;
save_p.setColorFilter(filter);
save_p.setColorFilter(filter.sk_filter());
cv->saveLayer(RenderBounds, &save_p);
p.setStrokeWidth(5.0);
},
[=](DisplayListBuilder& b) {
b.setColorFilter(filter);
b.setColorFilter(&filter);
b.saveLayer(&RenderBounds, true);
b.setColorFilter(nullptr);
b.setStrokeWidth(5.0);
})
.with_restore(cv_safe_restore, dl_safe_restore, true));
}
EXPECT_TRUE(filter->unique())
<< "saveLayer ColorFilter and bounds Cleanup";
}
{
sk_sp<SkImageFilter> filter = SkImageFilters::Arithmetic(
Expand Down Expand Up @@ -1146,40 +1141,38 @@ class CanvasCompareTester {
1.0, 1.0, 1.0, 1.0, 0,
};
// clang-format on
sk_sp<SkColorFilter> filter = SkColorFilters::Matrix(rotate_color_matrix);
DlMatrixColorFilter filter(rotate_color_matrix);
{
SkColor bg = SK_ColorWHITE;
RenderWith(testP, env, tolerance,
CaseParameters(
"ColorFilter == RotateRGB",
[=](SkCanvas*, SkPaint& p) {
p.setColor(SK_ColorYELLOW);
p.setColorFilter(filter);
p.setColorFilter(filter.sk_filter());
},
[=](DisplayListBuilder& b) {
b.setColor(SK_ColorYELLOW);
b.setColorFilter(filter);
b.setColorFilter(&filter);
})
.with_bg(bg));
}
EXPECT_TRUE(filter->unique()) << "ColorFilter == RotateRGB Cleanup";
filter = SkColorFilters::Matrix(invert_color_matrix);
filter = DlMatrixColorFilter(invert_color_matrix);
{
SkColor bg = SK_ColorWHITE;
RenderWith(testP, env, tolerance,
CaseParameters(
"ColorFilter == Invert",
[=](SkCanvas*, SkPaint& p) {
p.setColor(SK_ColorYELLOW);
p.setColorFilter(filter);
p.setColorFilter(filter.sk_filter());
},
[=](DisplayListBuilder& b) {
b.setColor(SK_ColorYELLOW);
b.setInvertColors(true);
})
.with_bg(bg));
}
EXPECT_TRUE(filter->unique()) << "ColorFilter == Invert Cleanup";
}

{
Expand Down
49 changes: 49 additions & 0 deletions display_list/display_list_color_filter.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// 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.

#include "flutter/display_list/display_list_color_filter.h"

namespace flutter {

std::shared_ptr<DlColorFilter> DlColorFilter::From(SkColorFilter* sk_filter) {
if (sk_filter == nullptr) {
return nullptr;
}
if (sk_filter == DlSrgbToLinearGammaColorFilter::sk_filter_.get()) {
// Skia implements these filters as a singleton.
return DlSrgbToLinearGammaColorFilter::instance;
}
if (sk_filter == DlLinearToSrgbGammaColorFilter::sk_filter_.get()) {
// Skia implements these filters as a singleton.
return DlLinearToSrgbGammaColorFilter::instance;
}
{
SkColor color;
SkBlendMode mode;
if (sk_filter->asAColorMode(&color, &mode)) {
return std::make_shared<DlBlendColorFilter>(color, mode);
}
}
{
float matrix[20];
if (sk_filter->asAColorMatrix(matrix)) {
return std::make_shared<DlMatrixColorFilter>(matrix);
}
}
return std::make_shared<DlUnknownColorFilter>(sk_ref_sp(sk_filter));
}

const std::shared_ptr<DlSrgbToLinearGammaColorFilter>
DlSrgbToLinearGammaColorFilter::instance =
std::make_shared<DlSrgbToLinearGammaColorFilter>();
const sk_sp<SkColorFilter> DlSrgbToLinearGammaColorFilter::sk_filter_ =
SkColorFilters::SRGBToLinearGamma();

const std::shared_ptr<DlLinearToSrgbGammaColorFilter>
DlLinearToSrgbGammaColorFilter::instance =
std::make_shared<DlLinearToSrgbGammaColorFilter>();
const sk_sp<SkColorFilter> DlLinearToSrgbGammaColorFilter::sk_filter_ =
SkColorFilters::LinearToSRGBGamma();

} // namespace flutter
Loading

0 comments on commit 70c1173

Please sign in to comment.