diff --git a/DEPS b/DEPS index fec38b9edaf32..da22d8b953382 100644 --- a/DEPS +++ b/DEPS @@ -27,7 +27,7 @@ vars = { 'skia_git': 'https://skia.googlesource.com', # OCMock is for testing only so there is no google clone 'ocmock_git': 'https://github.com/erikdoe/ocmock.git', - 'skia_revision': 'b3275e1fd64cbbf57a1e9a2ecb2db0812cfba4dc', + 'skia_revision': 'c71ae5140090290ad16b73bdb0aa6f4543c64a78', # WARNING: DO NOT EDIT canvaskit_cipd_instance MANUALLY # See `lib/web_ui/README.md` for how to roll CanvasKit to a new version. @@ -116,7 +116,7 @@ deps = { 'src': 'https://github.com/flutter/buildroot.git' + '@' + '8cbf38af7d48cc298ae86e614533b4b2d0dc6758', 'src/flutter/impeller': - Var('github_git') + '/flutter/impeller' + '@' + '144d29b12def5058b34c910b5f0343f5355a968d', + Var('github_git') + '/flutter/impeller' + '@' + '114e92d2d046b3496f2b9422946295efaae676dd', # Fuchsia compatibility # @@ -618,7 +618,7 @@ deps = { 'packages': [ { 'package': 'fuchsia/sdk/core/mac-amd64', - 'version': 'XGk8f98vkWo3LGch7wRT3bjpTDEnC1BPjJy1zAGiDqEC' + 'version': '5VwmuFnNNvR_3XAVU9Fo51Q0nLkRzeSZHYIOW_omotwC' } ], 'condition': 'host_os == "mac" and not download_fuchsia_sdk', @@ -628,7 +628,7 @@ deps = { 'packages': [ { 'package': 'fuchsia/sdk/core/linux-amd64', - 'version': 'bltm6P1RVx6jzhhgmH8-BkzYE4v9iICn_QQ0IUMifCMC' + 'version': '-T9kCGaceQI0js1gCuXCStBjE0cnE4kWHe-HCPhuzLQC' } ], 'condition': 'host_os == "linux" and not download_fuchsia_sdk', @@ -661,6 +661,12 @@ deps = { } hooks = [ + { + # Generate the Dart SDK's .dart_tool/package_confg.json file. + 'name': 'Generate .dart_tool/package_confg.json', + 'pattern': '.', + 'action': ['python3', 'src/third_party/dart/tools/generate_package_config.py'], + }, { # Update the Windows toolchain if necessary. 'name': 'win_toolchain', diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 93a6361fb7048..83cfcbc3b2076 100755 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -47,6 +47,8 @@ FILE: ../../../flutter/display_list/display_list_benchmarks_metal.cc FILE: ../../../flutter/display_list/display_list_benchmarks_metal.h FILE: ../../../flutter/display_list/display_list_benchmarks_software.cc FILE: ../../../flutter/display_list/display_list_benchmarks_software.h +FILE: ../../../flutter/display_list/display_list_blend_mode.cc +FILE: ../../../flutter/display_list/display_list_blend_mode.h FILE: ../../../flutter/display_list/display_list_builder.cc FILE: ../../../flutter/display_list/display_list_builder.h FILE: ../../../flutter/display_list/display_list_canvas_dispatcher.cc diff --git a/ci/licenses_golden/licenses_fuchsia b/ci/licenses_golden/licenses_fuchsia index cd5ac4b3c8ec8..b2ca0f332bda5 100644 --- a/ci/licenses_golden/licenses_fuchsia +++ b/ci/licenses_golden/licenses_fuchsia @@ -1,4 +1,4 @@ -Signature: 1619b0f17059554286b4f006025815a0 +Signature: 8d1b2cec132d08723316cc285e616cf7 UNUSED LICENSES: diff --git a/ci/licenses_golden/licenses_skia b/ci/licenses_golden/licenses_skia index 6c24b6a0fca41..3120d44644bb3 100644 --- a/ci/licenses_golden/licenses_skia +++ b/ci/licenses_golden/licenses_skia @@ -1,4 +1,4 @@ -Signature: c7fac558647a8e390ec8aa2b48044b1b +Signature: bf29309505065797ffef77b5ad71374d UNUSED LICENSES: @@ -6097,6 +6097,8 @@ FILE: ../../../third_party/skia/experimental/graphite/src/render/MiddleOutFanRen FILE: ../../../third_party/skia/experimental/graphite/src/render/StencilAndCoverDSS.h FILE: ../../../third_party/skia/experimental/graphite/src/render/TessellateCurvesRenderStep.cpp FILE: ../../../third_party/skia/experimental/graphite/src/render/TessellateCurvesRenderStep.h +FILE: ../../../third_party/skia/experimental/graphite/src/render/TessellateWedgesRenderStep.cpp +FILE: ../../../third_party/skia/experimental/graphite/src/render/TessellateWedgesRenderStep.h FILE: ../../../third_party/skia/gm/bug12866.cpp FILE: ../../../third_party/skia/include/core/SkAlphaType.h FILE: ../../../third_party/skia/include/core/SkColorType.h @@ -7773,13 +7775,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ==================================================================================================== LIBRARY: skia -ORIGIN: ../../../third_party/skia/src/ports/SkFontConfigInterface_direct.cpp + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/gpu/tessellate/MidpointContourParser.h + ../../../third_party/skia/LICENSE TYPE: LicenseType.bsd -FILE: ../../../third_party/skia/src/ports/SkFontConfigInterface_direct.cpp -FILE: ../../../third_party/skia/src/ports/SkFontConfigInterface_direct.h -FILE: ../../../third_party/skia/src/ports/SkFontConfigInterface_direct_factory.cpp +FILE: ../../../third_party/skia/src/gpu/tessellate/MidpointContourParser.h +FILE: ../../../third_party/skia/src/sksl/SkSLPosition.cpp ---------------------------------------------------------------------------------------------------- -Copyright 2009-2015 Google Inc. +Copyright 2022 Google LLC. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -7812,13 +7813,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ==================================================================================================== LIBRARY: skia -ORIGIN: ../../../third_party/skia/src/ports/SkFontHost_FreeType_common.cpp + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/ports/SkFontConfigInterface_direct.cpp + ../../../third_party/skia/LICENSE TYPE: LicenseType.bsd -FILE: ../../../third_party/skia/src/ports/SkFontHost_FreeType_common.cpp -FILE: ../../../third_party/skia/src/ports/SkFontHost_FreeType_common.h +FILE: ../../../third_party/skia/src/ports/SkFontConfigInterface_direct.cpp +FILE: ../../../third_party/skia/src/ports/SkFontConfigInterface_direct.h +FILE: ../../../third_party/skia/src/ports/SkFontConfigInterface_direct_factory.cpp ---------------------------------------------------------------------------------------------------- -Copyright 2006-2012 The Android Open Source Project -Copyright 2012 Mozilla Foundation +Copyright 2009-2015 Google Inc. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -7851,11 +7852,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ==================================================================================================== LIBRARY: skia -ORIGIN: ../../../third_party/skia/src/ports/SkMemory_mozalloc.cpp + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/ports/SkFontHost_FreeType_common.cpp + ../../../third_party/skia/LICENSE TYPE: LicenseType.bsd -FILE: ../../../third_party/skia/src/ports/SkMemory_mozalloc.cpp +FILE: ../../../third_party/skia/src/ports/SkFontHost_FreeType_common.cpp +FILE: ../../../third_party/skia/src/ports/SkFontHost_FreeType_common.h ---------------------------------------------------------------------------------------------------- -Copyright 2011 Google Inc. +Copyright 2006-2012 The Android Open Source Project Copyright 2012 Mozilla Foundation Redistribution and use in source and binary forms, with or without @@ -7889,31 +7891,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ==================================================================================================== LIBRARY: skia -ORIGIN: ../../../third_party/skia/src/sksl/GLSL.std.450.h -TYPE: LicenseType.unknown -FILE: ../../../third_party/skia/src/sksl/GLSL.std.450.h -FILE: ../../../third_party/skia/src/sksl/spirv.h ----------------------------------------------------------------------------------------------------- -Copyright (c) 2014-2016 The Khronos Group Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and/or associated documentation files (the "Materials"), -to deal in the Materials without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Materials, and to permit persons to whom the -Materials are furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Materials. -==================================================================================================== - -==================================================================================================== -LIBRARY: skia -ORIGIN: ../../../third_party/skia/src/sksl/SkSLPosition.cpp + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/ports/SkMemory_mozalloc.cpp + ../../../third_party/skia/LICENSE TYPE: LicenseType.bsd -FILE: ../../../third_party/skia/src/sksl/SkSLPosition.cpp +FILE: ../../../third_party/skia/src/ports/SkMemory_mozalloc.cpp ---------------------------------------------------------------------------------------------------- -Copyright 2022 Google LLC. +Copyright 2011 Google Inc. +Copyright 2012 Mozilla Foundation Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -7944,6 +7927,26 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ==================================================================================================== +==================================================================================================== +LIBRARY: skia +ORIGIN: ../../../third_party/skia/src/sksl/GLSL.std.450.h +TYPE: LicenseType.unknown +FILE: ../../../third_party/skia/src/sksl/GLSL.std.450.h +FILE: ../../../third_party/skia/src/sksl/spirv.h +---------------------------------------------------------------------------------------------------- +Copyright (c) 2014-2016 The Khronos Group Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and/or associated documentation files (the "Materials"), +to deal in the Materials without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Materials, and to permit persons to whom the +Materials are furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Materials. +==================================================================================================== + ==================================================================================================== LIBRARY: vulkanmemoryallocator ORIGIN: ../../../third_party/skia/third_party/vulkanmemoryallocator/include/vk_mem_alloc.h diff --git a/display_list/BUILD.gn b/display_list/BUILD.gn index 599719068a3a4..1f6366c19edb3 100644 --- a/display_list/BUILD.gn +++ b/display_list/BUILD.gn @@ -9,6 +9,8 @@ source_set("display_list") { "display_list.cc", "display_list.h", "display_list_attributes.h", + "display_list_blend_mode.cc", + "display_list_blend_mode.h", "display_list_builder.cc", "display_list_builder.h", "display_list_canvas_dispatcher.cc", diff --git a/display_list/display_list_benchmarks.cc b/display_list/display_list_benchmarks.cc index ee41cd1e46372..e34b1a036da27 100644 --- a/display_list/display_list_benchmarks.cc +++ b/display_list/display_list_benchmarks.cc @@ -802,7 +802,7 @@ void BM_DrawVertices(benchmark::State& state, sk_sp vertices = GetTestVertices(p, radius, 50, mode, vertex_count); total_vertex_count += vertex_count; - builder.drawVertices(vertices, SkBlendMode::kSrc); + builder.drawVertices(vertices, DlBlendMode::kSrc); } state.counters["VertexCount"] = total_vertex_count; diff --git a/display_list/display_list_blend_mode.cc b/display_list/display_list_blend_mode.cc new file mode 100644 index 0000000000000..a8f2425af73e3 --- /dev/null +++ b/display_list/display_list_blend_mode.cc @@ -0,0 +1,7 @@ +// 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_blend_mode.h" + +namespace flutter {} // namespace flutter diff --git a/display_list/display_list_blend_mode.h b/display_list/display_list_blend_mode.h new file mode 100644 index 0000000000000..32753daa09b5e --- /dev/null +++ b/display_list/display_list_blend_mode.h @@ -0,0 +1,78 @@ +// 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. + +#ifndef FLUTTER_DISPLAY_LIST_DISPLAY_LIST_BLEND_MODE_H_ +#define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_BLEND_MODE_H_ + +#include "include/core/SkBlender.h" + +namespace flutter { + +/// A enum define the blend mode. +/// Blends are operators that take in two colors (source, destination) and +/// return a new color. Blends are operators that take in two colors (source, +/// destination) and return a new color. Many of these operate the same on all 4 +/// components: red, green, blue, alpha. For these, we just document what +/// happens to one component, rather than naming each one separately. Different +/// SkColorTypes have different representations for color components: +/// 8-bit: 0..255 +/// 6-bit: 0..63 +/// 5-bit: 0..31 +/// 4-bit: 0..15 +/// floats: 0...1 +/// The documentation is expressed as if the component values are always 0..1 +/// (floats). For brevity, the documentation uses the following abbreviations s +/// : source d : destination sa : source alpha da : destination alpha Results +/// are abbreviated r : if all 4 components are computed in the same manner ra +/// : result alpha component rc : result "color": red, green, blue components +enum class DlBlendMode { + kClear, //!< r = 0 + kSrc, //!< r = s + kDst, //!< r = d + kSrcOver, //!< r = s + (1-sa)*d + kDstOver, //!< r = d + (1-da)*s + kSrcIn, //!< r = s * da + kDstIn, //!< r = d * sa + kSrcOut, //!< r = s * (1-da) + kDstOut, //!< r = d * (1-sa) + kSrcATop, //!< r = s*da + d*(1-sa) + kDstATop, //!< r = d*sa + s*(1-da) + kXor, //!< r = s*(1-da) + d*(1-sa) + kPlus, //!< r = min(s + d, 1) + kModulate, //!< r = s*d + kScreen, //!< r = s + d - s*d + + kOverlay, //!< multiply or screen, depending on destination + kDarken, //!< rc = s + d - max(s*da, d*sa), ra = kSrcOver + kLighten, //!< rc = s + d - min(s*da, d*sa), ra = kSrcOver + kColorDodge, //!< brighten destination to reflect source + kColorBurn, //!< darken destination to reflect source + kHardLight, //!< multiply or screen, depending on source + kSoftLight, //!< lighten or darken, depending on source + kDifference, //!< rc = s + d - 2*(min(s*da, d*sa)), ra = kSrcOver + kExclusion, //!< rc = s + d - two(s*d), ra = kSrcOver + kMultiply, //!< r = s*(1-da) + d*(1-sa) + s*d + + kHue, //!< hue of source with saturation and luminosity of destination + kSaturation, //!< saturation of source with hue and luminosity of destination + kColor, //!< hue and saturation of source with luminosity of destination + kLuminosity, //!< luminosity of source with hue and saturation of destination + + kLastCoeffMode = kScreen, //!< last porter duff blend mode + kLastSeparableMode = + kMultiply, //!< last blend mode operating separately on components + kLastMode = kLuminosity, //!< last valid value +}; + +inline DlBlendMode ToDl(SkBlendMode mode) { + return static_cast(mode); +} + +inline SkBlendMode ToSk(DlBlendMode mode) { + return static_cast(mode); +} + +} // namespace flutter + +#endif // FLUTTER_DISPLAY_LIST_DISPLAY_LIST_BLEND_MODE_H_ diff --git a/display_list/display_list_builder.cc b/display_list/display_list_builder.cc index 0d4f3bb6ad3bc..be2f60b8a6eea 100644 --- a/display_list/display_list_builder.cc +++ b/display_list/display_list_builder.cc @@ -4,6 +4,7 @@ #include "flutter/display_list/display_list_builder.h" +#include "flutter/display_list/display_list_blend_mode.h" #include "flutter/display_list/display_list_ops.h" namespace flutter { @@ -103,7 +104,7 @@ void DisplayListBuilder::onSetStrokeMiter(SkScalar limit) { void DisplayListBuilder::onSetColor(SkColor color) { Push(0, 0, current_color_ = color); } -void DisplayListBuilder::onSetBlendMode(SkBlendMode mode) { +void DisplayListBuilder::onSetBlendMode(DlBlendMode mode) { current_blender_ = nullptr; Push(0, 0, current_blend_mode_ = mode); UpdateCurrentOpacityCompatibility(); @@ -115,7 +116,7 @@ void DisplayListBuilder::onSetBlender(sk_sp blender) { SkPaint p; p.setBlender(blender); if (p.asBlendMode()) { - setBlendMode(p.asBlendMode().value()); + setBlendMode(ToDl(p.asBlendMode().value())); } else { // |current_blender_| supersedes any value of |current_blend_mode_| (current_blender_ = blender) // @@ -263,7 +264,7 @@ void DisplayListBuilder::setAttributesFromPaint( if (flags.applies_blend()) { std::optional mode_optional = paint.asBlendMode(); if (mode_optional) { - setBlendMode(mode_optional.value()); + setBlendMode(ToDl(mode_optional.value())); } else { setBlender(sk_ref_sp(paint.getBlender())); } @@ -479,7 +480,7 @@ void DisplayListBuilder::drawPaint() { Push(0, 1); CheckLayerOpacityCompatibility(); } -void DisplayListBuilder::drawColor(SkColor color, SkBlendMode mode) { +void DisplayListBuilder::drawColor(SkColor color, DlBlendMode mode) { Push(0, 1, color, mode); CheckLayerOpacityCompatibility(mode); } @@ -559,7 +560,7 @@ void DisplayListBuilder::drawPoints(SkCanvas::PointMode mode, UpdateLayerOpacityCompatibility(false); } void DisplayListBuilder::drawVertices(const sk_sp vertices, - SkBlendMode mode) { + DlBlendMode mode) { Push(0, 1, std::move(vertices), mode); // DrawVertices applies its colors to the paint so we have no way // of controlling opacity using the current paint attributes. @@ -625,7 +626,7 @@ void DisplayListBuilder::drawAtlas(const sk_sp atlas, const SkRect tex[], const SkColor colors[], int count, - SkBlendMode mode, + DlBlendMode mode, const SkSamplingOptions& sampling, const SkRect* cull_rect, bool render_with_attributes) { diff --git a/display_list/display_list_builder.h b/display_list/display_list_builder.h index 791105f43ac76..4c6ed0a41db0e 100644 --- a/display_list/display_list_builder.h +++ b/display_list/display_list_builder.h @@ -6,6 +6,7 @@ #define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_BUILDER_H_ #include "flutter/display_list/display_list.h" +#include "flutter/display_list/display_list_blend_mode.h" #include "flutter/display_list/display_list_comparable.h" #include "flutter/display_list/display_list_dispatcher.h" #include "flutter/display_list/display_list_flags.h" @@ -72,14 +73,14 @@ class DisplayListBuilder final : public virtual Dispatcher, onSetColor(color); } } - void setBlendMode(SkBlendMode mode) override { + void setBlendMode(DlBlendMode mode) override { if (current_blender_ || current_blend_mode_ != mode) { onSetBlendMode(mode); } } void setBlender(sk_sp blender) override { if (!blender) { - setBlendMode(SkBlendMode::kSrcOver); + setBlendMode(DlBlendMode::kSrcOver); } else if (current_blender_ != blender) { onSetBlender(std::move(blender)); } @@ -125,7 +126,7 @@ class DisplayListBuilder final : public virtual Dispatcher, return current_color_filter_; } bool isInvertColors() const { return current_invert_colors_; } - std::optional getBlendMode() const { + std::optional getBlendMode() const { if (current_blender_) { // The setters will turn "Mode" style blenders into "blend_mode"s return {}; @@ -134,7 +135,7 @@ class DisplayListBuilder final : public virtual Dispatcher, } sk_sp getBlender() const { return current_blender_ ? current_blender_ - : SkBlender::Mode(current_blend_mode_); + : SkBlender::Mode(ToSk(current_blend_mode_)); } sk_sp getPathEffect() const { return current_path_effect_; } std::shared_ptr getMaskFilter() const { @@ -184,7 +185,7 @@ class DisplayListBuilder final : public virtual Dispatcher, void clipPath(const SkPath& path, SkClipOp clip_op, bool is_aa) override; void drawPaint() override; - void drawColor(SkColor color, SkBlendMode mode) override; + void drawColor(SkColor color, DlBlendMode mode) override; void drawLine(const SkPoint& p0, const SkPoint& p1) override; void drawRect(const SkRect& rect) override; void drawOval(const SkRect& bounds) override; @@ -200,7 +201,7 @@ class DisplayListBuilder final : public virtual Dispatcher, uint32_t count, const SkPoint pts[]) override; void drawVertices(const sk_sp vertices, - SkBlendMode mode) override; + DlBlendMode mode) override; void drawImage(const sk_sp image, const SkPoint point, const SkSamplingOptions& sampling, @@ -228,7 +229,7 @@ class DisplayListBuilder final : public virtual Dispatcher, const SkRect tex[], const SkColor colors[], int count, - SkBlendMode mode, + DlBlendMode mode, const SkSamplingOptions& sampling, const SkRect* cullRect, bool render_with_attributes) override; @@ -322,8 +323,8 @@ class DisplayListBuilder final : public virtual Dispatcher, // in the future to include other (rarely used) modes that also modulate // the opacity of a rendering operation at the cost of a switch statement // or lookup table. - static bool IsOpacityCompatible(SkBlendMode mode) { - return (mode == SkBlendMode::kSrcOver); + static bool IsOpacityCompatible(DlBlendMode mode) { + return (mode == DlBlendMode::kSrcOver); } void UpdateCurrentOpacityCompatibility() { @@ -363,7 +364,7 @@ class DisplayListBuilder final : public virtual Dispatcher, // Check for opacity compatibility for an op that ignores the current // attributes and uses the indicated blend |mode| to render to the layer. // This is only used by |drawColor| currently. - void CheckLayerOpacityCompatibility(SkBlendMode mode) { + void CheckLayerOpacityCompatibility(DlBlendMode mode) { UpdateLayerOpacityCompatibility(IsOpacityCompatible(mode)); } @@ -376,7 +377,7 @@ class DisplayListBuilder final : public virtual Dispatcher, void onSetStrokeWidth(SkScalar width); void onSetStrokeMiter(SkScalar limit); void onSetColor(SkColor color); - void onSetBlendMode(SkBlendMode mode); + void onSetBlendMode(DlBlendMode mode); void onSetBlender(sk_sp blender); void onSetColorSource(const DlColorSource* source); void onSetImageFilter(sk_sp filter); @@ -396,7 +397,7 @@ class DisplayListBuilder final : public virtual Dispatcher, SkPaint::Cap current_stroke_cap_ = SkPaint::Cap::kButt_Cap; SkPaint::Join current_stroke_join_ = SkPaint::Join::kMiter_Join; // If |current_blender_| is set then |current_blend_mode_| should be ignored - SkBlendMode current_blend_mode_ = SkBlendMode::kSrcOver; + DlBlendMode current_blend_mode_ = DlBlendMode::kSrcOver; sk_sp current_blender_; std::shared_ptr current_color_source_; std::shared_ptr current_color_filter_; diff --git a/display_list/display_list_canvas_dispatcher.cc b/display_list/display_list_canvas_dispatcher.cc index c2d2223b74f30..db59c894c17de 100644 --- a/display_list/display_list_canvas_dispatcher.cc +++ b/display_list/display_list_canvas_dispatcher.cc @@ -4,6 +4,7 @@ #include "flutter/display_list/display_list_canvas_dispatcher.h" +#include "flutter/display_list/display_list_blend_mode.h" #include "flutter/fml/trace_event.h" namespace flutter { @@ -130,12 +131,12 @@ void DisplayListCanvasDispatcher::drawPaint() { } canvas_->drawPaint(sk_paint); } -void DisplayListCanvasDispatcher::drawColor(SkColor color, SkBlendMode mode) { +void DisplayListCanvasDispatcher::drawColor(SkColor color, DlBlendMode mode) { // SkCanvas::drawColor(SkColor) does the following conversion anyway // We do it here manually to increase precision on applying opacity SkColor4f color4f = SkColor4f::FromColor(color); color4f.fA *= opacity(); - canvas_->drawColor(color4f, mode); + canvas_->drawColor(color4f, ToSk(mode)); } void DisplayListCanvasDispatcher::drawLine(const SkPoint& p0, const SkPoint& p1) { @@ -173,8 +174,8 @@ void DisplayListCanvasDispatcher::drawPoints(SkCanvas::PointMode mode, canvas_->drawPoints(mode, count, pts, paint()); } void DisplayListCanvasDispatcher::drawVertices(const sk_sp vertices, - SkBlendMode mode) { - canvas_->drawVertices(vertices, mode, paint()); + DlBlendMode mode) { + canvas_->drawVertices(vertices, ToSk(mode), paint()); } void DisplayListCanvasDispatcher::drawImage(const sk_sp image, const SkPoint point, @@ -215,12 +216,12 @@ void DisplayListCanvasDispatcher::drawAtlas(const sk_sp atlas, const SkRect tex[], const SkColor colors[], int count, - SkBlendMode mode, + DlBlendMode mode, const SkSamplingOptions& sampling, const SkRect* cullRect, bool render_with_attributes) { - canvas_->drawAtlas(atlas.get(), xform, tex, colors, count, mode, sampling, - cullRect, safe_paint(render_with_attributes)); + canvas_->drawAtlas(atlas.get(), xform, tex, colors, count, ToSk(mode), + sampling, cullRect, safe_paint(render_with_attributes)); } void DisplayListCanvasDispatcher::drawPicture(const sk_sp picture, const SkMatrix* matrix, diff --git a/display_list/display_list_canvas_dispatcher.h b/display_list/display_list_canvas_dispatcher.h index 50f0ab0b7caf9..0f1ffc6c848f6 100644 --- a/display_list/display_list_canvas_dispatcher.h +++ b/display_list/display_list_canvas_dispatcher.h @@ -6,6 +6,7 @@ #define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_CANVAS_DISPATCHER_H_ #include "flutter/display_list/display_list.h" +#include "flutter/display_list/display_list_blend_mode.h" #include "flutter/display_list/display_list_dispatcher.h" #include "flutter/display_list/display_list_utils.h" #include "flutter/fml/macros.h" @@ -53,7 +54,7 @@ class DisplayListCanvasDispatcher : public virtual Dispatcher, void clipPath(const SkPath& path, SkClipOp clip_op, bool is_aa) override; void drawPaint() override; - void drawColor(SkColor color, SkBlendMode mode) override; + void drawColor(SkColor color, DlBlendMode mode) override; void drawLine(const SkPoint& p0, const SkPoint& p1) override; void drawRect(const SkRect& rect) override; void drawOval(const SkRect& bounds) override; @@ -69,7 +70,7 @@ class DisplayListCanvasDispatcher : public virtual Dispatcher, uint32_t count, const SkPoint pts[]) override; void drawVertices(const sk_sp vertices, - SkBlendMode mode) override; + DlBlendMode mode) override; void drawImage(const sk_sp image, const SkPoint point, const SkSamplingOptions& sampling, @@ -95,7 +96,7 @@ class DisplayListCanvasDispatcher : public virtual Dispatcher, const SkRect tex[], const SkColor colors[], int count, - SkBlendMode mode, + DlBlendMode mode, const SkSamplingOptions& sampling, const SkRect* cullRect, bool render_with_attributes) override; diff --git a/display_list/display_list_canvas_recorder.cc b/display_list/display_list_canvas_recorder.cc index 011e6ee139764..49c3dfb9bac94 100644 --- a/display_list/display_list_canvas_recorder.cc +++ b/display_list/display_list_canvas_recorder.cc @@ -4,6 +4,7 @@ #include "flutter/display_list/display_list_canvas_recorder.h" +#include "flutter/display_list/display_list_blend_mode.h" #include "flutter/display_list/display_list_builder.h" namespace flutter { @@ -147,7 +148,7 @@ void DisplayListCanvasRecorder::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint) { builder_->setAttributesFromPaint(paint, kDrawVerticesFlags); - builder_->drawVertices(sk_ref_sp(vertices), mode); + builder_->drawVertices(sk_ref_sp(vertices), ToDl(mode)); } void DisplayListCanvasRecorder::onDrawImage2(const SkImage* image, @@ -204,7 +205,7 @@ void DisplayListCanvasRecorder::onDrawAtlas2(const SkImage* image, if (paint != nullptr) { builder_->setAttributesFromPaint(*paint, kDrawAtlasWithPaintFlags); } - builder_->drawAtlas(sk_ref_sp(image), xform, src, colors, count, mode, + builder_->drawAtlas(sk_ref_sp(image), xform, src, colors, count, ToDl(mode), sampling, cull, paint != nullptr); } diff --git a/display_list/display_list_canvas_unittests.cc b/display_list/display_list_canvas_unittests.cc index 5d3cfeb5a6269..8460405a4ba45 100644 --- a/display_list/display_list_canvas_unittests.cc +++ b/display_list/display_list_canvas_unittests.cc @@ -761,9 +761,9 @@ class CanvasCompareTester { b.save(); b.clipRect(clip, SkClipOp::kIntersect, false); b.drawRect(rect); - b.setBlendMode(SkBlendMode::kClear); + b.setBlendMode(DlBlendMode::kClear); b.drawRect(rect); - b.setBlendMode(SkBlendMode::kSrcOver); + b.setBlendMode(DlBlendMode::kSrcOver); b.restore(); })); RenderWith(testP, env, tolerance, @@ -1039,7 +1039,7 @@ class CanvasCompareTester { p.setColor(blendableColor); }, [=](DisplayListBuilder& b) { - b.setBlendMode(SkBlendMode::kSrcIn); + b.setBlendMode(DlBlendMode::kSrcIn); b.setColor(blendableColor); }) .with_bg(bg)); @@ -1051,7 +1051,7 @@ class CanvasCompareTester { p.setColor(blendableColor); }, [=](DisplayListBuilder& b) { - b.setBlendMode(SkBlendMode::kDstIn); + b.setBlendMode(DlBlendMode::kDstIn); b.setColor(blendableColor); }) .with_bg(bg)); @@ -2129,7 +2129,7 @@ TEST_F(DisplayListCanvas, DrawColor) { canvas->drawColor(SK_ColorMAGENTA); }, [=](DisplayListBuilder& builder) { - builder.drawColor(SK_ColorMAGENTA, SkBlendMode::kSrcOver); + builder.drawColor(SK_ColorMAGENTA, DlBlendMode::kSrcOver); }, kDrawColorFlags)); } @@ -2503,7 +2503,7 @@ TEST_F(DisplayListCanvas, DrawVerticesWithColors) { canvas->drawVertices(vertices.get(), SkBlendMode::kSrcOver, paint); }, [=](DisplayListBuilder& builder) { // - builder.drawVertices(vertices, SkBlendMode::kSrcOver); + builder.drawVertices(vertices, DlBlendMode::kSrcOver); }, kDrawVerticesFlags) .set_draw_vertices()); @@ -2557,7 +2557,7 @@ TEST_F(DisplayListCanvas, DrawVerticesWithImage) { builder.setColorSource( &CanvasCompareTester::testImageColorSource); } - builder.drawVertices(vertices, SkBlendMode::kSrcOver); + builder.drawVertices(vertices, DlBlendMode::kSrcOver); }, kDrawVerticesFlags) .set_draw_vertices()); @@ -2834,7 +2834,7 @@ TEST_F(DisplayListCanvas, DrawAtlasNearest) { }, [=](DisplayListBuilder& builder) { builder.drawAtlas(image, xform, tex, colors, 4, // - SkBlendMode::kSrcOver, sampling, nullptr, true); + DlBlendMode::kSrcOver, sampling, nullptr, true); }, kDrawAtlasWithPaintFlags) .set_draw_atlas()); @@ -2874,7 +2874,7 @@ TEST_F(DisplayListCanvas, DrawAtlasNearestNoPaint) { }, [=](DisplayListBuilder& builder) { builder.drawAtlas(image, xform, tex, colors, 4, // - SkBlendMode::kSrcOver, sampling, // + DlBlendMode::kSrcOver, sampling, // nullptr, false); }, kDrawAtlasFlags) @@ -2914,7 +2914,7 @@ TEST_F(DisplayListCanvas, DrawAtlasLinear) { }, [=](DisplayListBuilder& builder) { builder.drawAtlas(image, xform, tex, colors, 2, // - SkBlendMode::kSrcOver, sampling, nullptr, true); + DlBlendMode::kSrcOver, sampling, nullptr, true); }, kDrawAtlasWithPaintFlags) .set_draw_atlas()); diff --git a/display_list/display_list_complexity_gl.cc b/display_list/display_list_complexity_gl.cc index e7364f57abbcb..71eb1b76a695c 100644 --- a/display_list/display_list_complexity_gl.cc +++ b/display_list/display_list_complexity_gl.cc @@ -478,7 +478,7 @@ void DisplayListGLComplexityCalculator::GLHelper::drawPoints( void DisplayListGLComplexityCalculator::GLHelper::drawVertices( const sk_sp vertices, - SkBlendMode mode) { + DlBlendMode mode) { // There is currently no way for us to get the VertexMode from the SkVertices // object, but for future reference: // diff --git a/display_list/display_list_complexity_gl.h b/display_list/display_list_complexity_gl.h index 55732c4e382a2..0d80f7ed63c38 100644 --- a/display_list/display_list_complexity_gl.h +++ b/display_list/display_list_complexity_gl.h @@ -55,7 +55,7 @@ class DisplayListGLComplexityCalculator uint32_t count, const SkPoint points[]) override; void drawVertices(const sk_sp vertices, - SkBlendMode mode) override; + DlBlendMode mode) override; void drawImage(const sk_sp image, const SkPoint point, const SkSamplingOptions& sampling, diff --git a/display_list/display_list_complexity_helper.h b/display_list/display_list_complexity_helper.h index 4e34b62bc1faa..30176bdd2b004 100644 --- a/display_list/display_list_complexity_helper.h +++ b/display_list/display_list_complexity_helper.h @@ -5,6 +5,7 @@ #ifndef FLUTTER_FLOW_DISPLAY_LIST_COMPLEXITY_HELPER_H_ #define FLUTTER_FLOW_DISPLAY_LIST_COMPLEXITY_HELPER_H_ +#include "flutter/display_list/display_list_blend_mode.h" #include "flutter/display_list/display_list_complexity.h" #include "flutter/display_list/display_list_dispatcher.h" #include "flutter/display_list/display_list_utils.h" @@ -106,7 +107,7 @@ class ComplexityCalculatorHelper void setStrokeJoin(SkPaint::Join join) override {} void setStrokeMiter(SkScalar limit) override {} void setColor(SkColor color) override {} - void setBlendMode(SkBlendMode mode) override {} + void setBlendMode(DlBlendMode mode) override {} void setBlender(sk_sp blender) override {} void setColorSource(const DlColorSource* source) override {} void setImageFilter(sk_sp filter) override {} @@ -128,7 +129,7 @@ class ComplexityCalculatorHelper current_paint_.setStrokeWidth(width); } - void drawColor(SkColor color, SkBlendMode mode) override { + void drawColor(SkColor color, DlBlendMode mode) override { if (IsComplex()) { return; } @@ -179,7 +180,7 @@ class ComplexityCalculatorHelper const SkRect tex[], const SkColor colors[], int count, - SkBlendMode mode, + DlBlendMode mode, const SkSamplingOptions& sampling, const SkRect* cull_rect, bool render_with_attributes) override { diff --git a/display_list/display_list_complexity_metal.cc b/display_list/display_list_complexity_metal.cc index 6d4983f06bc9b..17b6af9673b95 100644 --- a/display_list/display_list_complexity_metal.cc +++ b/display_list/display_list_complexity_metal.cc @@ -430,7 +430,7 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawPoints( void DisplayListMetalComplexityCalculator::MetalHelper::drawVertices( const sk_sp vertices, - SkBlendMode mode) { + DlBlendMode mode) { // There is currently no way for us to get the VertexMode from the SkVertices // object, but for future reference: // diff --git a/display_list/display_list_complexity_metal.h b/display_list/display_list_complexity_metal.h index 26131dee17585..ffba4c8ec4e70 100644 --- a/display_list/display_list_complexity_metal.h +++ b/display_list/display_list_complexity_metal.h @@ -55,7 +55,7 @@ class DisplayListMetalComplexityCalculator uint32_t count, const SkPoint points[]) override; void drawVertices(const sk_sp vertices, - SkBlendMode mode) override; + DlBlendMode mode) override; void drawImage(const sk_sp image, const SkPoint point, const SkSamplingOptions& sampling, diff --git a/display_list/display_list_complexity_unittests.cc b/display_list/display_list_complexity_unittests.cc index 88c6b3c9471c4..c669a874ba370 100644 --- a/display_list/display_list_complexity_unittests.cc +++ b/display_list/display_list_complexity_unittests.cc @@ -287,7 +287,7 @@ TEST(DisplayListComplexity, DrawVertices) { SkVertices::MakeCopy(SkVertices::VertexMode::kTriangles_VertexMode, points.size(), points.data(), nullptr, nullptr); DisplayListBuilder builder; - builder.drawVertices(vertices, SkBlendMode::kSrc); + builder.drawVertices(vertices, DlBlendMode::kSrc); auto display_list = builder.Build(); auto calculators = AccumulatorCalculators(); @@ -419,7 +419,7 @@ TEST(DisplayListComplexity, DrawAtlas) { DisplayListBuilder builder; builder.drawAtlas(image, xforms.data(), rects.data(), nullptr, 10, - SkBlendMode::kSrc, SkSamplingOptions(), nullptr, true); + DlBlendMode::kSrc, SkSamplingOptions(), nullptr, true); auto display_list = builder.Build(); auto calculators = AccumulatorCalculators(); diff --git a/display_list/display_list_dispatcher.h b/display_list/display_list_dispatcher.h index e4bf53fe7ebb6..cd25d7059e20f 100644 --- a/display_list/display_list_dispatcher.h +++ b/display_list/display_list_dispatcher.h @@ -6,6 +6,7 @@ #define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_DISPATCHER_H_ #include "flutter/display_list/display_list.h" +#include "flutter/display_list/display_list_blend_mode.h" #include "flutter/display_list/display_list_color_filter.h" #include "flutter/display_list/display_list_color_source.h" #include "flutter/display_list/display_list_mask_filter.h" @@ -45,7 +46,7 @@ class Dispatcher { // It is not reset by |setColorFilter|, but instead composed with that // filter so that the color inversion happens after the ColorFilter. virtual void setInvertColors(bool invert) = 0; - virtual void setBlendMode(SkBlendMode mode) = 0; + virtual void setBlendMode(DlBlendMode mode) = 0; virtual void setBlender(sk_sp blender) = 0; virtual void setPathEffect(sk_sp effect) = 0; virtual void setMaskFilter(const DlMaskFilter* filter) = 0; @@ -186,7 +187,7 @@ class Dispatcher { // method, the methods here will generally offer a boolean parameter // which specifies whether to honor the attributes of the display list // stream, or assume default attributes. - virtual void drawColor(SkColor color, SkBlendMode mode) = 0; + virtual void drawColor(SkColor color, DlBlendMode mode) = 0; virtual void drawPaint() = 0; virtual void drawLine(const SkPoint& p0, const SkPoint& p1) = 0; virtual void drawRect(const SkRect& rect) = 0; @@ -203,7 +204,7 @@ class Dispatcher { uint32_t count, const SkPoint points[]) = 0; virtual void drawVertices(const sk_sp vertices, - SkBlendMode mode) = 0; + DlBlendMode mode) = 0; virtual void drawImage(const sk_sp image, const SkPoint point, const SkSamplingOptions& sampling, @@ -229,7 +230,7 @@ class Dispatcher { const SkRect tex[], const SkColor colors[], int count, - SkBlendMode mode, + DlBlendMode mode, const SkSamplingOptions& sampling, const SkRect* cull_rect, bool render_with_attributes) = 0; diff --git a/display_list/display_list_enum_unittests.cc b/display_list/display_list_enum_unittests.cc index a45542b0f05b4..94556248ca886 100644 --- a/display_list/display_list_enum_unittests.cc +++ b/display_list/display_list_enum_unittests.cc @@ -2,6 +2,7 @@ // 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_blend_mode.h" #include "flutter/display_list/display_list_tile_mode.h" #include "flutter/display_list/types.h" #include "gtest/gtest.h" @@ -23,5 +24,53 @@ TEST(DisplayListEnum, ToSkTileMode) { ASSERT_EQ(ToSk(DlTileMode::kDecal), SkTileMode::kDecal); } +#define CHECK_TO_DLENUM(V) ASSERT_EQ(ToDl(SkBlendMode::V), DlBlendMode::V); +#define CHECK_TO_SKENUM(V) ASSERT_EQ(ToSk(DlBlendMode::V), SkBlendMode::V); + +#define FOR_EACH_ENUM(FUNC) \ + FUNC(kSrc) \ + FUNC(kClear) \ + FUNC(kSrc) \ + FUNC(kDst) \ + FUNC(kSrcOver) \ + FUNC(kDstOver) \ + FUNC(kSrcIn) \ + FUNC(kDstIn) \ + FUNC(kSrcOut) \ + FUNC(kDstOut) \ + FUNC(kSrcATop) \ + FUNC(kDstATop) \ + FUNC(kXor) \ + FUNC(kPlus) \ + FUNC(kModulate) \ + FUNC(kScreen) \ + FUNC(kOverlay) \ + FUNC(kDarken) \ + FUNC(kLighten) \ + FUNC(kColorDodge) \ + FUNC(kColorBurn) \ + FUNC(kHardLight) \ + FUNC(kSoftLight) \ + FUNC(kDifference) \ + FUNC(kExclusion) \ + FUNC(kMultiply) \ + FUNC(kHue) \ + FUNC(kSaturation) \ + FUNC(kColor) \ + FUNC(kLuminosity) \ + FUNC(kLastCoeffMode) \ + FUNC(kLastSeparableMode) \ + FUNC(kLastMode) + +TEST(DisplayListEnum, ToDlBlendMode){FOR_EACH_ENUM(CHECK_TO_DLENUM)} + +TEST(DisplayListEnum, ToSkBlendMode) { + FOR_EACH_ENUM(CHECK_TO_SKENUM) +} + +#undef CHECK_TO_DLENUM +#undef CHECK_TO_SKENUM +#undef FOR_EACH_ENUM + } // namespace testing } // namespace flutter diff --git a/display_list/display_list_ops.h b/display_list/display_list_ops.h index bb6abc56ef4c9..69535816ead73 100644 --- a/display_list/display_list_ops.h +++ b/display_list/display_list_ops.h @@ -6,6 +6,7 @@ #define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_OPS_H_ #include "flutter/display_list/display_list.h" +#include "flutter/display_list/display_list_blend_mode.h" #include "flutter/display_list/display_list_dispatcher.h" #include "flutter/display_list/types.h" #include "flutter/fml/macros.h" @@ -141,9 +142,9 @@ struct SetColorOp final : DLOp { struct SetBlendModeOp final : DLOp { static const auto kType = DisplayListOpType::kSetBlendMode; - explicit SetBlendModeOp(SkBlendMode mode) : mode(mode) {} + explicit SetBlendModeOp(DlBlendMode mode) : mode(mode) {} - const SkBlendMode mode; + const DlBlendMode mode; void dispatch(Dispatcher& dispatcher) const { dispatcher.setBlendMode(mode); } }; @@ -458,10 +459,10 @@ struct DrawPaintOp final : DLOp { struct DrawColorOp final : DLOp { static const auto kType = DisplayListOpType::kDrawColor; - DrawColorOp(SkColor color, SkBlendMode mode) : color(color), mode(mode) {} + DrawColorOp(SkColor color, DlBlendMode mode) : color(color), mode(mode) {} const SkColor color; - const SkBlendMode mode; + const DlBlendMode mode; void dispatch(Dispatcher& dispatcher) const { dispatcher.drawColor(color, mode); @@ -577,10 +578,10 @@ DEFINE_DRAW_POINTS_OP(Polygon, kPolygon_PointMode); struct DrawVerticesOp final : DLOp { static const auto kType = DisplayListOpType::kDrawVertices; - DrawVerticesOp(sk_sp vertices, SkBlendMode mode) + DrawVerticesOp(sk_sp vertices, DlBlendMode mode) : mode(mode), vertices(std::move(vertices)) {} - const SkBlendMode mode; + const DlBlendMode mode; const sk_sp vertices; void dispatch(Dispatcher& dispatcher) const { @@ -721,7 +722,7 @@ struct DrawImageLatticeOp final : DLOp { struct DrawAtlasBaseOp : DLOp { DrawAtlasBaseOp(const sk_sp atlas, int count, - SkBlendMode mode, + DlBlendMode mode, const SkSamplingOptions& sampling, bool has_colors, bool render_with_attributes) @@ -747,7 +748,7 @@ struct DrawAtlasOp final : DrawAtlasBaseOp { DrawAtlasOp(const sk_sp atlas, int count, - SkBlendMode mode, + DlBlendMode mode, const SkSamplingOptions& sampling, bool has_colors, bool render_with_attributes) @@ -763,7 +764,7 @@ struct DrawAtlasOp final : DrawAtlasBaseOp { const SkRect* tex = reinterpret_cast(xform + count); const SkColor* colors = has_colors ? reinterpret_cast(tex + count) : nullptr; - const SkBlendMode mode = static_cast(mode_index); + const DlBlendMode mode = static_cast(mode_index); dispatcher.drawAtlas(atlas, xform, tex, colors, count, mode, sampling, nullptr, render_with_attributes); } @@ -778,7 +779,7 @@ struct DrawAtlasCulledOp final : DrawAtlasBaseOp { DrawAtlasCulledOp(const sk_sp atlas, int count, - SkBlendMode mode, + DlBlendMode mode, const SkSamplingOptions& sampling, bool has_colors, const SkRect& cull_rect, @@ -798,7 +799,7 @@ struct DrawAtlasCulledOp final : DrawAtlasBaseOp { const SkRect* tex = reinterpret_cast(xform + count); const SkColor* colors = has_colors ? reinterpret_cast(tex + count) : nullptr; - const SkBlendMode mode = static_cast(mode_index); + const DlBlendMode mode = static_cast(mode_index); dispatcher.drawAtlas(atlas, xform, tex, colors, count, mode, sampling, &cull_rect, render_with_attributes); } diff --git a/display_list/display_list_test_utils.cc b/display_list/display_list_test_utils.cc index bdf455cb34e0d..3ba91c135b34f 100644 --- a/display_list/display_list_test_utils.cc +++ b/display_list/display_list_test_utils.cc @@ -62,7 +62,7 @@ sk_sp GetSampleNestedDisplayList() { sk_sp GetSampleDisplayList(int ops) { DisplayListBuilder builder(SkRect::MakeWH(150, 100)); for (int i = 0; i < ops; i++) { - builder.drawColor(SK_ColorRED, SkBlendMode::kSrc); + builder.drawColor(SK_ColorRED, DlBlendMode::kSrc); } return builder.Build(); } diff --git a/display_list/display_list_unittests.cc b/display_list/display_list_unittests.cc index 8e00a984d6c9f..cfc8b2521591c 100644 --- a/display_list/display_list_unittests.cc +++ b/display_list/display_list_unittests.cc @@ -338,12 +338,12 @@ std::vector allGroups = { } }, { "SetBlendModeOrBlender", { - {0, 8, 0, 0, [](DisplayListBuilder& b) {b.setBlendMode(SkBlendMode::kSrcIn);}}, - {0, 8, 0, 0, [](DisplayListBuilder& b) {b.setBlendMode(SkBlendMode::kDstIn);}}, + {0, 8, 0, 0, [](DisplayListBuilder& b) {b.setBlendMode(DlBlendMode::kSrcIn);}}, + {0, 8, 0, 0, [](DisplayListBuilder& b) {b.setBlendMode(DlBlendMode::kDstIn);}}, {0, 16, 0, 0, [](DisplayListBuilder& b) {b.setBlender(TestBlender1);}}, {0, 16, 0, 0, [](DisplayListBuilder& b) {b.setBlender(TestBlender2);}}, {0, 16, 0, 0, [](DisplayListBuilder& b) {b.setBlender(TestBlender3);}}, - {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setBlendMode(SkBlendMode::kSrcOver);}}, + {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setBlendMode(DlBlendMode::kSrcOver);}}, {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setBlender(nullptr);}}, } }, @@ -524,9 +524,9 @@ std::vector allGroups = { }, { "DrawColor", { // cv.drawColor becomes cv.drawPaint(paint) - {1, 16, 1, 24, [](DisplayListBuilder& b) {b.drawColor(SK_ColorBLUE, SkBlendMode::kSrcIn);}}, - {1, 16, 1, 24, [](DisplayListBuilder& b) {b.drawColor(SK_ColorBLUE, SkBlendMode::kDstIn);}}, - {1, 16, 1, 24, [](DisplayListBuilder& b) {b.drawColor(SK_ColorCYAN, SkBlendMode::kSrcIn);}}, + {1, 16, 1, 24, [](DisplayListBuilder& b) {b.drawColor(SK_ColorBLUE, DlBlendMode::kSrcIn);}}, + {1, 16, 1, 24, [](DisplayListBuilder& b) {b.drawColor(SK_ColorBLUE, DlBlendMode::kDstIn);}}, + {1, 16, 1, 24, [](DisplayListBuilder& b) {b.drawColor(SK_ColorCYAN, DlBlendMode::kSrcIn);}}, } }, { "DrawLine", { @@ -605,9 +605,9 @@ std::vector allGroups = { } }, { "DrawVertices", { - {1, 16, 1, 16, [](DisplayListBuilder& b) {b.drawVertices(TestVertices1, SkBlendMode::kSrcIn);}}, - {1, 16, 1, 16, [](DisplayListBuilder& b) {b.drawVertices(TestVertices1, SkBlendMode::kDstIn);}}, - {1, 16, 1, 16, [](DisplayListBuilder& b) {b.drawVertices(TestVertices2, SkBlendMode::kSrcIn);}}, + {1, 16, 1, 16, [](DisplayListBuilder& b) {b.drawVertices(TestVertices1, DlBlendMode::kSrcIn);}}, + {1, 16, 1, 16, [](DisplayListBuilder& b) {b.drawVertices(TestVertices1, DlBlendMode::kDstIn);}}, + {1, 16, 1, 16, [](DisplayListBuilder& b) {b.drawVertices(TestVertices2, DlBlendMode::kSrcIn);}}, } }, { "DrawImage", { @@ -700,51 +700,51 @@ std::vector allGroups = { {1, 40 + 32 + 32, 1, 40 + 32 + 32, [](DisplayListBuilder& b) { static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} }; static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} }; - b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, SkBlendMode::kSrcIn, + b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, DlBlendMode::kSrcIn, DisplayList::NearestSampling, nullptr, false);}}, {1, 40 + 32 + 32, 1, 40 + 32 + 32, [](DisplayListBuilder& b) { static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} }; static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} }; - b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, SkBlendMode::kSrcIn, + b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, DlBlendMode::kSrcIn, DisplayList::NearestSampling, nullptr, true);}}, {1, 40 + 32 + 32, 1, 40 + 32 + 32, [](DisplayListBuilder& b) { static SkRSXform xforms[] = { {0, 1, 0, 0}, {0, 1, 0, 0} }; static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} }; - b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, SkBlendMode::kSrcIn, + b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, DlBlendMode::kSrcIn, DisplayList::NearestSampling, nullptr, false);}}, {1, 40 + 32 + 32, 1, 40 + 32 + 32, [](DisplayListBuilder& b) { static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} }; static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 25, 30, 30} }; - b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, SkBlendMode::kSrcIn, + b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, DlBlendMode::kSrcIn, DisplayList::NearestSampling, nullptr, false);}}, {1, 40 + 32 + 32, 1, 40 + 32 + 32, [](DisplayListBuilder& b) { static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} }; static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} }; - b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, SkBlendMode::kSrcIn, + b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, DlBlendMode::kSrcIn, DisplayList::LinearSampling, nullptr, false);}}, {1, 40 + 32 + 32, 1, 40 + 32 + 32, [](DisplayListBuilder& b) { static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} }; static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} }; - b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, SkBlendMode::kDstIn, + b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, DlBlendMode::kDstIn, DisplayList::NearestSampling, nullptr, false);}}, {1, 56 + 32 + 32, 1, 56 + 32 + 32, [](DisplayListBuilder& b) { static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} }; static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} }; static SkRect cullRect = { 0, 0, 200, 200 }; - b.drawAtlas(TestImage2, xforms, texs, nullptr, 2, SkBlendMode::kSrcIn, + b.drawAtlas(TestImage2, xforms, texs, nullptr, 2, DlBlendMode::kSrcIn, DisplayList::NearestSampling, &cullRect, false);}}, {1, 40 + 32 + 32 + 8, 1, 40 + 32 + 32 + 8, [](DisplayListBuilder& b) { static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} }; static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} }; static SkColor colors[] = { SK_ColorBLUE, SK_ColorGREEN }; - b.drawAtlas(TestImage1, xforms, texs, colors, 2, SkBlendMode::kSrcIn, + b.drawAtlas(TestImage1, xforms, texs, colors, 2, DlBlendMode::kSrcIn, DisplayList::NearestSampling, nullptr, false);}}, {1, 56 + 32 + 32 + 8, 1, 56 + 32 + 32 + 8, [](DisplayListBuilder& b) { static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} }; static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} }; static SkColor colors[] = { SK_ColorBLUE, SK_ColorGREEN }; static SkRect cullRect = { 0, 0, 200, 200 }; - b.drawAtlas(TestImage1, xforms, texs, colors, 2, SkBlendMode::kSrcIn, + b.drawAtlas(TestImage1, xforms, texs, colors, 2, DlBlendMode::kSrcIn, DisplayList::NearestSampling, &cullRect, false);}}, } }, @@ -930,7 +930,7 @@ TEST(DisplayList, FullRotationsAreNop) { TEST(DisplayList, AllBlendModeNops) { DisplayListBuilder builder; - builder.setBlendMode(SkBlendMode::kSrcOver); + builder.setBlendMode(DlBlendMode::kSrcOver); builder.setBlender(nullptr); sk_sp dl = builder.Build(); ASSERT_EQ(dl->bytes(false), sizeof(DisplayList)); @@ -1138,9 +1138,9 @@ TEST(DisplayList, DisplayListSaveLayerBoundsWithAlphaFilter) { { // Testing behavior with an unboundable blend mode DisplayListBuilder builder(build_bounds); - builder.setBlendMode(SkBlendMode::kClear); + builder.setBlendMode(DlBlendMode::kClear); builder.saveLayer(&save_bounds, true); - builder.setBlendMode(SkBlendMode::kSrcOver); + builder.setBlendMode(DlBlendMode::kSrcOver); builder.drawRect(rect); builder.restore(); sk_sp display_list = builder.Build(); @@ -1150,9 +1150,9 @@ TEST(DisplayList, DisplayListSaveLayerBoundsWithAlphaFilter) { { // Same as previous with no save bounds DisplayListBuilder builder(build_bounds); - builder.setBlendMode(SkBlendMode::kClear); + builder.setBlendMode(DlBlendMode::kClear); builder.saveLayer(nullptr, true); - builder.setBlendMode(SkBlendMode::kSrcOver); + builder.setBlendMode(DlBlendMode::kSrcOver); builder.drawRect(rect); builder.restore(); sk_sp display_list = builder.Build(); @@ -1401,7 +1401,7 @@ TEST(DisplayList, SingleOpsMightSupportGroupOpacityWithOrWithoutBlendMode) { // Second test i the draw op with kSrc, // (usually fails group opacity) DisplayListBuilder builder; - builder.setBlendMode(SkBlendMode::kSrc); + builder.setBlendMode(DlBlendMode::kSrc); build(builder); auto display_list = builder.Build(); EXPECT_EQ(display_list->can_apply_group_opacity(), expect_with_kSrc) @@ -1420,8 +1420,8 @@ TEST(DisplayList, SingleOpsMightSupportGroupOpacityWithOrWithoutBlendMode) { #body, [](DisplayListBuilder& builder) { body }, expect, expect) RUN_TESTS(builder.drawPaint();); - RUN_TESTS2(builder.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);, true); - RUN_TESTS2(builder.drawColor(SK_ColorRED, SkBlendMode::kSrc);, false); + RUN_TESTS2(builder.drawColor(SK_ColorRED, DlBlendMode::kSrcOver);, true); + RUN_TESTS2(builder.drawColor(SK_ColorRED, DlBlendMode::kSrc);, false); RUN_TESTS(builder.drawLine({0, 0}, {10, 10});); RUN_TESTS(builder.drawRect({0, 0, 10, 10});); RUN_TESTS(builder.drawOval({0, 0, 10, 10});); @@ -1435,7 +1435,7 @@ TEST(DisplayList, SingleOpsMightSupportGroupOpacityWithOrWithoutBlendMode) { RUN_TESTS2(builder.drawPoints(SkCanvas::kPoints_PointMode, TestPointCount, TestPoints); , false); - RUN_TESTS2(builder.drawVertices(TestVertices1, SkBlendMode::kSrc);, false); + RUN_TESTS2(builder.drawVertices(TestVertices1, DlBlendMode::kSrc);, false); RUN_TESTS(builder.drawImage(TestImage1, {0, 0}, DisplayList::LinearSampling, true);); RUN_TESTS2( @@ -1463,11 +1463,11 @@ TEST(DisplayList, SingleOpsMightSupportGroupOpacityWithOrWithoutBlendMode) { static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}}; static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}}; RUN_TESTS2(builder.drawAtlas(TestImage1, xforms, texs, nullptr, 2, - SkBlendMode::kSrcIn, + DlBlendMode::kSrcIn, DisplayList::NearestSampling, nullptr, true); , false); RUN_TESTS2(builder.drawAtlas(TestImage1, xforms, texs, nullptr, 2, - SkBlendMode::kSrcIn, + DlBlendMode::kSrcIn, DisplayList::NearestSampling, nullptr, false); , false); RUN_TESTS(builder.drawPicture(TestPicture1, nullptr, true);); @@ -1522,7 +1522,7 @@ TEST(DisplayList, SaveLayerTrueSupportsGroupOpacityWithOverlappingChidren) { TEST(DisplayList, SaveLayerFalseWithSrcBlendSupportsGroupOpacity) { DisplayListBuilder builder; - builder.setBlendMode(SkBlendMode::kSrc); + builder.setBlendMode(DlBlendMode::kSrc); builder.saveLayer(nullptr, false); builder.drawRect({0, 0, 10, 10}); builder.restore(); @@ -1532,7 +1532,7 @@ TEST(DisplayList, SaveLayerFalseWithSrcBlendSupportsGroupOpacity) { TEST(DisplayList, SaveLayerTrueWithSrcBlendDoesNotSupportGroupOpacity) { DisplayListBuilder builder; - builder.setBlendMode(SkBlendMode::kSrc); + builder.setBlendMode(DlBlendMode::kSrc); builder.saveLayer(nullptr, true); builder.drawRect({0, 0, 10, 10}); builder.restore(); @@ -1543,7 +1543,7 @@ TEST(DisplayList, SaveLayerTrueWithSrcBlendDoesNotSupportGroupOpacity) { TEST(DisplayList, SaveLayerFalseSupportsGroupOpacityWithChildSrcBlend) { DisplayListBuilder builder; builder.saveLayer(nullptr, false); - builder.setBlendMode(SkBlendMode::kSrc); + builder.setBlendMode(DlBlendMode::kSrc); builder.drawRect({0, 0, 10, 10}); builder.restore(); auto display_list = builder.Build(); @@ -1553,7 +1553,7 @@ TEST(DisplayList, SaveLayerFalseSupportsGroupOpacityWithChildSrcBlend) { TEST(DisplayList, SaveLayerTrueSupportsGroupOpacityWithChildSrcBlend) { DisplayListBuilder builder; builder.saveLayer(nullptr, true); - builder.setBlendMode(SkBlendMode::kSrc); + builder.setBlendMode(DlBlendMode::kSrc); builder.drawRect({0, 0, 10, 10}); builder.restore(); auto display_list = builder.Build(); @@ -1721,9 +1721,9 @@ TEST(DisplayList, SaveLayerSrcBlendPreventsOpacityOptimization) { DisplayListBuilder builder; builder.setColor(SkColorSetARGB(127, 255, 255, 255)); - builder.setBlendMode(SkBlendMode::kSrc); + builder.setBlendMode(DlBlendMode::kSrc); builder.saveLayer(nullptr, true); - builder.setBlendMode(SkBlendMode::kSrcOver); + builder.setBlendMode(DlBlendMode::kSrcOver); builder.drawRect({10, 10, 20, 20}); builder.restore(); @@ -1769,7 +1769,7 @@ TEST(DisplayList, SaveLayerSrcBlendOnChildPreventsOpacityOptimization) { DisplayListBuilder builder; builder.setColor(SkColorSetARGB(127, 255, 255, 255)); builder.saveLayer(nullptr, true); - builder.setBlendMode(SkBlendMode::kSrc); + builder.setBlendMode(DlBlendMode::kSrc); builder.drawRect({10, 10, 20, 20}); builder.restore(); diff --git a/display_list/display_list_utils.cc b/display_list/display_list_utils.cc index e05485ee6ab43..6cd7ef75d80d3 100644 --- a/display_list/display_list_utils.cc +++ b/display_list/display_list_utils.cc @@ -5,8 +5,10 @@ #include "flutter/display_list/display_list_utils.h" #include +#include #include +#include "flutter/display_list/display_list_blend_mode.h" #include "flutter/display_list/display_list_canvas_dispatcher.h" #include "flutter/fml/logging.h" #include "third_party/skia/include/core/SkMaskFilter.h" @@ -67,8 +69,8 @@ void SkPaintDispatchHelper::setColor(SkColor color) { paint_.setAlphaf(paint_.getAlphaf() * opacity()); } } -void SkPaintDispatchHelper::setBlendMode(SkBlendMode mode) { - paint_.setBlendMode(mode); +void SkPaintDispatchHelper::setBlendMode(DlBlendMode mode) { + paint_.setBlendMode(ToSk(mode)); } void SkPaintDispatchHelper::setBlender(sk_sp blender) { paint_.setBlender(blender); @@ -256,13 +258,18 @@ void DisplayListBoundsCalculator::setStrokeWidth(SkScalar width) { void DisplayListBoundsCalculator::setStrokeMiter(SkScalar limit) { miter_limit_ = std::max(limit, 1.0f); } -void DisplayListBoundsCalculator::setBlendMode(SkBlendMode mode) { +void DisplayListBoundsCalculator::setBlendMode(DlBlendMode mode) { blend_mode_ = mode; } void DisplayListBoundsCalculator::setBlender(sk_sp blender) { SkPaint paint; paint.setBlender(std::move(blender)); - blend_mode_ = paint.asBlendMode(); + auto blend_mode = paint.asBlendMode(); + if (blend_mode.has_value()) { + blend_mode_ = ToDl(blend_mode.value()); + } else { + blend_mode_ = std::nullopt; + } } void DisplayListBoundsCalculator::setImageFilter(sk_sp filter) { image_filter_ = std::move(filter); @@ -371,7 +378,7 @@ void DisplayListBoundsCalculator::restore() { void DisplayListBoundsCalculator::drawPaint() { AccumulateUnbounded(); } -void DisplayListBoundsCalculator::drawColor(SkColor color, SkBlendMode mode) { +void DisplayListBoundsCalculator::drawColor(SkColor color, DlBlendMode mode) { AccumulateUnbounded(); } void DisplayListBoundsCalculator::drawLine(const SkPoint& p0, @@ -443,7 +450,7 @@ void DisplayListBoundsCalculator::drawPoints(SkCanvas::PointMode mode, } } void DisplayListBoundsCalculator::drawVertices(const sk_sp vertices, - SkBlendMode mode) { + DlBlendMode mode) { AccumulateOpBounds(vertices->bounds(), kDrawVerticesFlags); } void DisplayListBoundsCalculator::drawImage(const sk_sp image, @@ -495,7 +502,7 @@ void DisplayListBoundsCalculator::drawAtlas(const sk_sp atlas, const SkRect tex[], const SkColor colors[], int count, - SkBlendMode mode, + DlBlendMode mode, const SkSamplingOptions& sampling, const SkRect* cullRect, bool render_with_attributes) { @@ -674,43 +681,43 @@ bool DisplayListBoundsCalculator::paint_nops_on_transparency() { // destination pixel. // Mathematically, any time in the following equations where // the result is not d assuming source is 0 - case SkBlendMode::kClear: // r = 0 - case SkBlendMode::kSrc: // r = s - case SkBlendMode::kSrcIn: // r = s * da - case SkBlendMode::kDstIn: // r = d * sa - case SkBlendMode::kSrcOut: // r = s * (1-da) - case SkBlendMode::kDstATop: // r = d*sa + s*(1-da) - case SkBlendMode::kModulate: // r = s*d + case DlBlendMode::kClear: // r = 0 + case DlBlendMode::kSrc: // r = s + case DlBlendMode::kSrcIn: // r = s * da + case DlBlendMode::kDstIn: // r = d * sa + case DlBlendMode::kSrcOut: // r = s * (1-da) + case DlBlendMode::kDstATop: // r = d*sa + s*(1-da) + case DlBlendMode::kModulate: // r = s*d return false; break; // And in these equations, the result must be d if the // source is 0 - case SkBlendMode::kDst: // r = d - case SkBlendMode::kSrcOver: // r = s + (1-sa)*d - case SkBlendMode::kDstOver: // r = d + (1-da)*s - case SkBlendMode::kDstOut: // r = d * (1-sa) - case SkBlendMode::kSrcATop: // r = s*da + d*(1-sa) - case SkBlendMode::kXor: // r = s*(1-da) + d*(1-sa) - case SkBlendMode::kPlus: // r = min(s + d, 1) - case SkBlendMode::kScreen: // r = s + d - s*d - case SkBlendMode::kOverlay: // multiply or screen, depending on dest - case SkBlendMode::kDarken: // rc = s + d - max(s*da, d*sa), + case DlBlendMode::kDst: // r = d + case DlBlendMode::kSrcOver: // r = s + (1-sa)*d + case DlBlendMode::kDstOver: // r = d + (1-da)*s + case DlBlendMode::kDstOut: // r = d * (1-sa) + case DlBlendMode::kSrcATop: // r = s*da + d*(1-sa) + case DlBlendMode::kXor: // r = s*(1-da) + d*(1-sa) + case DlBlendMode::kPlus: // r = min(s + d, 1) + case DlBlendMode::kScreen: // r = s + d - s*d + case DlBlendMode::kOverlay: // multiply or screen, depending on dest + case DlBlendMode::kDarken: // rc = s + d - max(s*da, d*sa), // ra = kSrcOver - case SkBlendMode::kLighten: // rc = s + d - min(s*da, d*sa), + case DlBlendMode::kLighten: // rc = s + d - min(s*da, d*sa), // ra = kSrcOver - case SkBlendMode::kColorDodge: // brighten destination to reflect source - case SkBlendMode::kColorBurn: // darken destination to reflect source - case SkBlendMode::kHardLight: // multiply or screen, depending on source - case SkBlendMode::kSoftLight: // lighten or darken, depending on source - case SkBlendMode::kDifference: // rc = s + d - 2*(min(s*da, d*sa)), + case DlBlendMode::kColorDodge: // brighten destination to reflect source + case DlBlendMode::kColorBurn: // darken destination to reflect source + case DlBlendMode::kHardLight: // multiply or screen, depending on source + case DlBlendMode::kSoftLight: // lighten or darken, depending on source + case DlBlendMode::kDifference: // rc = s + d - 2*(min(s*da, d*sa)), // ra = kSrcOver - case SkBlendMode::kExclusion: // rc = s + d - two(s*d), ra = kSrcOver - case SkBlendMode::kMultiply: // r = s*(1-da) + d*(1-sa) + s*d - case SkBlendMode::kHue: // ra = kSrcOver - case SkBlendMode::kSaturation: // ra = kSrcOver - case SkBlendMode::kColor: // ra = kSrcOver - case SkBlendMode::kLuminosity: // ra = kSrcOver + case DlBlendMode::kExclusion: // rc = s + d - two(s*d), ra = kSrcOver + case DlBlendMode::kMultiply: // r = s*(1-da) + d*(1-sa) + s*d + case DlBlendMode::kHue: // ra = kSrcOver + case DlBlendMode::kSaturation: // ra = kSrcOver + case DlBlendMode::kColor: // ra = kSrcOver + case DlBlendMode::kLuminosity: // ra = kSrcOver return true; break; } diff --git a/display_list/display_list_utils.h b/display_list/display_list_utils.h index 4361bf67dd1b7..7646c56e93500 100644 --- a/display_list/display_list_utils.h +++ b/display_list/display_list_utils.h @@ -8,6 +8,7 @@ #include #include "flutter/display_list/display_list.h" +#include "flutter/display_list/display_list_blend_mode.h" #include "flutter/display_list/display_list_builder.h" #include "flutter/fml/logging.h" #include "flutter/fml/macros.h" @@ -52,7 +53,7 @@ class IgnoreAttributeDispatchHelper : public virtual Dispatcher { void setStrokeWidth(SkScalar width) override {} void setStrokeMiter(SkScalar limit) override {} void setColor(SkColor color) override {} - void setBlendMode(SkBlendMode mode) override {} + void setBlendMode(DlBlendMode mode) override {} void setBlender(sk_sp blender) override {} void setColorSource(const DlColorSource* source) override {} void setImageFilter(sk_sp filter) override {} @@ -97,7 +98,7 @@ class IgnoreDrawDispatchHelper : public virtual Dispatcher { void saveLayer(const SkRect* bounds, const SaveLayerOptions options) override {} void restore() override {} - void drawColor(SkColor color, SkBlendMode mode) override {} + void drawColor(SkColor color, DlBlendMode mode) override {} void drawPaint() override {} void drawLine(const SkPoint& p0, const SkPoint& p1) override {} void drawRect(const SkRect& rect) override {} @@ -114,7 +115,7 @@ class IgnoreDrawDispatchHelper : public virtual Dispatcher { uint32_t count, const SkPoint points[]) override {} void drawVertices(const sk_sp vertices, - SkBlendMode mode) override {} + DlBlendMode mode) override {} void drawImage(const sk_sp image, const SkPoint point, const SkSamplingOptions& sampling, @@ -140,7 +141,7 @@ class IgnoreDrawDispatchHelper : public virtual Dispatcher { const SkRect tex[], const SkColor colors[], int count, - SkBlendMode mode, + DlBlendMode mode, const SkSamplingOptions& sampling, const SkRect* cull_rect, bool render_with_attributes) override {} @@ -181,7 +182,7 @@ class SkPaintDispatchHelper : public virtual Dispatcher { void setColorSource(const DlColorSource* source) override; void setColorFilter(const DlColorFilter* filter) override; void setInvertColors(bool invert) override; - void setBlendMode(SkBlendMode mode) override; + void setBlendMode(DlBlendMode mode) override; void setBlender(sk_sp blender) override; void setPathEffect(sk_sp effect) override; void setMaskFilter(const DlMaskFilter* filter) override; @@ -398,7 +399,7 @@ class DisplayListBoundsCalculator final void setStyle(SkPaint::Style style) override; void setStrokeWidth(SkScalar width) override; void setStrokeMiter(SkScalar limit) override; - void setBlendMode(SkBlendMode mode) override; + void setBlendMode(DlBlendMode mode) override; void setBlender(sk_sp blender) override; void setImageFilter(sk_sp filter) override; void setColorFilter(const DlColorFilter* filter) override; @@ -410,7 +411,7 @@ class DisplayListBoundsCalculator final void restore() override; void drawPaint() override; - void drawColor(SkColor color, SkBlendMode mode) override; + void drawColor(SkColor color, DlBlendMode mode) override; void drawLine(const SkPoint& p0, const SkPoint& p1) override; void drawRect(const SkRect& rect) override; void drawOval(const SkRect& bounds) override; @@ -426,7 +427,7 @@ class DisplayListBoundsCalculator final uint32_t count, const SkPoint pts[]) override; void drawVertices(const sk_sp vertices, - SkBlendMode mode) override; + DlBlendMode mode) override; void drawImage(const sk_sp image, const SkPoint point, const SkSamplingOptions& sampling, @@ -452,7 +453,7 @@ class DisplayListBoundsCalculator final const SkRect tex[], const SkColor colors[], int count, - SkBlendMode mode, + DlBlendMode mode, const SkSamplingOptions& sampling, const SkRect* cullRect, bool render_with_attributes) override; @@ -570,7 +571,7 @@ class DisplayListBoundsCalculator final static constexpr SkScalar kMinStrokeWidth = 0.01; - std::optional blend_mode_ = SkBlendMode::kSrcOver; + std::optional blend_mode_ = DlBlendMode::kSrcOver; std::shared_ptr color_filter_; SkScalar half_stroke_width_ = kMinStrokeWidth; diff --git a/flow/layers/color_filter_layer.cc b/flow/layers/color_filter_layer.cc index bc58805817488..5624c063cc068 100644 --- a/flow/layers/color_filter_layer.cc +++ b/flow/layers/color_filter_layer.cc @@ -7,7 +7,7 @@ namespace flutter { ColorFilterLayer::ColorFilterLayer(sk_sp filter) - : filter_(std::move(filter)) {} + : filter_(std::move(filter)), render_count_(1) {} void ColorFilterLayer::Diff(DiffContext* context, const Layer* old_layer) { DiffContext::AutoSubtreeRestore subtree(context); @@ -29,12 +29,32 @@ void ColorFilterLayer::Preroll(PrerollContext* context, Layer::AutoPrerollSaveLayerState save = Layer::AutoPrerollSaveLayerState::Create(context); ContainerLayer::Preroll(context, matrix); + + if (render_count_ >= kMinimumRendersBeforeCachingFilterLayer) { + TryToPrepareRasterCache(context, this, matrix); + } else { + render_count_++; + TryToPrepareRasterCache(context, GetCacheableChild(), matrix); + } } void ColorFilterLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "ColorFilterLayer::Paint"); FML_DCHECK(needs_painting(context)); + if (context.raster_cache) { + if (context.raster_cache->Draw(this, *context.leaf_nodes_canvas)) { + return; + } + SkPaint paint; + paint.setColorFilter(filter_); + + if (context.raster_cache->Draw(GetCacheableChild(), + *context.leaf_nodes_canvas, &paint)) { + return; + } + } + SkPaint paint; paint.setColorFilter(filter_); diff --git a/flow/layers/color_filter_layer.h b/flow/layers/color_filter_layer.h index e19d69377a5d5..51432cea6a758 100644 --- a/flow/layers/color_filter_layer.h +++ b/flow/layers/color_filter_layer.h @@ -10,7 +10,7 @@ namespace flutter { -class ColorFilterLayer : public ContainerLayer { +class ColorFilterLayer : public MergedContainerLayer { public: explicit ColorFilterLayer(sk_sp filter); @@ -23,6 +23,9 @@ class ColorFilterLayer : public ContainerLayer { private: sk_sp filter_; + static constexpr int kMinimumRendersBeforeCachingFilterLayer = 3; + int render_count_; + FML_DISALLOW_COPY_AND_ASSIGN(ColorFilterLayer); }; diff --git a/flow/layers/color_filter_layer_unittests.cc b/flow/layers/color_filter_layer_unittests.cc index a48ca56409619..fe29ceac3a90b 100644 --- a/flow/layers/color_filter_layer_unittests.cc +++ b/flow/layers/color_filter_layer_unittests.cc @@ -213,5 +213,70 @@ TEST_F(ColorFilterLayerTest, Readback) { EXPECT_FALSE(preroll_context()->surface_needs_readback); } +TEST_F(ColorFilterLayerTest, ChildIsCached) { + auto layer_filter = + SkColorMatrixFilter::MakeLightingFilter(SK_ColorGREEN, SK_ColorYELLOW); + auto initial_transform = SkMatrix::Translate(50.0, 25.5); + auto other_transform = SkMatrix::Scale(1.0, 2.0); + const SkPath child_path = SkPath().addRect(SkRect::MakeWH(5.0f, 5.0f)); + auto mock_layer = std::make_shared(child_path); + auto layer = std::make_shared(layer_filter); + layer->Add(mock_layer); + + SkMatrix cache_ctm = initial_transform; + SkCanvas cache_canvas; + cache_canvas.setMatrix(cache_ctm); + SkCanvas other_canvas; + other_canvas.setMatrix(other_transform); + + use_mock_raster_cache(); + + EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0); + EXPECT_FALSE(raster_cache()->Draw(mock_layer.get(), other_canvas)); + EXPECT_FALSE(raster_cache()->Draw(mock_layer.get(), cache_canvas)); + + layer->Preroll(preroll_context(), initial_transform); + + EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)1); + EXPECT_FALSE(raster_cache()->Draw(mock_layer.get(), other_canvas)); + EXPECT_TRUE(raster_cache()->Draw(mock_layer.get(), cache_canvas)); +} + +TEST_F(ColorFilterLayerTest, ChildrenNotCached) { + auto layer_filter = + SkColorMatrixFilter::MakeLightingFilter(SK_ColorGREEN, SK_ColorYELLOW); + auto initial_transform = SkMatrix::Translate(50.0, 25.5); + auto other_transform = SkMatrix::Scale(1.0, 2.0); + const SkPath child_path1 = SkPath().addRect(SkRect::MakeWH(5.0f, 5.0f)); + const SkPath child_path2 = SkPath().addRect(SkRect::MakeWH(5.0f, 5.0f)); + auto mock_layer1 = std::make_shared(child_path1); + auto mock_layer2 = std::make_shared(child_path2); + auto layer = std::make_shared(layer_filter); + layer->Add(mock_layer1); + layer->Add(mock_layer2); + + SkMatrix cache_ctm = initial_transform; + SkCanvas cache_canvas; + cache_canvas.setMatrix(cache_ctm); + SkCanvas other_canvas; + other_canvas.setMatrix(other_transform); + + use_mock_raster_cache(); + + EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0); + EXPECT_FALSE(raster_cache()->Draw(mock_layer1.get(), other_canvas)); + EXPECT_FALSE(raster_cache()->Draw(mock_layer1.get(), cache_canvas)); + EXPECT_FALSE(raster_cache()->Draw(mock_layer2.get(), other_canvas)); + EXPECT_FALSE(raster_cache()->Draw(mock_layer2.get(), cache_canvas)); + + layer->Preroll(preroll_context(), initial_transform); + + EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)1); + EXPECT_FALSE(raster_cache()->Draw(mock_layer1.get(), other_canvas)); + EXPECT_FALSE(raster_cache()->Draw(mock_layer1.get(), cache_canvas)); + EXPECT_FALSE(raster_cache()->Draw(mock_layer2.get(), other_canvas)); + EXPECT_FALSE(raster_cache()->Draw(mock_layer2.get(), cache_canvas)); +} + } // namespace testing } // namespace flutter diff --git a/lib/ui/painting/canvas.cc b/lib/ui/painting/canvas.cc index 4e88270e001d6..e726de0cdcd4b 100644 --- a/lib/ui/painting/canvas.cc +++ b/lib/ui/painting/canvas.cc @@ -7,6 +7,7 @@ #include +#include "flutter/display_list/display_list_blend_mode.h" #include "flutter/display_list/display_list_builder.h" #include "flutter/display_list/display_list_canvas_dispatcher.h" #include "flutter/flow/layers/physical_shape_layer.h" @@ -254,11 +255,11 @@ void Canvas::clipPath(const CanvasPath* path, bool doAntiAlias) { } } -void Canvas::drawColor(SkColor color, SkBlendMode blend_mode) { +void Canvas::drawColor(SkColor color, DlBlendMode blend_mode) { if (display_list_recorder_) { builder()->drawColor(color, blend_mode); } else if (canvas_) { - canvas_->drawColor(color, blend_mode); + canvas_->drawColor(color, ToSk(blend_mode)); } } @@ -572,7 +573,7 @@ void Canvas::drawPoints(const Paint& paint, } void Canvas::drawVertices(const Vertices* vertices, - SkBlendMode blend_mode, + DlBlendMode blend_mode, const Paint& paint, const PaintData& paint_data) { if (!vertices) { @@ -586,7 +587,7 @@ void Canvas::drawVertices(const Vertices* vertices, builder()->drawVertices(vertices->vertices(), blend_mode); } else if (canvas_) { SkPaint sk_paint; - canvas_->drawVertices(vertices->vertices(), blend_mode, + canvas_->drawVertices(vertices->vertices(), ToSk(blend_mode), *paint.paint(sk_paint)); } } @@ -598,7 +599,7 @@ void Canvas::drawAtlas(const Paint& paint, const tonic::Float32List& transforms, const tonic::Float32List& rects, const tonic::Int32List& colors, - SkBlendMode blend_mode, + DlBlendMode blend_mode, const tonic::Float32List& cull_rect) { if (!atlas) { Dart_ThrowException( @@ -628,13 +629,14 @@ void Canvas::drawAtlas(const Paint& paint, with_attributes); } else if (canvas_) { SkPaint sk_paint; - canvas_->drawAtlas( - skImage.get(), reinterpret_cast(transforms.data()), - reinterpret_cast(rects.data()), - reinterpret_cast(colors.data()), - rects.num_elements() / 4, // SkRect have four floats. - blend_mode, sampling, reinterpret_cast(cull_rect.data()), - paint.paint(sk_paint)); + canvas_->drawAtlas(skImage.get(), + reinterpret_cast(transforms.data()), + reinterpret_cast(rects.data()), + reinterpret_cast(colors.data()), + rects.num_elements() / 4, // SkRect have four floats. + ToSk(blend_mode), sampling, + reinterpret_cast(cull_rect.data()), + paint.paint(sk_paint)); } } diff --git a/lib/ui/painting/canvas.h b/lib/ui/painting/canvas.h index 8e8fd107f9377..1d3c4e3bce19b 100644 --- a/lib/ui/painting/canvas.h +++ b/lib/ui/painting/canvas.h @@ -5,6 +5,7 @@ #ifndef FLUTTER_LIB_UI_PAINTING_CANVAS_H_ #define FLUTTER_LIB_UI_PAINTING_CANVAS_H_ +#include "flutter/display_list/display_list_blend_mode.h" #include "flutter/lib/ui/dart_wrapper.h" #include "flutter/lib/ui/painting/paint.h" #include "flutter/lib/ui/painting/path.h" @@ -62,7 +63,7 @@ class Canvas : public RefCountedDartWrappable, DisplayListOpFlags { void clipRRect(const RRect& rrect, bool doAntiAlias = true); void clipPath(const CanvasPath* path, bool doAntiAlias = true); - void drawColor(SkColor color, SkBlendMode blend_mode); + void drawColor(SkColor color, DlBlendMode blend_mode); void drawLine(double x1, double y1, double x2, @@ -149,7 +150,7 @@ class Canvas : public RefCountedDartWrappable, DisplayListOpFlags { const tonic::Float32List& points); void drawVertices(const Vertices* vertices, - SkBlendMode blend_mode, + DlBlendMode blend_mode, const Paint& paint, const PaintData& paint_data); @@ -160,7 +161,7 @@ class Canvas : public RefCountedDartWrappable, DisplayListOpFlags { const tonic::Float32List& transforms, const tonic::Float32List& rects, const tonic::Int32List& colors, - SkBlendMode blend_mode, + DlBlendMode blend_mode, const tonic::Float32List& cull_rect); void drawShadow(const CanvasPath* path, diff --git a/lib/ui/painting/paint.cc b/lib/ui/painting/paint.cc index 4aa339bf5ea13..c68d6523591d3 100644 --- a/lib/ui/painting/paint.cc +++ b/lib/ui/painting/paint.cc @@ -262,7 +262,7 @@ bool Paint::sync_to(DisplayListBuilder* builder, if (flags.applies_blend()) { uint32_t encoded_blend_mode = uint_data[kBlendModeIndex]; uint32_t blend_mode = encoded_blend_mode ^ kBlendModeDefault; - builder->setBlendMode(static_cast(blend_mode)); + builder->setBlendMode(static_cast(blend_mode)); } if (flags.applies_style()) { diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java b/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java index c8326a387e777..eeb55d2b99528 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java @@ -205,11 +205,19 @@ public long createForTextureLayer( layoutParams.topMargin = physicalTop; layoutParams.leftMargin = physicalLeft; wrapperView.setLayoutParams(layoutParams); - wrapperView.setLayoutDirection(request.direction); - wrapperView.addView(platformView.getView()); + + final View view = platformView.getView(); + if (view == null) { + throw new IllegalStateException( + "PlatformView#getView() returned null, but an Android view reference was expected."); + } else if (view.getParent() != null) { + throw new IllegalStateException( + "The Android view returned from PlatformView#getView() was already added to a parent view."); + } + wrapperView.addView(view); wrapperView.setOnDescendantFocusChangeListener( - (view, hasFocus) -> { + (v, hasFocus) -> { if (hasFocus) { platformViewsChannel.invokeViewFocused(viewId); } else if (textInputPlugin != null) { @@ -226,16 +234,13 @@ public long createForTextureLayer( public void dispose(int viewId) { final PlatformView platformView = platformViews.get(viewId); if (platformView != null) { - final ViewGroup pvParent = (ViewGroup) platformView.getView().getParent(); - if (pvParent != null) { - pvParent.removeView(platformView.getView()); - } platformViews.remove(viewId); platformView.dispose(); } // The platform view is displayed using a TextureLayer. final PlatformViewWrapper viewWrapper = viewWrappers.get(viewId); if (viewWrapper != null) { + viewWrapper.removeAllViews(); viewWrapper.release(); viewWrapper.unsetOnDescendantFocusChangeListener(); @@ -251,6 +256,7 @@ public void dispose(int viewId) { // https://github.com/flutter/flutter/issues/96679 final FlutterMutatorView parentView = platformViewParent.get(viewId); if (parentView != null) { + parentView.removeAllViews(); parentView.unsetOnDescendantFocusChangeListener(); final ViewGroup mutatorViewParent = (ViewGroup) parentView.getParent(); @@ -322,7 +328,12 @@ public void onTouch(@NonNull PlatformViewsChannel.PlatformViewTouch touch) { ensureValidAndroidVersion(Build.VERSION_CODES.KITKAT_WATCH); final float density = context.getResources().getDisplayMetrics().density; final MotionEvent event = toMotionEvent(density, touch); - platformView.getView().dispatchTouchEvent(event); + final View view = platformView.getView(); + if (view == null) { + Log.e(TAG, "Sending touch to a null view with id: " + viewId); + return; + } + view.dispatchTouchEvent(event); } @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) @@ -342,7 +353,12 @@ public void setDirection(int viewId, int direction) { return; } ensureValidAndroidVersion(Build.VERSION_CODES.KITKAT_WATCH); - platformViews.get(viewId).getView().setLayoutDirection(direction); + final View view = platformView.getView(); + if (view == null) { + Log.e(TAG, "Setting direction to a null view with id: " + viewId); + return; + } + view.setLayoutDirection(direction); } @Override @@ -352,7 +368,12 @@ public void clearFocus(int viewId) { Log.e(TAG, "Clearing focus on an unknown view with id: " + viewId); return; } - platformView.getView().clearFocus(); + final View view = platformView.getView(); + if (view == null) { + Log.e(TAG, "Clearing focus on a null view with id: " + viewId); + return; + } + view.clearFocus(); } private void ensureValidAndroidVersion(int minSdkVersion) { diff --git a/shell/platform/android/test/io/flutter/plugin/platform/PlatformViewsControllerTest.java b/shell/platform/android/test/io/flutter/plugin/platform/PlatformViewsControllerTest.java index 0398f88003630..37a0f588ed9b8 100644 --- a/shell/platform/android/test/io/flutter/plugin/platform/PlatformViewsControllerTest.java +++ b/shell/platform/android/test/io/flutter/plugin/platform/PlatformViewsControllerTest.java @@ -167,6 +167,35 @@ public void createPlatformViewMessage__throwsIfViewIsNull() { FlutterJNI jni = new FlutterJNI(); attach(jni, platformViewsController); + // Simulate create call from the framework. + createPlatformView( + jni, platformViewsController, platformViewId, "testType", /* hybrid=*/ false); + assertEquals(ShadowFlutterJNI.getResponses().size(), 1); + + assertThrows( + IllegalStateException.class, + () -> { + platformViewsController.initializePlatformViewIfNeeded(platformViewId); + }); + } + + @Test + @Config(shadows = {ShadowFlutterJNI.class, ShadowPlatformTaskQueue.class}) + public void createHybridPlatformViewMessage__throwsIfViewIsNull() { + PlatformViewsController platformViewsController = new PlatformViewsController(); + + int platformViewId = 0; + assertNull(platformViewsController.getPlatformViewById(platformViewId)); + + PlatformViewFactory viewFactory = mock(PlatformViewFactory.class); + PlatformView platformView = mock(PlatformView.class); + when(platformView.getView()).thenReturn(null); + when(viewFactory.create(any(), eq(platformViewId), any())).thenReturn(platformView); + platformViewsController.getRegistry().registerViewFactory("testType", viewFactory); + + FlutterJNI jni = new FlutterJNI(); + attach(jni, platformViewsController); + // Simulate create call from the framework. createPlatformView(jni, platformViewsController, platformViewId, "testType", /* hybrid=*/ true); assertEquals(ShadowFlutterJNI.getResponses().size(), 1); @@ -197,6 +226,37 @@ public void createPlatformViewMessage__throwsIfViewHasParent() { FlutterJNI jni = new FlutterJNI(); attach(jni, platformViewsController); + // Simulate create call from the framework. + createPlatformView( + jni, platformViewsController, platformViewId, "testType", /* hybrid=*/ false); + assertEquals(ShadowFlutterJNI.getResponses().size(), 1); + + assertThrows( + IllegalStateException.class, + () -> { + platformViewsController.initializePlatformViewIfNeeded(platformViewId); + }); + } + + @Test + @Config(shadows = {ShadowFlutterJNI.class, ShadowPlatformTaskQueue.class}) + public void createHybridPlatformViewMessage__throwsIfViewHasParent() { + PlatformViewsController platformViewsController = new PlatformViewsController(); + + int platformViewId = 0; + assertNull(platformViewsController.getPlatformViewById(platformViewId)); + + PlatformViewFactory viewFactory = mock(PlatformViewFactory.class); + PlatformView platformView = mock(PlatformView.class); + View androidView = mock(View.class); + when(androidView.getParent()).thenReturn(mock(ViewParent.class)); + when(platformView.getView()).thenReturn(androidView); + when(viewFactory.create(any(), eq(platformViewId), any())).thenReturn(platformView); + platformViewsController.getRegistry().registerViewFactory("testType", viewFactory); + + FlutterJNI jni = new FlutterJNI(); + attach(jni, platformViewsController); + // Simulate create call from the framework. createPlatformView(jni, platformViewsController, platformViewId, "testType", /* hybrid=*/ true); assertEquals(ShadowFlutterJNI.getResponses().size(), 1); @@ -283,6 +343,38 @@ public void disposeAndroidView__hybridComposition() { verify(platformView, times(1)).dispose(); } + @Test + @Config(shadows = {ShadowFlutterJNI.class, ShadowPlatformTaskQueue.class}) + public void disposeNullAndroidView() { + PlatformViewsController platformViewsController = new PlatformViewsController(); + + int platformViewId = 0; + assertNull(platformViewsController.getPlatformViewById(platformViewId)); + + PlatformViewFactory viewFactory = mock(PlatformViewFactory.class); + PlatformView platformView = mock(PlatformView.class); + + Context context = RuntimeEnvironment.application.getApplicationContext(); + View androidView = new View(context); + when(platformView.getView()).thenReturn(androidView); + when(viewFactory.create(any(), eq(platformViewId), any())).thenReturn(platformView); + platformViewsController.getRegistry().registerViewFactory("testType", viewFactory); + + FlutterJNI jni = new FlutterJNI(); + attach(jni, platformViewsController); + + // Simulate create call from the framework. + createPlatformView( + jni, platformViewsController, platformViewId, "testType", /* hybrid=*/ false); + platformViewsController.initializePlatformViewIfNeeded(platformViewId); + + when(platformView.getView()).thenReturn(null); + + // Simulate dispose call from the framework. + disposePlatformView(jni, platformViewsController, platformViewId); + verify(platformView, times(1)).dispose(); + } + @Test @Config( shadows = {