From 3df47dba60e99e1314deb3ab320dd2d8448243dd Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Mon, 6 Mar 2023 14:05:20 -0500 Subject: [PATCH 1/9] Roll Fuchsia Linux SDK from 4iq5VNjEcZIlrUtDK... to kQnUhe74CH6d0V1vj... (#40090) Roll Fuchsia Linux SDK from 4iq5VNjEcZIlrUtDK... to kQnUhe74CH6d0V1vj... --- DEPS | 2 +- ci/licenses_golden/licenses_fuchsia | 32 ++++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/DEPS b/DEPS index 69ad7a9a6f98c..8787180931125 100644 --- a/DEPS +++ b/DEPS @@ -839,7 +839,7 @@ deps = { 'packages': [ { 'package': 'fuchsia/sdk/core/linux-amd64', - 'version': '4iq5VNjEcZIlrUtDK0Ahy0k-Muc2zcgc4Erx5T86isAC' + 'version': 'kQnUhe74CH6d0V1vjnYMfd4hrpuJGwMFyXXqbbXbApsC' } ], 'condition': 'host_os == "linux" and not download_fuchsia_sdk', diff --git a/ci/licenses_golden/licenses_fuchsia b/ci/licenses_golden/licenses_fuchsia index a9d909b9f13dd..1d0be3a9d5150 100644 --- a/ci/licenses_golden/licenses_fuchsia +++ b/ci/licenses_golden/licenses_fuchsia @@ -1,4 +1,4 @@ -Signature: 68989a114a1be997c1ccb2c526f19108 +Signature: a5f9c24aca8e0acc99f8e09b33c0a342 ==================================================================================================== LIBRARY: fuchsia_sdk @@ -414,11 +414,21 @@ FILE: ../../../fuchsia/sdk/linux/arch/x64/sysroot/lib/librt.so FILE: ../../../fuchsia/sdk/linux/arch/x64/sysroot/lib/libzircon.so FILE: ../../../fuchsia/sdk/linux/dart/zircon/lib/src/fakes/handle_disposition.dart FILE: ../../../fuchsia/sdk/linux/data/config/symbol-index/config.json +FILE: ../../../fuchsia/sdk/linux/pkg/async-default/async-default.ifs +FILE: ../../../fuchsia/sdk/linux/pkg/fdio/fdio.ifs FILE: ../../../fuchsia/sdk/linux/pkg/inspect/inspect.json +FILE: ../../../fuchsia/sdk/linux/pkg/memfs/memfs.ifs +FILE: ../../../fuchsia/sdk/linux/pkg/svc/svc.ifs FILE: ../../../fuchsia/sdk/linux/pkg/sys/component/realm_builder_shard_sdk.json FILE: ../../../fuchsia/sdk/linux/pkg/syslog/client.shard.cmx +FILE: ../../../fuchsia/sdk/linux/pkg/syslog/syslog.ifs FILE: ../../../fuchsia/sdk/linux/pkg/syslog/syslog.json +FILE: ../../../fuchsia/sdk/linux/pkg/sysroot/libc.ifs +FILE: ../../../fuchsia/sdk/linux/pkg/sysroot/zircon.ifs +FILE: ../../../fuchsia/sdk/linux/pkg/trace-engine/trace-engine.ifs +FILE: ../../../fuchsia/sdk/linux/pkg/trace-provider-so/trace-provider-so.ifs FILE: ../../../fuchsia/sdk/linux/pkg/trace/trace.json +FILE: ../../../fuchsia/sdk/linux/pkg/vulkan/vulkan.ifs FILE: ../../../fuchsia/sdk/linux/pkg/vulkan/vulkan.json FILE: ../../../fuchsia/sdk/linux/pkg/vulkan_layers/data/vulkan/explicit_layer.d/VkLayer_image_pipe_swapchain.json FILE: ../../../fuchsia/sdk/linux/pkg/vulkan_layers/data/vulkan/explicit_layer.d/VkLayer_khronos_validation.json @@ -2160,11 +2170,21 @@ FILE: ../../../fuchsia/sdk/linux/arch/x64/sysroot/lib/librt.so FILE: ../../../fuchsia/sdk/linux/arch/x64/sysroot/lib/libzircon.so FILE: ../../../fuchsia/sdk/linux/dart/zircon/lib/src/fakes/handle_disposition.dart FILE: ../../../fuchsia/sdk/linux/data/config/symbol-index/config.json +FILE: ../../../fuchsia/sdk/linux/pkg/async-default/async-default.ifs +FILE: ../../../fuchsia/sdk/linux/pkg/fdio/fdio.ifs FILE: ../../../fuchsia/sdk/linux/pkg/inspect/inspect.json +FILE: ../../../fuchsia/sdk/linux/pkg/memfs/memfs.ifs +FILE: ../../../fuchsia/sdk/linux/pkg/svc/svc.ifs FILE: ../../../fuchsia/sdk/linux/pkg/sys/component/realm_builder_shard_sdk.json FILE: ../../../fuchsia/sdk/linux/pkg/syslog/client.shard.cmx +FILE: ../../../fuchsia/sdk/linux/pkg/syslog/syslog.ifs FILE: ../../../fuchsia/sdk/linux/pkg/syslog/syslog.json +FILE: ../../../fuchsia/sdk/linux/pkg/sysroot/libc.ifs +FILE: ../../../fuchsia/sdk/linux/pkg/sysroot/zircon.ifs +FILE: ../../../fuchsia/sdk/linux/pkg/trace-engine/trace-engine.ifs +FILE: ../../../fuchsia/sdk/linux/pkg/trace-provider-so/trace-provider-so.ifs FILE: ../../../fuchsia/sdk/linux/pkg/trace/trace.json +FILE: ../../../fuchsia/sdk/linux/pkg/vulkan/vulkan.ifs FILE: ../../../fuchsia/sdk/linux/pkg/vulkan/vulkan.json FILE: ../../../fuchsia/sdk/linux/pkg/vulkan_layers/data/vulkan/explicit_layer.d/VkLayer_image_pipe_swapchain.json FILE: ../../../fuchsia/sdk/linux/pkg/vulkan_layers/data/vulkan/explicit_layer.d/VkLayer_khronos_validation.json @@ -4512,11 +4532,21 @@ FILE: ../../../fuchsia/sdk/linux/arch/x64/sysroot/lib/librt.so FILE: ../../../fuchsia/sdk/linux/arch/x64/sysroot/lib/libzircon.so FILE: ../../../fuchsia/sdk/linux/dart/zircon/lib/src/fakes/handle_disposition.dart FILE: ../../../fuchsia/sdk/linux/data/config/symbol-index/config.json +FILE: ../../../fuchsia/sdk/linux/pkg/async-default/async-default.ifs +FILE: ../../../fuchsia/sdk/linux/pkg/fdio/fdio.ifs FILE: ../../../fuchsia/sdk/linux/pkg/inspect/inspect.json +FILE: ../../../fuchsia/sdk/linux/pkg/memfs/memfs.ifs +FILE: ../../../fuchsia/sdk/linux/pkg/svc/svc.ifs FILE: ../../../fuchsia/sdk/linux/pkg/sys/component/realm_builder_shard_sdk.json FILE: ../../../fuchsia/sdk/linux/pkg/syslog/client.shard.cmx +FILE: ../../../fuchsia/sdk/linux/pkg/syslog/syslog.ifs FILE: ../../../fuchsia/sdk/linux/pkg/syslog/syslog.json +FILE: ../../../fuchsia/sdk/linux/pkg/sysroot/libc.ifs +FILE: ../../../fuchsia/sdk/linux/pkg/sysroot/zircon.ifs +FILE: ../../../fuchsia/sdk/linux/pkg/trace-engine/trace-engine.ifs +FILE: ../../../fuchsia/sdk/linux/pkg/trace-provider-so/trace-provider-so.ifs FILE: ../../../fuchsia/sdk/linux/pkg/trace/trace.json +FILE: ../../../fuchsia/sdk/linux/pkg/vulkan/vulkan.ifs FILE: ../../../fuchsia/sdk/linux/pkg/vulkan/vulkan.json FILE: ../../../fuchsia/sdk/linux/pkg/vulkan_layers/data/vulkan/explicit_layer.d/VkLayer_image_pipe_swapchain.json FILE: ../../../fuchsia/sdk/linux/pkg/vulkan_layers/data/vulkan/explicit_layer.d/VkLayer_khronos_validation.json From b053d74305d2268863077195510f5054087276db Mon Sep 17 00:00:00 2001 From: Jim Graham Date: Mon, 6 Mar 2023 11:55:32 -0800 Subject: [PATCH 2/9] Sequester all Skia<->DL interactions into the skia sub-module (#40083) Sequester all Skia<->DL interactions into the skia sub-module --- ci/licenses_golden/excluded_files | 6 +- ci/licenses_golden/licenses_flutter | 26 +- display_list/BUILD.gn | 19 +- display_list/display_list.cc | 40 +- display_list/display_list.h | 51 +- display_list/display_list_attributes.h | 15 +- display_list/display_list_benchmarks.cc | 179 +- display_list/display_list_blend_mode.h | 8 - display_list/display_list_builder.cc | 44 +- display_list/display_list_builder.h | 447 +++-- .../display_list_builder_benchmarks.cc | 26 +- .../display_list_canvas_dispatcher.cc | 305 --- display_list/display_list_color.h | 1 + display_list/display_list_color_filter.cc | 185 +- display_list/display_list_color_filter.h | 46 +- .../display_list_color_filter_unittests.cc | 12 - display_list/display_list_color_source.cc | 16 +- display_list/display_list_color_source.h | 81 +- .../display_list_color_source_unittests.cc | 25 - display_list/display_list_complexity_gl.cc | 26 +- display_list/display_list_complexity_gl.h | 5 +- display_list/display_list_complexity_helper.h | 19 +- display_list/display_list_complexity_metal.cc | 28 +- display_list/display_list_complexity_metal.h | 5 +- .../display_list_complexity_unittests.cc | 91 +- display_list/display_list_enum_unittests.cc | 172 -- display_list/display_list_image_filter.h | 125 +- .../display_list_image_filter_unittests.cc | 29 +- display_list/display_list_mask_filter.h | 16 +- .../display_list_mask_filter_unittests.cc | 12 - display_list/display_list_ops.h | 284 +-- display_list/display_list_paint.h | 30 +- display_list/display_list_path_effect.h | 9 +- .../display_list_path_effect_unittests.cc | 13 - display_list/display_list_sampling_options.h | 36 - display_list/display_list_tile_mode.h | 8 - display_list/display_list_unittests.cc | 1691 +++++++++-------- display_list/display_list_utils.cc | 98 - display_list/display_list_utils.h | 107 +- display_list/display_list_vertices.cc | 7 - display_list/display_list_vertices.h | 11 - .../display_list_vertices_unittests.cc | 4 - display_list/dl_canvas.cc | 23 + display_list/dl_canvas.h | 8 + ...y_list_dispatcher.cc => dl_op_receiver.cc} | 4 +- ...lay_list_dispatcher.h => dl_op_receiver.h} | 7 +- ...unittests.cc => dl_rendering_unittests.cc} | 668 +++++-- display_list/skia/dl_sk_canvas.cc | 67 +- display_list/skia/dl_sk_canvas.h | 2 +- display_list/skia/dl_sk_conversions.cc | 235 +++ display_list/skia/dl_sk_conversions.h | 116 ++ .../skia/dl_sk_conversions_unittests.cc | 260 +++ display_list/skia/dl_sk_dispatcher.cc | 305 +++ .../dl_sk_dispatcher.h} | 22 +- display_list/skia/dl_sk_utils.cc | 102 + display_list/skia/dl_sk_utils.h | 85 + .../dl_sk_utils_unittests.cc} | 3 +- display_list/testing/dl_test_snippets.cc | 836 ++++---- display_list/testing/dl_test_snippets.h | 17 +- display_list/types.h | 1 - .../checkerboard_layertree_unittests.cc | 5 +- flow/layers/clip_path_layer_unittests.cc | 23 +- flow/layers/clip_rect_layer_unittests.cc | 21 +- flow/layers/clip_rrect_layer_unittests.cc | 21 +- flow/layers/display_list_layer_unittests.cc | 75 +- flow/layers/image_filter_layer_unittests.cc | 2 +- flow/layers/opacity_layer_unittests.cc | 19 +- flow/layers/physical_shape_layer.cc | 9 +- flow/layers/physical_shape_layer_unittests.cc | 23 +- flow/layers/shader_mask_layer_unittests.cc | 2 +- flow/raster_cache_unittests.cc | 3 +- flow/testing/diff_context_test.cc | 3 +- .../display_list/display_list_dispatcher.cc | 151 +- .../display_list/display_list_dispatcher.h | 103 +- .../display_list/display_list_unittests.cc | 300 +-- lib/ui/painting/canvas.cc | 142 +- lib/ui/painting/color_filter.cc | 6 +- lib/ui/painting/color_filter.h | 3 - lib/ui/painting/gradient.cc | 16 +- lib/ui/painting/gradient.h | 11 +- lib/ui/painting/image_filter.cc | 27 +- lib/ui/painting/image_filter.h | 5 +- lib/ui/painting/image_shader.cc | 6 +- lib/ui/painting/image_shader.h | 4 +- lib/ui/painting/paint.cc | 205 +- lib/ui/painting/paint.h | 12 +- shell/common/rasterizer.cc | 12 +- shell/common/snapshot_controller_skia.cc | 2 +- testing/display_list_testing.cc | 22 +- testing/display_list_testing.h | 9 +- 90 files changed, 4597 insertions(+), 3764 deletions(-) delete mode 100644 display_list/display_list_canvas_dispatcher.cc delete mode 100644 display_list/display_list_enum_unittests.cc create mode 100644 display_list/dl_canvas.cc rename display_list/{display_list_dispatcher.cc => dl_op_receiver.cc} (64%) rename display_list/{display_list_dispatcher.h => dl_op_receiver.h} (98%) rename display_list/{display_list_canvas_unittests.cc => dl_rendering_unittests.cc} (85%) create mode 100644 display_list/skia/dl_sk_conversions.cc create mode 100644 display_list/skia/dl_sk_conversions.h create mode 100644 display_list/skia/dl_sk_conversions_unittests.cc create mode 100644 display_list/skia/dl_sk_dispatcher.cc rename display_list/{display_list_canvas_dispatcher.h => skia/dl_sk_dispatcher.h} (85%) create mode 100644 display_list/skia/dl_sk_utils.cc create mode 100644 display_list/skia/dl_sk_utils.h rename display_list/{display_list_utils_unittests.cc => skia/dl_sk_utils_unittests.cc} (90%) diff --git a/ci/licenses_golden/excluded_files b/ci/licenses_golden/excluded_files index 72f2fb7edeb0d..071c6dced30dd 100644 --- a/ci/licenses_golden/excluded_files +++ b/ci/licenses_golden/excluded_files @@ -29,12 +29,10 @@ ../../../flutter/build ../../../flutter/ci ../../../flutter/common/README.md -../../../flutter/display_list/display_list_canvas_unittests.cc ../../../flutter/display_list/display_list_color_filter_unittests.cc ../../../flutter/display_list/display_list_color_source_unittests.cc ../../../flutter/display_list/display_list_color_unittests.cc ../../../flutter/display_list/display_list_complexity_unittests.cc -../../../flutter/display_list/display_list_enum_unittests.cc ../../../flutter/display_list/display_list_image_filter_unittests.cc ../../../flutter/display_list/display_list_mask_filter_unittests.cc ../../../flutter/display_list/display_list_matrix_clip_tracker_unittests.cc @@ -42,8 +40,10 @@ ../../../flutter/display_list/display_list_path_effect_unittests.cc ../../../flutter/display_list/display_list_rtree_unittests.cc ../../../flutter/display_list/display_list_unittests.cc -../../../flutter/display_list/display_list_utils_unittests.cc ../../../flutter/display_list/display_list_vertices_unittests.cc +../../../flutter/display_list/dl_rendering_unittests.cc +../../../flutter/display_list/skia/dl_sk_conversions_unittests.cc +../../../flutter/display_list/skia/dl_sk_utils_unittests.cc ../../../flutter/display_list/testing ../../../flutter/docs ../../../flutter/examples diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 10d1b022b1881..40f7e6f9f7533 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -714,8 +714,6 @@ ORIGIN: ../../../flutter/display_list/display_list_blend_mode.h + ../../../flutt ORIGIN: ../../../flutter/display_list/display_list_builder.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/display_list/display_list_builder.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/display_list/display_list_builder_benchmarks.cc + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/display_list/display_list_canvas_dispatcher.cc + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/display_list/display_list_canvas_dispatcher.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/display_list/display_list_color.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/display_list/display_list_color_filter.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/display_list/display_list_color_filter.h + ../../../flutter/LICENSE @@ -729,8 +727,6 @@ ORIGIN: ../../../flutter/display_list/display_list_complexity_gl.h + ../../../fl ORIGIN: ../../../flutter/display_list/display_list_complexity_helper.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/display_list/display_list_complexity_metal.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/display_list/display_list_complexity_metal.h + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/display_list/display_list_dispatcher.cc + ../../../flutter/LICENSE -ORIGIN: ../../../flutter/display_list/display_list_dispatcher.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/display_list/display_list_flags.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/display_list/display_list_flags.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/display_list/display_list_image.cc + ../../../flutter/LICENSE @@ -759,9 +755,18 @@ ORIGIN: ../../../flutter/display_list/display_list_utils.cc + ../../../flutter/L ORIGIN: ../../../flutter/display_list/display_list_utils.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/display_list/display_list_vertices.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/display_list/display_list_vertices.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/display_list/dl_canvas.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/display_list/dl_canvas.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/display_list/dl_op_receiver.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/display_list/dl_op_receiver.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/display_list/skia/dl_sk_canvas.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/display_list/skia/dl_sk_canvas.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/display_list/skia/dl_sk_conversions.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/display_list/skia/dl_sk_conversions.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/display_list/skia/dl_sk_dispatcher.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/display_list/skia/dl_sk_dispatcher.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/display_list/skia/dl_sk_utils.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/display_list/skia/dl_sk_utils.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/display_list/types.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/flow/compositor_context.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/flow/compositor_context.h + ../../../flutter/LICENSE @@ -3241,8 +3246,6 @@ 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_builder_benchmarks.cc -FILE: ../../../flutter/display_list/display_list_canvas_dispatcher.cc -FILE: ../../../flutter/display_list/display_list_canvas_dispatcher.h FILE: ../../../flutter/display_list/display_list_color.h FILE: ../../../flutter/display_list/display_list_color_filter.cc FILE: ../../../flutter/display_list/display_list_color_filter.h @@ -3256,8 +3259,6 @@ FILE: ../../../flutter/display_list/display_list_complexity_gl.h FILE: ../../../flutter/display_list/display_list_complexity_helper.h FILE: ../../../flutter/display_list/display_list_complexity_metal.cc FILE: ../../../flutter/display_list/display_list_complexity_metal.h -FILE: ../../../flutter/display_list/display_list_dispatcher.cc -FILE: ../../../flutter/display_list/display_list_dispatcher.h FILE: ../../../flutter/display_list/display_list_flags.cc FILE: ../../../flutter/display_list/display_list_flags.h FILE: ../../../flutter/display_list/display_list_image.cc @@ -3286,9 +3287,18 @@ FILE: ../../../flutter/display_list/display_list_utils.cc FILE: ../../../flutter/display_list/display_list_utils.h FILE: ../../../flutter/display_list/display_list_vertices.cc FILE: ../../../flutter/display_list/display_list_vertices.h +FILE: ../../../flutter/display_list/dl_canvas.cc FILE: ../../../flutter/display_list/dl_canvas.h +FILE: ../../../flutter/display_list/dl_op_receiver.cc +FILE: ../../../flutter/display_list/dl_op_receiver.h FILE: ../../../flutter/display_list/skia/dl_sk_canvas.cc FILE: ../../../flutter/display_list/skia/dl_sk_canvas.h +FILE: ../../../flutter/display_list/skia/dl_sk_conversions.cc +FILE: ../../../flutter/display_list/skia/dl_sk_conversions.h +FILE: ../../../flutter/display_list/skia/dl_sk_dispatcher.cc +FILE: ../../../flutter/display_list/skia/dl_sk_dispatcher.h +FILE: ../../../flutter/display_list/skia/dl_sk_utils.cc +FILE: ../../../flutter/display_list/skia/dl_sk_utils.h FILE: ../../../flutter/display_list/types.h FILE: ../../../flutter/flow/compositor_context.cc FILE: ../../../flutter/flow/compositor_context.h diff --git a/display_list/BUILD.gn b/display_list/BUILD.gn index 35e6c8f689302..83d5b40acd59d 100644 --- a/display_list/BUILD.gn +++ b/display_list/BUILD.gn @@ -16,8 +16,6 @@ source_set("display_list") { "display_list_blend_mode.h", "display_list_builder.cc", "display_list_builder.h", - "display_list_canvas_dispatcher.cc", - "display_list_canvas_dispatcher.h", "display_list_color.h", "display_list_color_filter.cc", "display_list_color_filter.h", @@ -29,8 +27,6 @@ source_set("display_list") { "display_list_complexity_gl.h", "display_list_complexity_metal.cc", "display_list_complexity_metal.h", - "display_list_dispatcher.cc", - "display_list_dispatcher.h", "display_list_flags.cc", "display_list_flags.h", "display_list_image.cc", @@ -59,9 +55,18 @@ source_set("display_list") { "display_list_utils.h", "display_list_vertices.cc", "display_list_vertices.h", + "dl_canvas.cc", "dl_canvas.h", + "dl_op_receiver.cc", + "dl_op_receiver.h", "skia/dl_sk_canvas.cc", "skia/dl_sk_canvas.h", + "skia/dl_sk_conversions.cc", + "skia/dl_sk_conversions.h", + "skia/dl_sk_dispatcher.cc", + "skia/dl_sk_dispatcher.h", + "skia/dl_sk_utils.cc", + "skia/dl_sk_utils.h", "types.h", ] @@ -93,7 +98,6 @@ if (enable_unittests) { "display_list_color_source_unittests.cc", "display_list_color_unittests.cc", "display_list_complexity_unittests.cc", - "display_list_enum_unittests.cc", "display_list_image_filter_unittests.cc", "display_list_mask_filter_unittests.cc", "display_list_matrix_clip_tracker_unittests.cc", @@ -101,8 +105,9 @@ if (enable_unittests) { "display_list_path_effect_unittests.cc", "display_list_rtree_unittests.cc", "display_list_unittests.cc", - "display_list_utils_unittests.cc", "display_list_vertices_unittests.cc", + "skia/dl_sk_conversions_unittests.cc", + "skia/dl_sk_utils_unittests.cc", ] deps = [ @@ -130,7 +135,7 @@ if (enable_unittests) { executable("display_list_rendertests") { testonly = true - sources = [ "display_list_canvas_unittests.cc" ] + sources = [ "dl_rendering_unittests.cc" ] deps = [ ":display_list", diff --git a/display_list/display_list.cc b/display_list/display_list.cc index defde8be4be04..5ac4ea57b24e7 100644 --- a/display_list/display_list.cc +++ b/display_list/display_list.cc @@ -6,7 +6,6 @@ #include "flutter/display_list/display_list.h" #include "flutter/display_list/display_list_builder.h" -#include "flutter/display_list/display_list_canvas_dispatcher.h" #include "flutter/display_list/display_list_ops.h" #include "flutter/fml/trace_event.h" @@ -134,38 +133,40 @@ class VectorCuller final : public Culler { std::vector::const_iterator end_; }; -void DisplayList::Dispatch(Dispatcher& ctx) const { +void DisplayList::Dispatch(DlOpReceiver& receiver) const { uint8_t* ptr = storage_.get(); - Dispatch(ctx, ptr, ptr + byte_count_, NopCuller::instance); + Dispatch(receiver, ptr, ptr + byte_count_, NopCuller::instance); } -void DisplayList::Dispatch(Dispatcher& ctx, const SkRect& cull_rect) const { + +void DisplayList::Dispatch(DlOpReceiver& receiver, + const SkRect& cull_rect) const { if (cull_rect.isEmpty()) { return; } if (cull_rect.contains(bounds())) { - Dispatch(ctx); + Dispatch(receiver); return; } const DlRTree* rtree = this->rtree().get(); FML_DCHECK(rtree != nullptr); if (rtree == nullptr) { FML_LOG(ERROR) << "dispatched with culling rect on DL with no rtree"; - Dispatch(ctx); + Dispatch(receiver); return; } uint8_t* ptr = storage_.get(); std::vector rect_indices; rtree->search(cull_rect, &rect_indices); VectorCuller culler(rtree, rect_indices); - Dispatch(ctx, ptr, ptr + byte_count_, culler); + Dispatch(receiver, ptr, ptr + byte_count_, culler); } -void DisplayList::Dispatch(Dispatcher& dispatcher, +void DisplayList::Dispatch(DlOpReceiver& receiver, uint8_t* ptr, uint8_t* end, Culler& culler) const { DispatchContext context = { - .dispatcher = dispatcher, + .receiver = receiver, .cur_index = 0, // next_render_index will be initialized by culler.init() .next_restore_index = std::numeric_limits::max(), @@ -294,27 +295,6 @@ static bool CompareOps(uint8_t* ptrA, return true; } -void DisplayList::RenderTo(DisplayListBuilder* builder) const { - if (!builder) { - return; - } - if (has_rtree()) { - Dispatch(builder->asDispatcher(), builder->GetLocalClipBounds()); - } else { - Dispatch(builder->asDispatcher()); - } -} - -void DisplayList::RenderTo(SkCanvas* canvas, SkScalar opacity) const { - FML_DCHECK(can_apply_group_opacity() || opacity >= SK_Scalar1); - DisplayListCanvasDispatcher dispatcher(canvas, opacity); - if (has_rtree()) { - Dispatch(dispatcher, canvas->getLocalClipBounds()); - } else { - Dispatch(dispatcher); - } -} - bool DisplayList::Equals(const DisplayList* other) const { if (this == other) { return true; diff --git a/display_list/display_list.h b/display_list/display_list.h index dde26766feedc..a66040a3a8026 100644 --- a/display_list/display_list.h +++ b/display_list/display_list.h @@ -18,41 +18,36 @@ // // This file contains the definitions for: // DisplayList: the base class that holds the information about the -// sequence of operations and can dispatch them to a Dispatcher -// Dispatcher: a pure virtual interface which can be implemented to field -// the requests for purposes such as sending them to an SkCanvas -// or detecting various rendering optimization scenarios -// DisplayListBuilder: a class for constructing a DisplayList from the same -// calls defined in the Dispatcher +// sequence of operations and can dispatch them to a DlOpReceiver +// DlOpReceiver: a pure virtual interface which can be implemented to field +// the requests for purposes such as sending them to an SkCanvas +// or detecting various rendering optimization scenarios +// DisplayListBuilder: a class for constructing a DisplayList from DlCanvas +// method calls and which can act as a DlOpReceiver as well // // Other files include various class definitions for dealing with display // lists, such as: -// display_list_canvas.h: classes to interact between SkCanvas and DisplayList -// (SkCanvas->DisplayList adapter and vice versa) +// skia/dl_sk_*.h: classes to interact between SkCanvas and DisplayList +// (SkCanvas->DisplayList adapter and vice versa) // // display_list_utils.h: various utility classes to ease implementing -// a Dispatcher, including NOP implementations of +// a DlOpReceiver, including NOP implementations of // the attribute, clip, and transform methods, // classes to track attributes, clips, and transforms // and a class to compute the bounds of a DisplayList -// Any class implementing Dispatcher can inherit from +// Any class implementing DlOpReceiver can inherit from // these utility classes to simplify its creation // // The Flutter DisplayList mechanism is used in a similar manner to the Skia -// SkPicture mechanism. The primary means of communication into and out -// of the DisplayList is through the Dispatcher virtual class which -// provides a nearly 1:1 translation between the records of the DisplayList -// to method calls. +// SkPicture mechanism. // -// A DisplayList must be created using a DisplayListBuilder using either its -// stateful methods inherited from Dispatcher, or from its stateless methods -// inherited from DlCanvas. +// A DisplayList must be created using a DisplayListBuilder using its stateless +// methods inherited from DlCanvas. // -// A DisplayList can be read back by implementing the Dispatcher virtual +// A DisplayList can be read back by implementing the DlOpReceiver virtual // methods (with help from some of the classes in the utils file) and -// passing an instance to the dispatch() method, or it can be rendered -// to Skia using a DisplayListCanvasDispatcher or simply by passing an -// SkCanvas pointer to its renderTo() method. +// passing an instance to the Dispatch() method, or it can be rendered +// to Skia using a DlSkCanvasDispatcher. // // The mechanism is inspired by the SkLiteDL class that is not directly // supported by Skia, but has been recommended as a basis for custom @@ -155,7 +150,7 @@ enum class DisplayListOpType { }; #undef DL_OP_TO_ENUM_VALUE -class Dispatcher; +class DlOpReceiver; class DisplayListBuilder; class SaveLayerOptions { @@ -231,7 +226,7 @@ class DisplayListStorage { class Culler; // The base class that contains a sequence of rendering operations -// for dispatch to a Dispatcher. These objects must be instantiated +// for dispatch to a DlOpReceiver. These objects must be instantiated // through an instance of DisplayListBuilder::build(). class DisplayList : public SkRefCnt { public: @@ -239,12 +234,8 @@ class DisplayList : public SkRefCnt { ~DisplayList(); - void Dispatch(Dispatcher& ctx) const; - void Dispatch(Dispatcher& ctx, const SkRect& cull_rect) const; - - void RenderTo(DisplayListBuilder* builder) const; - - void RenderTo(SkCanvas* canvas, SkScalar opacity = SK_Scalar1) const; + void Dispatch(DlOpReceiver& ctx) const; + void Dispatch(DlOpReceiver& ctx, const SkRect& cull_rect) const; // From historical behavior, SkPicture always included nested bytes, // but nested ops are only included if requested. The defaults used @@ -300,7 +291,7 @@ class DisplayList : public SkRefCnt { const bool can_apply_group_opacity_; const sk_sp rtree_; - void Dispatch(Dispatcher& ctx, + void Dispatch(DlOpReceiver& ctx, uint8_t* ptr, uint8_t* end, Culler& culler) const; diff --git a/display_list/display_list_attributes.h b/display_list/display_list_attributes.h index 051e4efd65f7c..aa10863f4fb73 100644 --- a/display_list/display_list_attributes.h +++ b/display_list/display_list_attributes.h @@ -36,10 +36,6 @@ namespace flutter { // wrong type of instance. // (eg. DlColorFilter::asBlend() or DlMaskFilter::asBlur()) // -// - Skiafiable: -// The classes override an |skia_object| method to easily obtain a Skia -// version of the attribute on demand. -// // - Immutable: // Neither the base class or any of the subclasses specify any mutation // methods. Instances are often passed around as const as a reminder, @@ -56,7 +52,7 @@ namespace flutter { // compared using a |memcmp| when performing a |DisplayList::Equals|. // // - Passed by Pointer: -// The data shared via the |Dispatcher::set| calls are stored +// The data shared via the |DlOpReceiver::set| calls are stored // in the buffer itself and so their lifetime is controlled by the // DisplayList. That memory cannot be shared as by a |shared_ptr| // because the memory may be freed outside the control of the shared @@ -70,7 +66,7 @@ namespace flutter { // - Shared_Ptr-able: // The classes support a method to return a |std::shared_ptr| version of // themselves, safely instantiating a new copy of the object into a -// shared_ptr using |std::make_shared|. For those dispatcher objects +// shared_ptr using |std::make_shared|. For those receiver objects // that may want to hold on to the contents of the object (typically // in a |current_attribute_| field), they can obtain a shared_ptr // copy safely and easily using the |shared| method. @@ -79,11 +75,9 @@ namespace flutter { // |D| is the base type for the attribute // (i.e. DlColorFilter, etc.) -// |S| is the base type for the Skia version of the attribute -// (i.e. SkColorFilter, etc.) // |T| is the enum that describes the specific subclasses // (i.e DlColorFilterType, etc.) -template +template class DlAttribute { public: // Return the recognized specific type of the attribute. @@ -98,9 +92,6 @@ class DlAttribute { // version is not tied to the storage of this particular instance. virtual std::shared_ptr shared() const = 0; - // Return an equivalent sk_sp version of this object. - virtual sk_sp skia_object() const = 0; - // Perform a content aware |==| comparison of the Attribute. bool operator==(D const& other) const { return type() == other.type() && equals_(other); diff --git a/display_list/display_list_benchmarks.cc b/display_list/display_list_benchmarks.cc index d7f763831e9d6..1e3e2b1b40eac 100644 --- a/display_list/display_list_benchmarks.cc +++ b/display_list/display_list_benchmarks.cc @@ -5,6 +5,7 @@ #include "flutter/display_list/display_list_benchmarks.h" #include "flutter/display_list/display_list_builder.h" #include "flutter/display_list/display_list_flags.h" +#include "flutter/display_list/skia/dl_sk_canvas.h" #include "third_party/skia/include/core/SkPoint.h" #include "third_party/skia/include/core/SkSurface.h" @@ -76,27 +77,27 @@ void BM_DrawLine(benchmark::State& state, unsigned attributes) { auto surface_provider = DlSurfaceProvider::Create(backend_type); DisplayListBuilder builder; - builder.SetAttributesFromPaint(GetPaintForRun(attributes), - DisplayListOpFlags::kDrawLineFlags); + DlPaint paint = GetPaintForRun(attributes); + AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawLineFlags); size_t length = state.range(0); surface_provider->InitializeSurface(length, length); auto surface = surface_provider->GetPrimarySurface()->sk_surface(); - auto canvas = surface->getCanvas(); + auto canvas = DlSkCanvasAdapter(surface->getCanvas()); state.counters["DrawCallCount"] = kLinesToDraw; for (size_t i = 0; i < kLinesToDraw; i++) { - builder.drawLine(SkPoint::Make(i % length, 0), - SkPoint::Make(length - i % length, length)); + builder.DrawLine(SkPoint::Make(i % length, 0), + SkPoint::Make(length - i % length, length), paint); } auto display_list = builder.Build(); // We only want to time the actual rasterization. for ([[maybe_unused]] auto _ : state) { - display_list->RenderTo(canvas); + canvas.DrawDisplayList(display_list); surface->flushAndSubmit(true); } @@ -114,15 +115,15 @@ void BM_DrawRect(benchmark::State& state, unsigned attributes) { auto surface_provider = DlSurfaceProvider::Create(backend_type); DisplayListBuilder builder; - builder.SetAttributesFromPaint(GetPaintForRun(attributes), - DisplayListOpFlags::kDrawRectFlags); + DlPaint paint = GetPaintForRun(attributes); + AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawRectFlags); size_t length = state.range(0); size_t canvas_size = length * 2; surface_provider->InitializeSurface(canvas_size, canvas_size); auto surface = surface_provider->GetPrimarySurface()->sk_surface(); - auto canvas = surface->getCanvas(); + auto canvas = DlSkCanvasAdapter(surface->getCanvas()); // As rects have SkScalar dimensions, we want to ensure that we also // draw rects with non-integer position and size @@ -131,7 +132,7 @@ void BM_DrawRect(benchmark::State& state, state.counters["DrawCallCount"] = kRectsToDraw; for (size_t i = 0; i < kRectsToDraw; i++) { - builder.drawRect(rect); + builder.DrawRect(rect, paint); rect.offset(offset, offset); if (rect.right() > canvas_size) { rect.offset(-canvas_size, 0); @@ -145,7 +146,7 @@ void BM_DrawRect(benchmark::State& state, // We only want to time the actual rasterization. for ([[maybe_unused]] auto _ : state) { - display_list->RenderTo(canvas); + canvas.DrawDisplayList(display_list); surface->flushAndSubmit(true); } @@ -163,22 +164,22 @@ void BM_DrawOval(benchmark::State& state, unsigned attributes) { auto surface_provider = DlSurfaceProvider::Create(backend_type); DisplayListBuilder builder; - builder.SetAttributesFromPaint(GetPaintForRun(attributes), - DisplayListOpFlags::kDrawOvalFlags); + DlPaint paint = GetPaintForRun(attributes); + AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawOvalFlags); size_t length = state.range(0); size_t canvas_size = length * 2; surface_provider->InitializeSurface(canvas_size, canvas_size); auto surface = surface_provider->GetPrimarySurface()->sk_surface(); - auto canvas = surface->getCanvas(); + auto canvas = DlSkCanvasAdapter(surface->getCanvas()); SkRect rect = SkRect::MakeXYWH(0, 0, length * 1.5f, length); const SkScalar offset = 0.5f; state.counters["DrawCallCount"] = kOvalsToDraw; for (size_t i = 0; i < kOvalsToDraw; i++) { - builder.drawOval(rect); + builder.DrawOval(rect, paint); rect.offset(offset, offset); if (rect.right() > canvas_size) { rect.offset(-canvas_size, 0); @@ -191,7 +192,7 @@ void BM_DrawOval(benchmark::State& state, // We only want to time the actual rasterization. for ([[maybe_unused]] auto _ : state) { - display_list->RenderTo(canvas); + canvas.DrawDisplayList(display_list); surface->flushAndSubmit(true); } @@ -209,15 +210,15 @@ void BM_DrawCircle(benchmark::State& state, unsigned attributes) { auto surface_provider = DlSurfaceProvider::Create(backend_type); DisplayListBuilder builder; - builder.SetAttributesFromPaint(GetPaintForRun(attributes), - DisplayListOpFlags::kDrawCircleFlags); + DlPaint paint = GetPaintForRun(attributes); + AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawCircleFlags); size_t length = state.range(0); size_t canvas_size = length * 2; surface_provider->InitializeSurface(canvas_size, canvas_size); auto surface = surface_provider->GetPrimarySurface()->sk_surface(); - auto canvas = surface->getCanvas(); + auto canvas = DlSkCanvasAdapter(surface->getCanvas()); SkScalar radius = length / 2.0f; const SkScalar offset = 0.5f; @@ -226,7 +227,7 @@ void BM_DrawCircle(benchmark::State& state, state.counters["DrawCallCount"] = kCirclesToDraw; for (size_t i = 0; i < kCirclesToDraw; i++) { - builder.drawCircle(center, radius); + builder.DrawCircle(center, radius, paint); center.offset(offset, offset); if (center.x() + radius > canvas_size) { center.set(radius, center.y()); @@ -239,7 +240,7 @@ void BM_DrawCircle(benchmark::State& state, // We only want to time the actual rasterization. for ([[maybe_unused]] auto _ : state) { - display_list->RenderTo(canvas); + canvas.DrawDisplayList(display_list); surface->flushAndSubmit(true); } @@ -258,15 +259,15 @@ void BM_DrawRRect(benchmark::State& state, SkRRect::Type type) { auto surface_provider = DlSurfaceProvider::Create(backend_type); DisplayListBuilder builder; - builder.SetAttributesFromPaint(GetPaintForRun(attributes), - DisplayListOpFlags::kDrawRRectFlags); + DlPaint paint = GetPaintForRun(attributes); + AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawRRectFlags); size_t length = state.range(0); size_t canvas_size = length * 2; surface_provider->InitializeSurface(canvas_size, canvas_size); auto surface = surface_provider->GetPrimarySurface()->sk_surface(); - auto canvas = surface->getCanvas(); + auto canvas = DlSkCanvasAdapter(surface->getCanvas()); SkVector radii[4] = {}; switch (type) { @@ -304,7 +305,7 @@ void BM_DrawRRect(benchmark::State& state, state.counters["DrawCallCount"] = kRRectsToDraw; for (size_t i = 0; i < kRRectsToDraw; i++) { - builder.drawRRect(rrect); + builder.DrawRRect(rrect, paint); rrect.offset(offset, offset); if (rrect.rect().right() > canvas_size) { rrect.offset(-canvas_size, 0); @@ -317,7 +318,7 @@ void BM_DrawRRect(benchmark::State& state, // We only want to time the actual rasterization. for ([[maybe_unused]] auto _ : state) { - display_list->RenderTo(canvas); + canvas.DrawDisplayList(display_list); surface->flushAndSubmit(true); } @@ -339,15 +340,15 @@ void BM_DrawDRRect(benchmark::State& state, SkRRect::Type type) { auto surface_provider = DlSurfaceProvider::Create(backend_type); DisplayListBuilder builder; - builder.SetAttributesFromPaint(GetPaintForRun(attributes), - DisplayListOpFlags::kDrawDRRectFlags); + DlPaint paint = GetPaintForRun(attributes); + AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawDRRectFlags); size_t length = state.range(0); size_t canvas_size = length * 2; surface_provider->InitializeSurface(canvas_size, canvas_size); auto surface = surface_provider->GetPrimarySurface()->sk_surface(); - auto canvas = surface->getCanvas(); + auto canvas = DlSkCanvasAdapter(surface->getCanvas()); SkVector radii[4] = {}; switch (type) { @@ -386,7 +387,7 @@ void BM_DrawDRRect(benchmark::State& state, state.counters["DrawCallCount"] = kDRRectsToDraw; for (size_t i = 0; i < kDRRectsToDraw; i++) { rrect.inset(0.1f * length, 0.1f * length, &rrect_2); - builder.drawDRRect(rrect, rrect_2); + builder.DrawDRRect(rrect, rrect_2, paint); rrect.offset(offset, offset); if (rrect.rect().right() > canvas_size) { rrect.offset(-canvas_size, 0); @@ -399,7 +400,7 @@ void BM_DrawDRRect(benchmark::State& state, // We only want to time the actual rasterization. for ([[maybe_unused]] auto _ : state) { - display_list->RenderTo(canvas); + canvas.DrawDisplayList(display_list); surface->flushAndSubmit(true); } @@ -413,8 +414,8 @@ void BM_DrawArc(benchmark::State& state, unsigned attributes) { auto surface_provider = DlSurfaceProvider::Create(backend_type); DisplayListBuilder builder; - builder.SetAttributesFromPaint(GetPaintForRun(attributes), - DisplayListOpFlags::kDrawArcNoCenterFlags); + DlPaint paint = GetPaintForRun(attributes); + AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawArcNoCenterFlags); @@ -422,7 +423,7 @@ void BM_DrawArc(benchmark::State& state, size_t canvas_size = length * 2; surface_provider->InitializeSurface(canvas_size, canvas_size); auto surface = surface_provider->GetPrimarySurface()->sk_surface(); - auto canvas = surface->getCanvas(); + auto canvas = DlSkCanvasAdapter(surface->getCanvas()); SkScalar starting_angle = 0.0f; SkScalar offset = 0.5f; @@ -436,7 +437,7 @@ void BM_DrawArc(benchmark::State& state, state.counters["DrawCallCount"] = kArcSweepSetsToDraw * segment_sweeps.size(); for (size_t i = 0; i < kArcSweepSetsToDraw; i++) { for (SkScalar sweep : segment_sweeps) { - builder.drawArc(bounds, starting_angle, sweep, false); + builder.DrawArc(bounds, starting_angle, sweep, false, paint); starting_angle += sweep + 5.0f; } bounds.offset(offset, offset); @@ -452,7 +453,7 @@ void BM_DrawArc(benchmark::State& state, // We only want to time the actual rasterization. for ([[maybe_unused]] auto _ : state) { - display_list->RenderTo(canvas); + canvas.DrawDisplayList(display_list); surface->flushAndSubmit(true); } @@ -629,14 +630,14 @@ void BM_DrawPath(benchmark::State& state, SkPath::Verb type) { auto surface_provider = DlSurfaceProvider::Create(backend_type); DisplayListBuilder builder; - builder.SetAttributesFromPaint(GetPaintForRun(attributes), - DisplayListOpFlags::kDrawPathFlags); + DlPaint paint = GetPaintForRun(attributes); + AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawPathFlags); size_t length = kFixedCanvasSize; surface_provider->InitializeSurface(length, length); auto surface = surface_provider->GetPrimarySurface()->sk_surface(); - auto canvas = surface->getCanvas(); + auto canvas = DlSkCanvasAdapter(surface->getCanvas()); SkPath path; @@ -650,12 +651,12 @@ void BM_DrawPath(benchmark::State& state, state.counters["VerbCount"] = path.countVerbs(); state.counters["DrawCallCount"] = 1; - builder.drawPath(path); + builder.DrawPath(path, paint); auto display_list = builder.Build(); // We only want to time the actual rasterization. for ([[maybe_unused]] auto _ : state) { - display_list->RenderTo(canvas); + canvas.DrawDisplayList(display_list); surface->flushAndSubmit(true); } @@ -767,14 +768,14 @@ void BM_DrawVertices(benchmark::State& state, DlVertexMode mode) { auto surface_provider = DlSurfaceProvider::Create(backend_type); DisplayListBuilder builder; - builder.SetAttributesFromPaint(GetPaintForRun(attributes), - DisplayListOpFlags::kDrawVerticesFlags); + DlPaint paint = GetPaintForRun(attributes); + AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawVerticesFlags); size_t length = kFixedCanvasSize; surface_provider->InitializeSurface(length, length); auto surface = surface_provider->GetPrimarySurface()->sk_surface(); - auto canvas = surface->getCanvas(); + auto canvas = DlSkCanvasAdapter(surface->getCanvas()); SkPoint center = SkPoint::Make(length / 2.0f, length / 2.0f); @@ -791,7 +792,7 @@ void BM_DrawVertices(benchmark::State& state, std::shared_ptr vertices = GetTestVertices(p, radius, 50, mode, vertex_count); total_vertex_count += vertex_count; - builder.drawVertices(vertices, DlBlendMode::kSrc); + builder.DrawVertices(vertices.get(), DlBlendMode::kSrc, paint); } state.counters["VertexCount"] = total_vertex_count; @@ -801,7 +802,7 @@ void BM_DrawVertices(benchmark::State& state, // We only want to time the actual rasterization. for ([[maybe_unused]] auto _ : state) { - display_list->RenderTo(canvas); + canvas.DrawDisplayList(display_list); surface->flushAndSubmit(true); } @@ -863,26 +864,18 @@ void BM_DrawPoints(benchmark::State& state, DlCanvas::PointMode mode) { auto surface_provider = DlSurfaceProvider::Create(backend_type); DisplayListBuilder builder; - SkPaint paint; + DlPaint paint = GetPaintForRun(attributes); + switch (mode) { case DlCanvas::PointMode::kPoints: - builder.SetAttributesFromPaint( - GetPaintForRun(attributes), - DisplayListOpFlags::kDrawPointsAsPointsFlags); AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawPointsAsPointsFlags); break; case DlCanvas::PointMode::kLines: - builder.SetAttributesFromPaint( - GetPaintForRun(attributes), - DisplayListOpFlags::kDrawPointsAsLinesFlags); AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawPointsAsLinesFlags); break; case DlCanvas::PointMode::kPolygon: - builder.SetAttributesFromPaint( - GetPaintForRun(attributes), - DisplayListOpFlags::kDrawPointsAsPolygonFlags); AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawPointsAsPolygonFlags); break; @@ -891,7 +884,7 @@ void BM_DrawPoints(benchmark::State& state, size_t length = kFixedCanvasSize; surface_provider->InitializeSurface(length, length); auto surface = surface_provider->GetPrimarySurface()->sk_surface(); - auto canvas = surface->getCanvas(); + auto canvas = DlSkCanvasAdapter(surface->getCanvas()); size_t point_count = state.range(0); state.SetComplexityN(point_count); @@ -900,12 +893,12 @@ void BM_DrawPoints(benchmark::State& state, std::vector points = GetTestPoints(point_count, SkISize::Make(length, length)); - builder.drawPoints(mode, points.size(), points.data()); + builder.DrawPoints(mode, points.size(), points.data(), paint); auto display_list = builder.Build(); for ([[maybe_unused]] auto _ : state) { - display_list->RenderTo(canvas); + canvas.DrawDisplayList(display_list); surface->flushAndSubmit(true); } @@ -933,8 +926,8 @@ void BM_DrawImage(benchmark::State& state, bool upload_bitmap) { auto surface_provider = DlSurfaceProvider::Create(backend_type); DisplayListBuilder builder; - builder.SetAttributesFromPaint(GetPaintForRun(attributes), - DisplayListOpFlags::kDrawImageWithPaintFlags); + DlPaint paint = GetPaintForRun(attributes); + AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawImageWithPaintFlags); @@ -942,7 +935,7 @@ void BM_DrawImage(benchmark::State& state, size_t canvas_size = 2 * bitmap_size; surface_provider->InitializeSurface(canvas_size, canvas_size); auto surface = surface_provider->GetPrimarySurface()->sk_surface(); - auto canvas = surface->getCanvas(); + auto canvas = DlSkCanvasAdapter(surface->getCanvas()); sk_sp image; std::shared_ptr offscreen_instance; @@ -969,7 +962,7 @@ void BM_DrawImage(benchmark::State& state, for (size_t i = 0; i < kImagesToDraw; i++) { image = upload_bitmap ? ImageFromBitmapWithNewID(bitmap) : offscreen->makeImageSnapshot(); - builder.drawImage(DlImage::Make(image), dst, options, true); + builder.DrawImage(DlImage::Make(image), dst, options, &paint); dst.offset(offset, offset); if (dst.x() + bitmap_size > canvas_size) { @@ -983,7 +976,7 @@ void BM_DrawImage(benchmark::State& state, auto display_list = builder.Build(); for ([[maybe_unused]] auto _ : state) { - display_list->RenderTo(canvas); + canvas.DrawDisplayList(display_list); surface->flushAndSubmit(true); } @@ -1016,9 +1009,8 @@ void BM_DrawImageRect(benchmark::State& state, bool upload_bitmap) { auto surface_provider = DlSurfaceProvider::Create(backend_type); DisplayListBuilder builder; - builder.SetAttributesFromPaint( - GetPaintForRun(attributes), - DisplayListOpFlags::kDrawImageRectWithPaintFlags); + DlPaint paint = GetPaintForRun(attributes); + AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawImageRectWithPaintFlags); @@ -1026,7 +1018,7 @@ void BM_DrawImageRect(benchmark::State& state, size_t canvas_size = 2 * bitmap_size; surface_provider->InitializeSurface(canvas_size, canvas_size); auto surface = surface_provider->GetPrimarySurface()->sk_surface(); - auto canvas = surface->getCanvas(); + auto canvas = DlSkCanvasAdapter(surface->getCanvas()); sk_sp image; std::shared_ptr offscreen_instance; @@ -1056,7 +1048,7 @@ void BM_DrawImageRect(benchmark::State& state, for (size_t i = 0; i < kImagesToDraw; i++) { image = upload_bitmap ? ImageFromBitmapWithNewID(bitmap) : offscreen->makeImageSnapshot(); - builder.drawImageRect(DlImage::Make(image), src, dst, options, true, + builder.DrawImageRect(DlImage::Make(image), src, dst, options, &paint, constraint); dst.offset(offset, offset); if (dst.right() > canvas_size) { @@ -1070,7 +1062,7 @@ void BM_DrawImageRect(benchmark::State& state, auto display_list = builder.Build(); for ([[maybe_unused]] auto _ : state) { - display_list->RenderTo(canvas); + canvas.DrawDisplayList(display_list); surface->flushAndSubmit(true); } @@ -1104,9 +1096,8 @@ void BM_DrawImageNine(benchmark::State& state, bool upload_bitmap) { auto surface_provider = DlSurfaceProvider::Create(backend_type); DisplayListBuilder builder; - builder.SetAttributesFromPaint( - GetPaintForRun(attributes), - DisplayListOpFlags::kDrawImageNineWithPaintFlags); + DlPaint paint = GetPaintForRun(attributes); + AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawImageNineWithPaintFlags); @@ -1114,7 +1105,7 @@ void BM_DrawImageNine(benchmark::State& state, size_t canvas_size = 2 * bitmap_size; surface_provider->InitializeSurface(canvas_size, canvas_size); auto surface = surface_provider->GetPrimarySurface()->sk_surface(); - auto canvas = surface->getCanvas(); + auto canvas = DlSkCanvasAdapter(surface->getCanvas()); SkIRect center = SkIRect::MakeXYWH(bitmap_size / 4, bitmap_size / 4, bitmap_size / 2, bitmap_size / 2); @@ -1145,7 +1136,7 @@ void BM_DrawImageNine(benchmark::State& state, for (size_t i = 0; i < kImagesToDraw; i++) { image = upload_bitmap ? ImageFromBitmapWithNewID(bitmap) : offscreen->makeImageSnapshot(); - builder.drawImageNine(DlImage::Make(image), center, dst, filter, true); + builder.DrawImageNine(DlImage::Make(image), center, dst, filter, &paint); dst.offset(offset, offset); if (dst.right() > canvas_size) { dst.offsetTo(0, dst.y()); @@ -1158,7 +1149,7 @@ void BM_DrawImageNine(benchmark::State& state, auto display_list = builder.Build(); for ([[maybe_unused]] auto _ : state) { - display_list->RenderTo(canvas); + canvas.DrawDisplayList(display_list); surface->flushAndSubmit(true); } @@ -1181,15 +1172,15 @@ void BM_DrawTextBlob(benchmark::State& state, unsigned attributes) { auto surface_provider = DlSurfaceProvider::Create(backend_type); DisplayListBuilder builder; - builder.SetAttributesFromPaint(GetPaintForRun(attributes), - DisplayListOpFlags::kDrawTextBlobFlags); + DlPaint paint = GetPaintForRun(attributes); + AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawTextBlobFlags); size_t draw_calls = state.range(0); size_t canvas_size = kFixedCanvasSize; surface_provider->InitializeSurface(canvas_size, canvas_size); auto surface = surface_provider->GetPrimarySurface()->sk_surface(); - auto canvas = surface->getCanvas(); + auto canvas = DlSkCanvasAdapter(surface->getCanvas()); state.counters["DrawCallCount_Varies"] = draw_calls; state.counters["GlyphCount"] = draw_calls; @@ -1198,13 +1189,13 @@ void BM_DrawTextBlob(benchmark::State& state, for (size_t i = 0; i < draw_calls; i++) { character[0] = 'A' + (i % 26); auto blob = SkTextBlob::MakeFromString(character, SkFont()); - builder.drawTextBlob(blob, 50.0f, 50.0f); + builder.DrawTextBlob(blob, 50.0f, 50.0f, paint); } auto display_list = builder.Build(); for ([[maybe_unused]] auto _ : state) { - display_list->RenderTo(canvas); + canvas.DrawDisplayList(display_list); surface->flushAndSubmit(true); } @@ -1228,14 +1219,14 @@ void BM_DrawShadow(benchmark::State& state, SkPath::Verb type) { auto surface_provider = DlSurfaceProvider::Create(backend_type); DisplayListBuilder builder; - builder.SetAttributesFromPaint(GetPaintForRun(attributes), - DisplayListOpFlags::kDrawShadowFlags); + DlPaint paint = GetPaintForRun(attributes); + AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawShadowFlags); size_t length = kFixedCanvasSize; surface_provider->InitializeSurface(length, length); auto surface = surface_provider->GetPrimarySurface()->sk_surface(); - auto canvas = surface->getCanvas(); + auto canvas = DlSkCanvasAdapter(surface->getCanvas()); SkPath path; @@ -1264,12 +1255,12 @@ void BM_DrawShadow(benchmark::State& state, // We can hardcode dpr to 1.0f as we're varying elevation, and dpr is only // ever used in conjunction with elevation. - builder.drawShadow(path, SK_ColorBLUE, elevation, transparent_occluder, 1.0f); + builder.DrawShadow(path, SK_ColorBLUE, elevation, transparent_occluder, 1.0f); auto display_list = builder.Build(); // We only want to time the actual rasterization. for ([[maybe_unused]] auto _ : state) { - display_list->RenderTo(canvas); + canvas.DrawDisplayList(display_list); surface->flushAndSubmit(true); } @@ -1292,14 +1283,14 @@ void BM_SaveLayer(benchmark::State& state, size_t save_depth) { auto surface_provider = DlSurfaceProvider::Create(backend_type); DisplayListBuilder builder; - builder.SetAttributesFromPaint(GetPaintForRun(attributes), - DisplayListOpFlags::kSaveLayerFlags); + DlPaint paint = GetPaintForRun(attributes); + AnnotateAttributes(attributes, state, DisplayListOpFlags::kSaveLayerFlags); size_t length = kFixedCanvasSize; surface_provider->InitializeSurface(length, length); auto surface = surface_provider->GetPrimarySurface()->sk_surface(); - auto canvas = surface->getCanvas(); + auto canvas = DlSkCanvasAdapter(surface->getCanvas()); size_t save_layer_calls = state.range(0); @@ -1311,19 +1302,19 @@ void BM_SaveLayer(benchmark::State& state, state.counters["DrawCallCount_Varies"] = save_layer_calls * save_depth; for (size_t i = 0; i < save_layer_calls; i++) { for (size_t j = 0; j < save_depth; j++) { - builder.saveLayer(nullptr, false); - builder.drawRect(rect1); - builder.drawRect(rect2); + builder.SaveLayer(nullptr, nullptr); + builder.DrawRect(rect1, paint); + builder.DrawRect(rect2, paint); } for (size_t j = 0; j < save_depth; j++) { - builder.restore(); + builder.Restore(); } } auto display_list = builder.Build(); // We only want to time the actual rasterization. for ([[maybe_unused]] auto _ : state) { - display_list->RenderTo(canvas); + canvas.DrawDisplayList(display_list); surface->flushAndSubmit(true); } diff --git a/display_list/display_list_blend_mode.h b/display_list/display_list_blend_mode.h index b1cdbee48b40b..2b5daa9c5a569 100644 --- a/display_list/display_list_blend_mode.h +++ b/display_list/display_list_blend_mode.h @@ -66,14 +66,6 @@ enum class DlBlendMode { kDefaultMode = kSrcOver, }; -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 160f35e005eb8..9c9fef01024ea 100644 --- a/display_list/display_list_builder.cc +++ b/display_list/display_list_builder.cc @@ -6,7 +6,6 @@ #include "flutter/display_list/display_list.h" #include "flutter/display_list/display_list_blend_mode.h" -#include "flutter/display_list/display_list_canvas_dispatcher.h" #include "flutter/display_list/display_list_color_source.h" #include "flutter/display_list/display_list_ops.h" #include "fml/logging.h" @@ -250,8 +249,8 @@ void DisplayListBuilder::onSetImageFilter(const DlImageFilter* filter) { new (pod) DlMatrixImageFilter(matrix_filter); break; } - case DlImageFilterType::kComposeFilter: - case DlImageFilterType::kLocalMatrixFilter: + case DlImageFilterType::kCompose: + case DlImageFilterType::kLocalMatrix: case DlImageFilterType::kColorFilter: { Push(0, 0, filter); break; @@ -843,7 +842,7 @@ void DisplayListBuilder::drawPoints(PointMode mode, } void* data_ptr; - FML_DCHECK(count < Dispatcher::kMaxDrawPointsCount); + FML_DCHECK(count < DlOpReceiver::kMaxDrawPointsCount); int bytes = count * sizeof(SkPoint); RectBoundsAccumulator ptBounds; for (size_t i = 0; i < count; i++) { @@ -947,9 +946,9 @@ void DisplayListBuilder::drawImageRect(const sk_sp image, const SkRect& dst, DlImageSampling sampling, bool render_with_attributes, - SkCanvas::SrcRectConstraint constraint) { + bool enforce_src_edges) { Push(0, 1, image, src, dst, sampling, render_with_attributes, - constraint); + enforce_src_edges); CheckLayerOpacityCompatibility(render_with_attributes); DisplayListAttributeFlags flags = render_with_attributes ? kDrawImageRectWithPaintFlags @@ -962,15 +961,12 @@ void DisplayListBuilder::DrawImageRect(const sk_sp& image, DlImageSampling sampling, const DlPaint* paint, bool enforce_src_edges) { - SkCanvas::SrcRectConstraint constraint = - enforce_src_edges ? SkCanvas::kStrict_SrcRectConstraint - : SkCanvas::kFast_SrcRectConstraint; if (paint != nullptr) { SetAttributesFromPaint(*paint, DisplayListOpFlags::kDrawImageRectWithPaintFlags); - drawImageRect(image, src, dst, sampling, true, constraint); + drawImageRect(image, src, dst, sampling, true, enforce_src_edges); } else { - drawImageRect(image, src, dst, sampling, false, constraint); + drawImageRect(image, src, dst, sampling, false, enforce_src_edges); } } void DisplayListBuilder::drawImageNine(const sk_sp image, @@ -1077,18 +1073,12 @@ void DisplayListBuilder::DrawAtlas(const sk_sp& atlas, void DisplayListBuilder::DrawDisplayList(const sk_sp display_list, SkScalar opacity) { DlPaint current_paint = current_; - if (opacity < SK_Scalar1) { - SaveLayer(&display_list->bounds(), &DlPaint().setOpacity(opacity)); - } - Push(0, 1, display_list); - if (opacity < SK_Scalar1) { - Restore(); - // Not really necessary if the developer is interacting with us via - // our attribute-state-less DlCanvas methods, but this avoids surprises - // for those who may have been using the stateful Dispatcher methods. - SetAttributesFromPaint(current_paint, - DisplayListOpFlags::kSaveLayerWithPaintFlags); - } + Push(0, 1, display_list, opacity); + // Not really necessary if the developer is interacting with us via + // our attribute-state-less DlCanvas methods, but this avoids surprises + // for those who may have been using the stateful Dispatcher methods. + SetAttributesFromPaint(current_paint, + DisplayListOpFlags::kSaveLayerWithPaintFlags); const SkRect bounds = display_list->bounds(); switch (accumulator()->type()) { @@ -1142,8 +1132,8 @@ void DisplayListBuilder::DrawShadow(const SkPath& path, ? Push(0, 1, path, color, elevation, dpr) : Push(0, 1, path, color, elevation, dpr); - SkRect shadow_bounds = DisplayListCanvasDispatcher::ComputeShadowBounds( - path, elevation, dpr, GetTransform()); + SkRect shadow_bounds = + DlCanvas::ComputeShadowBounds(path, elevation, dpr, GetTransform()); AccumulateOpBounds(shadow_bounds, kDrawShadowFlags); UpdateLayerOpacityCompatibility(false); } @@ -1190,7 +1180,7 @@ bool DisplayListBuilder::AdjustBoundsForPaint(SkRect& bounds, pad = std::max(pad, SK_ScalarSqrt2); } SkScalar min_stroke_width = 0.01; - pad *= std::max(getStrokeWidth() * 0.5f, min_stroke_width); + pad *= std::max(current_.getStrokeWidth() * 0.5f, min_stroke_width); bounds.outset(pad, pad); } } @@ -1259,7 +1249,7 @@ bool DisplayListBuilder::paint_nops_on_transparency() { // For example, DstIn is used by masking layers. // https://code.google.com/p/skia/issues/detail?id=1291 // https://crbug.com/401593 - switch (getBlendMode()) { + switch (current_.getBlendMode()) { // For each of the following transfer modes, if the source // alpha is zero (our transparent black), the resulting // blended pixel is not necessarily equal to the original diff --git a/display_list/display_list_builder.h b/display_list/display_list_builder.h index 4226d6a3cfcfe..505984e312e32 100644 --- a/display_list/display_list_builder.h +++ b/display_list/display_list_builder.h @@ -8,7 +8,6 @@ #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" #include "flutter/display_list/display_list_image.h" #include "flutter/display_list/display_list_matrix_clip_tracker.h" @@ -17,17 +16,18 @@ #include "flutter/display_list/display_list_sampling_options.h" #include "flutter/display_list/display_list_utils.h" #include "flutter/display_list/dl_canvas.h" +#include "flutter/display_list/dl_op_receiver.h" #include "flutter/display_list/types.h" #include "flutter/fml/macros.h" namespace flutter { // The primary class used to build a display list. The list of methods -// here matches the list of methods invoked on a |Dispatcher| combined +// here matches the list of methods invoked on a |DlOpReceiver| combined // with the list of methods invoked on a |DlCanvas|. class DisplayListBuilder final : public virtual DlCanvas, public SkRefCnt, - virtual Dispatcher, + virtual DlOpReceiver, DisplayListOpFlags { public: static constexpr SkRect kMaxCullRect = @@ -39,168 +39,330 @@ class DisplayListBuilder final : public virtual DlCanvas, explicit DisplayListBuilder(const SkRect& cull_rect = kMaxCullRect, bool prepare_rtree = false); + ~DisplayListBuilder(); + + // |DlCanvas| SkISize GetBaseLayerSize() const override; + // |DlCanvas| SkImageInfo GetImageInfo() const override; - ~DisplayListBuilder(); + // |DlCanvas| + void Save() override; + + // |DlCanvas| + void SaveLayer(const SkRect* bounds, + const DlPaint* paint = nullptr, + const DlImageFilter* backdrop = nullptr) override; + // |DlCanvas| + void Restore() override; + // |DlCanvas| + int GetSaveCount() const override { return layer_stack_.size(); } + // |DlCanvas| + void RestoreToCount(int restore_count) override; + + // |DlCanvas| + void Translate(SkScalar tx, SkScalar ty) override; + // |DlCanvas| + void Scale(SkScalar sx, SkScalar sy) override; + // |DlCanvas| + void Rotate(SkScalar degrees) override; + // |DlCanvas| + void Skew(SkScalar sx, SkScalar sy) override; + + // clang-format off + // 2x3 2D affine subset of a 4x4 transform in row major order + // |DlCanvas| + void Transform2DAffine(SkScalar mxx, SkScalar mxy, SkScalar mxt, + SkScalar myx, SkScalar myy, SkScalar myt) override; + // full 4x4 transform in row major order + // |DlCanvas| + void TransformFullPerspective( + SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt, + SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt, + SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt, + SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt) override; + // clang-format on + // |DlCanvas| + void TransformReset() override; + // |DlCanvas| + void Transform(const SkMatrix* matrix) override; + // |DlCanvas| + void Transform(const SkM44* matrix44) override; + // |DlCanvas| + void SetTransform(const SkMatrix* matrix) override { + TransformReset(); + Transform(matrix); + } + // |DlCanvas| + void SetTransform(const SkM44* matrix44) override { + TransformReset(); + Transform(matrix44); + } + using DlCanvas::Transform; - Dispatcher& asDispatcher() { return *this; } + /// Returns the 4x4 full perspective transform representing all transform + /// operations executed so far in this DisplayList within the enclosing + /// save stack. + // |DlCanvas| + SkM44 GetTransformFullPerspective() const override { + return tracker_.matrix_4x4(); + } + /// Returns the 3x3 partial perspective transform representing all transform + /// operations executed so far in this DisplayList within the enclosing + /// save stack. + // |DlCanvas| + SkMatrix GetTransform() const override { return tracker_.matrix_3x3(); } + // |DlCanvas| + void ClipRect(const SkRect& rect, ClipOp clip_op, bool is_aa) override; + // |DlCanvas| + void ClipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) override; + // |DlCanvas| + void ClipPath(const SkPath& path, ClipOp clip_op, bool is_aa) override; + + /// Conservative estimate of the bounds of all outstanding clip operations + /// measured in the coordinate space within which this DisplayList will + /// be rendered. + // |DlCanvas| + SkRect GetDestinationClipBounds() const override { + return tracker_.device_cull_rect(); + } + /// Conservative estimate of the bounds of all outstanding clip operations + /// transformed into the local coordinate space in which currently + /// recorded rendering operations are interpreted. + // |DlCanvas| + SkRect GetLocalClipBounds() const override { + return tracker_.local_cull_rect(); + } + + /// Return true iff the supplied bounds are easily shown to be outside + /// of the current clip bounds. This method may conservatively return + /// false if it cannot make the determination. + // |DlCanvas| + bool QuickReject(const SkRect& bounds) const override; + + // |DlCanvas| + void DrawPaint(const DlPaint& paint) override; + // |DlCanvas| + void DrawColor(DlColor color, DlBlendMode mode) override; + // |DlCanvas| + void DrawLine(const SkPoint& p0, + const SkPoint& p1, + const DlPaint& paint) override; + // |DlCanvas| + void DrawRect(const SkRect& rect, const DlPaint& paint) override; + // |DlCanvas| + void DrawOval(const SkRect& bounds, const DlPaint& paint) override; + // |DlCanvas| + void DrawCircle(const SkPoint& center, + SkScalar radius, + const DlPaint& paint) override; + // |DlCanvas| + void DrawRRect(const SkRRect& rrect, const DlPaint& paint) override; + // |DlCanvas| + void DrawDRRect(const SkRRect& outer, + const SkRRect& inner, + const DlPaint& paint) override; + // |DlCanvas| + void DrawPath(const SkPath& path, const DlPaint& paint) override; + // |DlCanvas| + void DrawArc(const SkRect& bounds, + SkScalar start, + SkScalar sweep, + bool useCenter, + const DlPaint& paint) override; + // |DlCanvas| + void DrawPoints(PointMode mode, + uint32_t count, + const SkPoint pts[], + const DlPaint& paint) override; + // |DlCanvas| + void DrawVertices(const DlVertices* vertices, + DlBlendMode mode, + const DlPaint& paint) override; + using DlCanvas::DrawVertices; + // |DlCanvas| + void DrawImage(const sk_sp& image, + const SkPoint point, + DlImageSampling sampling, + const DlPaint* paint = nullptr) override; + // |DlCanvas| + void DrawImageRect(const sk_sp& image, + const SkRect& src, + const SkRect& dst, + DlImageSampling sampling, + const DlPaint* paint = nullptr, + bool enforce_src_edges = false) override; + // |DlCanvas| + void DrawImageNine(const sk_sp& image, + const SkIRect& center, + const SkRect& dst, + DlFilterMode filter, + const DlPaint* paint = nullptr) override; + // |DlCanvas| + void DrawAtlas(const sk_sp& atlas, + const SkRSXform xform[], + const SkRect tex[], + const DlColor colors[], + int count, + DlBlendMode mode, + DlImageSampling sampling, + const SkRect* cullRect, + const DlPaint* paint = nullptr) override; + // |DlCanvas| + void DrawDisplayList(const sk_sp display_list, + SkScalar opacity = SK_Scalar1) override; + // |DlCanvas| + void DrawTextBlob(const sk_sp& blob, + SkScalar x, + SkScalar y, + const DlPaint& paint) override; + // |DlCanvas| + void DrawShadow(const SkPath& path, + const DlColor color, + const SkScalar elevation, + bool transparent_occluder, + SkScalar dpr) override; + + // |DlCanvas| + void Flush() override {} + + sk_sp Build(); + + private: + // This method exposes the internal stateful DlOpReceiver implementation + // of the DisplayListBuilder, primarily for testing purposes. Its use + // is obsolete and forbidden in every other case and is only shared to a + // pair of "friend" accessors in the benchmark/unittest files. + DlOpReceiver& asReceiver() { return *this; } + + friend DlOpReceiver& DisplayListBuilderBenchmarkAccessor( + DisplayListBuilder& builder); + friend DlOpReceiver& DisplayListBuilderTestingAccessor( + DisplayListBuilder& builder); + + void SetAttributesFromPaint(const DlPaint& paint, + const DisplayListAttributeFlags flags); + + // |DlOpReceiver| void setAntiAlias(bool aa) override { if (current_.isAntiAlias() != aa) { onSetAntiAlias(aa); } } + // |DlOpReceiver| void setDither(bool dither) override { if (current_.isDither() != dither) { onSetDither(dither); } } + // |DlOpReceiver| void setInvertColors(bool invert) override { if (current_.isInvertColors() != invert) { onSetInvertColors(invert); } } + // |DlOpReceiver| void setStrokeCap(DlStrokeCap cap) override { if (current_.getStrokeCap() != cap) { onSetStrokeCap(cap); } } + // |DlOpReceiver| void setStrokeJoin(DlStrokeJoin join) override { if (current_.getStrokeJoin() != join) { onSetStrokeJoin(join); } } + // |DlOpReceiver| void setStyle(DlDrawStyle style) override { if (current_.getDrawStyle() != style) { onSetStyle(style); } } + // |DlOpReceiver| void setStrokeWidth(float width) override { if (current_.getStrokeWidth() != width) { onSetStrokeWidth(width); } } + // |DlOpReceiver| void setStrokeMiter(float limit) override { if (current_.getStrokeMiter() != limit) { onSetStrokeMiter(limit); } } + // |DlOpReceiver| void setColor(DlColor color) override { if (current_.getColor() != color) { onSetColor(color); } } + // |DlOpReceiver| void setBlendMode(DlBlendMode mode) override { if (current_.getBlendMode() != mode) { onSetBlendMode(mode); } } + // |DlOpReceiver| void setColorSource(const DlColorSource* source) override { if (NotEquals(current_.getColorSource(), source)) { onSetColorSource(source); } } + // |DlOpReceiver| void setImageFilter(const DlImageFilter* filter) override { if (NotEquals(current_.getImageFilter(), filter)) { onSetImageFilter(filter); } } + // |DlOpReceiver| void setColorFilter(const DlColorFilter* filter) override { if (NotEquals(current_.getColorFilter(), filter)) { onSetColorFilter(filter); } } + // |DlOpReceiver| void setPathEffect(const DlPathEffect* effect) override { if (NotEquals(current_.getPathEffect(), effect)) { onSetPathEffect(effect); } } + // |DlOpReceiver| void setMaskFilter(const DlMaskFilter* filter) override { if (NotEquals(current_.getMaskFilter(), filter)) { onSetMaskFilter(filter); } } - bool isAntiAlias() const { return current_.isAntiAlias(); } - bool isDither() const { return current_.isDither(); } - DlDrawStyle getStyle() const { return current_.getDrawStyle(); } - DlColor getColor() const { return current_.getColor(); } - float getStrokeWidth() const { return current_.getStrokeWidth(); } - float getStrokeMiter() const { return current_.getStrokeMiter(); } - DlStrokeCap getStrokeCap() const { return current_.getStrokeCap(); } - DlStrokeJoin getStrokeJoin() const { return current_.getStrokeJoin(); } - std::shared_ptr getColorSource() const { - return current_.getColorSource(); - } - std::shared_ptr getColorFilter() const { - return current_.getColorFilter(); - } - bool isInvertColors() const { return current_.isInvertColors(); } - DlBlendMode getBlendMode() const { return current_.getBlendMode(); } - std::shared_ptr getPathEffect() const { - return current_.getPathEffect(); - } - std::shared_ptr getMaskFilter() const { - return current_.getMaskFilter(); - } - std::shared_ptr getImageFilter() const { - return current_.getImageFilter(); - } - - void Save() override; + // |DlOpReceiver| void save() override { Save(); } - // Only the |renders_with_attributes()| option will be accepted here. Any // other flags will be ignored and calculated anew as the DisplayList is // built. Alternatively, use the |saveLayer(SkRect, bool)| method. + // |DlOpReceiver| void saveLayer(const SkRect* bounds, const SaveLayerOptions options, const DlImageFilter* backdrop) override; - // Convenience method with just a boolean to indicate whether the saveLayer - // should apply the rendering attributes. - void saveLayer(const SkRect* bounds, bool renders_with_attributes) { - saveLayer(bounds, - renders_with_attributes ? SaveLayerOptions::kWithAttributes - : SaveLayerOptions::kNoAttributes, - nullptr); - } - void SaveLayer(const SkRect* bounds, - const DlPaint* paint = nullptr, - const DlImageFilter* backdrop = nullptr) override; - void Restore() override; + // |DlOpReceiver| void restore() override { Restore(); } - int GetSaveCount() const override { return layer_stack_.size(); } - void RestoreToCount(int restore_count) override; - void restoreToCount(int restore_count) { RestoreToCount(restore_count); } - void Translate(SkScalar tx, SkScalar ty) override; - void Scale(SkScalar sx, SkScalar sy) override; - void Rotate(SkScalar degrees) override; - void Skew(SkScalar sx, SkScalar sy) override; + // |DlOpReceiver| void translate(SkScalar tx, SkScalar ty) override { Translate(tx, ty); } + // |DlOpReceiver| void scale(SkScalar sx, SkScalar sy) override { Scale(sx, sy); } + // |DlOpReceiver| void rotate(SkScalar degrees) override { Rotate(degrees); } + // |DlOpReceiver| void skew(SkScalar sx, SkScalar sy) override { Skew(sx, sy); } - void SetAttributesFromPaint(const DlPaint& paint, - const DisplayListAttributeFlags flags); - // clang-format off - - // 2x3 2D affine subset of a 4x4 transform in row major order - void Transform2DAffine(SkScalar mxx, SkScalar mxy, SkScalar mxt, - SkScalar myx, SkScalar myy, SkScalar myt) override; + // |DlOpReceiver| void transform2DAffine(SkScalar mxx, SkScalar mxy, SkScalar mxt, SkScalar myx, SkScalar myy, SkScalar myt) override { Transform2DAffine(mxx, mxy, mxt, myx, myy, myt); } - // full 4x4 transform in row major order - void TransformFullPerspective( - SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt, - SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt, - SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt, - SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt) override; + // |DlOpReceiver| void transformFullPerspective( SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt, SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt, @@ -211,148 +373,73 @@ class DisplayListBuilder final : public virtual DlCanvas, mzx, mzy, mzz, mzt, mwx, mwy, mwz, mwt); } - // clang-format on - void TransformReset() override; - void Transform(const SkMatrix* matrix) override; - void Transform(const SkM44* matrix44) override; - void SetTransform(const SkMatrix* matrix) override { - TransformReset(); - Transform(matrix); - } - void SetTransform(const SkM44* matrix44) override { - TransformReset(); - Transform(matrix44); - } - using DlCanvas::Transform; + // clang-format off + // |DlOpReceiver| void transformReset() override { TransformReset(); } - void transform(const SkMatrix* matrix) { Transform(matrix); } - void transform(const SkM44* matrix44) { Transform(matrix44); } - void transform(const SkMatrix& matrix) { Transform(&matrix); } - void transform(const SkM44& matrix44) { Transform(&matrix44); } - - /// Returns the 4x4 full perspective transform representing all transform - /// operations executed so far in this DisplayList within the enclosing - /// save stack. - SkM44 GetTransformFullPerspective() const override { - return tracker_.matrix_4x4(); - } - /// Returns the 3x3 partial perspective transform representing all transform - /// operations executed so far in this DisplayList within the enclosing - /// save stack. - SkMatrix GetTransform() const override { return tracker_.matrix_3x3(); } - void ClipRect(const SkRect& rect, ClipOp clip_op, bool is_aa) override; - void ClipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) override; - void ClipPath(const SkPath& path, ClipOp clip_op, bool is_aa) override; + // |DlOpReceiver| void clipRect(const SkRect& rect, ClipOp clip_op, bool is_aa) override { ClipRect(rect, clip_op, is_aa); } + // |DlOpReceiver| void clipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) override { ClipRRect(rrect, clip_op, is_aa); } + // |DlOpReceiver| void clipPath(const SkPath& path, ClipOp clip_op, bool is_aa) override { ClipPath(path, clip_op, is_aa); } - /// Conservative estimate of the bounds of all outstanding clip operations - /// measured in the coordinate space within which this DisplayList will - /// be rendered. - SkRect GetDestinationClipBounds() const override { - return tracker_.device_cull_rect(); - } - /// Conservative estimate of the bounds of all outstanding clip operations - /// transformed into the local coordinate space in which currently - /// recorded rendering operations are interpreted. - SkRect GetLocalClipBounds() const override { - return tracker_.local_cull_rect(); - } - - /// Return true iff the supplied bounds are easily shown to be outside - /// of the current clip bounds. This method may conservatively return - /// false if it cannot make the determination. - bool QuickReject(const SkRect& bounds) const override; - + // |DlOpReceiver| void drawPaint() override; - void DrawPaint(const DlPaint& paint) override; - void DrawColor(DlColor color, DlBlendMode mode) override; + // |DlOpReceiver| void drawColor(DlColor color, DlBlendMode mode) override { DrawColor(color, mode); } + // |DlOpReceiver| void drawLine(const SkPoint& p0, const SkPoint& p1) override; - void DrawLine(const SkPoint& p0, - const SkPoint& p1, - const DlPaint& paint) override; + // |DlOpReceiver| void drawRect(const SkRect& rect) override; - void DrawRect(const SkRect& rect, const DlPaint& paint) override; + // |DlOpReceiver| void drawOval(const SkRect& bounds) override; - void DrawOval(const SkRect& bounds, const DlPaint& paint) override; + // |DlOpReceiver| void drawCircle(const SkPoint& center, SkScalar radius) override; - void DrawCircle(const SkPoint& center, - SkScalar radius, - const DlPaint& paint) override; + // |DlOpReceiver| void drawRRect(const SkRRect& rrect) override; - void DrawRRect(const SkRRect& rrect, const DlPaint& paint) override; + // |DlOpReceiver| void drawDRRect(const SkRRect& outer, const SkRRect& inner) override; - void DrawDRRect(const SkRRect& outer, - const SkRRect& inner, - const DlPaint& paint) override; + // |DlOpReceiver| void drawPath(const SkPath& path) override; - void DrawPath(const SkPath& path, const DlPaint& paint) override; + // |DlOpReceiver| void drawArc(const SkRect& bounds, SkScalar start, SkScalar sweep, bool useCenter) override; - void DrawArc(const SkRect& bounds, - SkScalar start, - SkScalar sweep, - bool useCenter, - const DlPaint& paint) override; + // |DlOpReceiver| void drawPoints(PointMode mode, uint32_t count, const SkPoint pts[]) override; - void DrawPoints(PointMode mode, - uint32_t count, - const SkPoint pts[], - const DlPaint& paint) override; + // |DlOpReceiver| void drawVertices(const DlVertices* vertices, DlBlendMode mode) override; - void drawVertices(const std::shared_ptr vertices, - DlBlendMode mode) { - drawVertices(vertices.get(), mode); - } - void DrawVertices(const DlVertices* vertices, - DlBlendMode mode, - const DlPaint& paint) override; - using DlCanvas::DrawVertices; + + // |DlOpReceiver| void drawImage(const sk_sp image, const SkPoint point, DlImageSampling sampling, bool render_with_attributes) override; - void DrawImage(const sk_sp& image, - const SkPoint point, - DlImageSampling sampling, - const DlPaint* paint = nullptr) override; + // |DlOpReceiver| void drawImageRect( const sk_sp image, const SkRect& src, const SkRect& dst, DlImageSampling sampling, bool render_with_attributes, - SkCanvas::SrcRectConstraint constraint = - SkCanvas::SrcRectConstraint::kFast_SrcRectConstraint) override; - void DrawImageRect(const sk_sp& image, - const SkRect& src, - const SkRect& dst, - DlImageSampling sampling, - const DlPaint* paint = nullptr, - bool enforce_src_edges = false) override; + bool enforce_src_edges = false) override; + // |DlOpReceiver| void drawImageNine(const sk_sp image, const SkIRect& center, const SkRect& dst, DlFilterMode filter, bool render_with_attributes) override; - void DrawImageNine(const sk_sp& image, - const SkIRect& center, - const SkRect& dst, - DlFilterMode filter, - const DlPaint* paint = nullptr) override; + // |DlOpReceiver| void drawAtlas(const sk_sp atlas, const SkRSXform xform[], const SkRect tex[], @@ -362,32 +449,17 @@ class DisplayListBuilder final : public virtual DlCanvas, DlImageSampling sampling, const SkRect* cullRect, bool render_with_attributes) override; - void DrawAtlas(const sk_sp& atlas, - const SkRSXform xform[], - const SkRect tex[], - const DlColor colors[], - int count, - DlBlendMode mode, - DlImageSampling sampling, - const SkRect* cullRect, - const DlPaint* paint = nullptr) override; - void DrawDisplayList(const sk_sp display_list, - SkScalar opacity) override; - void drawDisplayList(const sk_sp display_list) override { - DrawDisplayList(display_list, SK_Scalar1); + + // |DlOpReceiver| + void drawDisplayList(const sk_sp display_list, + SkScalar opacity) override { + DrawDisplayList(display_list, opacity); } + // |DlOpReceiver| void drawTextBlob(const sk_sp blob, SkScalar x, SkScalar y) override; - void DrawTextBlob(const sk_sp& blob, - SkScalar x, - SkScalar y, - const DlPaint& paint) override; - void DrawShadow(const SkPath& path, - const DlColor color, - const SkScalar elevation, - bool transparent_occluder, - SkScalar dpr) override; + // |DlOpReceiver| void drawShadow(const SkPath& path, const DlColor color, const SkScalar elevation, @@ -396,11 +468,6 @@ class DisplayListBuilder final : public virtual DlCanvas, DrawShadow(path, color, elevation, transparent_occluder, dpr); } - void Flush() override {} - - sk_sp Build(); - - private: void checkForDeferredSave(); DisplayListStorage storage_; diff --git a/display_list/display_list_builder_benchmarks.cc b/display_list/display_list_builder_benchmarks.cc index 7405901f4b473..87f4bfc947613 100644 --- a/display_list/display_list_builder_benchmarks.cc +++ b/display_list/display_list_builder_benchmarks.cc @@ -6,6 +6,11 @@ #include "flutter/display_list/testing/dl_test_snippets.h" namespace flutter { + +DlOpReceiver& DisplayListBuilderBenchmarkAccessor(DisplayListBuilder& builder) { + return builder.asReceiver(); +} + namespace { static std::vector allRenderingOps = @@ -19,10 +24,11 @@ enum class DisplayListBuilderBenchmarkType { }; static void InvokeAllRenderingOps(DisplayListBuilder& builder) { + DlOpReceiver& receiver = DisplayListBuilderBenchmarkAccessor(builder); for (auto& group : allRenderingOps) { for (size_t i = 0; i < group.variants.size(); i++) { auto& invocation = group.variants[i]; - invocation.Invoke(builder); + invocation.Invoke(receiver); } } } @@ -69,8 +75,8 @@ static void BM_DisplayListBuilderWithScaleAndTranslate( bool prepare_rtree = NeedPrepareRTree(type); while (state.KeepRunning()) { DisplayListBuilder builder(prepare_rtree); - builder.scale(3.5, 3.5); - builder.translate(10.3, 6.9); + builder.Scale(3.5, 3.5); + builder.Translate(10.3, 6.9); InvokeAllRenderingOps(builder); Complete(builder, type); } @@ -82,7 +88,7 @@ static void BM_DisplayListBuilderWithPerspective( bool prepare_rtree = NeedPrepareRTree(type); while (state.KeepRunning()) { DisplayListBuilder builder(prepare_rtree); - builder.transformFullPerspective(0, 1, 0, 12, 1, 0, 0, 33, 3, 2, 5, 29, 0, + builder.TransformFullPerspective(0, 1, 0, 12, 1, 0, 0, 33, 3, 2, 5, 29, 0, 0, 0, 12); InvokeAllRenderingOps(builder); Complete(builder, type); @@ -96,7 +102,7 @@ static void BM_DisplayListBuilderWithClipRect( bool prepare_rtree = NeedPrepareRTree(type); while (state.KeepRunning()) { DisplayListBuilder builder(prepare_rtree); - builder.clipRect(clip_bounds, DlCanvas::ClipOp::kIntersect, true); + builder.ClipRect(clip_bounds, DlCanvas::ClipOp::kIntersect, true); InvokeAllRenderingOps(builder); Complete(builder, type); } @@ -108,12 +114,13 @@ static void BM_DisplayListBuilderWithSaveLayer( bool prepare_rtree = NeedPrepareRTree(type); while (state.KeepRunning()) { DisplayListBuilder builder(prepare_rtree); + DlOpReceiver& receiver = DisplayListBuilderBenchmarkAccessor(builder); for (auto& group : allRenderingOps) { for (size_t i = 0; i < group.variants.size(); i++) { auto& invocation = group.variants[i]; - builder.saveLayer(nullptr, false); - invocation.Invoke(builder); - builder.restore(); + builder.SaveLayer(nullptr, nullptr); + invocation.Invoke(receiver); + builder.Restore(); } } Complete(builder, type); @@ -129,11 +136,12 @@ static void BM_DisplayListBuilderWithSaveLayerAndImageFilter( bool prepare_rtree = NeedPrepareRTree(type); while (state.KeepRunning()) { DisplayListBuilder builder(prepare_rtree); + DlOpReceiver& receiver = DisplayListBuilderBenchmarkAccessor(builder); for (auto& group : allRenderingOps) { for (size_t i = 0; i < group.variants.size(); i++) { auto& invocation = group.variants[i]; builder.SaveLayer(&layer_bounds, &layer_paint); - invocation.Invoke(builder); + invocation.Invoke(receiver); builder.Restore(); } } diff --git a/display_list/display_list_canvas_dispatcher.cc b/display_list/display_list_canvas_dispatcher.cc deleted file mode 100644 index 34dbe83a19868..0000000000000 --- a/display_list/display_list_canvas_dispatcher.cc +++ /dev/null @@ -1,305 +0,0 @@ -// 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_canvas_dispatcher.h" - -#include "flutter/display_list/display_list_blend_mode.h" -#include "flutter/fml/trace_event.h" - -namespace flutter { - -const SkScalar kLightHeight = 600; -const SkScalar kLightRadius = 800; - -static SkClipOp ToSk(DlCanvas::ClipOp op) { - return static_cast(op); -} - -static SkCanvas::PointMode ToSk(DlCanvas::PointMode mode) { - return static_cast(mode); -} - -const SkPaint* DisplayListCanvasDispatcher::safe_paint(bool use_attributes) { - if (use_attributes) { - // The accumulated SkPaint object will already have incorporated - // any attribute overrides. - return &paint(); - } else if (has_opacity()) { - temp_paint_.setAlphaf(opacity()); - return &temp_paint_; - } else { - return nullptr; - } -} - -void DisplayListCanvasDispatcher::save() { - canvas_->save(); - // save has no impact on attributes, but it needs to register a record - // on the restore stack so that the eventual call to restore() will - // know what to do at that time. We could annotate the restore record - // with a flag that the record came from a save call, but it is simpler - // to just pass in the current opacity value as the value to be used by - // the children and let the utility calls notice that it didn't change. - save_opacity(opacity()); -} -void DisplayListCanvasDispatcher::restore() { - canvas_->restore(); - restore_opacity(); -} -void DisplayListCanvasDispatcher::saveLayer(const SkRect* bounds, - const SaveLayerOptions options, - const DlImageFilter* backdrop) { - if (bounds == nullptr && options.can_distribute_opacity() && - backdrop == nullptr) { - // We know that: - // - no bounds is needed for clipping here - // - no backdrop filter is used to initialize the layer - // - the current attributes only have an alpha - // - the children are compatible with individually rendering with - // an inherited opacity - // Therefore we can just use a save instead of a saveLayer and pass the - // intended opacity to the children. - canvas_->save(); - // If the saveLayer does not use attributes, the children should continue - // to render with the inherited opacity unmodified. If attributes are to - // be applied, the children should render with the combination of the - // inherited opacity combined with the alpha from the current color. - save_opacity(options.renders_with_attributes() ? combined_opacity() - : opacity()); - } else { - TRACE_EVENT0("flutter", "Canvas::saveLayer"); - const SkPaint* paint = safe_paint(options.renders_with_attributes()); - const sk_sp sk_backdrop = - backdrop ? backdrop->skia_object() : nullptr; - canvas_->saveLayer( - SkCanvas::SaveLayerRec(bounds, paint, sk_backdrop.get(), 0)); - // saveLayer will apply the current opacity on behalf of the children - // so they will inherit an opaque opacity. - save_opacity(SK_Scalar1); - } -} - -void DisplayListCanvasDispatcher::translate(SkScalar tx, SkScalar ty) { - canvas_->translate(tx, ty); -} -void DisplayListCanvasDispatcher::scale(SkScalar sx, SkScalar sy) { - canvas_->scale(sx, sy); -} -void DisplayListCanvasDispatcher::rotate(SkScalar degrees) { - canvas_->rotate(degrees); -} -void DisplayListCanvasDispatcher::skew(SkScalar sx, SkScalar sy) { - canvas_->skew(sx, sy); -} -// clang-format off -// 2x3 2D affine subset of a 4x4 transform in row major order -void DisplayListCanvasDispatcher::transform2DAffine( - SkScalar mxx, SkScalar mxy, SkScalar mxt, - SkScalar myx, SkScalar myy, SkScalar myt) { - // Internally concat(SkMatrix) gets redirected to concat(SkM44) - // so we just jump directly to the SkM44 version - canvas_->concat(SkM44(mxx, mxy, 0, mxt, - myx, myy, 0, myt, - 0, 0, 1, 0, - 0, 0, 0, 1)); -} -// full 4x4 transform in row major order -void DisplayListCanvasDispatcher::transformFullPerspective( - SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt, - SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt, - SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt, - SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt) { - canvas_->concat(SkM44(mxx, mxy, mxz, mxt, - myx, myy, myz, myt, - mzx, mzy, mzz, mzt, - mwx, mwy, mwz, mwt)); -} -// clang-format on -void DisplayListCanvasDispatcher::transformReset() { - canvas_->setMatrix(original_transform_); -} - -void DisplayListCanvasDispatcher::clipRect(const SkRect& rect, - ClipOp clip_op, - bool is_aa) { - canvas_->clipRect(rect, ToSk(clip_op), is_aa); -} -void DisplayListCanvasDispatcher::clipRRect(const SkRRect& rrect, - ClipOp clip_op, - bool is_aa) { - canvas_->clipRRect(rrect, ToSk(clip_op), is_aa); -} -void DisplayListCanvasDispatcher::clipPath(const SkPath& path, - ClipOp clip_op, - bool is_aa) { - canvas_->clipPath(path, ToSk(clip_op), is_aa); -} - -void DisplayListCanvasDispatcher::drawPaint() { - const SkPaint& sk_paint = paint(); - SkImageFilter* filter = sk_paint.getImageFilter(); - if (filter && !filter->asColorFilter(nullptr)) { - // drawPaint does an implicit saveLayer if an SkImageFilter is - // present that cannot be replaced by an SkColorFilter. - TRACE_EVENT0("flutter", "Canvas::saveLayer"); - } - canvas_->drawPaint(sk_paint); -} -void DisplayListCanvasDispatcher::drawColor(DlColor 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, ToSk(mode)); -} -void DisplayListCanvasDispatcher::drawLine(const SkPoint& p0, - const SkPoint& p1) { - canvas_->drawLine(p0, p1, paint()); -} -void DisplayListCanvasDispatcher::drawRect(const SkRect& rect) { - canvas_->drawRect(rect, paint()); -} -void DisplayListCanvasDispatcher::drawOval(const SkRect& bounds) { - canvas_->drawOval(bounds, paint()); -} -void DisplayListCanvasDispatcher::drawCircle(const SkPoint& center, - SkScalar radius) { - canvas_->drawCircle(center, radius, paint()); -} -void DisplayListCanvasDispatcher::drawRRect(const SkRRect& rrect) { - canvas_->drawRRect(rrect, paint()); -} -void DisplayListCanvasDispatcher::drawDRRect(const SkRRect& outer, - const SkRRect& inner) { - canvas_->drawDRRect(outer, inner, paint()); -} -void DisplayListCanvasDispatcher::drawPath(const SkPath& path) { - canvas_->drawPath(path, paint()); -} -void DisplayListCanvasDispatcher::drawArc(const SkRect& bounds, - SkScalar start, - SkScalar sweep, - bool useCenter) { - canvas_->drawArc(bounds, start, sweep, useCenter, paint()); -} -void DisplayListCanvasDispatcher::drawPoints(PointMode mode, - uint32_t count, - const SkPoint pts[]) { - canvas_->drawPoints(ToSk(mode), count, pts, paint()); -} -void DisplayListCanvasDispatcher::drawVertices(const DlVertices* vertices, - DlBlendMode mode) { - canvas_->drawVertices(vertices->skia_object(), ToSk(mode), paint()); -} -void DisplayListCanvasDispatcher::drawImage(const sk_sp image, - const SkPoint point, - DlImageSampling sampling, - bool render_with_attributes) { - canvas_->drawImage(image ? image->skia_image() : nullptr, point.fX, point.fY, - ToSk(sampling), safe_paint(render_with_attributes)); -} -void DisplayListCanvasDispatcher::drawImageRect( - const sk_sp image, - const SkRect& src, - const SkRect& dst, - DlImageSampling sampling, - bool render_with_attributes, - SkCanvas::SrcRectConstraint constraint) { - canvas_->drawImageRect(image ? image->skia_image() : nullptr, src, dst, - ToSk(sampling), safe_paint(render_with_attributes), - constraint); -} -void DisplayListCanvasDispatcher::drawImageNine(const sk_sp image, - const SkIRect& center, - const SkRect& dst, - DlFilterMode filter, - bool render_with_attributes) { - if (!image) { - return; - } - auto skia_image = image->skia_image(); - if (!skia_image) { - return; - } - canvas_->drawImageNine(skia_image.get(), center, dst, ToSk(filter), - safe_paint(render_with_attributes)); -} -void DisplayListCanvasDispatcher::drawAtlas(const sk_sp atlas, - const SkRSXform xform[], - const SkRect tex[], - const DlColor colors[], - int count, - DlBlendMode mode, - DlImageSampling sampling, - const SkRect* cullRect, - bool render_with_attributes) { - if (!atlas) { - return; - } - auto skia_atlas = atlas->skia_image(); - if (!skia_atlas) { - return; - } - const SkColor* sk_colors = reinterpret_cast(colors); - canvas_->drawAtlas(skia_atlas.get(), xform, tex, sk_colors, count, ToSk(mode), - ToSk(sampling), cullRect, - safe_paint(render_with_attributes)); -} -void DisplayListCanvasDispatcher::drawDisplayList( - const sk_sp display_list) { - int save_count = canvas_->save(); - display_list->RenderTo(canvas_, opacity()); - canvas_->restoreToCount(save_count); -} -void DisplayListCanvasDispatcher::drawTextBlob(const sk_sp blob, - SkScalar x, - SkScalar y) { - canvas_->drawTextBlob(blob, x, y, paint()); -} - -SkRect DisplayListCanvasDispatcher::ComputeShadowBounds(const SkPath& path, - float elevation, - SkScalar dpr, - const SkMatrix& ctm) { - SkRect shadow_bounds(path.getBounds()); - SkShadowUtils::GetLocalBounds( - ctm, path, SkPoint3::Make(0, 0, dpr * elevation), - SkPoint3::Make(0, -1, 1), kLightRadius / kLightHeight, - SkShadowFlags::kDirectionalLight_ShadowFlag, &shadow_bounds); - return shadow_bounds; -} - -void DisplayListCanvasDispatcher::DrawShadow(SkCanvas* canvas, - const SkPath& path, - DlColor color, - float elevation, - bool transparentOccluder, - SkScalar dpr) { - const SkScalar kAmbientAlpha = 0.039f; - const SkScalar kSpotAlpha = 0.25f; - - uint32_t flags = transparentOccluder - ? SkShadowFlags::kTransparentOccluder_ShadowFlag - : SkShadowFlags::kNone_ShadowFlag; - flags |= SkShadowFlags::kDirectionalLight_ShadowFlag; - SkColor in_ambient = SkColorSetA(color, kAmbientAlpha * SkColorGetA(color)); - SkColor in_spot = SkColorSetA(color, kSpotAlpha * SkColorGetA(color)); - SkColor ambient_color, spot_color; - SkShadowUtils::ComputeTonalColors(in_ambient, in_spot, &ambient_color, - &spot_color); - SkShadowUtils::DrawShadow(canvas, path, SkPoint3::Make(0, 0, dpr * elevation), - SkPoint3::Make(0, -1, 1), - kLightRadius / kLightHeight, ambient_color, - spot_color, flags); -} - -void DisplayListCanvasDispatcher::drawShadow(const SkPath& path, - const DlColor color, - const SkScalar elevation, - bool transparent_occluder, - SkScalar dpr) { - DrawShadow(canvas_, path, color, elevation, transparent_occluder, dpr); -} - -} // namespace flutter diff --git a/display_list/display_list_color.h b/display_list/display_list_color.h index d84ccd4342a93..855df42deffe8 100644 --- a/display_list/display_list_color.h +++ b/display_list/display_list_color.h @@ -35,6 +35,7 @@ struct DlColor { uint32_t argb; bool isOpaque() const { return getAlpha() == 0xFF; } + bool isTransparent() const { return getAlpha() == 0; } int getAlpha() const { return argb >> 24; } int getRed() const { return (argb >> 16) & 0xFF; } diff --git a/display_list/display_list_color_filter.cc b/display_list/display_list_color_filter.cc index 6f46b0256d564..778214ecd8d78 100644 --- a/display_list/display_list_color_filter.cc +++ b/display_list/display_list_color_filter.cc @@ -8,16 +8,193 @@ namespace flutter { +std::shared_ptr DlBlendColorFilter::Make(DlColor color, + DlBlendMode mode) { + switch (mode) { + case DlBlendMode::kDst: { + return nullptr; + } + case DlBlendMode::kSrcOver: { + if (color.isTransparent()) { + return nullptr; + } + if (color.isOpaque()) { + mode = DlBlendMode::kSrc; + } + break; + } + case DlBlendMode::kDstOver: + case DlBlendMode::kDstOut: + case DlBlendMode::kSrcATop: + case DlBlendMode::kXor: + case DlBlendMode::kDarken: { + if (color.isTransparent()) { + return nullptr; + } + break; + } + case DlBlendMode::kDstIn: { + if (color.isOpaque()) { + return nullptr; + } + break; + } + default: + break; + } + return std::make_shared(color, mode); +} + +bool DlBlendColorFilter::modifies_transparent_black() const { + switch (mode_) { + // These modes all act like kSrc when the dest is all 0s. + // So they modify transparent black when the src color is + // not transparent. + case DlBlendMode::kSrc: + case DlBlendMode::kSrcOver: + case DlBlendMode::kDstOver: + case DlBlendMode::kSrcOut: + case DlBlendMode::kDstATop: + case DlBlendMode::kXor: + case DlBlendMode::kPlus: + case DlBlendMode::kScreen: + case DlBlendMode::kOverlay: + case DlBlendMode::kDarken: + case DlBlendMode::kLighten: + case DlBlendMode::kColorDodge: + case DlBlendMode::kColorBurn: + case DlBlendMode::kHardLight: + case DlBlendMode::kSoftLight: + case DlBlendMode::kDifference: + case DlBlendMode::kExclusion: + case DlBlendMode::kMultiply: + case DlBlendMode::kHue: + case DlBlendMode::kSaturation: + case DlBlendMode::kColor: + case DlBlendMode::kLuminosity: + return !color_.isTransparent(); + + // These modes are all like kDst when the dest is all 0s. + // So they never modify transparent black. + case DlBlendMode::kClear: + case DlBlendMode::kDst: + case DlBlendMode::kSrcIn: + case DlBlendMode::kDstIn: + case DlBlendMode::kDstOut: + case DlBlendMode::kSrcATop: + case DlBlendMode::kModulate: + return false; + } +} + +bool DlBlendColorFilter::can_commute_with_opacity() const { + switch (mode_) { + case DlBlendMode::kClear: + case DlBlendMode::kDst: + case DlBlendMode::kSrcIn: + case DlBlendMode::kDstIn: + case DlBlendMode::kDstOut: + case DlBlendMode::kSrcATop: + case DlBlendMode::kModulate: + return true; + + case DlBlendMode::kSrc: + case DlBlendMode::kSrcOver: + case DlBlendMode::kDstOver: + case DlBlendMode::kSrcOut: + case DlBlendMode::kDstATop: + case DlBlendMode::kXor: + case DlBlendMode::kPlus: + case DlBlendMode::kScreen: + case DlBlendMode::kOverlay: + case DlBlendMode::kDarken: + case DlBlendMode::kLighten: + case DlBlendMode::kColorDodge: + case DlBlendMode::kColorBurn: + case DlBlendMode::kHardLight: + case DlBlendMode::kSoftLight: + case DlBlendMode::kDifference: + case DlBlendMode::kExclusion: + case DlBlendMode::kMultiply: + case DlBlendMode::kHue: + case DlBlendMode::kSaturation: + case DlBlendMode::kColor: + case DlBlendMode::kLuminosity: + return color_.isTransparent(); + } +} + +std::shared_ptr DlMatrixColorFilter::Make( + const float matrix[20]) { + float product = 0; + for (int i = 0; i < 20; i++) { + product *= matrix[i]; + } + // If any of the elements of the matrix are infinity or NaN, then + // |product| will be NaN, otherwise 0. + if (product == 0) { + return std::make_shared(matrix); + } + return nullptr; +} + +bool DlMatrixColorFilter::modifies_transparent_black() const { + // Values are considered in non-premultiplied form when the matrix is + // applied, but we only care about this answer for whether it leaves + // an incoming color with a transparent alpha as transparent on output. + // Thus, we only need to consider the alpha part of the matrix equation, + // which is the last row. Since the incoming alpha value is 0, the last + // equation ends up becoming A' = matrix_[19]. Negative results will be + // clamped to the range [0,1] so we only care about positive values. + // Non-finite values are clamped to a zero alpha. + return (SkScalarIsFinite(matrix_[19]) && matrix_[19] > 0); +} + +bool DlMatrixColorFilter::can_commute_with_opacity() const { + // We need to check if: + // filter(color) * opacity == filter(color * opacity). + // + // filter(RGBA) = R' = [ R*m[ 0] + G*m[ 1] + B*m[ 2] + A*m[ 3] + m[ 4] ] + // G' = [ R*m[ 5] + G*m[ 6] + B*m[ 7] + A*m[ 8] + m[ 9] ] + // B' = [ R*m[10] + G*m[11] + B*m[12] + A*m[13] + m[14] ] + // A' = [ R*m[15] + G*m[16] + B*m[17] + A*m[18] + m[19] ] + // + // Applying the opacity only affects the alpha value since the operations + // are performed on non-premultiplied colors. (If the data is stored in + // premultiplied form, though, there may be rounding errors due to + // premul->unpremul->premul conversions.) + + // We test for the successful cases and return false if they fail so that + // we fail and return false if any matrix values are NaN. + + // If any of the alpha column are non-zero then the prior alpha affects + // the result color, so applying opacity before the filter will change + // the incoming alpha and therefore the colors that are produced. + if (!(matrix_[3] == 0 && // A does not affect R' + matrix_[8] == 0 && // A does not affect G' + matrix_[13] == 0)) { // A does not affect B' + return false; + } + + // Similarly, if any of the alpha row are non-zero then the prior colors + // affect the result alpha in a way that prevents opacity from commuting + // through the filter operation. + if (!(matrix_[15] == 0 && // R does not affect A' + matrix_[16] == 0 && // G does not affect A' + matrix_[17] == 0 && // B does not affect A' + matrix_[19] == 0)) { // A' is not offset by an absolute value + return false; + } + + return true; +} + const std::shared_ptr DlSrgbToLinearGammaColorFilter::instance = std::make_shared(); -const sk_sp DlSrgbToLinearGammaColorFilter::sk_filter_ = - SkColorFilters::SRGBToLinearGamma(); const std::shared_ptr DlLinearToSrgbGammaColorFilter::instance = std::make_shared(); -const sk_sp DlLinearToSrgbGammaColorFilter::sk_filter_ = - SkColorFilters::LinearToSRGBGamma(); } // namespace flutter diff --git a/display_list/display_list_color_filter.h b/display_list/display_list_color_filter.h index 240f3619320ed..b02bad4d2d598 100644 --- a/display_list/display_list_color_filter.h +++ b/display_list/display_list_color_filter.h @@ -28,8 +28,7 @@ enum class DlColorFilterType { kLinearToSrgbGamma, }; -class DlColorFilter - : public DlAttribute { +class DlColorFilter : public DlAttribute { public: // Return a boolean indicating whether the color filtering operation will // modify transparent black. This is typically used to determine if applying @@ -68,23 +67,18 @@ class DlBlendColorFilter final : public DlColorFilter { DlBlendColorFilter(const DlBlendColorFilter* filter) : DlBlendColorFilter(filter->color_, filter->mode_) {} + static std::shared_ptr Make(DlColor color, DlBlendMode mode); + DlColorFilterType type() const override { return DlColorFilterType::kBlend; } size_t size() const override { return sizeof(*this); } - bool modifies_transparent_black() const override { - // Look at blend and color to make a faster determination? - sk_sp sk_filter = skia_object(); - return sk_filter && - sk_filter->filterColor(SK_ColorTRANSPARENT) != SK_ColorTRANSPARENT; - } + + bool modifies_transparent_black() const override; + bool can_commute_with_opacity() const override; std::shared_ptr shared() const override { return std::make_shared(this); } - sk_sp skia_object() const override { - return SkColorFilters::Blend(color_, ToSk(mode_)); - } - const DlBlendColorFilter* asBlend() const override { return this; } DlColor color() const { return color_; } @@ -114,6 +108,10 @@ class DlBlendColorFilter final : public DlColorFilter { // // The resulting color [oR,oG,oB,oA] is then clamped to the range of // valid pixel components before storing in the output. +// +// The incoming and outgoing [iR,iG,iB,iA] and [oR,oG,oB,oA] are +// considered to be non-premultiplied. When working on premultiplied +// pixel data, the necessary pre<->non-pre conversions must be performed. class DlMatrixColorFilter final : public DlColorFilter { public: DlMatrixColorFilter(const float matrix[20]) { @@ -124,30 +122,18 @@ class DlMatrixColorFilter final : public DlColorFilter { DlMatrixColorFilter(const DlMatrixColorFilter* filter) : DlMatrixColorFilter(filter->matrix_) {} + static std::shared_ptr Make(const float matrix[20]); + DlColorFilterType type() const override { return DlColorFilterType::kMatrix; } size_t size() const override { return sizeof(*this); } - bool modifies_transparent_black() const override { - // Look at the matrix to make a faster determination? - // Basically, are the translation components all 0? - sk_sp sk_filter = skia_object(); - return sk_filter && - sk_filter->filterColor(SK_ColorTRANSPARENT) != SK_ColorTRANSPARENT; - } - bool can_commute_with_opacity() const override { - return matrix_[3] == 0 && matrix_[8] == 0 && matrix_[13] == 0 && - matrix_[15] == 0 && matrix_[16] == 0 && matrix_[17] == 0 && - (matrix_[18] >= 0.0 && matrix_[18] <= 1.0) && matrix_[19] == 0; - } + bool modifies_transparent_black() const override; + bool can_commute_with_opacity() const override; std::shared_ptr shared() const override { return std::make_shared(this); } - sk_sp skia_object() const override { - return SkColorFilters::Matrix(matrix_); - } - const DlMatrixColorFilter* asMatrix() const override { return this; } const float& operator[](int index) const { return matrix_[index]; } @@ -186,7 +172,6 @@ class DlSrgbToLinearGammaColorFilter final : public DlColorFilter { bool can_commute_with_opacity() const override { return true; } std::shared_ptr shared() const override { return instance; } - sk_sp skia_object() const override { return sk_filter_; } protected: bool equals_(const DlColorFilter& other) const override { @@ -195,7 +180,6 @@ class DlSrgbToLinearGammaColorFilter final : public DlColorFilter { } private: - static const sk_sp sk_filter_; friend class DlColorFilter; }; @@ -219,7 +203,6 @@ class DlLinearToSrgbGammaColorFilter final : public DlColorFilter { bool can_commute_with_opacity() const override { return true; } std::shared_ptr shared() const override { return instance; } - sk_sp skia_object() const override { return sk_filter_; } protected: bool equals_(const DlColorFilter& other) const override { @@ -228,7 +211,6 @@ class DlLinearToSrgbGammaColorFilter final : public DlColorFilter { } private: - static const sk_sp sk_filter_; friend class DlColorFilter; }; diff --git a/display_list/display_list_color_filter_unittests.cc b/display_list/display_list_color_filter_unittests.cc index 2403a6db4c9b4..efdd1b538a148 100644 --- a/display_list/display_list_color_filter_unittests.cc +++ b/display_list/display_list_color_filter_unittests.cc @@ -17,18 +17,6 @@ static const float kMatrix[20] = { 16, 17, 18, 19, 20, // }; -TEST(DisplayListColorFilter, BuilderSetGet) { - DlBlendColorFilter filter(DlColor::kRed(), DlBlendMode::kDstATop); - DisplayListBuilder builder; - ASSERT_EQ(builder.getColorFilter(), nullptr); - builder.setColorFilter(&filter); - ASSERT_NE(builder.getColorFilter(), nullptr); - ASSERT_TRUE( - Equals(builder.getColorFilter(), static_cast(&filter))); - builder.setColorFilter(nullptr); - ASSERT_EQ(builder.getColorFilter(), nullptr); -} - TEST(DisplayListColorFilter, BlendConstructor) { DlBlendColorFilter filter(DlColor::kRed(), DlBlendMode::kDstATop); } diff --git a/display_list/display_list_color_source.cc b/display_list/display_list_color_source.cc index 94c9fbb8b5975..01da26d267167 100644 --- a/display_list/display_list_color_source.cc +++ b/display_list/display_list_color_source.cc @@ -19,7 +19,7 @@ static void DlGradientDeleter(void* p) { ::operator delete(p); } -std::shared_ptr DlColorSource::MakeLinear( +std::shared_ptr DlColorSource::MakeLinear( const SkPoint start_point, const SkPoint end_point, uint32_t stop_count, @@ -37,10 +37,10 @@ std::shared_ptr DlColorSource::MakeLinear( DlLinearGradientColorSource(start_point, end_point, stop_count, colors, stops, tile_mode, matrix), DlGradientDeleter); - return std::move(ret); + return ret; } -std::shared_ptr DlColorSource::MakeRadial( +std::shared_ptr DlColorSource::MakeRadial( SkPoint center, SkScalar radius, uint32_t stop_count, @@ -57,10 +57,10 @@ std::shared_ptr DlColorSource::MakeRadial( ret.reset(new (storage) DlRadialGradientColorSource( center, radius, stop_count, colors, stops, tile_mode, matrix), DlGradientDeleter); - return std::move(ret); + return ret; } -std::shared_ptr DlColorSource::MakeConical( +std::shared_ptr DlColorSource::MakeConical( SkPoint start_center, SkScalar start_radius, SkPoint end_center, @@ -80,10 +80,10 @@ std::shared_ptr DlColorSource::MakeConical( start_center, start_radius, end_center, end_radius, stop_count, colors, stops, tile_mode, matrix), DlGradientDeleter); - return std::move(ret); + return ret; } -std::shared_ptr DlColorSource::MakeSweep( +std::shared_ptr DlColorSource::MakeSweep( SkPoint center, SkScalar start, SkScalar end, @@ -102,7 +102,7 @@ std::shared_ptr DlColorSource::MakeSweep( DlSweepGradientColorSource(center, start, end, stop_count, colors, stops, tile_mode, matrix), DlGradientDeleter); - return std::move(ret); + return ret; } std::shared_ptr DlColorSource::MakeRuntimeEffect( diff --git a/display_list/display_list_color_source.h b/display_list/display_list_color_source.h index 7705893ad4ed0..52937226381c7 100644 --- a/display_list/display_list_color_source.h +++ b/display_list/display_list_color_source.h @@ -63,10 +63,9 @@ enum class DlColorSourceType { #endif // IMPELLER_ENABLE_3D }; -class DlColorSource - : public DlAttribute { +class DlColorSource : public DlAttribute { public: - static std::shared_ptr MakeLinear( + static std::shared_ptr MakeLinear( const SkPoint start_point, const SkPoint end_point, uint32_t stop_count, @@ -75,7 +74,7 @@ class DlColorSource DlTileMode tile_mode, const SkMatrix* matrix = nullptr); - static std::shared_ptr MakeRadial( + static std::shared_ptr MakeRadial( SkPoint center, SkScalar radius, uint32_t stop_count, @@ -84,7 +83,7 @@ class DlColorSource DlTileMode tile_mode, const SkMatrix* matrix = nullptr); - static std::shared_ptr MakeConical( + static std::shared_ptr MakeConical( SkPoint start_center, SkScalar start_radius, SkPoint end_center, @@ -95,7 +94,7 @@ class DlColorSource DlTileMode tile_mode, const SkMatrix* matrix = nullptr); - static std::shared_ptr MakeSweep( + static std::shared_ptr MakeSweep( SkPoint center, SkScalar start, SkScalar end, @@ -190,10 +189,6 @@ class DlColorColorSource final : public DlColorSource { DlColor color() const { return color_; } - sk_sp skia_object() const override { - return SkShaders::Color(color_); - } - protected: bool equals_(DlColorSource const& other) const override { FML_DCHECK(other.type() == DlColorSourceType::kColor); @@ -263,15 +258,6 @@ class DlImageColorSource final : public SkRefCnt, DlTileMode vertical_tile_mode() const { return vertical_tile_mode_; } DlImageSampling sampling() const { return sampling_; } - virtual sk_sp skia_object() const override { - if (!image_->skia_image()) { - return nullptr; - } - return image_->skia_image()->makeShader(ToSk(horizontal_tile_mode_), - ToSk(vertical_tile_mode_), - ToSk(sampling_), matrix_ptr()); - } - protected: bool equals_(DlColorSource const& other) const override { FML_DCHECK(other.type() == DlColorSourceType::kImage); @@ -386,13 +372,6 @@ class DlLinearGradientColorSource final : public DlGradientColorSourceBase { const SkPoint& start_point() const { return start_point_; } const SkPoint& end_point() const { return end_point_; } - sk_sp skia_object() const override { - SkPoint pts[] = {start_point_, end_point_}; - const SkColor* sk_colors = reinterpret_cast(colors()); - return SkGradientShader::MakeLinear(pts, sk_colors, stops(), stop_count(), - ToSk(tile_mode()), 0, matrix_ptr()); - } - protected: virtual const void* pod() const override { return this + 1; } @@ -454,13 +433,6 @@ class DlRadialGradientColorSource final : public DlGradientColorSourceBase { SkPoint center() const { return center_; } SkScalar radius() const { return radius_; } - sk_sp skia_object() const override { - const SkColor* sk_colors = reinterpret_cast(colors()); - return SkGradientShader::MakeRadial(center_, radius_, sk_colors, stops(), - stop_count(), ToSk(tile_mode()), 0, - matrix_ptr()); - } - protected: virtual const void* pod() const override { return this + 1; } @@ -525,13 +497,6 @@ class DlConicalGradientColorSource final : public DlGradientColorSourceBase { SkPoint end_center() const { return end_center_; } SkScalar end_radius() const { return end_radius_; } - sk_sp skia_object() const override { - const SkColor* sk_colors = reinterpret_cast(colors()); - return SkGradientShader::MakeTwoPointConical( - start_center_, start_radius_, end_center_, end_radius_, sk_colors, - stops(), stop_count(), ToSk(tile_mode()), 0, matrix_ptr()); - } - protected: virtual const void* pod() const override { return this + 1; } @@ -604,13 +569,6 @@ class DlSweepGradientColorSource final : public DlGradientColorSourceBase { SkScalar start() const { return start_; } SkScalar end() const { return end_; } - sk_sp skia_object() const override { - const SkColor* sk_colors = reinterpret_cast(colors()); - return SkGradientShader::MakeSweep(center_.x(), center_.y(), sk_colors, - stops(), stop_count(), ToSk(tile_mode()), - start_, end_, 0, matrix_ptr()); - } - protected: virtual const void* pod() const override { return this + 1; } @@ -693,35 +651,6 @@ class DlRuntimeEffectColorSource final : public DlColorSource { return uniform_data_; } - sk_sp skia_object() const override { - if (!runtime_effect_) { - return nullptr; - } - if (!runtime_effect_->skia_runtime_effect()) { - return nullptr; - } - std::vector> sk_samplers(samplers_.size()); - for (size_t i = 0; i < samplers_.size(); i++) { - auto sampler = samplers_[i]; - if (sampler == nullptr) { - return nullptr; - } - sk_samplers[i] = sampler->skia_object(); - } - - auto ref = new std::shared_ptr>(uniform_data_); - auto uniform_data = SkData::MakeWithProc( - uniform_data_->data(), uniform_data_->size(), - [](const void* ptr, void* context) { - delete reinterpret_cast>*>( - context); - }, - ref); - - return runtime_effect_->skia_runtime_effect()->makeShader( - uniform_data, sk_samplers.data(), sk_samplers.size()); - } - protected: bool equals_(DlColorSource const& other) const override { FML_DCHECK(other.type() == DlColorSourceType::kRuntimeEffect); diff --git a/display_list/display_list_color_source_unittests.cc b/display_list/display_list_color_source_unittests.cc index a4c982c9c4d23..582d723e0e469 100644 --- a/display_list/display_list_color_source_unittests.cc +++ b/display_list/display_list_color_source_unittests.cc @@ -86,19 +86,6 @@ static constexpr SkPoint kTestPoints2[2] = { SkPoint::Make(107, 118), }; -TEST(DisplayListColorSource, BuilderSetGet) { - DlImageColorSource source(kTestImage1, DlTileMode::kClamp, DlTileMode::kClamp, - DlImageSampling::kLinear, &kTestMatrix1); - DisplayListBuilder builder; - ASSERT_EQ(builder.getColorSource(), nullptr); - builder.setColorSource(&source); - ASSERT_NE(builder.getColorSource(), nullptr); - ASSERT_TRUE( - Equals(builder.getColorSource(), static_cast(&source))); - builder.setColorSource(nullptr); - ASSERT_EQ(builder.getColorSource(), nullptr); -} - TEST(DisplayListColorSource, ColorConstructor) { DlColorColorSource source(SK_ColorRED); } @@ -763,23 +750,11 @@ TEST(DisplayListColorSource, RuntimeEffect) { ASSERT_EQ(source1->asConicalGradient(), nullptr); ASSERT_EQ(source1->asSweepGradient(), nullptr); - ASSERT_NE(source1->skia_object(), nullptr); - ASSERT_EQ(source3->skia_object(), nullptr); - TestEquals(source1, source1); TestEquals(source3, source3); TestNotEquals(source1, source2, "SkRuntimeEffect differs"); TestNotEquals(source2, source3, "SkRuntimeEffect differs"); } -TEST(DisplayListColorSource, RuntimeEffectWithNullSampler) { - std::shared_ptr source1 = - DlColorSource::MakeRuntimeEffect( - kTestRuntimeEffect1, {nullptr}, - std::make_shared>()); - - ASSERT_EQ(source1->skia_object(), nullptr); -} - } // namespace testing } // namespace flutter diff --git a/display_list/display_list_complexity_gl.cc b/display_list/display_list_complexity_gl.cc index 40c3bde6d25cc..165744df7cf18 100644 --- a/display_list/display_list_complexity_gl.cc +++ b/display_list/display_list_complexity_gl.cc @@ -114,7 +114,7 @@ void DisplayListGLComplexityCalculator::GLHelper::drawRect(const SkRect& rect) { // // There is also a kStrokeAndFill_Style that Skia exposes, but we do not // currently use it anywhere in Flutter. - if (Style() == SkPaint::Style::kFill_Style) { + if (DrawStyle() == DlDrawStyle::kFill) { // No real difference for AA with filled styles unsigned int area = rect.width() * rect.height(); @@ -165,7 +165,7 @@ void DisplayListGLComplexityCalculator::GLHelper::drawOval( // There is also a kStrokeAndFill_Style that Skia exposes, but we do not // currently use it anywhere in Flutter. - if (Style() == SkPaint::Style::kFill_Style) { + if (DrawStyle() == DlDrawStyle::kFill) { // With filled styles, there is no significant AA penalty. // m = 1/6000 // c = 0 @@ -199,7 +199,7 @@ void DisplayListGLComplexityCalculator::GLHelper::drawCircle( // There is also a kStrokeAndFill_Style that Skia exposes, but we do not // currently use it anywhere in Flutter. - if (Style() == SkPaint::Style::kFill_Style) { + if (DrawStyle() == DlDrawStyle::kFill) { // We can ignore pi here unsigned int area = radius * radius; // m = 1/525 @@ -245,7 +245,7 @@ void DisplayListGLComplexityCalculator::GLHelper::drawRRect( // These values were worked out by creating a straight line graph (y=mx+c) // approximately matching the measured data, normalising the data so that // 0.0005ms resulted in a score of 100 then simplifying down the formula. - if (Style() == SkPaint::Style::kFill_Style || + if (DrawStyle() == DlDrawStyle::kFill || ((rrect.getType() == SkRRect::Type::kSimple_Type) && IsAntiAliased())) { unsigned int area = rrect.width() * rrect.height(); // m = 1/3200 @@ -295,7 +295,7 @@ void DisplayListGLComplexityCalculator::GLHelper::drawDRRect( // // There is also a kStrokeAndFill_Style that Skia exposes, but we do not // currently use it anywhere in Flutter. - if (Style() == SkPaint::Style::kFill_Style) { + if (DrawStyle() == DlDrawStyle::kFill) { unsigned int area = outer.width() * outer.height(); if (outer.getType() == SkRRect::Type::kComplex_Type) { // m = 1/500 @@ -382,7 +382,7 @@ void DisplayListGLComplexityCalculator::GLHelper::drawArc( // // There is also a kStrokeAndFill_Style that Skia exposes, but we do not // currently use it anywhere in Flutter. - if (Style() == SkPaint::Style::kStroke_Style) { + if (DrawStyle() == DlDrawStyle::kStroke) { if (IsAntiAliased()) { // m = 1/3800 // c = 12 @@ -550,7 +550,7 @@ void DisplayListGLComplexityCalculator::GLHelper::ImageRect( const SkISize& size, bool texture_backed, bool render_with_attributes, - SkCanvas::SrcRectConstraint constraint) { + bool enforce_src_edges) { if (IsComplex()) { return; } @@ -563,10 +563,8 @@ void DisplayListGLComplexityCalculator::GLHelper::ImageRect( // approximately matching the measured data, normalising the data so that // 0.0005ms resulted in a score of 100 then simplifying down the formula. unsigned int complexity; - if (!texture_backed || - (texture_backed && render_with_attributes && - constraint == SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint && - IsAntiAliased())) { + if (!texture_backed || (texture_backed && render_with_attributes && + enforce_src_edges && IsAntiAliased())) { unsigned int area = size.width() * size.height(); // m = 1/4000 // c = 5 @@ -610,11 +608,15 @@ void DisplayListGLComplexityCalculator::GLHelper::drawImageNine( } void DisplayListGLComplexityCalculator::GLHelper::drawDisplayList( - const sk_sp display_list) { + const sk_sp display_list, + SkScalar opacity) { if (IsComplex()) { return; } GLHelper helper(Ceiling() - CurrentComplexityScore()); + if (opacity < SK_Scalar1 && !display_list->can_apply_group_opacity()) { + helper.saveLayer(nullptr, SaveLayerOptions::kWithAttributes, nullptr); + } display_list->Dispatch(helper); AccumulateComplexity(helper.ComplexityScore()); } diff --git a/display_list/display_list_complexity_gl.h b/display_list/display_list_complexity_gl.h index 9756943e88312..821c69613f8a4 100644 --- a/display_list/display_list_complexity_gl.h +++ b/display_list/display_list_complexity_gl.h @@ -65,7 +65,8 @@ class DisplayListGLComplexityCalculator const SkRect& dst, DlFilterMode filter, bool render_with_attributes) override; - void drawDisplayList(const sk_sp display_list) override; + void drawDisplayList(const sk_sp display_list, + SkScalar opacity) override; void drawTextBlob(const sk_sp blob, SkScalar x, SkScalar y) override; @@ -79,7 +80,7 @@ class DisplayListGLComplexityCalculator void ImageRect(const SkISize& size, bool texture_backed, bool render_with_attributes, - SkCanvas::SrcRectConstraint constraint) override; + bool enforce_src_edges) override; unsigned int BatchedComplexity() override; diff --git a/display_list/display_list_complexity_helper.h b/display_list/display_list_complexity_helper.h index eb738b95dca9b..df3ced300e38e 100644 --- a/display_list/display_list_complexity_helper.h +++ b/display_list/display_list_complexity_helper.h @@ -7,8 +7,8 @@ #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" +#include "flutter/display_list/dl_op_receiver.h" namespace flutter { @@ -92,7 +92,7 @@ namespace flutter { // y = 4x class ComplexityCalculatorHelper - : public virtual Dispatcher, + : public virtual DlOpReceiver, public virtual IgnoreClipDispatchHelper, public virtual IgnoreTransformDispatchHelper { public: @@ -121,7 +121,7 @@ class ComplexityCalculatorHelper void setAntiAlias(bool aa) override { current_paint_.setAntiAlias(aa); } void setStyle(DlDrawStyle style) override { - current_paint_.setStyle(ToSk(style)); + current_paint_.setDrawStyle(style); } void setStrokeWidth(SkScalar width) override { @@ -150,12 +150,12 @@ class ComplexityCalculatorHelper const SkRect& dst, DlImageSampling sampling, bool render_with_attributes, - SkCanvas::SrcRectConstraint constraint) override { + bool enforce_src_edges = false) override { if (IsComplex()) { return; } ImageRect(image->dimensions(), image->isTextureBacked(), - render_with_attributes, constraint); + render_with_attributes, enforce_src_edges); } void drawAtlas(const sk_sp atlas, @@ -174,8 +174,7 @@ class ComplexityCalculatorHelper // This is equivalent to calling drawImageRect lots of times for (int i = 0; i < count; i++) { ImageRect(SkISize::Make(tex[i].width(), tex[i].height()), true, - render_with_attributes, - SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint); + render_with_attributes, true); } } @@ -211,7 +210,7 @@ class ComplexityCalculatorHelper inline bool IsAntiAliased() { return current_paint_.isAntiAlias(); } inline bool IsHairline() { return current_paint_.getStrokeWidth() == 0.0f; } - inline SkPaint::Style Style() { return current_paint_.getStyle(); } + inline DlDrawStyle DrawStyle() { return current_paint_.getDrawStyle(); } inline bool IsComplex() { return is_complex_; } inline unsigned int Ceiling() { return ceiling_; } inline unsigned int CurrentComplexityScore() { return complexity_score_; } @@ -248,7 +247,7 @@ class ComplexityCalculatorHelper virtual void ImageRect(const SkISize& size, bool texture_backed, bool render_with_attributes, - SkCanvas::SrcRectConstraint constraint) = 0; + bool enforce_src_edges) = 0; // This calculates and returns the cost of draw calls which are batched and // thus have a time cost proportional to the number of draw calls made, such @@ -256,7 +255,7 @@ class ComplexityCalculatorHelper virtual unsigned int BatchedComplexity() = 0; private: - SkPaint current_paint_; + DlPaint current_paint_; // If we exceed the ceiling (defaults to the largest number representable // by unsigned int), then set the is_complex_ bool and we no longer diff --git a/display_list/display_list_complexity_metal.cc b/display_list/display_list_complexity_metal.cc index 2cd5c7c2c8d93..8edb87abc404d 100644 --- a/display_list/display_list_complexity_metal.cc +++ b/display_list/display_list_complexity_metal.cc @@ -128,7 +128,7 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawRect( // // There is also a kStrokeAndFill_Style that Skia exposes, but we do not // currently use it anywhere in Flutter. - if (Style() == SkPaint::Style::kFill_Style) { + if (DrawStyle() == DlDrawStyle::kFill) { // No real difference for AA with filled styles. unsigned int area = rect.width() * rect.height(); @@ -170,7 +170,7 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawOval( // There is also a kStrokeAndFill_Style that Skia exposes, but we do not // currently use it anywhere in Flutter. - if (Style() == SkPaint::Style::kFill_Style) { + if (DrawStyle() == DlDrawStyle::kFill) { // With filled styles, there is no significant AA penalty. // m = 1/16000 // c = 0 @@ -204,7 +204,7 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawCircle( // There is also a kStrokeAndFill_Style that Skia exposes, but we do not // currently use it anywhere in Flutter. - if (Style() == SkPaint::Style::kFill_Style) { + if (DrawStyle() == DlDrawStyle::kFill) { // We can ignore pi here. unsigned int area = radius * radius; // m = 1/1300 @@ -244,7 +244,7 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawRRect( // // Expensive: All filled style, symmetric w/AA. bool expensive = - (Style() == SkPaint::Style::kFill_Style) || + (DrawStyle() == DlDrawStyle::kFill) || ((rrect.getType() == SkRRect::Type::kSimple_Type) && IsAntiAliased()); unsigned int complexity; @@ -292,7 +292,7 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawDRRect( // // There is also a kStrokeAndFill_Style that Skia exposes, but we do not // currently use it anywhere in Flutter. - if (Style() == SkPaint::Style::kFill_Style) { + if (DrawStyle() == DlDrawStyle::kFill) { unsigned int area = outer.width() * outer.height(); if (outer.getType() == SkRRect::Type::kComplex_Type) { // m = 1/1000 @@ -374,7 +374,7 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawArc( // // There is also a kStrokeAndFill_Style that Skia exposes, but we do not // currently use it anywhere in Flutter. - if (Style() == SkPaint::Style::kStroke_Style) { + if (DrawStyle() == DlDrawStyle::kStroke) { if (IsAntiAliased()) { // m = 1/8500 // c = 16 @@ -493,7 +493,7 @@ void DisplayListMetalComplexityCalculator::MetalHelper::ImageRect( const SkISize& size, bool texture_backed, bool render_with_attributes, - SkCanvas::SrcRectConstraint constraint) { + bool enforce_src_edges) { if (IsComplex()) { return; } @@ -512,16 +512,12 @@ void DisplayListMetalComplexityCalculator::MetalHelper::ImageRect( // m = 1/23000 // c = 2.3 complexity = (area + 52900) * 2 / 115; - if (render_with_attributes && - constraint == SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint && - IsAntiAliased()) { + if (render_with_attributes && enforce_src_edges && IsAntiAliased()) { // There's about a 30% performance penalty from the baseline. complexity *= 1.3f; } } else { - if (render_with_attributes && - constraint == SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint && - IsAntiAliased()) { + if (render_with_attributes && enforce_src_edges && IsAntiAliased()) { // m = 1/12200 // c = 2.75 complexity = (area + 33550) * 2 / 61; @@ -556,11 +552,15 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawImageNine( } void DisplayListMetalComplexityCalculator::MetalHelper::drawDisplayList( - const sk_sp display_list) { + const sk_sp display_list, + SkScalar opacity) { if (IsComplex()) { return; } MetalHelper helper(Ceiling() - CurrentComplexityScore()); + if (opacity < SK_Scalar1 && !display_list->can_apply_group_opacity()) { + helper.saveLayer(nullptr, SaveLayerOptions::kWithAttributes, nullptr); + } display_list->Dispatch(helper); AccumulateComplexity(helper.ComplexityScore()); } diff --git a/display_list/display_list_complexity_metal.h b/display_list/display_list_complexity_metal.h index 530335e343f30..94d3ca591bd92 100644 --- a/display_list/display_list_complexity_metal.h +++ b/display_list/display_list_complexity_metal.h @@ -65,7 +65,8 @@ class DisplayListMetalComplexityCalculator const SkRect& dst, DlFilterMode filter, bool render_with_attributes) override; - void drawDisplayList(const sk_sp display_list) override; + void drawDisplayList(const sk_sp display_list, + SkScalar opacity) override; void drawTextBlob(const sk_sp blob, SkScalar x, SkScalar y) override; @@ -79,7 +80,7 @@ class DisplayListMetalComplexityCalculator void ImageRect(const SkISize& size, bool texture_backed, bool render_with_attributes, - SkCanvas::SrcRectConstraint constraint) override; + bool enforce_src_edges) override; unsigned int BatchedComplexity() override; diff --git a/display_list/display_list_complexity_unittests.cc b/display_list/display_list_complexity_unittests.cc index b459a78b35c1b..3d4f9b0f5d1a3 100644 --- a/display_list/display_list_complexity_unittests.cc +++ b/display_list/display_list_complexity_unittests.cc @@ -76,12 +76,13 @@ TEST(DisplayListComplexity, NestedDisplayList) { TEST(DisplayListComplexity, AntiAliasing) { DisplayListBuilder builder_no_aa; - builder_no_aa.drawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100)); + builder_no_aa.DrawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100), + DlPaint()); auto display_list_no_aa = builder_no_aa.Build(); DisplayListBuilder builder_aa; - builder_aa.setAntiAlias(true); - builder_aa.drawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100)); + builder_aa.DrawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100), + DlPaint().setAntiAlias(true)); auto display_list_aa = builder_aa.Build(); auto calculators = AccumulatorCalculators(); @@ -93,13 +94,13 @@ TEST(DisplayListComplexity, AntiAliasing) { TEST(DisplayListComplexity, StrokeWidth) { DisplayListBuilder builder_stroke_0; - builder_stroke_0.setStrokeWidth(0.0f); - builder_stroke_0.drawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100)); + builder_stroke_0.DrawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100), + DlPaint().setStrokeWidth(0.0f)); auto display_list_stroke_0 = builder_stroke_0.Build(); DisplayListBuilder builder_stroke_1; - builder_stroke_1.setStrokeWidth(1.0f); - builder_stroke_1.drawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100)); + builder_stroke_0.DrawLine(SkPoint::Make(0, 0), SkPoint::Make(100, 100), + DlPaint().setStrokeWidth(1.0f)); auto display_list_stroke_1 = builder_stroke_1.Build(); auto calculators = AccumulatorCalculators(); @@ -111,13 +112,13 @@ TEST(DisplayListComplexity, StrokeWidth) { TEST(DisplayListComplexity, Style) { DisplayListBuilder builder_filled; - builder_filled.setStyle(DlDrawStyle::kFill); - builder_filled.drawRect(SkRect::MakeXYWH(10, 10, 80, 80)); + builder_filled.DrawRect(SkRect::MakeXYWH(10, 10, 80, 80), + DlPaint().setDrawStyle(DlDrawStyle::kFill)); auto display_list_filled = builder_filled.Build(); DisplayListBuilder builder_stroked; - builder_stroked.setStyle(DlDrawStyle::kStroke); - builder_stroked.drawRect(SkRect::MakeXYWH(10, 10, 80, 80)); + builder_stroked.DrawRect(SkRect::MakeXYWH(10, 10, 80, 80), + DlPaint().setDrawStyle(DlDrawStyle::kStroke)); auto display_list_stroked = builder_stroked.Build(); auto calculators = AccumulatorCalculators(); @@ -129,7 +130,7 @@ TEST(DisplayListComplexity, Style) { TEST(DisplayListComplexity, SaveLayers) { DisplayListBuilder builder; - builder.saveLayer(nullptr, true); + builder.SaveLayer(nullptr, nullptr); auto display_list = builder.Build(); auto calculators = AccumulatorCalculators(); @@ -144,7 +145,7 @@ TEST(DisplayListComplexity, DrawPath) { line_path.moveTo(SkPoint::Make(0, 0)); line_path.lineTo(SkPoint::Make(10, 10)); line_path.close(); - builder_line.drawPath(line_path); + builder_line.DrawPath(line_path, DlPaint()); auto display_list_line = builder_line.Build(); DisplayListBuilder builder_quad; @@ -152,7 +153,7 @@ TEST(DisplayListComplexity, DrawPath) { quad_path.moveTo(SkPoint::Make(0, 0)); quad_path.quadTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20)); quad_path.close(); - builder_quad.drawPath(quad_path); + builder_quad.DrawPath(quad_path, DlPaint()); auto display_list_quad = builder_quad.Build(); DisplayListBuilder builder_conic; @@ -160,7 +161,7 @@ TEST(DisplayListComplexity, DrawPath) { conic_path.moveTo(SkPoint::Make(0, 0)); conic_path.conicTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20), 1.5f); conic_path.close(); - builder_conic.drawPath(conic_path); + builder_conic.DrawPath(conic_path, DlPaint()); auto display_list_conic = builder_conic.Build(); DisplayListBuilder builder_cubic; @@ -168,7 +169,7 @@ TEST(DisplayListComplexity, DrawPath) { cubic_path.moveTo(SkPoint::Make(0, 0)); cubic_path.cubicTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20), SkPoint::Make(20, 20)); - builder_cubic.drawPath(cubic_path); + builder_cubic.DrawPath(cubic_path, DlPaint()); auto display_list_cubic = builder_cubic.Build(); auto calculators = AccumulatorCalculators(); @@ -186,7 +187,7 @@ TEST(DisplayListComplexity, DrawShadow) { line_path.moveTo(SkPoint::Make(0, 0)); line_path.lineTo(SkPoint::Make(10, 10)); line_path.close(); - builder_line.drawShadow(line_path, SK_ColorRED, 10.0f, false, 1.0f); + builder_line.DrawShadow(line_path, SK_ColorRED, 10.0f, false, 1.0f); auto display_list_line = builder_line.Build(); DisplayListBuilder builder_quad; @@ -194,7 +195,7 @@ TEST(DisplayListComplexity, DrawShadow) { quad_path.moveTo(SkPoint::Make(0, 0)); quad_path.quadTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20)); quad_path.close(); - builder_quad.drawShadow(quad_path, SK_ColorRED, 10.0f, false, 1.0f); + builder_quad.DrawShadow(quad_path, SK_ColorRED, 10.0f, false, 1.0f); auto display_list_quad = builder_quad.Build(); DisplayListBuilder builder_conic; @@ -202,7 +203,7 @@ TEST(DisplayListComplexity, DrawShadow) { conic_path.moveTo(SkPoint::Make(0, 0)); conic_path.conicTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20), 1.5f); conic_path.close(); - builder_conic.drawShadow(conic_path, SK_ColorRED, 10.0f, false, 1.0f); + builder_conic.DrawShadow(conic_path, SK_ColorRED, 10.0f, false, 1.0f); auto display_list_conic = builder_conic.Build(); DisplayListBuilder builder_cubic; @@ -210,7 +211,7 @@ TEST(DisplayListComplexity, DrawShadow) { cubic_path.moveTo(SkPoint::Make(0, 0)); cubic_path.cubicTo(SkPoint::Make(10, 10), SkPoint::Make(10, 20), SkPoint::Make(20, 20)); - builder_cubic.drawShadow(cubic_path, SK_ColorRED, 10.0f, false, 1.0f); + builder_cubic.DrawShadow(cubic_path, SK_ColorRED, 10.0f, false, 1.0f); auto display_list_cubic = builder_cubic.Build(); auto calculators = AccumulatorCalculators(); @@ -224,7 +225,7 @@ TEST(DisplayListComplexity, DrawShadow) { TEST(DisplayListComplexity, DrawOval) { DisplayListBuilder builder; - builder.drawOval(SkRect::MakeXYWH(10, 10, 100, 80)); + builder.DrawOval(SkRect::MakeXYWH(10, 10, 100, 80), DlPaint()); auto display_list = builder.Build(); auto calculators = AccumulatorCalculators(); @@ -235,7 +236,7 @@ TEST(DisplayListComplexity, DrawOval) { TEST(DisplayListComplexity, DrawCircle) { DisplayListBuilder builder; - builder.drawCircle(SkPoint::Make(50, 50), 10.0f); + builder.DrawCircle(SkPoint::Make(50, 50), 10.0f, DlPaint()); auto display_list = builder.Build(); auto calculators = AccumulatorCalculators(); @@ -246,8 +247,9 @@ TEST(DisplayListComplexity, DrawCircle) { TEST(DisplayListComplexity, DrawRRect) { DisplayListBuilder builder; - builder.drawRRect( - SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 10, 80, 80), 2.0f, 3.0f)); + builder.DrawRRect( + SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 10, 80, 80), 2.0f, 3.0f), + DlPaint()); auto display_list = builder.Build(); auto calculators = AccumulatorCalculators(); @@ -262,7 +264,7 @@ TEST(DisplayListComplexity, DrawDRRect) { SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 10, 80, 80), 2.0f, 3.0f); SkRRect inner = SkRRect::MakeRectXY(SkRect::MakeXYWH(15, 15, 70, 70), 1.5f, 1.5f); - builder.drawDRRect(outer, inner); + builder.DrawDRRect(outer, inner, DlPaint()); auto display_list = builder.Build(); auto calculators = AccumulatorCalculators(); @@ -273,7 +275,8 @@ TEST(DisplayListComplexity, DrawDRRect) { TEST(DisplayListComplexity, DrawArc) { DisplayListBuilder builder; - builder.drawArc(SkRect::MakeXYWH(10, 10, 100, 80), 0.0f, 10.0f, true); + builder.DrawArc(SkRect::MakeXYWH(10, 10, 100, 80), 0.0f, 10.0f, true, + DlPaint()); auto display_list = builder.Build(); auto calculators = AccumulatorCalculators(); @@ -287,7 +290,7 @@ TEST(DisplayListComplexity, DrawVertices) { auto vertices = DlVertices::Make(DlVertexMode::kTriangles, points.size(), points.data(), nullptr, nullptr); DisplayListBuilder builder; - builder.drawVertices(vertices, DlBlendMode::kSrc); + builder.DrawVertices(vertices.get(), DlBlendMode::kSrc, DlPaint()); auto display_list = builder.Build(); auto calculators = AccumulatorCalculators(); @@ -301,12 +304,12 @@ TEST(DisplayListComplexity, DrawTextBlob) { "The quick brown fox jumps over the lazy dog.", SkFont()); DisplayListBuilder builder; - builder.drawTextBlob(text_blob, 0.0f, 0.0f); + builder.DrawTextBlob(text_blob, 0.0f, 0.0f, DlPaint()); auto display_list = builder.Build(); DisplayListBuilder builder_multiple; - builder_multiple.drawTextBlob(text_blob, 0.0f, 0.0f); - builder_multiple.drawTextBlob(text_blob, 0.0f, 0.0f); + builder_multiple.DrawTextBlob(text_blob, 0.0f, 0.0f, DlPaint()); + builder_multiple.DrawTextBlob(text_blob, 0.0f, 0.0f, DlPaint()); auto display_list_multiple = builder_multiple.Build(); auto calculators = AccumulatorCalculators(); @@ -320,18 +323,18 @@ TEST(DisplayListComplexity, DrawTextBlob) { TEST(DisplayListComplexity, DrawPoints) { auto points = GetTestPoints(); DisplayListBuilder builder_lines; - builder_lines.drawPoints(DlCanvas::PointMode::kLines, points.size(), - points.data()); + builder_lines.DrawPoints(DlCanvas::PointMode::kLines, points.size(), + points.data(), DlPaint()); auto display_list_lines = builder_lines.Build(); DisplayListBuilder builder_points; - builder_points.drawPoints(DlCanvas::PointMode::kPoints, points.size(), - points.data()); + builder_points.DrawPoints(DlCanvas::PointMode::kPoints, points.size(), + points.data(), DlPaint()); auto display_list_points = builder_points.Build(); DisplayListBuilder builder_polygon; - builder_polygon.drawPoints(DlCanvas::PointMode::kPolygon, points.size(), - points.data()); + builder_polygon.DrawPoints(DlCanvas::PointMode::kPolygon, points.size(), + points.data(), DlPaint()); auto display_list_polygon = builder_polygon.Build(); auto calculators = AccumulatorCalculators(); @@ -351,8 +354,8 @@ TEST(DisplayListComplexity, DrawImage) { auto image = SkImage::MakeFromBitmap(bitmap); DisplayListBuilder builder; - builder.drawImage(DlImage::Make(image), SkPoint::Make(0, 0), - DlImageSampling::kNearestNeighbor, false); + builder.DrawImage(DlImage::Make(image), SkPoint::Make(0, 0), + DlImageSampling::kNearestNeighbor, nullptr); auto display_list = builder.Build(); auto calculators = AccumulatorCalculators(); @@ -373,8 +376,8 @@ TEST(DisplayListComplexity, DrawImageNine) { SkRect dest = SkRect::MakeXYWH(0, 0, 50, 50); DisplayListBuilder builder; - builder.drawImageNine(DlImage::Make(image), center, dest, - DlFilterMode::kNearest, true); + builder.DrawImageNine(DlImage::Make(image), center, dest, + DlFilterMode::kNearest, nullptr); auto display_list = builder.Build(); auto calculators = AccumulatorCalculators(); @@ -395,8 +398,8 @@ TEST(DisplayListComplexity, DrawImageRect) { SkRect dest = SkRect::MakeXYWH(0, 0, 50, 50); DisplayListBuilder builder; - builder.drawImageRect(DlImage::Make(image), src, dest, - DlImageSampling::kNearestNeighbor, true); + builder.DrawImageRect(DlImage::Make(image), src, dest, + DlImageSampling::kNearestNeighbor, nullptr); auto display_list = builder.Build(); auto calculators = AccumulatorCalculators(); @@ -421,9 +424,9 @@ TEST(DisplayListComplexity, DrawAtlas) { } DisplayListBuilder builder; - builder.drawAtlas(DlImage::Make(image), xforms.data(), rects.data(), nullptr, + builder.DrawAtlas(DlImage::Make(image), xforms.data(), rects.data(), nullptr, 10, DlBlendMode::kSrc, DlImageSampling::kNearestNeighbor, - nullptr, true); + nullptr, nullptr); auto display_list = builder.Build(); auto calculators = AccumulatorCalculators(); diff --git a/display_list/display_list_enum_unittests.cc b/display_list/display_list_enum_unittests.cc deleted file mode 100644 index 0da01c0cbdd1c..0000000000000 --- a/display_list/display_list_enum_unittests.cc +++ /dev/null @@ -1,172 +0,0 @@ -// 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" -#include "flutter/display_list/display_list_paint.h" -#include "flutter/display_list/display_list_sampling_options.h" -#include "flutter/display_list/display_list_tile_mode.h" -#include "flutter/display_list/display_list_vertices.h" -#include "flutter/display_list/types.h" -#include "gtest/gtest.h" -#include "include/core/SkSamplingOptions.h" - -namespace flutter { -namespace testing { - -TEST(DisplayListEnum, ToDlTileMode) { - ASSERT_EQ(ToDl(SkTileMode::kClamp), DlTileMode::kClamp); - ASSERT_EQ(ToDl(SkTileMode::kRepeat), DlTileMode::kRepeat); - ASSERT_EQ(ToDl(SkTileMode::kMirror), DlTileMode::kMirror); - ASSERT_EQ(ToDl(SkTileMode::kDecal), DlTileMode::kDecal); -} - -TEST(DisplayListEnum, ToSkTileMode) { - ASSERT_EQ(ToSk(DlTileMode::kClamp), SkTileMode::kClamp); - ASSERT_EQ(ToSk(DlTileMode::kRepeat), SkTileMode::kRepeat); - ASSERT_EQ(ToSk(DlTileMode::kMirror), SkTileMode::kMirror); - ASSERT_EQ(ToSk(DlTileMode::kDecal), SkTileMode::kDecal); -} - -TEST(DisplayListEnum, ToDlDrawStyle) { - ASSERT_EQ(ToDl(SkPaint::Style::kFill_Style), DlDrawStyle::kFill); - ASSERT_EQ(ToDl(SkPaint::Style::kStroke_Style), DlDrawStyle::kStroke); - ASSERT_EQ(ToDl(SkPaint::Style::kStrokeAndFill_Style), - DlDrawStyle::kStrokeAndFill); -} - -TEST(DisplayListEnum, ToSkDrawStyle) { - ASSERT_EQ(ToSk(DlDrawStyle::kFill), SkPaint::Style::kFill_Style); - ASSERT_EQ(ToSk(DlDrawStyle::kStroke), SkPaint::Style::kStroke_Style); - ASSERT_EQ(ToSk(DlDrawStyle::kStrokeAndFill), - SkPaint::Style::kStrokeAndFill_Style); -} - -TEST(DisplayListEnum, ToDlStrokeCap) { - ASSERT_EQ(ToDl(SkPaint::Cap::kButt_Cap), DlStrokeCap::kButt); - ASSERT_EQ(ToDl(SkPaint::Cap::kRound_Cap), DlStrokeCap::kRound); - ASSERT_EQ(ToDl(SkPaint::Cap::kSquare_Cap), DlStrokeCap::kSquare); -} - -TEST(DisplayListEnum, ToSkStrokeCap) { - ASSERT_EQ(ToSk(DlStrokeCap::kButt), SkPaint::Cap::kButt_Cap); - ASSERT_EQ(ToSk(DlStrokeCap::kRound), SkPaint::Cap::kRound_Cap); - ASSERT_EQ(ToSk(DlStrokeCap::kSquare), SkPaint::Cap::kSquare_Cap); -} - -TEST(DisplayListEnum, ToDlStrokeJoin) { - ASSERT_EQ(ToDl(SkPaint::Join::kMiter_Join), DlStrokeJoin::kMiter); - ASSERT_EQ(ToDl(SkPaint::Join::kRound_Join), DlStrokeJoin::kRound); - ASSERT_EQ(ToDl(SkPaint::Join::kBevel_Join), DlStrokeJoin::kBevel); -} - -TEST(DisplayListEnum, ToSkStrokeJoin) { - ASSERT_EQ(ToSk(DlStrokeJoin::kMiter), SkPaint::Join::kMiter_Join); - ASSERT_EQ(ToSk(DlStrokeJoin::kRound), SkPaint::Join::kRound_Join); - ASSERT_EQ(ToSk(DlStrokeJoin::kBevel), SkPaint::Join::kBevel_Join); -} - -TEST(DisplayListEnum, ToDlVertexMode) { - ASSERT_EQ(ToDl(SkVertices::VertexMode::kTriangles_VertexMode), - DlVertexMode::kTriangles); - ASSERT_EQ(ToDl(SkVertices::VertexMode::kTriangleStrip_VertexMode), - DlVertexMode::kTriangleStrip); - ASSERT_EQ(ToDl(SkVertices::VertexMode::kTriangleFan_VertexMode), - DlVertexMode::kTriangleFan); -} - -TEST(DisplayListEnum, ToSkVertexMode) { - ASSERT_EQ(ToSk(DlVertexMode::kTriangles), - SkVertices::VertexMode::kTriangles_VertexMode); - ASSERT_EQ(ToSk(DlVertexMode::kTriangleStrip), - SkVertices::VertexMode::kTriangleStrip_VertexMode); - ASSERT_EQ(ToSk(DlVertexMode::kTriangleFan), - SkVertices::VertexMode::kTriangleFan_VertexMode); -} - -TEST(DisplayListEnum, ToDlFilterMode) { - ASSERT_EQ(ToDl(SkFilterMode::kLinear), DlFilterMode::kLinear); - ASSERT_EQ(ToDl(SkFilterMode::kNearest), DlFilterMode::kNearest); - ASSERT_EQ(ToDl(SkFilterMode::kLast), DlFilterMode::kLast); -} - -TEST(DisplayListEnum, ToSkFilterMode) { - ASSERT_EQ(ToSk(DlFilterMode::kLinear), SkFilterMode::kLinear); - ASSERT_EQ(ToSk(DlFilterMode::kNearest), SkFilterMode::kNearest); - ASSERT_EQ(ToSk(DlFilterMode::kLast), SkFilterMode::kLast); -} - -TEST(DisplayListEnum, ToDlImageSampling) { - ASSERT_EQ(ToDl(SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone)), - DlImageSampling::kLinear); - ASSERT_EQ( - ToDl(SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear)), - DlImageSampling::kMipmapLinear); - ASSERT_EQ( - ToDl(SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone)), - DlImageSampling::kNearestNeighbor); - ASSERT_EQ(ToDl(SkSamplingOptions(SkCubicResampler{1 / 3.0f, 1 / 3.0f})), - DlImageSampling::kCubic); -} - -TEST(DisplayListEnum, ToSkSamplingOptions) { - ASSERT_EQ(ToSk(DlImageSampling::kLinear), - SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone)); - ASSERT_EQ(ToSk(DlImageSampling::kMipmapLinear), - SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear)); - ASSERT_EQ(ToSk(DlImageSampling::kNearestNeighbor), - SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone)); - ASSERT_EQ(ToSk(DlImageSampling::kCubic), - SkSamplingOptions(SkCubicResampler{1 / 3.0f, 1 / 3.0f})); -} - -#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_image_filter.h b/display_list/display_list_image_filter.h index 5e29bdb6b677a..c497d4f2bc53f 100644 --- a/display_list/display_list_image_filter.h +++ b/display_list/display_list_image_filter.h @@ -29,9 +29,9 @@ enum class DlImageFilterType { kDilate, kErode, kMatrix, - kComposeFilter, + kCompose, kColorFilter, - kLocalMatrixFilter, + kLocalMatrix, }; class DlBlurImageFilter; @@ -42,8 +42,7 @@ class DlLocalMatrixImageFilter; class DlComposeImageFilter; class DlColorFilterImageFilter; -class DlImageFilter - : public DlAttribute { +class DlImageFilter : public DlAttribute { public: enum class MatrixCapability { kTranslate, @@ -227,6 +226,16 @@ class DlBlurImageFilter final : public DlImageFilter { explicit DlBlurImageFilter(const DlBlurImageFilter& filter) : DlBlurImageFilter(&filter) {} + static std::shared_ptr Make(SkScalar sigma_x, + SkScalar sigma_y, + DlTileMode tile_mode) { + if (SkScalarIsFinite(sigma_x) && sigma_x > SK_ScalarNearlyZero && + SkScalarIsFinite(sigma_y) && sigma_y > SK_ScalarNearlyZero) { + return std::make_shared(sigma_x, sigma_y, tile_mode); + } + return nullptr; + } + std::shared_ptr shared() const override { return std::make_shared(this); } @@ -262,10 +271,6 @@ class DlBlurImageFilter final : public DlImageFilter { SkScalar sigma_y() const { return sigma_y_; } DlTileMode tile_mode() const { return tile_mode_; } - sk_sp skia_object() const override { - return SkImageFilters::Blur(sigma_x_, sigma_y_, ToSk(tile_mode_), nullptr); - } - protected: bool equals_(const DlImageFilter& other) const override { FML_DCHECK(other.type() == DlImageFilterType::kBlur); @@ -289,6 +294,15 @@ class DlDilateImageFilter final : public DlImageFilter { explicit DlDilateImageFilter(const DlDilateImageFilter& filter) : DlDilateImageFilter(&filter) {} + static std::shared_ptr Make(SkScalar radius_x, + SkScalar radius_y) { + if (SkScalarIsFinite(radius_x) && radius_x > SK_ScalarNearlyZero && + SkScalarIsFinite(radius_y) && radius_y > SK_ScalarNearlyZero) { + return std::make_shared(radius_x, radius_y); + } + return nullptr; + } + std::shared_ptr shared() const override { return std::make_shared(this); } @@ -323,10 +337,6 @@ class DlDilateImageFilter final : public DlImageFilter { SkScalar radius_x() const { return radius_x_; } SkScalar radius_y() const { return radius_y_; } - sk_sp skia_object() const override { - return SkImageFilters::Dilate(radius_x_, radius_y_, nullptr); - } - protected: bool equals_(const DlImageFilter& other) const override { FML_DCHECK(other.type() == DlImageFilterType::kDilate); @@ -348,6 +358,15 @@ class DlErodeImageFilter final : public DlImageFilter { explicit DlErodeImageFilter(const DlErodeImageFilter& filter) : DlErodeImageFilter(&filter) {} + static std::shared_ptr Make(SkScalar radius_x, + SkScalar radius_y) { + if (SkScalarIsFinite(radius_x) && radius_x > SK_ScalarNearlyZero && + SkScalarIsFinite(radius_y) && radius_y > SK_ScalarNearlyZero) { + return std::make_shared(radius_x, radius_y); + } + return nullptr; + } + std::shared_ptr shared() const override { return std::make_shared(this); } @@ -382,10 +401,6 @@ class DlErodeImageFilter final : public DlImageFilter { SkScalar radius_x() const { return radius_x_; } SkScalar radius_y() const { return radius_y_; } - sk_sp skia_object() const override { - return SkImageFilters::Erode(radius_x_, radius_y_, nullptr); - } - protected: bool equals_(const DlImageFilter& other) const override { FML_DCHECK(other.type() == DlImageFilterType::kErode); @@ -407,6 +422,14 @@ class DlMatrixImageFilter final : public DlImageFilter { explicit DlMatrixImageFilter(const DlMatrixImageFilter& filter) : DlMatrixImageFilter(&filter) {} + static std::shared_ptr Make(const SkMatrix& matrix, + DlImageSampling sampling) { + if (matrix.isFinite() && !matrix.isIdentity()) { + return std::make_shared(matrix, sampling); + } + return nullptr; + } + std::shared_ptr shared() const override { return std::make_shared(this); } @@ -460,10 +483,6 @@ class DlMatrixImageFilter final : public DlImageFilter { return &input_bounds; } - sk_sp skia_object() const override { - return SkImageFilters::MatrixTransform(matrix_, ToSk(sampling_), nullptr); - } - protected: bool equals_(const DlImageFilter& other) const override { FML_DCHECK(other.type() == DlImageFilterType::kMatrix); @@ -478,8 +497,8 @@ class DlMatrixImageFilter final : public DlImageFilter { class DlComposeImageFilter final : public DlImageFilter { public: - DlComposeImageFilter(std::shared_ptr outer, - std::shared_ptr inner) + DlComposeImageFilter(std::shared_ptr outer, + std::shared_ptr inner) : outer_(std::move(outer)), inner_(std::move(inner)) {} DlComposeImageFilter(const DlImageFilter* outer, const DlImageFilter* inner) : outer_(outer->shared()), inner_(inner->shared()) {} @@ -490,17 +509,29 @@ class DlComposeImageFilter final : public DlImageFilter { explicit DlComposeImageFilter(const DlComposeImageFilter& filter) : DlComposeImageFilter(&filter) {} + static std::shared_ptr Make( + std::shared_ptr outer, + std::shared_ptr inner) { + if (!outer) { + return inner; + } + if (!inner) { + return outer; + } + return std::make_shared(outer, inner); + } + std::shared_ptr shared() const override { return std::make_shared(this); } DlImageFilterType type() const override { - return DlImageFilterType::kComposeFilter; + return DlImageFilterType::kCompose; } size_t size() const override { return sizeof(*this); } - std::shared_ptr outer() const { return outer_; } - std::shared_ptr inner() const { return inner_; } + std::shared_ptr outer() const { return outer_; } + std::shared_ptr inner() const { return inner_; } const DlComposeImageFilter* asCompose() const override { return this; } @@ -525,30 +556,25 @@ class DlComposeImageFilter final : public DlImageFilter { const SkMatrix& ctm, SkIRect& input_bounds) const override; - sk_sp skia_object() const override { - return SkImageFilters::Compose(outer_->skia_object(), - inner_->skia_object()); - } - MatrixCapability matrix_capability() const override { return std::min(outer_->matrix_capability(), inner_->matrix_capability()); } protected: bool equals_(const DlImageFilter& other) const override { - FML_DCHECK(other.type() == DlImageFilterType::kComposeFilter); + FML_DCHECK(other.type() == DlImageFilterType::kCompose); auto that = static_cast(&other); return (Equals(outer_, that->outer_) && Equals(inner_, that->inner_)); } private: - std::shared_ptr outer_; - std::shared_ptr inner_; + std::shared_ptr outer_; + std::shared_ptr inner_; }; class DlColorFilterImageFilter final : public DlImageFilter { public: - explicit DlColorFilterImageFilter(std::shared_ptr filter) + explicit DlColorFilterImageFilter(std::shared_ptr filter) : color_filter_(std::move(filter)) {} explicit DlColorFilterImageFilter(const DlColorFilter* filter) : color_filter_(filter->shared()) {} @@ -559,6 +585,14 @@ class DlColorFilterImageFilter final : public DlImageFilter { explicit DlColorFilterImageFilter(const DlColorFilterImageFilter& filter) : DlColorFilterImageFilter(&filter) {} + static std::shared_ptr Make( + std::shared_ptr filter) { + if (filter) { + return std::make_shared(filter); + } + return nullptr; + } + std::shared_ptr shared() const override { return std::make_shared(color_filter_); } @@ -568,7 +602,7 @@ class DlColorFilterImageFilter final : public DlImageFilter { } size_t size() const override { return sizeof(*this); } - const std::shared_ptr color_filter() const { + const std::shared_ptr color_filter() const { return color_filter_; } @@ -602,10 +636,6 @@ class DlColorFilterImageFilter final : public DlImageFilter { return map_device_bounds(output_bounds, ctm, input_bounds); } - sk_sp skia_object() const override { - return SkImageFilters::ColorFilter(color_filter_->skia_object(), nullptr); - } - MatrixCapability matrix_capability() const override { return MatrixCapability::kComplex; } @@ -623,7 +653,7 @@ class DlColorFilterImageFilter final : public DlImageFilter { } private: - std::shared_ptr color_filter_; + std::shared_ptr color_filter_; }; class DlLocalMatrixImageFilter final : public DlImageFilter { @@ -640,7 +670,7 @@ class DlLocalMatrixImageFilter final : public DlImageFilter { } DlImageFilterType type() const override { - return DlImageFilterType::kLocalMatrixFilter; + return DlImageFilterType::kLocalMatrix; } size_t size() const override { return sizeof(*this); } @@ -689,20 +719,9 @@ class DlLocalMatrixImageFilter final : public DlImageFilter { output_bounds, SkMatrix::Concat(ctm, matrix_), input_bounds); } - sk_sp skia_object() const override { - if (!image_filter_) { - return nullptr; - } - sk_sp skia_object = image_filter_->skia_object(); - if (!skia_object) { - return nullptr; - } - return skia_object->makeWithLocalMatrix(matrix_); - } - protected: bool equals_(const DlImageFilter& other) const override { - FML_DCHECK(other.type() == DlImageFilterType::kLocalMatrixFilter); + FML_DCHECK(other.type() == DlImageFilterType::kLocalMatrix); auto that = static_cast(&other); return (matrix_ == that->matrix_ && Equals(image_filter_, that->image_filter_)); diff --git a/display_list/display_list_image_filter_unittests.cc b/display_list/display_list_image_filter_unittests.cc index 7e125dbd85ccb..1cc0231e1e45e 100644 --- a/display_list/display_list_image_filter_unittests.cc +++ b/display_list/display_list_image_filter_unittests.cc @@ -17,21 +17,6 @@ namespace flutter { namespace testing { -TEST(DisplayListImageFilter, BuilderSetGet) { - DlBlurImageFilter filter(5.0, 5.0, DlTileMode::kDecal); - DisplayListBuilder builder; - - ASSERT_EQ(builder.getImageFilter(), nullptr); - - builder.setImageFilter(&filter); - ASSERT_NE(builder.getImageFilter(), nullptr); - ASSERT_TRUE( - Equals(builder.getImageFilter(), static_cast(&filter))); - - builder.setImageFilter(nullptr); - ASSERT_EQ(builder.getImageFilter(), nullptr); -} - // SkRect::contains treats the rect as a half-open interval which is // appropriate for so many operations. Unfortunately, we are using // it here to test containment of the corners of a transformed quad @@ -708,8 +693,8 @@ TEST(DisplayListImageFilter, LocalImageFilterBounds) { SkImageFilters::ColorFilter( SkColorFilters::Blend(SK_ColorRED, SkBlendMode::kSrcOver), nullptr), SkImageFilters::Dilate(5.0, 10.0, nullptr), - SkImageFilters::MatrixTransform(filter_matrix, - ToSk(DlImageSampling::kLinear), nullptr), + SkImageFilters::MatrixTransform( + filter_matrix, SkSamplingOptions(SkFilterMode::kLinear), nullptr), SkImageFilters::Compose( SkImageFilters::Blur(5.0, 6.0, SkTileMode::kRepeat, nullptr), SkImageFilters::ColorFilter( @@ -785,15 +770,5 @@ TEST(DisplayListImageFilter, LocalImageFilterBounds) { } } -TEST(DisplayListImageFilter, LocalImageSkiaNull) { - auto blur_filter = - std::make_shared(0, 0, DlTileMode::kClamp); - DlLocalMatrixImageFilter dl_local_matrix_filter(SkMatrix::RotateDeg(45), - blur_filter); - // With sigmas set to zero on the blur filter, Skia will return a null filter. - // The local matrix filter should return nullptr instead of crashing. - ASSERT_EQ(dl_local_matrix_filter.skia_object(), nullptr); -} - } // namespace testing } // namespace flutter diff --git a/display_list/display_list_mask_filter.h b/display_list/display_list_mask_filter.h index 7e8c67826ea99..c48dae53c9d5a 100644 --- a/display_list/display_list_mask_filter.h +++ b/display_list/display_list_mask_filter.h @@ -20,8 +20,7 @@ class DlBlurMaskFilter; // An enumerated type for the supported MaskFilter operations. enum class DlMaskFilterType { kBlur }; -class DlMaskFilter - : public DlAttribute { +class DlMaskFilter : public DlAttribute { public: // Return a DlBlurMaskFilter pointer to this object iff it is a Blur // type of MaskFilter, otherwise return nullptr. @@ -43,6 +42,15 @@ class DlBlurMaskFilter final : public DlMaskFilter { : DlBlurMaskFilter(filter->style_, filter->sigma_, filter->respect_ctm_) { } + static std::shared_ptr Make(SkBlurStyle style, + SkScalar sigma, + bool respect_ctm = true) { + if (SkScalarIsFinite(sigma) && sigma > 0) { + return std::make_shared(style, sigma, respect_ctm); + } + return nullptr; + } + DlMaskFilterType type() const override { return DlMaskFilterType::kBlur; } size_t size() const override { return sizeof(*this); } @@ -50,10 +58,6 @@ class DlBlurMaskFilter final : public DlMaskFilter { return std::make_shared(this); } - sk_sp skia_object() const override { - return SkMaskFilter::MakeBlur(style_, sigma_, respect_ctm_); - } - const DlBlurMaskFilter* asBlur() const override { return this; } SkBlurStyle style() const { return style_; } diff --git a/display_list/display_list_mask_filter_unittests.cc b/display_list/display_list_mask_filter_unittests.cc index 5ae2261c63204..b7943607268be 100644 --- a/display_list/display_list_mask_filter_unittests.cc +++ b/display_list/display_list_mask_filter_unittests.cc @@ -12,18 +12,6 @@ namespace flutter { namespace testing { -TEST(DisplayListMaskFilter, BuilderSetGet) { - DlBlurMaskFilter filter(SkBlurStyle::kNormal_SkBlurStyle, 5.0); - DisplayListBuilder builder; - ASSERT_EQ(builder.getMaskFilter(), nullptr); - builder.setMaskFilter(&filter); - ASSERT_NE(builder.getMaskFilter(), nullptr); - ASSERT_TRUE( - Equals(builder.getMaskFilter(), static_cast(&filter))); - builder.setMaskFilter(nullptr); - ASSERT_EQ(builder.getMaskFilter(), nullptr); -} - TEST(DisplayListMaskFilter, BlurConstructor) { DlBlurMaskFilter filter(SkBlurStyle::kNormal_SkBlurStyle, 5.0); } diff --git a/display_list/display_list_ops.h b/display_list/display_list_ops.h index fb949b5419b7c..d0d084585f5c4 100644 --- a/display_list/display_list_ops.h +++ b/display_list/display_list_ops.h @@ -8,8 +8,8 @@ #include "display_list_color_source.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_sampling_options.h" +#include "flutter/display_list/dl_op_receiver.h" #include "flutter/display_list/types.h" #include "flutter/fml/macros.h" @@ -37,7 +37,7 @@ namespace flutter { // cheap to deal with a complicated "lifetime" tracking to // determine if they will be used. struct DispatchContext { - Dispatcher& dispatcher; + DlOpReceiver& receiver; int cur_index; int next_render_index; @@ -111,7 +111,7 @@ struct DLOp { const bool value; \ \ void dispatch(DispatchContext& ctx) const { \ - ctx.dispatcher.set##name(value); \ + ctx.receiver.set##name(value); \ } \ }; DEFINE_SET_BOOL_OP(AntiAlias) @@ -129,7 +129,7 @@ DEFINE_SET_BOOL_OP(InvertColors) const DlStroke##name value; \ \ void dispatch(DispatchContext& ctx) const { \ - ctx.dispatcher.setStroke##name(value); \ + ctx.receiver.setStroke##name(value); \ } \ }; DEFINE_SET_ENUM_OP(Cap) @@ -144,7 +144,7 @@ struct SetStyleOp final : DLOp { const DlDrawStyle style; - void dispatch(DispatchContext& ctx) const { ctx.dispatcher.setStyle(style); } + void dispatch(DispatchContext& ctx) const { ctx.receiver.setStyle(style); } }; // 4 byte header + 4 byte payload packs into minimum 8 bytes struct SetStrokeWidthOp final : DLOp { @@ -155,7 +155,7 @@ struct SetStrokeWidthOp final : DLOp { const float width; void dispatch(DispatchContext& ctx) const { - ctx.dispatcher.setStrokeWidth(width); + ctx.receiver.setStrokeWidth(width); } }; // 4 byte header + 4 byte payload packs into minimum 8 bytes @@ -167,7 +167,7 @@ struct SetStrokeMiterOp final : DLOp { const float limit; void dispatch(DispatchContext& ctx) const { - ctx.dispatcher.setStrokeMiter(limit); + ctx.receiver.setStrokeMiter(limit); } }; @@ -179,7 +179,7 @@ struct SetColorOp final : DLOp { const DlColor color; - void dispatch(DispatchContext& ctx) const { ctx.dispatcher.setColor(color); } + void dispatch(DispatchContext& ctx) const { ctx.receiver.setColor(color); } }; // 4 byte header + 4 byte payload packs into minimum 8 bytes struct SetBlendModeOp final : DLOp { @@ -189,8 +189,8 @@ struct SetBlendModeOp final : DLOp { const DlBlendMode mode; - void dispatch(DispatchContext& ctx) const { - ctx.dispatcher.setBlendMode(mode); + void dispatch(DispatchContext& ctx) const { // + ctx.receiver.setBlendMode(mode); } }; @@ -207,7 +207,7 @@ struct SetBlendModeOp final : DLOp { Clear##name##Op() {} \ \ void dispatch(DispatchContext& ctx) const { \ - ctx.dispatcher.set##name(nullptr); \ + ctx.receiver.set##name(nullptr); \ } \ }; \ struct SetPod##name##Op final : DLOp { \ @@ -217,7 +217,7 @@ struct SetBlendModeOp final : DLOp { \ void dispatch(DispatchContext& ctx) const { \ const Dl##name* filter = reinterpret_cast(this + 1); \ - ctx.dispatcher.set##name(filter); \ + ctx.receiver.set##name(filter); \ } \ }; DEFINE_SET_CLEAR_DLATTR_OP(ColorFilter, ColorFilter, filter) @@ -242,7 +242,7 @@ struct SetImageColorSourceOp : DLOp { const DlImageColorSource source; void dispatch(DispatchContext& ctx) const { - ctx.dispatcher.setColorSource(&source); + ctx.receiver.setColorSource(&source); } }; @@ -259,7 +259,7 @@ struct SetRuntimeEffectColorSourceOp : DLOp { const DlRuntimeEffectColorSource source; void dispatch(DispatchContext& ctx) const { - ctx.dispatcher.setColorSource(&source); + ctx.receiver.setColorSource(&source); } DisplayListCompare equals(const SetRuntimeEffectColorSourceOp* other) const { @@ -278,7 +278,7 @@ struct SetSceneColorSourceOp : DLOp { const DlSceneColorSource source; void dispatch(DispatchContext& ctx) const { - ctx.dispatcher.setColorSource(&source); + ctx.receiver.setColorSource(&source); } DisplayListCompare equals(const SetSceneColorSourceOp* other) const { @@ -298,7 +298,7 @@ struct SetSharedImageFilterOp : DLOp { const std::shared_ptr filter; void dispatch(DispatchContext& ctx) const { - ctx.dispatcher.setImageFilter(filter.get()); + ctx.receiver.setImageFilter(filter.get()); } DisplayListCompare equals(const SetSharedImageFilterOp* other) const { @@ -336,7 +336,7 @@ struct SaveOp final : SaveOpBase { void dispatch(DispatchContext& ctx) const { if (save_needed(ctx)) { - ctx.dispatcher.save(); + ctx.receiver.save(); } } }; @@ -348,7 +348,7 @@ struct SaveLayerOp final : SaveOpBase { void dispatch(DispatchContext& ctx) const { if (save_needed(ctx)) { - ctx.dispatcher.saveLayer(nullptr, options); + ctx.receiver.saveLayer(nullptr, options); } } }; @@ -363,7 +363,7 @@ struct SaveLayerBoundsOp final : SaveOpBase { void dispatch(DispatchContext& ctx) const { if (save_needed(ctx)) { - ctx.dispatcher.saveLayer(&rect, options); + ctx.receiver.saveLayer(&rect, options); } } }; @@ -379,7 +379,7 @@ struct SaveLayerBackdropOp final : SaveOpBase { void dispatch(DispatchContext& ctx) const { if (save_needed(ctx)) { - ctx.dispatcher.saveLayer(nullptr, options, backdrop.get()); + ctx.receiver.saveLayer(nullptr, options, backdrop.get()); } } @@ -403,7 +403,7 @@ struct SaveLayerBackdropBoundsOp final : SaveOpBase { void dispatch(DispatchContext& ctx) const { if (save_needed(ctx)) { - ctx.dispatcher.saveLayer(&rect, options, backdrop.get()); + ctx.receiver.saveLayer(&rect, options, backdrop.get()); } } @@ -423,7 +423,7 @@ struct RestoreOp final : DLOp { void dispatch(DispatchContext& ctx) const { DispatchContext::SaveInfo& info = ctx.save_infos.back(); if (info.save_was_needed) { - ctx.dispatcher.restore(); + ctx.receiver.restore(); } ctx.next_restore_index = info.previous_restore_index; ctx.save_infos.pop_back(); @@ -447,7 +447,7 @@ struct TranslateOp final : TransformClipOpBase { void dispatch(DispatchContext& ctx) const { if (op_needed(ctx)) { - ctx.dispatcher.translate(tx, ty); + ctx.receiver.translate(tx, ty); } } }; @@ -463,7 +463,7 @@ struct ScaleOp final : TransformClipOpBase { void dispatch(DispatchContext& ctx) const { if (op_needed(ctx)) { - ctx.dispatcher.scale(sx, sy); + ctx.receiver.scale(sx, sy); } } }; @@ -477,7 +477,7 @@ struct RotateOp final : TransformClipOpBase { void dispatch(DispatchContext& ctx) const { if (op_needed(ctx)) { - ctx.dispatcher.rotate(degrees); + ctx.receiver.rotate(degrees); } } }; @@ -493,7 +493,7 @@ struct SkewOp final : TransformClipOpBase { void dispatch(DispatchContext& ctx) const { if (op_needed(ctx)) { - ctx.dispatcher.skew(sx, sy); + ctx.receiver.skew(sx, sy); } } }; @@ -513,8 +513,8 @@ struct Transform2DAffineOp final : TransformClipOpBase { void dispatch(DispatchContext& ctx) const { if (op_needed(ctx)) { - ctx.dispatcher.transform2DAffine(mxx, mxy, mxt, // - myx, myy, myt); + ctx.receiver.transform2DAffine(mxx, mxy, mxt, // + myx, myy, myt); } } }; @@ -542,10 +542,10 @@ struct TransformFullPerspectiveOp final : TransformClipOpBase { void dispatch(DispatchContext& ctx) const { if (op_needed(ctx)) { - ctx.dispatcher.transformFullPerspective(mxx, mxy, mxz, mxt, // - myx, myy, myz, myt, // - mzx, mzy, mzz, mzt, // - mwx, mwy, mwz, mwt); + ctx.receiver.transformFullPerspective(mxx, mxy, mxz, mxt, // + myx, myy, myz, myt, // + mzx, mzy, mzz, mzt, // + mwx, mwy, mwz, mwt); } } }; @@ -558,7 +558,7 @@ struct TransformResetOp final : TransformClipOpBase { void dispatch(DispatchContext& ctx) const { if (op_needed(ctx)) { - ctx.dispatcher.transformReset(); + ctx.receiver.transformReset(); } } }; @@ -585,8 +585,8 @@ struct TransformResetOp final : TransformClipOpBase { \ void dispatch(DispatchContext& ctx) const { \ if (op_needed(ctx)) { \ - ctx.dispatcher.clip##shapetype(shape, DlCanvas::ClipOp::k##clipop, \ - is_aa); \ + ctx.receiver.clip##shapetype(shape, DlCanvas::ClipOp::k##clipop, \ + is_aa); \ } \ } \ }; @@ -596,27 +596,27 @@ DEFINE_CLIP_SHAPE_OP(Rect, Difference) DEFINE_CLIP_SHAPE_OP(RRect, Difference) #undef DEFINE_CLIP_SHAPE_OP -#define DEFINE_CLIP_PATH_OP(clipop) \ - struct Clip##clipop##PathOp final : TransformClipOpBase { \ - static const auto kType = DisplayListOpType::kClip##clipop##Path; \ - \ - Clip##clipop##PathOp(SkPath path, bool is_aa) \ - : is_aa(is_aa), path(path) {} \ - \ - const bool is_aa; \ - const SkPath path; \ - \ - void dispatch(DispatchContext& ctx) const { \ - if (op_needed(ctx)) { \ - ctx.dispatcher.clipPath(path, DlCanvas::ClipOp::k##clipop, is_aa); \ - } \ - } \ - \ - DisplayListCompare equals(const Clip##clipop##PathOp* other) const { \ - return is_aa == other->is_aa && path == other->path \ - ? DisplayListCompare::kEqual \ - : DisplayListCompare::kNotEqual; \ - } \ +#define DEFINE_CLIP_PATH_OP(clipop) \ + struct Clip##clipop##PathOp final : TransformClipOpBase { \ + static const auto kType = DisplayListOpType::kClip##clipop##Path; \ + \ + Clip##clipop##PathOp(SkPath path, bool is_aa) \ + : is_aa(is_aa), path(path) {} \ + \ + const bool is_aa; \ + const SkPath path; \ + \ + void dispatch(DispatchContext& ctx) const { \ + if (op_needed(ctx)) { \ + ctx.receiver.clipPath(path, DlCanvas::ClipOp::k##clipop, is_aa); \ + } \ + } \ + \ + DisplayListCompare equals(const Clip##clipop##PathOp* other) const { \ + return is_aa == other->is_aa && path == other->path \ + ? DisplayListCompare::kEqual \ + : DisplayListCompare::kNotEqual; \ + } \ }; DEFINE_CLIP_PATH_OP(Intersect) DEFINE_CLIP_PATH_OP(Difference) @@ -636,7 +636,7 @@ struct DrawPaintOp final : DrawOpBase { void dispatch(DispatchContext& ctx) const { if (op_needed(ctx)) { - ctx.dispatcher.drawPaint(); + ctx.receiver.drawPaint(); } } }; @@ -652,7 +652,7 @@ struct DrawColorOp final : DrawOpBase { void dispatch(DispatchContext& ctx) const { if (op_needed(ctx)) { - ctx.dispatcher.drawColor(color, mode); + ctx.receiver.drawColor(color, mode); } } }; @@ -672,7 +672,7 @@ struct DrawColorOp final : DrawOpBase { \ void dispatch(DispatchContext& ctx) const { \ if (op_needed(ctx)) { \ - ctx.dispatcher.draw##op_name(arg_name); \ + ctx.receiver.draw##op_name(arg_name); \ } \ } \ }; @@ -692,7 +692,7 @@ struct DrawPathOp final : DrawOpBase { void dispatch(DispatchContext& ctx) const { if (op_needed(ctx)) { - ctx.dispatcher.drawPath(path); + ctx.receiver.drawPath(path); } } @@ -720,7 +720,7 @@ struct DrawPathOp final : DrawOpBase { \ void dispatch(DispatchContext& ctx) const { \ if (op_needed(ctx)) { \ - ctx.dispatcher.draw##op_name(name1, name2); \ + ctx.receiver.draw##op_name(name1, name2); \ } \ } \ }; @@ -743,7 +743,7 @@ struct DrawArcOp final : DrawOpBase { void dispatch(DispatchContext& ctx) const { if (op_needed(ctx)) { - ctx.dispatcher.drawArc(bounds, start, sweep, center); + ctx.receiver.drawArc(bounds, start, sweep, center); } } }; @@ -754,20 +754,20 @@ struct DrawArcOp final : DrawOpBase { // so this op will always pack efficiently // The point type is packed into 3 different OpTypes to avoid expanding // the fixed payload beyond the 8 bytes -#define DEFINE_DRAW_POINTS_OP(name, mode) \ - struct Draw##name##Op final : DrawOpBase { \ - static const auto kType = DisplayListOpType::kDraw##name; \ - \ - explicit Draw##name##Op(uint32_t count) : count(count) {} \ - \ - const uint32_t count; \ - \ - void dispatch(DispatchContext& ctx) const { \ - if (op_needed(ctx)) { \ - const SkPoint* pts = reinterpret_cast(this + 1); \ - ctx.dispatcher.drawPoints(DlCanvas::PointMode::mode, count, pts); \ - } \ - } \ +#define DEFINE_DRAW_POINTS_OP(name, mode) \ + struct Draw##name##Op final : DrawOpBase { \ + static const auto kType = DisplayListOpType::kDraw##name; \ + \ + explicit Draw##name##Op(uint32_t count) : count(count) {} \ + \ + const uint32_t count; \ + \ + void dispatch(DispatchContext& ctx) const { \ + if (op_needed(ctx)) { \ + const SkPoint* pts = reinterpret_cast(this + 1); \ + ctx.receiver.drawPoints(DlCanvas::PointMode::mode, count, pts); \ + } \ + } \ }; DEFINE_DRAW_POINTS_OP(Points, kPoints); DEFINE_DRAW_POINTS_OP(Lines, kLines); @@ -792,38 +792,38 @@ struct DrawVerticesOp final : DrawOpBase { if (op_needed(ctx)) { const DlVertices* vertices = reinterpret_cast(this + 1); - ctx.dispatcher.drawVertices(vertices, mode); + ctx.receiver.drawVertices(vertices, mode); } } }; // 4 byte header + 40 byte payload uses 44 bytes but is rounded up to 48 bytes // (4 bytes unused) -#define DEFINE_DRAW_IMAGE_OP(name, with_attributes) \ - struct name##Op final : DrawOpBase { \ - static const auto kType = DisplayListOpType::k##name; \ - \ - name##Op(const sk_sp image, \ - const SkPoint& point, \ - DlImageSampling sampling) \ - : point(point), sampling(sampling), image(std::move(image)) {} \ - \ - const SkPoint point; \ - const DlImageSampling sampling; \ - const sk_sp image; \ - \ - void dispatch(DispatchContext& ctx) const { \ - if (op_needed(ctx)) { \ - ctx.dispatcher.drawImage(image, point, sampling, with_attributes); \ - } \ - } \ - \ - DisplayListCompare equals(const name##Op* other) const { \ - return (point == other->point && sampling == other->sampling && \ - image->Equals(other->image)) \ - ? DisplayListCompare::kEqual \ - : DisplayListCompare::kNotEqual; \ - } \ +#define DEFINE_DRAW_IMAGE_OP(name, with_attributes) \ + struct name##Op final : DrawOpBase { \ + static const auto kType = DisplayListOpType::k##name; \ + \ + name##Op(const sk_sp image, \ + const SkPoint& point, \ + DlImageSampling sampling) \ + : point(point), sampling(sampling), image(std::move(image)) {} \ + \ + const SkPoint point; \ + const DlImageSampling sampling; \ + const sk_sp image; \ + \ + void dispatch(DispatchContext& ctx) const { \ + if (op_needed(ctx)) { \ + ctx.receiver.drawImage(image, point, sampling, with_attributes); \ + } \ + } \ + \ + DisplayListCompare equals(const name##Op* other) const { \ + return (point == other->point && sampling == other->sampling && \ + image->Equals(other->image)) \ + ? DisplayListCompare::kEqual \ + : DisplayListCompare::kNotEqual; \ + } \ }; DEFINE_DRAW_IMAGE_OP(DrawImage, false) DEFINE_DRAW_IMAGE_OP(DrawImageWithAttr, true) @@ -839,25 +839,25 @@ struct DrawImageRectOp final : DrawOpBase { const SkRect& dst, DlImageSampling sampling, bool render_with_attributes, - SkCanvas::SrcRectConstraint constraint) + bool enforce_src_edges) : src(src), dst(dst), sampling(sampling), render_with_attributes(render_with_attributes), - constraint(constraint), + enforce_src_edges(enforce_src_edges), image(std::move(image)) {} const SkRect src; const SkRect dst; const DlImageSampling sampling; const bool render_with_attributes; - const SkCanvas::SrcRectConstraint constraint; + const bool enforce_src_edges; const sk_sp image; void dispatch(DispatchContext& ctx) const { if (op_needed(ctx)) { - ctx.dispatcher.drawImageRect(image, src, dst, sampling, - render_with_attributes, constraint); + ctx.receiver.drawImageRect(image, src, dst, sampling, + render_with_attributes, enforce_src_edges); } } @@ -865,7 +865,8 @@ struct DrawImageRectOp final : DrawOpBase { return (src == other->src && dst == other->dst && sampling == other->sampling && render_with_attributes == other->render_with_attributes && - constraint == other->constraint && image->Equals(other->image)) + enforce_src_edges == other->enforce_src_edges && + image->Equals(other->image)) ? DisplayListCompare::kEqual : DisplayListCompare::kNotEqual; } @@ -889,8 +890,8 @@ struct DrawImageRectOp final : DrawOpBase { \ void dispatch(DispatchContext& ctx) const { \ if (op_needed(ctx)) { \ - ctx.dispatcher.drawImageNine(image, center, dst, mode, \ - render_with_attributes); \ + ctx.receiver.drawImageNine(image, center, dst, mode, \ + render_with_attributes); \ } \ } \ \ @@ -976,8 +977,8 @@ struct DrawAtlasOp final : DrawAtlasBaseOp { const DlColor* colors = has_colors ? reinterpret_cast(tex + count) : nullptr; const DlBlendMode mode = static_cast(mode_index); - ctx.dispatcher.drawAtlas(atlas, xform, tex, colors, count, mode, sampling, - nullptr, render_with_attributes); + ctx.receiver.drawAtlas(atlas, xform, tex, colors, count, mode, sampling, + nullptr, render_with_attributes); } } @@ -1021,8 +1022,8 @@ struct DrawAtlasCulledOp final : DrawAtlasBaseOp { const DlColor* colors = has_colors ? reinterpret_cast(tex + count) : nullptr; const DlBlendMode mode = static_cast(mode_index); - ctx.dispatcher.drawAtlas(atlas, xform, tex, colors, count, mode, sampling, - &cull_rect, render_with_attributes); + ctx.receiver.drawAtlas(atlas, xform, tex, colors, count, mode, sampling, + &cull_rect, render_with_attributes); } } @@ -1041,19 +1042,22 @@ struct DrawAtlasCulledOp final : DrawAtlasBaseOp { struct DrawDisplayListOp final : DrawOpBase { static const auto kType = DisplayListOpType::kDrawDisplayList; - explicit DrawDisplayListOp(const sk_sp display_list) - : display_list(std::move(display_list)) {} + explicit DrawDisplayListOp(const sk_sp display_list, + SkScalar opacity) + : opacity(opacity), display_list(std::move(display_list)) {} + SkScalar opacity; const sk_sp display_list; void dispatch(DispatchContext& ctx) const { if (op_needed(ctx)) { - ctx.dispatcher.drawDisplayList(display_list); + ctx.receiver.drawDisplayList(display_list, opacity); } } DisplayListCompare equals(const DrawDisplayListOp* other) const { - return display_list->Equals(other->display_list) + return (opacity == other->opacity && + display_list->Equals(other->display_list)) ? DisplayListCompare::kEqual : DisplayListCompare::kNotEqual; } @@ -1073,33 +1077,33 @@ struct DrawTextBlobOp final : DrawOpBase { void dispatch(DispatchContext& ctx) const { if (op_needed(ctx)) { - ctx.dispatcher.drawTextBlob(blob, x, y); + ctx.receiver.drawTextBlob(blob, x, y); } } }; // 4 byte header + 28 byte payload packs evenly into 32 bytes -#define DEFINE_DRAW_SHADOW_OP(name, transparent_occluder) \ - struct Draw##name##Op final : DrawOpBase { \ - static const auto kType = DisplayListOpType::kDraw##name; \ - \ - Draw##name##Op(const SkPath& path, \ - DlColor color, \ - SkScalar elevation, \ - SkScalar dpr) \ - : color(color), elevation(elevation), dpr(dpr), path(path) {} \ - \ - const DlColor color; \ - const SkScalar elevation; \ - const SkScalar dpr; \ - const SkPath path; \ - \ - void dispatch(DispatchContext& ctx) const { \ - if (op_needed(ctx)) { \ - ctx.dispatcher.drawShadow(path, color, elevation, \ - transparent_occluder, dpr); \ - } \ - } \ +#define DEFINE_DRAW_SHADOW_OP(name, transparent_occluder) \ + struct Draw##name##Op final : DrawOpBase { \ + static const auto kType = DisplayListOpType::kDraw##name; \ + \ + Draw##name##Op(const SkPath& path, \ + DlColor color, \ + SkScalar elevation, \ + SkScalar dpr) \ + : color(color), elevation(elevation), dpr(dpr), path(path) {} \ + \ + const DlColor color; \ + const SkScalar elevation; \ + const SkScalar dpr; \ + const SkPath path; \ + \ + void dispatch(DispatchContext& ctx) const { \ + if (op_needed(ctx)) { \ + ctx.receiver.drawShadow(path, color, elevation, transparent_occluder, \ + dpr); \ + } \ + } \ }; DEFINE_DRAW_SHADOW_OP(Shadow, false) DEFINE_DRAW_SHADOW_OP(ShadowTransparentOccluder, true) diff --git a/display_list/display_list_paint.h b/display_list/display_list_paint.h index 871be229e7400..7bfdbfa309417 100644 --- a/display_list/display_list_paint.h +++ b/display_list/display_list_paint.h @@ -25,14 +25,6 @@ enum class DlDrawStyle { kDefaultStyle = kFill, }; -inline DlDrawStyle ToDl(SkPaint::Style style) { - return static_cast(style); -} - -inline SkPaint::Style ToSk(DlDrawStyle style) { - return static_cast(style); -} - enum class DlStrokeCap { kButt, //!< no stroke extension kRound, //!< adds circle @@ -42,14 +34,6 @@ enum class DlStrokeCap { kDefaultCap = kButt, }; -inline DlStrokeCap ToDl(SkPaint::Cap cap) { - return static_cast(cap); -} - -inline SkPaint::Cap ToSk(DlStrokeCap cap) { - return static_cast(cap); -} - enum class DlStrokeJoin { kMiter, //!< extends to miter limit kRound, //!< adds circle @@ -59,14 +43,6 @@ enum class DlStrokeJoin { kDefaultJoin = kMiter, }; -inline DlStrokeJoin ToDl(SkPaint::Join join) { - return static_cast(join); -} - -inline SkPaint::Join ToSk(DlStrokeJoin join) { - return static_cast(join); -} - class DlPaint { public: static constexpr DlColor kDefaultColor = DlColor::kBlack(); @@ -174,7 +150,7 @@ class DlPaint { } const DlColorFilter* getColorFilterPtr() const { return colorFilter_.get(); } DlPaint& setColorFilter(const std::shared_ptr filter) { - colorFilter_ = filter ? filter->shared() : nullptr; + colorFilter_ = filter; return *this; } DlPaint& setColorFilter(const DlColorFilter* filter) { @@ -216,6 +192,10 @@ class DlPaint { pathEffect_ = pathEffect; return *this; } + DlPaint& setPathEffect(const DlPathEffect* effect) { + pathEffect_ = effect ? effect->shared() : nullptr; + return *this; + } bool isDefault() const { return *this == kDefault; } diff --git a/display_list/display_list_path_effect.h b/display_list/display_list_path_effect.h index d03f1944dfc4d..f8bd030254f60 100644 --- a/display_list/display_list_path_effect.h +++ b/display_list/display_list_path_effect.h @@ -25,8 +25,7 @@ enum class DlPathEffectType { kDash, }; -class DlPathEffect - : public DlAttribute { +class DlPathEffect : public DlAttribute { public: virtual const DlDashPathEffect* asDash() const { return nullptr; } @@ -77,13 +76,11 @@ class DlDashPathEffect final : public DlPathEffect { const DlDashPathEffect* asDash() const override { return this; } - sk_sp skia_object() const override { - return SkDashPathEffect::Make(intervals(), count_, phase_); - } - const SkScalar* intervals() const { return reinterpret_cast(this + 1); } + int count() const { return count_; } + SkScalar phase() const { return phase_; } std::optional effect_bounds(SkRect& rect) const override; diff --git a/display_list/display_list_path_effect_unittests.cc b/display_list/display_list_path_effect_unittests.cc index 0067c37c3234b..e111108cd2974 100644 --- a/display_list/display_list_path_effect_unittests.cc +++ b/display_list/display_list_path_effect_unittests.cc @@ -13,19 +13,6 @@ namespace flutter { namespace testing { -TEST(DisplayListPathEffect, BuilderSetGet) { - const SkScalar test_dashes[] = {4.0, 2.0}; - auto dash_path_effect = DlDashPathEffect::Make(test_dashes, 2, 0.0); - DisplayListBuilder builder; - ASSERT_EQ(builder.getPathEffect(), nullptr); - builder.setPathEffect(dash_path_effect.get()); - ASSERT_NE(builder.getPathEffect(), nullptr); - ASSERT_TRUE(Equals(builder.getPathEffect(), - static_cast(dash_path_effect.get()))); - builder.setPathEffect(nullptr); - ASSERT_EQ(builder.getPathEffect(), nullptr); -} - TEST(DisplayListPathEffect, EffectShared) { const SkScalar TestDashes2[] = {1.0, 1.5}; auto effect = DlDashPathEffect::Make(TestDashes2, 2, 0.0); diff --git a/display_list/display_list_sampling_options.h b/display_list/display_list_sampling_options.h index b3f1afa5fa322..c3896bf6d57be 100644 --- a/display_list/display_list_sampling_options.h +++ b/display_list/display_list_sampling_options.h @@ -16,14 +16,6 @@ enum class DlFilterMode { kLast = kLinear, }; -inline DlFilterMode ToDl(const SkFilterMode filter_mode) { - return static_cast(filter_mode); -} - -inline SkFilterMode ToSk(const DlFilterMode filter_mode) { - return static_cast(filter_mode); -} - enum class DlImageSampling { kNearestNeighbor, kLinear, @@ -31,34 +23,6 @@ enum class DlImageSampling { kCubic, }; -inline DlImageSampling ToDl(const SkSamplingOptions& so) { - if (so.useCubic) { - return DlImageSampling::kCubic; - } - if (so.filter == SkFilterMode::kLinear) { - if (so.mipmap == SkMipmapMode::kNone) { - return DlImageSampling::kLinear; - } - if (so.mipmap == SkMipmapMode::kLinear) { - return DlImageSampling::kMipmapLinear; - } - } - return DlImageSampling::kNearestNeighbor; -} - -inline SkSamplingOptions ToSk(DlImageSampling sampling) { - switch (sampling) { - case DlImageSampling::kCubic: - return SkSamplingOptions(SkCubicResampler{1 / 3.0f, 1 / 3.0f}); - case DlImageSampling::kLinear: - return SkSamplingOptions(SkFilterMode::kLinear); - case DlImageSampling::kMipmapLinear: - return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear); - case DlImageSampling::kNearestNeighbor: - return SkSamplingOptions(SkFilterMode::kNearest); - } -} - } // namespace flutter #endif // FLUTTER_DISPLAY_LIST_DISPLAY_LIST_SAMPLING_OPTIONS_H_ diff --git a/display_list/display_list_tile_mode.h b/display_list/display_list_tile_mode.h index 0be9b54ae307d..15c04cffdc82f 100644 --- a/display_list/display_list_tile_mode.h +++ b/display_list/display_list_tile_mode.h @@ -30,14 +30,6 @@ enum class DlTileMode { kDecal, }; -inline DlTileMode ToDl(SkTileMode sk_mode) { - return static_cast(sk_mode); -} - -inline SkTileMode ToSk(DlTileMode dl_mode) { - return static_cast(dl_mode); -} - } // namespace flutter #endif // FLUTTER_DISPLAY_LIST_DISPLAY_LIST_TILE_MODE_H_ diff --git a/display_list/display_list_unittests.cc b/display_list/display_list_unittests.cc index c7b2311301821..6b8897cdce954 100644 --- a/display_list/display_list_unittests.cc +++ b/display_list/display_list_unittests.cc @@ -14,6 +14,7 @@ #include "flutter/display_list/display_list_paint.h" #include "flutter/display_list/display_list_rtree.h" #include "flutter/display_list/display_list_utils.h" +#include "flutter/display_list/skia/dl_sk_dispatcher.h" #include "flutter/display_list/testing/dl_test_snippets.h" #include "flutter/fml/logging.h" #include "flutter/fml/math.h" @@ -24,6 +25,11 @@ #include "third_party/skia/include/core/SkSurface.h" namespace flutter { + +DlOpReceiver& DisplayListBuilderTestingAccessor(DisplayListBuilder& builder) { + return builder.asReceiver(); +} + namespace testing { static std::vector allGroups = @@ -32,7 +38,61 @@ static std::vector allGroups = using ClipOp = DlCanvas::ClipOp; using PointMode = DlCanvas::PointMode; -TEST(DisplayList, BuilderCanBeReused) { +template +class DisplayListTestBase : public BaseT { + public: + DisplayListTestBase() = default; + + static DlOpReceiver& ToReceiver(DisplayListBuilder& builder) { + return DisplayListBuilderTestingAccessor(builder); + } + + static sk_sp Build(DisplayListInvocation& invocation) { + DisplayListBuilder builder; + invocation.Invoke(ToReceiver(builder)); + return builder.Build(); + } + + static sk_sp Build(size_t g_index, size_t v_index) { + DisplayListBuilder builder; + DlOpReceiver& receiver = + DisplayListTestBase<::testing::Test>::ToReceiver(builder); + unsigned int op_count = 0; + size_t byte_count = 0; + for (size_t i = 0; i < allGroups.size(); i++) { + DisplayListInvocationGroup& group = allGroups[i]; + size_t j = (i == g_index ? v_index : 0); + if (j >= group.variants.size()) { + continue; + } + DisplayListInvocation& invocation = group.variants[j]; + op_count += invocation.op_count(); + byte_count += invocation.raw_byte_count(); + invocation.invoker(receiver); + } + sk_sp dl = builder.Build(); + std::string name; + if (g_index >= allGroups.size()) { + name = "Default"; + } else { + name = allGroups[g_index].op_name; + if (v_index >= allGroups[g_index].variants.size()) { + name += " skipped"; + } else { + name += " variant " + std::to_string(v_index + 1); + } + } + EXPECT_EQ(dl->op_count(false), op_count) << name; + EXPECT_EQ(dl->bytes(false), byte_count + sizeof(DisplayList)) << name; + return dl; + } + + private: + FML_DISALLOW_COPY_AND_ASSIGN(DisplayListTestBase); +}; +using DisplayListTest = DisplayListTestBase<::testing::Test>; + +TEST_F(DisplayListTest, BuilderCanBeReused) { DisplayListBuilder builder(kTestBounds); builder.DrawRect(kTestBounds, DlPaint()); auto dl = builder.Build(); @@ -41,7 +101,7 @@ TEST(DisplayList, BuilderCanBeReused) { ASSERT_TRUE(dl->Equals(dl2)); } -TEST(DisplayList, BuilderBoundsTransformComparedToSkia) { +TEST_F(DisplayListTest, BuilderBoundsTransformComparedToSkia) { const SkRect frame_rect = SkRect::MakeLTRB(10, 10, 100, 100); DisplayListBuilder builder(frame_rect); SkPictureRecorder recorder; @@ -53,60 +113,60 @@ TEST(DisplayList, BuilderBoundsTransformComparedToSkia) { ASSERT_EQ(builder.GetTransform(), canvas->getTotalMatrix()); } -TEST(DisplayList, BuilderInitialClipBounds) { +TEST_F(DisplayListTest, BuilderInitialClipBounds) { SkRect cull_rect = SkRect::MakeWH(100, 100); SkRect clip_bounds = SkRect::MakeWH(100, 100); DisplayListBuilder builder(cull_rect); ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds); } -TEST(DisplayList, BuilderInitialClipBoundsNaN) { +TEST_F(DisplayListTest, BuilderInitialClipBoundsNaN) { SkRect cull_rect = SkRect::MakeWH(SK_ScalarNaN, SK_ScalarNaN); SkRect clip_bounds = SkRect::MakeEmpty(); DisplayListBuilder builder(cull_rect); ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds); } -TEST(DisplayList, BuilderClipBoundsAfterClipRect) { +TEST_F(DisplayListTest, BuilderClipBoundsAfterClipRect) { SkRect cull_rect = SkRect::MakeWH(100, 100); SkRect clip_rect = SkRect::MakeLTRB(10, 10, 20, 20); SkRect clip_bounds = SkRect::MakeLTRB(10, 10, 20, 20); DisplayListBuilder builder(cull_rect); - builder.clipRect(clip_rect, ClipOp::kIntersect, false); + builder.ClipRect(clip_rect, ClipOp::kIntersect, false); ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds); } -TEST(DisplayList, BuilderClipBoundsAfterClipRRect) { +TEST_F(DisplayListTest, BuilderClipBoundsAfterClipRRect) { SkRect cull_rect = SkRect::MakeWH(100, 100); SkRect clip_rect = SkRect::MakeLTRB(10, 10, 20, 20); SkRRect clip_rrect = SkRRect::MakeRectXY(clip_rect, 2, 2); SkRect clip_bounds = SkRect::MakeLTRB(10, 10, 20, 20); DisplayListBuilder builder(cull_rect); - builder.clipRRect(clip_rrect, ClipOp::kIntersect, false); + builder.ClipRRect(clip_rrect, ClipOp::kIntersect, false); ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds); } -TEST(DisplayList, BuilderClipBoundsAfterClipPath) { +TEST_F(DisplayListTest, BuilderClipBoundsAfterClipPath) { SkRect cull_rect = SkRect::MakeWH(100, 100); SkPath clip_path = SkPath().addRect(10, 10, 15, 15).addRect(15, 15, 20, 20); SkRect clip_bounds = SkRect::MakeLTRB(10, 10, 20, 20); DisplayListBuilder builder(cull_rect); - builder.clipPath(clip_path, ClipOp::kIntersect, false); + builder.ClipPath(clip_path, ClipOp::kIntersect, false); ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds); } -TEST(DisplayList, BuilderInitialClipBoundsNonZero) { +TEST_F(DisplayListTest, BuilderInitialClipBoundsNonZero) { SkRect cull_rect = SkRect::MakeLTRB(10, 10, 100, 100); SkRect clip_bounds = SkRect::MakeLTRB(10, 10, 100, 100); DisplayListBuilder builder(cull_rect); ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds); } -TEST(DisplayList, SingleOpSizes) { +TEST_F(DisplayListTest, SingleOpSizes) { for (auto& group : allGroups) { for (size_t i = 0; i < group.variants.size(); i++) { auto& invocation = group.variants[i]; - sk_sp dl = invocation.Build(); + sk_sp dl = Build(invocation); auto desc = group.op_name + "(variant " + std::to_string(i + 1) + ")"; ASSERT_EQ(dl->op_count(false), invocation.op_count()) << desc; ASSERT_EQ(dl->bytes(false), invocation.byte_count()) << desc; @@ -114,11 +174,11 @@ TEST(DisplayList, SingleOpSizes) { } } -TEST(DisplayList, SingleOpDisplayListsNotEqualEmpty) { +TEST_F(DisplayListTest, SingleOpDisplayListsNotEqualEmpty) { sk_sp empty = DisplayListBuilder().Build(); for (auto& group : allGroups) { for (size_t i = 0; i < group.variants.size(); i++) { - sk_sp dl = group.variants[i].Build(); + sk_sp dl = Build(group.variants[i]); auto desc = group.op_name + "(variant " + std::to_string(i + 1) + " != empty)"; if (group.variants[i].is_empty()) { @@ -132,15 +192,16 @@ TEST(DisplayList, SingleOpDisplayListsNotEqualEmpty) { } } -TEST(DisplayList, SingleOpDisplayListsRecapturedAreEqual) { +TEST_F(DisplayListTest, SingleOpDisplayListsRecapturedAreEqual) { for (auto& group : allGroups) { for (size_t i = 0; i < group.variants.size(); i++) { - sk_sp dl = group.variants[i].Build(); + sk_sp dl = Build(group.variants[i]); // Verify recapturing the replay of the display list is Equals() // when dispatching directly from the DL to another builder - DisplayListBuilder builder; - dl->Dispatch(builder.asDispatcher()); - sk_sp copy = builder.Build(); + DisplayListBuilder copy_builder; + DlOpReceiver& r = ToReceiver(copy_builder); + dl->Dispatch(r); + sk_sp copy = copy_builder.Build(); auto desc = group.op_name + "(variant " + std::to_string(i + 1) + " == copy)"; ASSERT_EQ(copy->op_count(false), dl->op_count(false)) << desc; @@ -154,13 +215,13 @@ TEST(DisplayList, SingleOpDisplayListsRecapturedAreEqual) { } } -TEST(DisplayList, SingleOpDisplayListsCompareToEachOther) { +TEST_F(DisplayListTest, SingleOpDisplayListsCompareToEachOther) { for (auto& group : allGroups) { std::vector> lists_a; std::vector> lists_b; for (size_t i = 0; i < group.variants.size(); i++) { - lists_a.push_back(group.variants[i].Build()); - lists_b.push_back(group.variants[i].Build()); + lists_a.push_back(Build(group.variants[i])); + lists_b.push_back(Build(group.variants[i])); } for (size_t i = 0; i < lists_a.size(); i++) { @@ -190,13 +251,13 @@ TEST(DisplayList, SingleOpDisplayListsCompareToEachOther) { } } -TEST(DisplayList, SingleOpDisplayListsAreEqualWhetherOrNotToPrepareRtree) { +TEST_F(DisplayListTest, SingleOpDisplayListsAreEqualWithOrWithoutRtree) { for (auto& group : allGroups) { for (size_t i = 0; i < group.variants.size(); i++) { DisplayListBuilder builder1(/*prepare_rtree=*/false); DisplayListBuilder builder2(/*prepare_rtree=*/true); - group.variants[i].invoker(builder1); - group.variants[i].invoker(builder2); + group.variants[i].invoker(ToReceiver(builder1)); + group.variants[i].invoker(ToReceiver(builder2)); sk_sp dl1 = builder1.Build(); sk_sp dl2 = builder2.Build(); @@ -214,13 +275,14 @@ TEST(DisplayList, SingleOpDisplayListsAreEqualWhetherOrNotToPrepareRtree) { } } -TEST(DisplayList, FullRotationsAreNop) { +TEST_F(DisplayListTest, FullRotationsAreNop) { DisplayListBuilder builder; - builder.rotate(0); - builder.rotate(360); - builder.rotate(720); - builder.rotate(1080); - builder.rotate(1440); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.rotate(0); + receiver.rotate(360); + receiver.rotate(720); + receiver.rotate(1080); + receiver.rotate(1440); sk_sp dl = builder.Build(); ASSERT_EQ(dl->bytes(false), sizeof(DisplayList)); ASSERT_EQ(dl->bytes(true), sizeof(DisplayList)); @@ -228,9 +290,10 @@ TEST(DisplayList, FullRotationsAreNop) { ASSERT_EQ(dl->op_count(true), 0u); } -TEST(DisplayList, AllBlendModeNops) { +TEST_F(DisplayListTest, AllBlendModeNops) { DisplayListBuilder builder; - builder.setBlendMode(DlBlendMode::kSrcOver); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.setBlendMode(DlBlendMode::kSrcOver); sk_sp dl = builder.Build(); ASSERT_EQ(dl->bytes(false), sizeof(DisplayList)); ASSERT_EQ(dl->bytes(true), sizeof(DisplayList)); @@ -238,39 +301,7 @@ TEST(DisplayList, AllBlendModeNops) { ASSERT_EQ(dl->op_count(true), 0u); } -static sk_sp Build(size_t g_index, size_t v_index) { - DisplayListBuilder builder; - unsigned int op_count = 0; - size_t byte_count = 0; - for (size_t i = 0; i < allGroups.size(); i++) { - DisplayListInvocationGroup& group = allGroups[i]; - size_t j = (i == g_index ? v_index : 0); - if (j >= group.variants.size()) { - continue; - } - DisplayListInvocation& invocation = group.variants[j]; - op_count += invocation.op_count(); - byte_count += invocation.raw_byte_count(); - invocation.invoker(builder); - } - sk_sp dl = builder.Build(); - std::string name; - if (g_index >= allGroups.size()) { - name = "Default"; - } else { - name = allGroups[g_index].op_name; - if (v_index >= allGroups[g_index].variants.size()) { - name += " skipped"; - } else { - name += " variant " + std::to_string(v_index + 1); - } - } - EXPECT_EQ(dl->op_count(false), op_count) << name; - EXPECT_EQ(dl->bytes(false), byte_count + sizeof(DisplayList)) << name; - return dl; -} - -TEST(DisplayList, DisplayListsWithVaryingOpComparisons) { +TEST_F(DisplayListTest, DisplayListsWithVaryingOpComparisons) { sk_sp default_dl = Build(allGroups.size(), 0); ASSERT_TRUE(default_dl->Equals(*default_dl)) << "Default == itself"; for (size_t gi = 0; gi < allGroups.size(); gi++) { @@ -303,7 +334,7 @@ TEST(DisplayList, DisplayListsWithVaryingOpComparisons) { } } -TEST(DisplayList, DisplayListSaveLayerBoundsWithAlphaFilter) { +TEST_F(DisplayListTest, DisplayListSaveLayerBoundsWithAlphaFilter) { SkRect build_bounds = SkRect::MakeLTRB(-100, -100, 200, 200); SkRect save_bounds = SkRect::MakeWH(100, 100); SkRect rect = SkRect::MakeLTRB(30, 30, 70, 70); @@ -325,13 +356,16 @@ TEST(DisplayList, DisplayListSaveLayerBoundsWithAlphaFilter) { }; // clang-format on DlMatrixColorFilter alpha_color_filter(alpha_matrix); + sk_sp sk_alpha_color_filter = + SkColorFilters::Matrix(alpha_matrix); { // No tricky stuff, just verifying drawing a rect produces rect bounds DisplayListBuilder builder(build_bounds); - builder.saveLayer(&save_bounds, true); - builder.drawRect(rect); - builder.restore(); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.saveLayer(&save_bounds, SaveLayerOptions::kWithAttributes); + receiver.drawRect(rect); + receiver.restore(); sk_sp display_list = builder.Build(); ASSERT_EQ(display_list->bounds(), rect); } @@ -339,11 +373,12 @@ TEST(DisplayList, DisplayListSaveLayerBoundsWithAlphaFilter) { { // Now checking that a normal color filter still produces rect bounds DisplayListBuilder builder(build_bounds); - builder.setColorFilter(&base_color_filter); - builder.saveLayer(&save_bounds, true); - builder.setColorFilter(nullptr); - builder.drawRect(rect); - builder.restore(); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.setColorFilter(&base_color_filter); + receiver.saveLayer(&save_bounds, SaveLayerOptions::kWithAttributes); + receiver.setColorFilter(nullptr); + receiver.drawRect(rect); + receiver.restore(); sk_sp display_list = builder.Build(); ASSERT_EQ(display_list->bounds(), rect); } @@ -356,7 +391,7 @@ TEST(DisplayList, DisplayListSaveLayerBoundsWithAlphaFilter) { SkRTreeFactory rtree_factory; SkCanvas* canvas = recorder.beginRecording(build_bounds, &rtree_factory); SkPaint p1; - p1.setColorFilter(alpha_color_filter.skia_object()); + p1.setColorFilter(sk_alpha_color_filter); canvas->saveLayer(save_bounds, &p1); SkPaint p2; canvas->drawRect(rect, p2); @@ -371,11 +406,12 @@ TEST(DisplayList, DisplayListSaveLayerBoundsWithAlphaFilter) { // cull rect of the DisplayListBuilder when it encounters a // save layer that modifies an unbounded region DisplayListBuilder builder(build_bounds); - builder.setColorFilter(&alpha_color_filter); - builder.saveLayer(&save_bounds, true); - builder.setColorFilter(nullptr); - builder.drawRect(rect); - builder.restore(); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.setColorFilter(&alpha_color_filter); + receiver.saveLayer(&save_bounds, SaveLayerOptions::kWithAttributes); + receiver.setColorFilter(nullptr); + receiver.drawRect(rect); + receiver.restore(); sk_sp display_list = builder.Build(); ASSERT_EQ(display_list->bounds(), build_bounds); } @@ -384,11 +420,12 @@ TEST(DisplayList, DisplayListSaveLayerBoundsWithAlphaFilter) { // Verifying that the save layer bounds are not relevant // to the behavior in the previous example DisplayListBuilder builder(build_bounds); - builder.setColorFilter(&alpha_color_filter); - builder.saveLayer(nullptr, true); - builder.setColorFilter(nullptr); - builder.drawRect(rect); - builder.restore(); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.setColorFilter(&alpha_color_filter); + receiver.saveLayer(nullptr, SaveLayerOptions::kWithAttributes); + receiver.setColorFilter(nullptr); + receiver.drawRect(rect); + receiver.restore(); sk_sp display_list = builder.Build(); ASSERT_EQ(display_list->bounds(), build_bounds); } @@ -397,12 +434,13 @@ TEST(DisplayList, DisplayListSaveLayerBoundsWithAlphaFilter) { // Making sure hiding a ColorFilter as an ImageFilter will // generate the same behavior as setting it as a ColorFilter DisplayListBuilder builder(build_bounds); + DlOpReceiver& receiver = ToReceiver(builder); DlColorFilterImageFilter color_filter_image_filter(base_color_filter); - builder.setImageFilter(&color_filter_image_filter); - builder.saveLayer(&save_bounds, true); - builder.setImageFilter(nullptr); - builder.drawRect(rect); - builder.restore(); + receiver.setImageFilter(&color_filter_image_filter); + receiver.saveLayer(&save_bounds, SaveLayerOptions::kWithAttributes); + receiver.setImageFilter(nullptr); + receiver.drawRect(rect); + receiver.restore(); sk_sp display_list = builder.Build(); ASSERT_EQ(display_list->bounds(), rect); } @@ -411,12 +449,13 @@ TEST(DisplayList, DisplayListSaveLayerBoundsWithAlphaFilter) { // Making sure hiding a problematic ColorFilter as an ImageFilter // will generate the same behavior as setting it as a ColorFilter DisplayListBuilder builder(build_bounds); + DlOpReceiver& receiver = ToReceiver(builder); DlColorFilterImageFilter color_filter_image_filter(alpha_color_filter); - builder.setImageFilter(&color_filter_image_filter); - builder.saveLayer(&save_bounds, true); - builder.setImageFilter(nullptr); - builder.drawRect(rect); - builder.restore(); + receiver.setImageFilter(&color_filter_image_filter); + receiver.saveLayer(&save_bounds, SaveLayerOptions::kWithAttributes); + receiver.setImageFilter(nullptr); + receiver.drawRect(rect); + receiver.restore(); sk_sp display_list = builder.Build(); ASSERT_EQ(display_list->bounds(), build_bounds); } @@ -424,12 +463,13 @@ TEST(DisplayList, DisplayListSaveLayerBoundsWithAlphaFilter) { { // Same as above (ImageFilter hiding ColorFilter) with no save bounds DisplayListBuilder builder(build_bounds); + DlOpReceiver& receiver = ToReceiver(builder); DlColorFilterImageFilter color_filter_image_filter(alpha_color_filter); - builder.setImageFilter(&color_filter_image_filter); - builder.saveLayer(nullptr, true); - builder.setImageFilter(nullptr); - builder.drawRect(rect); - builder.restore(); + receiver.setImageFilter(&color_filter_image_filter); + receiver.saveLayer(nullptr, SaveLayerOptions::kWithAttributes); + receiver.setImageFilter(nullptr); + receiver.drawRect(rect); + receiver.restore(); sk_sp display_list = builder.Build(); ASSERT_EQ(display_list->bounds(), build_bounds); } @@ -437,11 +477,12 @@ TEST(DisplayList, DisplayListSaveLayerBoundsWithAlphaFilter) { { // Testing behavior with an unboundable blend mode DisplayListBuilder builder(build_bounds); - builder.setBlendMode(DlBlendMode::kClear); - builder.saveLayer(&save_bounds, true); - builder.setBlendMode(DlBlendMode::kSrcOver); - builder.drawRect(rect); - builder.restore(); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.setBlendMode(DlBlendMode::kClear); + receiver.saveLayer(&save_bounds, SaveLayerOptions::kWithAttributes); + receiver.setBlendMode(DlBlendMode::kSrcOver); + receiver.drawRect(rect); + receiver.restore(); sk_sp display_list = builder.Build(); ASSERT_EQ(display_list->bounds(), build_bounds); } @@ -449,17 +490,18 @@ TEST(DisplayList, DisplayListSaveLayerBoundsWithAlphaFilter) { { // Same as previous with no save bounds DisplayListBuilder builder(build_bounds); - builder.setBlendMode(DlBlendMode::kClear); - builder.saveLayer(nullptr, true); - builder.setBlendMode(DlBlendMode::kSrcOver); - builder.drawRect(rect); - builder.restore(); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.setBlendMode(DlBlendMode::kClear); + receiver.saveLayer(nullptr, SaveLayerOptions::kWithAttributes); + receiver.setBlendMode(DlBlendMode::kSrcOver); + receiver.drawRect(rect); + receiver.restore(); sk_sp display_list = builder.Build(); ASSERT_EQ(display_list->bounds(), build_bounds); } } -TEST(DisplayList, NestedOpCountMetricsSameAsSkPicture) { +TEST_F(DisplayListTest, NestedOpCountMetricsSameAsSkPicture) { SkPictureRecorder recorder; recorder.beginRecording(SkRect::MakeWH(150, 100)); SkCanvas* canvas = recorder.getRecordingCanvas(); @@ -480,14 +522,16 @@ TEST(DisplayList, NestedOpCountMetricsSameAsSkPicture) { ASSERT_EQ(picture->approximateOpCount(true), 36); DisplayListBuilder builder(SkRect::MakeWH(150, 100)); + DlOpReceiver& receiver = ToReceiver(builder); for (int y = 10; y <= 60; y += 10) { for (int x = 10; x <= 60; x += 10) { - builder.setColor(((x + y) % 20) == 10 ? SK_ColorRED : SK_ColorBLUE); - builder.drawRect(SkRect::MakeXYWH(x, y, 80, 80)); + receiver.setColor(((x + y) % 20) == 10 ? SK_ColorRED : SK_ColorBLUE); + receiver.drawRect(SkRect::MakeXYWH(x, y, 80, 80)); } } DisplayListBuilder outer_builder(SkRect::MakeWH(150, 100)); - outer_builder.drawDisplayList(builder.Build()); + DlOpReceiver& outer_receiver = ToReceiver(outer_builder); + outer_receiver.drawDisplayList(builder.Build()); auto display_list = outer_builder.Build(); ASSERT_EQ(display_list->op_count(), 1u); @@ -499,7 +543,7 @@ TEST(DisplayList, NestedOpCountMetricsSameAsSkPicture) { static_cast(display_list->op_count(true))); } -TEST(DisplayList, DisplayListFullPerspectiveTransformHandling) { +TEST_F(DisplayListTest, DisplayListFullPerspectiveTransformHandling) { // SkM44 constructor takes row-major order SkM44 sk_matrix = SkM44( // clang-format off @@ -512,8 +556,9 @@ TEST(DisplayList, DisplayListFullPerspectiveTransformHandling) { { // First test == DisplayListBuilder builder; - // builder.transformFullPerspective takes row-major order - builder.transformFullPerspective( + DlOpReceiver& receiver = ToReceiver(builder); + // receiver.transformFullPerspective takes row-major order + receiver.transformFullPerspective( // clang-format off 1, 2, 3, 4, 5, 6, 7, 8, @@ -524,14 +569,18 @@ TEST(DisplayList, DisplayListFullPerspectiveTransformHandling) { sk_sp display_list = builder.Build(); sk_sp surface = SkSurface::MakeRasterN32Premul(10, 10); SkCanvas* canvas = surface->getCanvas(); - display_list->RenderTo(canvas); + // We can't use DlSkCanvas.DrawDisplayList as that method protects + // the canvas against mutations from the display list being drawn. + auto dispatcher = DlSkCanvasDispatcher(surface->getCanvas()); + display_list->Dispatch(dispatcher); SkM44 dl_matrix = canvas->getLocalToDevice(); ASSERT_EQ(sk_matrix, dl_matrix); } { // Next test != DisplayListBuilder builder; - // builder.transformFullPerspective takes row-major order - builder.transformFullPerspective( + DlOpReceiver& receiver = ToReceiver(builder); + // receiver.transformFullPerspective takes row-major order + receiver.transformFullPerspective( // clang-format off 1, 5, 9, 13, 2, 6, 7, 11, @@ -542,33 +591,41 @@ TEST(DisplayList, DisplayListFullPerspectiveTransformHandling) { sk_sp display_list = builder.Build(); sk_sp surface = SkSurface::MakeRasterN32Premul(10, 10); SkCanvas* canvas = surface->getCanvas(); - display_list->RenderTo(canvas); + // We can't use DlSkCanvas.DrawDisplayList as that method protects + // the canvas against mutations from the display list being drawn. + auto dispatcher = DlSkCanvasDispatcher(surface->getCanvas()); + display_list->Dispatch(dispatcher); SkM44 dl_matrix = canvas->getLocalToDevice(); ASSERT_NE(sk_matrix, dl_matrix); } } -TEST(DisplayList, DisplayListTransformResetHandling) { +TEST_F(DisplayListTest, DisplayListTransformResetHandling) { DisplayListBuilder builder; - builder.scale(20.0, 20.0); - builder.transformReset(); - auto list = builder.Build(); - ASSERT_NE(list, nullptr); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.scale(20.0, 20.0); + receiver.transformReset(); + auto display_list = builder.Build(); + ASSERT_NE(display_list, nullptr); sk_sp surface = SkSurface::MakeRasterN32Premul(10, 10); SkCanvas* canvas = surface->getCanvas(); - list->RenderTo(canvas); + // We can't use DlSkCanvas.DrawDisplayList as that method protects + // the canvas against mutations from the display list being drawn. + auto dispatcher = DlSkCanvasDispatcher(surface->getCanvas()); + display_list->Dispatch(dispatcher); ASSERT_TRUE(canvas->getTotalMatrix().isIdentity()); } -TEST(DisplayList, SingleOpsMightSupportGroupOpacityWithOrWithoutBlendMode) { +TEST_F(DisplayListTest, SingleOpsMightSupportGroupOpacityBlendMode) { auto run_tests = [](const std::string& name, - void build(DisplayListBuilder & builder), - bool expect_for_op, bool expect_with_kSrc) { + void build(DlOpReceiver & receiver), bool expect_for_op, + bool expect_with_kSrc) { { // First test is the draw op, by itself // (usually supports group opacity) DisplayListBuilder builder; - build(builder); + DlOpReceiver& receiver = ToReceiver(builder); + build(receiver); auto display_list = builder.Build(); EXPECT_EQ(display_list->can_apply_group_opacity(), expect_for_op) << "{" << std::endl @@ -579,12 +636,13 @@ TEST(DisplayList, SingleOpsMightSupportGroupOpacityWithOrWithoutBlendMode) { // Second test i the draw op with kSrc, // (usually fails group opacity) DisplayListBuilder builder; - builder.setBlendMode(DlBlendMode::kSrc); - build(builder); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.setBlendMode(DlBlendMode::kSrc); + build(receiver); auto display_list = builder.Build(); EXPECT_EQ(display_list->can_apply_group_opacity(), expect_with_kSrc) << "{" << std::endl - << " builder.setBlendMode(kSrc);" << std::endl + << " receiver.setBlendMode(kSrc);" << std::endl << " " << name << std::endl << "}"; } @@ -592,150 +650,163 @@ TEST(DisplayList, SingleOpsMightSupportGroupOpacityWithOrWithoutBlendMode) { #define RUN_TESTS(body) \ run_tests( \ - #body, [](DisplayListBuilder& builder) { body }, true, false) + #body, [](DlOpReceiver& receiver) { body }, true, false) #define RUN_TESTS2(body, expect) \ run_tests( \ - #body, [](DisplayListBuilder& builder) { body }, expect, expect) - - RUN_TESTS(builder.drawPaint();); - 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});); - RUN_TESTS(builder.drawCircle({10, 10}, 5);); - RUN_TESTS(builder.drawRRect(SkRRect::MakeRectXY({0, 0, 10, 10}, 2, 2));); - RUN_TESTS(builder.drawDRRect(SkRRect::MakeRectXY({0, 0, 10, 10}, 2, 2), - SkRRect::MakeRectXY({2, 2, 8, 8}, 2, 2));); - RUN_TESTS(builder.drawPath( + #body, [](DlOpReceiver& receiver) { body }, expect, expect) + + RUN_TESTS(receiver.drawPaint();); + RUN_TESTS2(receiver.drawColor(SK_ColorRED, DlBlendMode::kSrcOver);, true); + RUN_TESTS2(receiver.drawColor(SK_ColorRED, DlBlendMode::kSrc);, false); + RUN_TESTS(receiver.drawLine({0, 0}, {10, 10});); + RUN_TESTS(receiver.drawRect({0, 0, 10, 10});); + RUN_TESTS(receiver.drawOval({0, 0, 10, 10});); + RUN_TESTS(receiver.drawCircle({10, 10}, 5);); + RUN_TESTS(receiver.drawRRect(SkRRect::MakeRectXY({0, 0, 10, 10}, 2, 2));); + RUN_TESTS(receiver.drawDRRect(SkRRect::MakeRectXY({0, 0, 10, 10}, 2, 2), + SkRRect::MakeRectXY({2, 2, 8, 8}, 2, 2));); + RUN_TESTS(receiver.drawPath( SkPath().addOval({0, 0, 10, 10}).addOval({5, 5, 15, 15}));); - RUN_TESTS(builder.drawArc({0, 0, 10, 10}, 0, math::kPi, true);); - RUN_TESTS2(builder.drawPoints(PointMode::kPoints, TestPointCount, TestPoints); + RUN_TESTS(receiver.drawArc({0, 0, 10, 10}, 0, math::kPi, true);); + RUN_TESTS2( + receiver.drawPoints(PointMode::kPoints, TestPointCount, TestPoints); + , false); + RUN_TESTS2(receiver.drawVertices(TestVertices1.get(), DlBlendMode::kSrc); , false); - RUN_TESTS2(builder.drawVertices(TestVertices1, DlBlendMode::kSrc);, false); - RUN_TESTS(builder.drawImage(TestImage1, {0, 0}, kLinearSampling, true);); - RUN_TESTS2(builder.drawImage(TestImage1, {0, 0}, kLinearSampling, false); - , true); - RUN_TESTS(builder.drawImageRect(TestImage1, {10, 10, 20, 20}, {0, 0, 10, 10}, - kNearestSampling, true);); - RUN_TESTS2(builder.drawImageRect(TestImage1, {10, 10, 20, 20}, {0, 0, 10, 10}, - kNearestSampling, false); + RUN_TESTS(receiver.drawImage(TestImage1, {0, 0}, kLinearSampling, true);); + RUN_TESTS2(receiver.drawImage(TestImage1, {0, 0}, kLinearSampling, false); , true); - RUN_TESTS(builder.drawImageNine(TestImage2, {20, 20, 30, 30}, {0, 0, 20, 20}, - DlFilterMode::kLinear, true);); - RUN_TESTS2(builder.drawImageNine(TestImage2, {20, 20, 30, 30}, {0, 0, 20, 20}, - DlFilterMode::kLinear, false); + RUN_TESTS(receiver.drawImageRect(TestImage1, {10, 10, 20, 20}, {0, 0, 10, 10}, + kNearestSampling, true, + SkCanvas::kFast_SrcRectConstraint);); + RUN_TESTS2(receiver.drawImageRect(TestImage1, {10, 10, 20, 20}, + {0, 0, 10, 10}, kNearestSampling, false, + SkCanvas::kFast_SrcRectConstraint); , true); + RUN_TESTS(receiver.drawImageNine(TestImage2, {20, 20, 30, 30}, {0, 0, 20, 20}, + DlFilterMode::kLinear, true);); + RUN_TESTS2( + receiver.drawImageNine(TestImage2, {20, 20, 30, 30}, {0, 0, 20, 20}, + DlFilterMode::kLinear, false); + , true); 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, - DlBlendMode::kSrcIn, kNearestSampling, nullptr, true); + receiver.drawAtlas(TestImage1, xforms, texs, nullptr, 2, + DlBlendMode::kSrcIn, kNearestSampling, nullptr, true); , false); RUN_TESTS2( - builder.drawAtlas(TestImage1, xforms, texs, nullptr, 2, - DlBlendMode::kSrcIn, kNearestSampling, nullptr, false); + receiver.drawAtlas(TestImage1, xforms, texs, nullptr, 2, + DlBlendMode::kSrcIn, kNearestSampling, nullptr, false); , false); EXPECT_TRUE(TestDisplayList1->can_apply_group_opacity()); - RUN_TESTS2(builder.drawDisplayList(TestDisplayList1);, true); + RUN_TESTS2(receiver.drawDisplayList(TestDisplayList1);, true); { static DisplayListBuilder builder; - builder.drawRect({0, 0, 10, 10}); - builder.drawRect({5, 5, 15, 15}); + builder.DrawRect({0, 0, 10, 10}, DlPaint()); + builder.DrawRect({5, 5, 15, 15}, DlPaint()); static auto display_list = builder.Build(); - RUN_TESTS2(builder.drawDisplayList(display_list);, false); + RUN_TESTS2(receiver.drawDisplayList(display_list);, false); } - RUN_TESTS(builder.drawTextBlob(TestBlob1, 0, 0);); - RUN_TESTS2(builder.drawShadow(kTestPath1, SK_ColorBLACK, 1.0, false, 1.0); + RUN_TESTS(receiver.drawTextBlob(TestBlob1, 0, 0);); + RUN_TESTS2(receiver.drawShadow(kTestPath1, SK_ColorBLACK, 1.0, false, 1.0); , false); #undef RUN_TESTS2 #undef RUN_TESTS } -TEST(DisplayList, OverlappingOpsDoNotSupportGroupOpacity) { +TEST_F(DisplayListTest, OverlappingOpsDoNotSupportGroupOpacity) { DisplayListBuilder builder; + DlOpReceiver& receiver = ToReceiver(builder); for (int i = 0; i < 10; i++) { - builder.drawRect(SkRect::MakeXYWH(i * 10, 0, 30, 30)); + receiver.drawRect(SkRect::MakeXYWH(i * 10, 0, 30, 30)); } auto display_list = builder.Build(); EXPECT_FALSE(display_list->can_apply_group_opacity()); } -TEST(DisplayList, SaveLayerFalseSupportsGroupOpacityWithOverlappingChidren) { +TEST_F(DisplayListTest, SaveLayerFalseSupportsGroupOpacityOverlappingChidren) { DisplayListBuilder builder; - builder.saveLayer(nullptr, false); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.saveLayer(nullptr, SaveLayerOptions::kNoAttributes); for (int i = 0; i < 10; i++) { - builder.drawRect(SkRect::MakeXYWH(i * 10, 0, 30, 30)); + receiver.drawRect(SkRect::MakeXYWH(i * 10, 0, 30, 30)); } - builder.restore(); + receiver.restore(); auto display_list = builder.Build(); EXPECT_TRUE(display_list->can_apply_group_opacity()); } -TEST(DisplayList, SaveLayerTrueSupportsGroupOpacityWithOverlappingChidren) { +TEST_F(DisplayListTest, SaveLayerTrueSupportsGroupOpacityOverlappingChidren) { DisplayListBuilder builder; - builder.saveLayer(nullptr, true); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.saveLayer(nullptr, SaveLayerOptions::kWithAttributes); for (int i = 0; i < 10; i++) { - builder.drawRect(SkRect::MakeXYWH(i * 10, 0, 30, 30)); + receiver.drawRect(SkRect::MakeXYWH(i * 10, 0, 30, 30)); } - builder.restore(); + receiver.restore(); auto display_list = builder.Build(); EXPECT_TRUE(display_list->can_apply_group_opacity()); } -TEST(DisplayList, SaveLayerFalseWithSrcBlendSupportsGroupOpacity) { +TEST_F(DisplayListTest, SaveLayerFalseWithSrcBlendSupportsGroupOpacity) { DisplayListBuilder builder; - builder.setBlendMode(DlBlendMode::kSrc); - builder.saveLayer(nullptr, false); - builder.drawRect({0, 0, 10, 10}); - builder.restore(); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.setBlendMode(DlBlendMode::kSrc); + receiver.saveLayer(nullptr, SaveLayerOptions::kNoAttributes); + receiver.drawRect({0, 0, 10, 10}); + receiver.restore(); auto display_list = builder.Build(); EXPECT_TRUE(display_list->can_apply_group_opacity()); } -TEST(DisplayList, SaveLayerTrueWithSrcBlendDoesNotSupportGroupOpacity) { +TEST_F(DisplayListTest, SaveLayerTrueWithSrcBlendDoesNotSupportGroupOpacity) { DisplayListBuilder builder; - builder.setBlendMode(DlBlendMode::kSrc); - builder.saveLayer(nullptr, true); - builder.drawRect({0, 0, 10, 10}); - builder.restore(); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.setBlendMode(DlBlendMode::kSrc); + receiver.saveLayer(nullptr, SaveLayerOptions::kWithAttributes); + receiver.drawRect({0, 0, 10, 10}); + receiver.restore(); auto display_list = builder.Build(); EXPECT_FALSE(display_list->can_apply_group_opacity()); } -TEST(DisplayList, SaveLayerFalseSupportsGroupOpacityWithChildSrcBlend) { +TEST_F(DisplayListTest, SaveLayerFalseSupportsGroupOpacityWithChildSrcBlend) { DisplayListBuilder builder; - builder.saveLayer(nullptr, false); - builder.setBlendMode(DlBlendMode::kSrc); - builder.drawRect({0, 0, 10, 10}); - builder.restore(); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.saveLayer(nullptr, SaveLayerOptions::kNoAttributes); + receiver.setBlendMode(DlBlendMode::kSrc); + receiver.drawRect({0, 0, 10, 10}); + receiver.restore(); auto display_list = builder.Build(); EXPECT_TRUE(display_list->can_apply_group_opacity()); } -TEST(DisplayList, SaveLayerTrueSupportsGroupOpacityWithChildSrcBlend) { +TEST_F(DisplayListTest, SaveLayerTrueSupportsGroupOpacityWithChildSrcBlend) { DisplayListBuilder builder; - builder.saveLayer(nullptr, true); - builder.setBlendMode(DlBlendMode::kSrc); - builder.drawRect({0, 0, 10, 10}); - builder.restore(); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.saveLayer(nullptr, SaveLayerOptions::kWithAttributes); + receiver.setBlendMode(DlBlendMode::kSrc); + receiver.drawRect({0, 0, 10, 10}); + receiver.restore(); auto display_list = builder.Build(); EXPECT_TRUE(display_list->can_apply_group_opacity()); } -TEST(DisplayList, SaveLayerBoundsSnapshotsImageFilter) { +TEST_F(DisplayListTest, SaveLayerBoundsSnapshotsImageFilter) { DisplayListBuilder builder; - builder.saveLayer(nullptr, true); - builder.drawRect({50, 50, 100, 100}); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.saveLayer(nullptr, SaveLayerOptions::kWithAttributes); + receiver.drawRect({50, 50, 100, 100}); // This image filter should be ignored since it was not set before saveLayer - builder.setImageFilter(&kTestBlurImageFilter1); - builder.restore(); + receiver.setImageFilter(&kTestBlurImageFilter1); + receiver.restore(); SkRect bounds = builder.Build()->bounds(); EXPECT_EQ(bounds, SkRect::MakeLTRB(50, 50, 100, 100)); } -class SaveLayerOptionsExpector : public virtual Dispatcher, +class SaveLayerOptionsExpector : public virtual DlOpReceiver, public IgnoreAttributeDispatchHelper, public IgnoreClipDispatchHelper, public IgnoreTransformDispatchHelper, @@ -762,51 +833,54 @@ class SaveLayerOptionsExpector : public virtual Dispatcher, int save_layer_count_ = 0; }; -TEST(DisplayList, SaveLayerOneSimpleOpSupportsOpacityOptimization) { +TEST_F(DisplayListTest, SaveLayerOneSimpleOpInheritsOpacity) { SaveLayerOptions expected = SaveLayerOptions::kWithAttributes.with_can_distribute_opacity(); SaveLayerOptionsExpector expector(expected); DisplayListBuilder builder; - builder.setColor(SkColorSetARGB(127, 255, 255, 255)); - builder.saveLayer(nullptr, true); - builder.drawRect({10, 10, 20, 20}); - builder.restore(); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.setColor(SkColorSetARGB(127, 255, 255, 255)); + receiver.saveLayer(nullptr, SaveLayerOptions::kWithAttributes); + receiver.drawRect({10, 10, 20, 20}); + receiver.restore(); builder.Build()->Dispatch(expector); EXPECT_EQ(expector.save_layer_count(), 1); } -TEST(DisplayList, SaveLayerNoAttributesSupportsOpacityOptimization) { +TEST_F(DisplayListTest, SaveLayerNoAttributesInheritsOpacity) { SaveLayerOptions expected = SaveLayerOptions::kNoAttributes.with_can_distribute_opacity(); SaveLayerOptionsExpector expector(expected); DisplayListBuilder builder; - builder.saveLayer(nullptr, false); - builder.drawRect({10, 10, 20, 20}); - builder.restore(); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.saveLayer(nullptr, SaveLayerOptions::kNoAttributes); + receiver.drawRect({10, 10, 20, 20}); + receiver.restore(); builder.Build()->Dispatch(expector); EXPECT_EQ(expector.save_layer_count(), 1); } -TEST(DisplayList, SaveLayerTwoOverlappingOpsPreventsOpacityOptimization) { +TEST_F(DisplayListTest, SaveLayerTwoOverlappingOpsDoesNotInheritOpacity) { SaveLayerOptions expected = SaveLayerOptions::kWithAttributes; SaveLayerOptionsExpector expector(expected); DisplayListBuilder builder; - builder.setColor(SkColorSetARGB(127, 255, 255, 255)); - builder.saveLayer(nullptr, true); - builder.drawRect({10, 10, 20, 20}); - builder.drawRect({15, 15, 25, 25}); - builder.restore(); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.setColor(SkColorSetARGB(127, 255, 255, 255)); + receiver.saveLayer(nullptr, SaveLayerOptions::kWithAttributes); + receiver.drawRect({10, 10, 20, 20}); + receiver.drawRect({15, 15, 25, 25}); + receiver.restore(); builder.Build()->Dispatch(expector); EXPECT_EQ(expector.save_layer_count(), 1); } -TEST(DisplayList, NestedSaveLayersMightSupportOpacityOptimization) { +TEST_F(DisplayListTest, NestedSaveLayersMightInheritOpacity) { SaveLayerOptions expected1 = SaveLayerOptions::kWithAttributes.with_can_distribute_opacity(); SaveLayerOptions expected2 = SaveLayerOptions::kWithAttributes; @@ -815,21 +889,22 @@ TEST(DisplayList, NestedSaveLayersMightSupportOpacityOptimization) { SaveLayerOptionsExpector expector({expected1, expected2, expected3}); DisplayListBuilder builder; - builder.setColor(SkColorSetARGB(127, 255, 255, 255)); - builder.saveLayer(nullptr, true); - builder.saveLayer(nullptr, true); - builder.drawRect({10, 10, 20, 20}); - builder.saveLayer(nullptr, true); - builder.drawRect({15, 15, 25, 25}); - builder.restore(); - builder.restore(); - builder.restore(); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.setColor(SkColorSetARGB(127, 255, 255, 255)); + receiver.saveLayer(nullptr, SaveLayerOptions::kWithAttributes); + receiver.saveLayer(nullptr, SaveLayerOptions::kWithAttributes); + receiver.drawRect({10, 10, 20, 20}); + receiver.saveLayer(nullptr, SaveLayerOptions::kWithAttributes); + receiver.drawRect({15, 15, 25, 25}); + receiver.restore(); + receiver.restore(); + receiver.restore(); builder.Build()->Dispatch(expector); EXPECT_EQ(expector.save_layer_count(), 3); } -TEST(DisplayList, NestedSaveLayersCanBothSupportOpacityOptimization) { +TEST_F(DisplayListTest, NestedSaveLayersCanBothSupportOpacityOptimization) { SaveLayerOptions expected1 = SaveLayerOptions::kWithAttributes.with_can_distribute_opacity(); SaveLayerOptions expected2 = @@ -837,112 +912,119 @@ TEST(DisplayList, NestedSaveLayersCanBothSupportOpacityOptimization) { SaveLayerOptionsExpector expector({expected1, expected2}); DisplayListBuilder builder; - builder.setColor(SkColorSetARGB(127, 255, 255, 255)); - builder.saveLayer(nullptr, true); - builder.saveLayer(nullptr, false); - builder.drawRect({10, 10, 20, 20}); - builder.restore(); - builder.restore(); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.setColor(SkColorSetARGB(127, 255, 255, 255)); + receiver.saveLayer(nullptr, SaveLayerOptions::kWithAttributes); + receiver.saveLayer(nullptr, SaveLayerOptions::kNoAttributes); + receiver.drawRect({10, 10, 20, 20}); + receiver.restore(); + receiver.restore(); builder.Build()->Dispatch(expector); EXPECT_EQ(expector.save_layer_count(), 2); } -TEST(DisplayList, SaveLayerImageFilterPreventsOpacityOptimization) { +TEST_F(DisplayListTest, SaveLayerImageFilterDoesNotInheritOpacity) { SaveLayerOptions expected = SaveLayerOptions::kWithAttributes; SaveLayerOptionsExpector expector(expected); DisplayListBuilder builder; - builder.setColor(SkColorSetARGB(127, 255, 255, 255)); - builder.setImageFilter(&kTestBlurImageFilter1); - builder.saveLayer(nullptr, true); - builder.setImageFilter(nullptr); - builder.drawRect({10, 10, 20, 20}); - builder.restore(); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.setColor(SkColorSetARGB(127, 255, 255, 255)); + receiver.setImageFilter(&kTestBlurImageFilter1); + receiver.saveLayer(nullptr, SaveLayerOptions::kWithAttributes); + receiver.setImageFilter(nullptr); + receiver.drawRect({10, 10, 20, 20}); + receiver.restore(); builder.Build()->Dispatch(expector); EXPECT_EQ(expector.save_layer_count(), 1); } -TEST(DisplayList, SaveLayerColorFilterPreventsOpacityOptimization) { +TEST_F(DisplayListTest, SaveLayerColorFilterDoesNotInheritOpacity) { SaveLayerOptions expected = SaveLayerOptions::kWithAttributes; SaveLayerOptionsExpector expector(expected); DisplayListBuilder builder; - builder.setColor(SkColorSetARGB(127, 255, 255, 255)); - builder.setColorFilter(&kTestMatrixColorFilter1); - builder.saveLayer(nullptr, true); - builder.setColorFilter(nullptr); - builder.drawRect({10, 10, 20, 20}); - builder.restore(); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.setColor(SkColorSetARGB(127, 255, 255, 255)); + receiver.setColorFilter(&kTestMatrixColorFilter1); + receiver.saveLayer(nullptr, SaveLayerOptions::kWithAttributes); + receiver.setColorFilter(nullptr); + receiver.drawRect({10, 10, 20, 20}); + receiver.restore(); builder.Build()->Dispatch(expector); EXPECT_EQ(expector.save_layer_count(), 1); } -TEST(DisplayList, SaveLayerSrcBlendPreventsOpacityOptimization) { +TEST_F(DisplayListTest, SaveLayerSrcBlendDoesNotInheritOpacity) { SaveLayerOptions expected = SaveLayerOptions::kWithAttributes; SaveLayerOptionsExpector expector(expected); DisplayListBuilder builder; - builder.setColor(SkColorSetARGB(127, 255, 255, 255)); - builder.setBlendMode(DlBlendMode::kSrc); - builder.saveLayer(nullptr, true); - builder.setBlendMode(DlBlendMode::kSrcOver); - builder.drawRect({10, 10, 20, 20}); - builder.restore(); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.setColor(SkColorSetARGB(127, 255, 255, 255)); + receiver.setBlendMode(DlBlendMode::kSrc); + receiver.saveLayer(nullptr, SaveLayerOptions::kWithAttributes); + receiver.setBlendMode(DlBlendMode::kSrcOver); + receiver.drawRect({10, 10, 20, 20}); + receiver.restore(); builder.Build()->Dispatch(expector); EXPECT_EQ(expector.save_layer_count(), 1); } -TEST(DisplayList, SaveLayerImageFilterOnChildSupportsOpacityOptimization) { +TEST_F(DisplayListTest, SaveLayerImageFilterOnChildInheritsOpacity) { SaveLayerOptions expected = SaveLayerOptions::kWithAttributes.with_can_distribute_opacity(); SaveLayerOptionsExpector expector(expected); DisplayListBuilder builder; - builder.setColor(SkColorSetARGB(127, 255, 255, 255)); - builder.saveLayer(nullptr, true); - builder.setImageFilter(&kTestBlurImageFilter1); - builder.drawRect({10, 10, 20, 20}); - builder.restore(); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.setColor(SkColorSetARGB(127, 255, 255, 255)); + receiver.saveLayer(nullptr, SaveLayerOptions::kWithAttributes); + receiver.setImageFilter(&kTestBlurImageFilter1); + receiver.drawRect({10, 10, 20, 20}); + receiver.restore(); builder.Build()->Dispatch(expector); EXPECT_EQ(expector.save_layer_count(), 1); } -TEST(DisplayList, SaveLayerColorFilterOnChildPreventsOpacityOptimization) { +TEST_F(DisplayListTest, SaveLayerColorFilterOnChildDoesNotInheritOpacity) { SaveLayerOptions expected = SaveLayerOptions::kWithAttributes; SaveLayerOptionsExpector expector(expected); DisplayListBuilder builder; - builder.setColor(SkColorSetARGB(127, 255, 255, 255)); - builder.saveLayer(nullptr, true); - builder.setColorFilter(&kTestMatrixColorFilter1); - builder.drawRect({10, 10, 20, 20}); - builder.restore(); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.setColor(SkColorSetARGB(127, 255, 255, 255)); + receiver.saveLayer(nullptr, SaveLayerOptions::kWithAttributes); + receiver.setColorFilter(&kTestMatrixColorFilter1); + receiver.drawRect({10, 10, 20, 20}); + receiver.restore(); builder.Build()->Dispatch(expector); EXPECT_EQ(expector.save_layer_count(), 1); } -TEST(DisplayList, SaveLayerSrcBlendOnChildPreventsOpacityOptimization) { +TEST_F(DisplayListTest, SaveLayerSrcBlendOnChildDoesNotInheritOpacity) { SaveLayerOptions expected = SaveLayerOptions::kWithAttributes; SaveLayerOptionsExpector expector(expected); DisplayListBuilder builder; - builder.setColor(SkColorSetARGB(127, 255, 255, 255)); - builder.saveLayer(nullptr, true); - builder.setBlendMode(DlBlendMode::kSrc); - builder.drawRect({10, 10, 20, 20}); - builder.restore(); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.setColor(SkColorSetARGB(127, 255, 255, 255)); + receiver.saveLayer(nullptr, SaveLayerOptions::kWithAttributes); + receiver.setBlendMode(DlBlendMode::kSrc); + receiver.drawRect({10, 10, 20, 20}); + receiver.restore(); builder.Build()->Dispatch(expector); EXPECT_EQ(expector.save_layer_count(), 1); } -TEST(DisplayList, FlutterSvgIssue661BoundsWereEmpty) { +TEST_F(DisplayListTest, FlutterSvgIssue661BoundsWereEmpty) { // See https://github.com/dnfield/flutter_svg/issues/661 SkPath path1; @@ -1013,42 +1095,40 @@ TEST(DisplayList, FlutterSvgIssue661BoundsWereEmpty) { path2.close(); DisplayListBuilder builder; + DlPaint paint = DlPaint(DlColor::kWhite()).setAntiAlias(true); { - builder.save(); - builder.clipRect({0, 0, 100, 100}, ClipOp::kIntersect, true); + builder.Save(); + builder.ClipRect({0, 0, 100, 100}, ClipOp::kIntersect, true); { - builder.save(); - builder.transform2DAffine(2.17391, 0, -2547.83, // + builder.Save(); + builder.Transform2DAffine(2.17391, 0, -2547.83, // 0, 2.04082, -500); { - builder.save(); - builder.clipRect({1172, 245, 1218, 294}, ClipOp::kIntersect, true); + builder.Save(); + builder.ClipRect({1172, 245, 1218, 294}, ClipOp::kIntersect, true); { - builder.saveLayer(nullptr, SaveLayerOptions::kWithAttributes, - nullptr); + builder.SaveLayer(nullptr, nullptr, nullptr); { - builder.save(); - builder.transform2DAffine(1.4375, 0, 1164.09, // + builder.Save(); + builder.Transform2DAffine(1.4375, 0, 1164.09, // 0, 1.53125, 236.548); - builder.setAntiAlias(1); - builder.setColor(0xffffffff); - builder.drawPath(path1); - builder.restore(); + builder.DrawPath(path1, paint); + builder.Restore(); } { - builder.save(); - builder.transform2DAffine(1.4375, 0, 1164.09, // + builder.Save(); + builder.Transform2DAffine(1.4375, 0, 1164.09, // 0, 1.53125, 236.548); - builder.drawPath(path2); - builder.restore(); + builder.DrawPath(path2, paint); + builder.Restore(); } - builder.restore(); + builder.Restore(); } - builder.restore(); + builder.Restore(); } - builder.restore(); + builder.Restore(); } - builder.restore(); + builder.Restore(); } sk_sp display_list = builder.Build(); // Prior to the fix, the bounds were empty. @@ -1070,16 +1150,17 @@ TEST(DisplayList, FlutterSvgIssue661BoundsWereEmpty) { EXPECT_EQ(display_list->bytes(), sizeof(DisplayList) + 352u); } -TEST(DisplayList, TranslateAffectsCurrentTransform) { +TEST_F(DisplayListTest, TranslateAffectsCurrentTransform) { DisplayListBuilder builder; - builder.translate(12.3, 14.5); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.translate(12.3, 14.5); SkMatrix matrix = SkMatrix::Translate(12.3, 14.5); SkM44 m44 = SkM44(matrix); SkM44 cur_m44 = builder.GetTransformFullPerspective(); SkMatrix cur_matrix = builder.GetTransform(); ASSERT_EQ(cur_m44, m44); ASSERT_EQ(cur_matrix, matrix); - builder.translate(10, 10); + receiver.translate(10, 10); // CurrentTransform has changed ASSERT_NE(builder.GetTransformFullPerspective(), m44); ASSERT_NE(builder.GetTransform(), cur_matrix); @@ -1088,16 +1169,17 @@ TEST(DisplayList, TranslateAffectsCurrentTransform) { ASSERT_EQ(cur_matrix, matrix); } -TEST(DisplayList, ScaleAffectsCurrentTransform) { +TEST_F(DisplayListTest, ScaleAffectsCurrentTransform) { DisplayListBuilder builder; - builder.scale(12.3, 14.5); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.scale(12.3, 14.5); SkMatrix matrix = SkMatrix::Scale(12.3, 14.5); SkM44 m44 = SkM44(matrix); SkM44 cur_m44 = builder.GetTransformFullPerspective(); SkMatrix cur_matrix = builder.GetTransform(); ASSERT_EQ(cur_m44, m44); ASSERT_EQ(cur_matrix, matrix); - builder.translate(10, 10); + receiver.translate(10, 10); // CurrentTransform has changed ASSERT_NE(builder.GetTransformFullPerspective(), m44); ASSERT_NE(builder.GetTransform(), cur_matrix); @@ -1106,16 +1188,17 @@ TEST(DisplayList, ScaleAffectsCurrentTransform) { ASSERT_EQ(cur_matrix, matrix); } -TEST(DisplayList, RotateAffectsCurrentTransform) { +TEST_F(DisplayListTest, RotateAffectsCurrentTransform) { DisplayListBuilder builder; - builder.rotate(12.3); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.rotate(12.3); SkMatrix matrix = SkMatrix::RotateDeg(12.3); SkM44 m44 = SkM44(matrix); SkM44 cur_m44 = builder.GetTransformFullPerspective(); SkMatrix cur_matrix = builder.GetTransform(); ASSERT_EQ(cur_m44, m44); ASSERT_EQ(cur_matrix, matrix); - builder.translate(10, 10); + receiver.translate(10, 10); // CurrentTransform has changed ASSERT_NE(builder.GetTransformFullPerspective(), m44); ASSERT_NE(builder.GetTransform(), cur_matrix); @@ -1124,16 +1207,17 @@ TEST(DisplayList, RotateAffectsCurrentTransform) { ASSERT_EQ(cur_matrix, matrix); } -TEST(DisplayList, SkewAffectsCurrentTransform) { +TEST_F(DisplayListTest, SkewAffectsCurrentTransform) { DisplayListBuilder builder; - builder.skew(12.3, 14.5); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.skew(12.3, 14.5); SkMatrix matrix = SkMatrix::Skew(12.3, 14.5); SkM44 m44 = SkM44(matrix); SkM44 cur_m44 = builder.GetTransformFullPerspective(); SkMatrix cur_matrix = builder.GetTransform(); ASSERT_EQ(cur_m44, m44); ASSERT_EQ(cur_matrix, matrix); - builder.translate(10, 10); + receiver.translate(10, 10); // CurrentTransform has changed ASSERT_NE(builder.GetTransformFullPerspective(), m44); ASSERT_NE(builder.GetTransform(), cur_matrix); @@ -1142,10 +1226,11 @@ TEST(DisplayList, SkewAffectsCurrentTransform) { ASSERT_EQ(cur_matrix, matrix); } -TEST(DisplayList, TransformAffectsCurrentTransform) { +TEST_F(DisplayListTest, TransformAffectsCurrentTransform) { DisplayListBuilder builder; - builder.transform2DAffine(3, 0, 12.3, // - 1, 5, 14.5); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.transform2DAffine(3, 0, 12.3, // + 1, 5, 14.5); SkMatrix matrix = SkMatrix::MakeAll(3, 0, 12.3, // 1, 5, 14.5, // 0, 0, 1); @@ -1154,7 +1239,7 @@ TEST(DisplayList, TransformAffectsCurrentTransform) { SkMatrix cur_matrix = builder.GetTransform(); ASSERT_EQ(cur_m44, m44); ASSERT_EQ(cur_matrix, matrix); - builder.translate(10, 10); + receiver.translate(10, 10); // CurrentTransform has changed ASSERT_NE(builder.GetTransformFullPerspective(), m44); ASSERT_NE(builder.GetTransform(), cur_matrix); @@ -1163,12 +1248,13 @@ TEST(DisplayList, TransformAffectsCurrentTransform) { ASSERT_EQ(cur_matrix, matrix); } -TEST(DisplayList, FullTransformAffectsCurrentTransform) { +TEST_F(DisplayListTest, FullTransformAffectsCurrentTransform) { DisplayListBuilder builder; - builder.transformFullPerspective(3, 0, 4, 12.3, // - 1, 5, 3, 14.5, // - 0, 0, 7, 16.2, // - 0, 0, 0, 1); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.transformFullPerspective(3, 0, 4, 12.3, // + 1, 5, 3, 14.5, // + 0, 0, 7, 16.2, // + 0, 0, 0, 1); SkMatrix matrix = SkMatrix::MakeAll(3, 0, 12.3, // 1, 5, 14.5, // 0, 0, 1); @@ -1180,7 +1266,7 @@ TEST(DisplayList, FullTransformAffectsCurrentTransform) { SkMatrix cur_matrix = builder.GetTransform(); ASSERT_EQ(cur_m44, m44); ASSERT_EQ(cur_matrix, matrix); - builder.translate(10, 10); + receiver.translate(10, 10); // CurrentTransform has changed ASSERT_NE(builder.GetTransformFullPerspective(), m44); ASSERT_NE(builder.GetTransform(), cur_matrix); @@ -1189,10 +1275,11 @@ TEST(DisplayList, FullTransformAffectsCurrentTransform) { ASSERT_EQ(cur_matrix, matrix); } -TEST(DisplayList, ClipRectAffectsClipBounds) { +TEST_F(DisplayListTest, ClipRectAffectsClipBounds) { DisplayListBuilder builder; + DlOpReceiver& receiver = ToReceiver(builder); SkRect clip_bounds = SkRect::MakeLTRB(10.2, 11.3, 20.4, 25.7); - builder.clipRect(clip_bounds, ClipOp::kIntersect, false); + receiver.clipRect(clip_bounds, ClipOp::kIntersect, false); // Save initial return values for testing restored values SkRect initial_local_bounds = builder.GetLocalClipBounds(); @@ -1200,38 +1287,39 @@ TEST(DisplayList, ClipRectAffectsClipBounds) { ASSERT_EQ(initial_local_bounds, clip_bounds); ASSERT_EQ(initial_destination_bounds, clip_bounds); - builder.save(); - builder.clipRect({0, 0, 15, 15}, ClipOp::kIntersect, false); + receiver.save(); + receiver.clipRect({0, 0, 15, 15}, ClipOp::kIntersect, false); // Both clip bounds have changed ASSERT_NE(builder.GetLocalClipBounds(), clip_bounds); ASSERT_NE(builder.GetDestinationClipBounds(), clip_bounds); // Previous return values have not changed ASSERT_EQ(initial_local_bounds, clip_bounds); ASSERT_EQ(initial_destination_bounds, clip_bounds); - builder.restore(); + receiver.restore(); // save/restore returned the values to their original values ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds); ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds); - builder.save(); - builder.scale(2, 2); + receiver.save(); + receiver.scale(2, 2); SkRect scaled_clip_bounds = SkRect::MakeLTRB(5.1, 5.65, 10.2, 12.85); ASSERT_EQ(builder.GetLocalClipBounds(), scaled_clip_bounds); // Destination bounds are unaffected by transform ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds); - builder.restore(); + receiver.restore(); // save/restore returned the values to their original values ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds); ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds); } -TEST(DisplayList, ClipRectDoAAAffectsClipBounds) { +TEST_F(DisplayListTest, ClipRectDoAAAffectsClipBounds) { DisplayListBuilder builder; + DlOpReceiver& receiver = ToReceiver(builder); SkRect clip_bounds = SkRect::MakeLTRB(10.2, 11.3, 20.4, 25.7); SkRect clip_expanded_bounds = SkRect::MakeLTRB(10, 11, 21, 26); - builder.clipRect(clip_bounds, ClipOp::kIntersect, true); + receiver.clipRect(clip_bounds, ClipOp::kIntersect, true); // Save initial return values for testing restored values SkRect initial_local_bounds = builder.GetLocalClipBounds(); @@ -1239,57 +1327,59 @@ TEST(DisplayList, ClipRectDoAAAffectsClipBounds) { ASSERT_EQ(initial_local_bounds, clip_expanded_bounds); ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds); - builder.save(); - builder.clipRect({0, 0, 15, 15}, ClipOp::kIntersect, true); + receiver.save(); + receiver.clipRect({0, 0, 15, 15}, ClipOp::kIntersect, true); // Both clip bounds have changed ASSERT_NE(builder.GetLocalClipBounds(), clip_expanded_bounds); ASSERT_NE(builder.GetDestinationClipBounds(), clip_expanded_bounds); // Previous return values have not changed ASSERT_EQ(initial_local_bounds, clip_expanded_bounds); ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds); - builder.restore(); + receiver.restore(); // save/restore returned the values to their original values ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds); ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds); - builder.save(); - builder.scale(2, 2); + receiver.save(); + receiver.scale(2, 2); SkRect scaled_expanded_bounds = SkRect::MakeLTRB(5, 5.5, 10.5, 13); ASSERT_EQ(builder.GetLocalClipBounds(), scaled_expanded_bounds); // Destination bounds are unaffected by transform ASSERT_EQ(builder.GetDestinationClipBounds(), clip_expanded_bounds); - builder.restore(); + receiver.restore(); // save/restore returned the values to their original values ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds); ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds); } -TEST(DisplayList, ClipRectAffectsClipBoundsWithMatrix) { +TEST_F(DisplayListTest, ClipRectAffectsClipBoundsWithMatrix) { DisplayListBuilder builder; + DlOpReceiver& receiver = ToReceiver(builder); SkRect clip_bounds_1 = SkRect::MakeLTRB(0, 0, 10, 10); SkRect clip_bounds_2 = SkRect::MakeLTRB(10, 10, 20, 20); - builder.save(); - builder.clipRect(clip_bounds_1, ClipOp::kIntersect, false); - builder.translate(10, 0); - builder.clipRect(clip_bounds_1, ClipOp::kIntersect, false); + receiver.save(); + receiver.clipRect(clip_bounds_1, ClipOp::kIntersect, false); + receiver.translate(10, 0); + receiver.clipRect(clip_bounds_1, ClipOp::kIntersect, false); ASSERT_TRUE(builder.GetDestinationClipBounds().isEmpty()); - builder.restore(); + receiver.restore(); - builder.save(); - builder.clipRect(clip_bounds_1, ClipOp::kIntersect, false); - builder.translate(-10, -10); - builder.clipRect(clip_bounds_2, ClipOp::kIntersect, false); + receiver.save(); + receiver.clipRect(clip_bounds_1, ClipOp::kIntersect, false); + receiver.translate(-10, -10); + receiver.clipRect(clip_bounds_2, ClipOp::kIntersect, false); ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds_1); - builder.restore(); + receiver.restore(); } -TEST(DisplayList, ClipRRectAffectsClipBounds) { +TEST_F(DisplayListTest, ClipRRectAffectsClipBounds) { DisplayListBuilder builder; + DlOpReceiver& receiver = ToReceiver(builder); SkRect clip_bounds = SkRect::MakeLTRB(10.2, 11.3, 20.4, 25.7); SkRRect clip = SkRRect::MakeRectXY(clip_bounds, 3, 2); - builder.clipRRect(clip, ClipOp::kIntersect, false); + receiver.clipRRect(clip, ClipOp::kIntersect, false); // Save initial return values for testing restored values SkRect initial_local_bounds = builder.GetLocalClipBounds(); @@ -1297,39 +1387,40 @@ TEST(DisplayList, ClipRRectAffectsClipBounds) { ASSERT_EQ(initial_local_bounds, clip_bounds); ASSERT_EQ(initial_destination_bounds, clip_bounds); - builder.save(); - builder.clipRect({0, 0, 15, 15}, ClipOp::kIntersect, false); + receiver.save(); + receiver.clipRect({0, 0, 15, 15}, ClipOp::kIntersect, false); // Both clip bounds have changed ASSERT_NE(builder.GetLocalClipBounds(), clip_bounds); ASSERT_NE(builder.GetDestinationClipBounds(), clip_bounds); // Previous return values have not changed ASSERT_EQ(initial_local_bounds, clip_bounds); ASSERT_EQ(initial_destination_bounds, clip_bounds); - builder.restore(); + receiver.restore(); // save/restore returned the values to their original values ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds); ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds); - builder.save(); - builder.scale(2, 2); + receiver.save(); + receiver.scale(2, 2); SkRect scaled_clip_bounds = SkRect::MakeLTRB(5.1, 5.65, 10.2, 12.85); ASSERT_EQ(builder.GetLocalClipBounds(), scaled_clip_bounds); // Destination bounds are unaffected by transform ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds); - builder.restore(); + receiver.restore(); // save/restore returned the values to their original values ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds); ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds); } -TEST(DisplayList, ClipRRectDoAAAffectsClipBounds) { +TEST_F(DisplayListTest, ClipRRectDoAAAffectsClipBounds) { DisplayListBuilder builder; + DlOpReceiver& receiver = ToReceiver(builder); SkRect clip_bounds = SkRect::MakeLTRB(10.2, 11.3, 20.4, 25.7); SkRect clip_expanded_bounds = SkRect::MakeLTRB(10, 11, 21, 26); SkRRect clip = SkRRect::MakeRectXY(clip_bounds, 3, 2); - builder.clipRRect(clip, ClipOp::kIntersect, true); + receiver.clipRRect(clip, ClipOp::kIntersect, true); // Save initial return values for testing restored values SkRect initial_local_bounds = builder.GetLocalClipBounds(); @@ -1337,60 +1428,62 @@ TEST(DisplayList, ClipRRectDoAAAffectsClipBounds) { ASSERT_EQ(initial_local_bounds, clip_expanded_bounds); ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds); - builder.save(); - builder.clipRect({0, 0, 15, 15}, ClipOp::kIntersect, true); + receiver.save(); + receiver.clipRect({0, 0, 15, 15}, ClipOp::kIntersect, true); // Both clip bounds have changed ASSERT_NE(builder.GetLocalClipBounds(), clip_expanded_bounds); ASSERT_NE(builder.GetDestinationClipBounds(), clip_expanded_bounds); // Previous return values have not changed ASSERT_EQ(initial_local_bounds, clip_expanded_bounds); ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds); - builder.restore(); + receiver.restore(); // save/restore returned the values to their original values ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds); ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds); - builder.save(); - builder.scale(2, 2); + receiver.save(); + receiver.scale(2, 2); SkRect scaled_expanded_bounds = SkRect::MakeLTRB(5, 5.5, 10.5, 13); ASSERT_EQ(builder.GetLocalClipBounds(), scaled_expanded_bounds); // Destination bounds are unaffected by transform ASSERT_EQ(builder.GetDestinationClipBounds(), clip_expanded_bounds); - builder.restore(); + receiver.restore(); // save/restore returned the values to their original values ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds); ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds); } -TEST(DisplayList, ClipRRectAffectsClipBoundsWithMatrix) { +TEST_F(DisplayListTest, ClipRRectAffectsClipBoundsWithMatrix) { DisplayListBuilder builder; + DlOpReceiver& receiver = ToReceiver(builder); SkRect clip_bounds_1 = SkRect::MakeLTRB(0, 0, 10, 10); SkRect clip_bounds_2 = SkRect::MakeLTRB(10, 10, 20, 20); SkRRect clip1 = SkRRect::MakeRectXY(clip_bounds_1, 3, 2); SkRRect clip2 = SkRRect::MakeRectXY(clip_bounds_2, 3, 2); - builder.save(); - builder.clipRRect(clip1, ClipOp::kIntersect, false); - builder.translate(10, 0); - builder.clipRRect(clip1, ClipOp::kIntersect, false); + receiver.save(); + receiver.clipRRect(clip1, ClipOp::kIntersect, false); + receiver.translate(10, 0); + receiver.clipRRect(clip1, ClipOp::kIntersect, false); ASSERT_TRUE(builder.GetDestinationClipBounds().isEmpty()); - builder.restore(); + receiver.restore(); - builder.save(); - builder.clipRRect(clip1, ClipOp::kIntersect, false); - builder.translate(-10, -10); - builder.clipRRect(clip2, ClipOp::kIntersect, false); + receiver.save(); + receiver.clipRRect(clip1, ClipOp::kIntersect, false); + receiver.translate(-10, -10); + receiver.clipRRect(clip2, ClipOp::kIntersect, false); ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds_1); - builder.restore(); + receiver.restore(); } -TEST(DisplayList, ClipPathAffectsClipBounds) { +TEST_F(DisplayListTest, ClipPathAffectsClipBounds) { DisplayListBuilder builder; + DlOpReceiver& receiver = ToReceiver(builder); SkPath clip = SkPath().addCircle(10.2, 11.3, 2).addCircle(20.4, 25.7, 2); SkRect clip_bounds = SkRect::MakeLTRB(8.2, 9.3, 22.4, 27.7); - builder.clipPath(clip, ClipOp::kIntersect, false); + receiver.clipPath(clip, ClipOp::kIntersect, false); // Save initial return values for testing restored values SkRect initial_local_bounds = builder.GetLocalClipBounds(); @@ -1398,38 +1491,39 @@ TEST(DisplayList, ClipPathAffectsClipBounds) { ASSERT_EQ(initial_local_bounds, clip_bounds); ASSERT_EQ(initial_destination_bounds, clip_bounds); - builder.save(); - builder.clipRect({0, 0, 15, 15}, ClipOp::kIntersect, false); + receiver.save(); + receiver.clipRect({0, 0, 15, 15}, ClipOp::kIntersect, false); // Both clip bounds have changed ASSERT_NE(builder.GetLocalClipBounds(), clip_bounds); ASSERT_NE(builder.GetDestinationClipBounds(), clip_bounds); // Previous return values have not changed ASSERT_EQ(initial_local_bounds, clip_bounds); ASSERT_EQ(initial_destination_bounds, clip_bounds); - builder.restore(); + receiver.restore(); // save/restore returned the values to their original values ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds); ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds); - builder.save(); - builder.scale(2, 2); + receiver.save(); + receiver.scale(2, 2); SkRect scaled_clip_bounds = SkRect::MakeLTRB(4.1, 4.65, 11.2, 13.85); ASSERT_EQ(builder.GetLocalClipBounds(), scaled_clip_bounds); // Destination bounds are unaffected by transform ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds); - builder.restore(); + receiver.restore(); // save/restore returned the values to their original values ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds); ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds); } -TEST(DisplayList, ClipPathDoAAAffectsClipBounds) { +TEST_F(DisplayListTest, ClipPathDoAAAffectsClipBounds) { DisplayListBuilder builder; + DlOpReceiver& receiver = ToReceiver(builder); SkPath clip = SkPath().addCircle(10.2, 11.3, 2).addCircle(20.4, 25.7, 2); SkRect clip_expanded_bounds = SkRect::MakeLTRB(8, 9, 23, 28); - builder.clipPath(clip, ClipOp::kIntersect, true); + receiver.clipPath(clip, ClipOp::kIntersect, true); // Save initial return values for testing restored values SkRect initial_local_bounds = builder.GetLocalClipBounds(); @@ -1437,59 +1531,61 @@ TEST(DisplayList, ClipPathDoAAAffectsClipBounds) { ASSERT_EQ(initial_local_bounds, clip_expanded_bounds); ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds); - builder.save(); - builder.clipRect({0, 0, 15, 15}, ClipOp::kIntersect, true); + receiver.save(); + receiver.clipRect({0, 0, 15, 15}, ClipOp::kIntersect, true); // Both clip bounds have changed ASSERT_NE(builder.GetLocalClipBounds(), clip_expanded_bounds); ASSERT_NE(builder.GetDestinationClipBounds(), clip_expanded_bounds); // Previous return values have not changed ASSERT_EQ(initial_local_bounds, clip_expanded_bounds); ASSERT_EQ(initial_destination_bounds, clip_expanded_bounds); - builder.restore(); + receiver.restore(); // save/restore returned the values to their original values ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds); ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds); - builder.save(); - builder.scale(2, 2); + receiver.save(); + receiver.scale(2, 2); SkRect scaled_expanded_bounds = SkRect::MakeLTRB(4, 4.5, 11.5, 14); ASSERT_EQ(builder.GetLocalClipBounds(), scaled_expanded_bounds); // Destination bounds are unaffected by transform ASSERT_EQ(builder.GetDestinationClipBounds(), clip_expanded_bounds); - builder.restore(); + receiver.restore(); // save/restore returned the values to their original values ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds); ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds); } -TEST(DisplayList, ClipPathAffectsClipBoundsWithMatrix) { +TEST_F(DisplayListTest, ClipPathAffectsClipBoundsWithMatrix) { DisplayListBuilder builder; + DlOpReceiver& receiver = ToReceiver(builder); SkRect clip_bounds = SkRect::MakeLTRB(0, 0, 10, 10); SkPath clip1 = SkPath().addCircle(2.5, 2.5, 2.5).addCircle(7.5, 7.5, 2.5); SkPath clip2 = SkPath().addCircle(12.5, 12.5, 2.5).addCircle(17.5, 17.5, 2.5); - builder.save(); - builder.clipPath(clip1, ClipOp::kIntersect, false); - builder.translate(10, 0); - builder.clipPath(clip1, ClipOp::kIntersect, false); + receiver.save(); + receiver.clipPath(clip1, ClipOp::kIntersect, false); + receiver.translate(10, 0); + receiver.clipPath(clip1, ClipOp::kIntersect, false); ASSERT_TRUE(builder.GetDestinationClipBounds().isEmpty()); - builder.restore(); + receiver.restore(); - builder.save(); - builder.clipPath(clip1, ClipOp::kIntersect, false); - builder.translate(-10, -10); - builder.clipPath(clip2, ClipOp::kIntersect, false); + receiver.save(); + receiver.clipPath(clip1, ClipOp::kIntersect, false); + receiver.translate(-10, -10); + receiver.clipPath(clip2, ClipOp::kIntersect, false); ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds); - builder.restore(); + receiver.restore(); } -TEST(DisplayList, DiffClipRectDoesNotAffectClipBounds) { +TEST_F(DisplayListTest, DiffClipRectDoesNotAffectClipBounds) { DisplayListBuilder builder; + DlOpReceiver& receiver = ToReceiver(builder); SkRect diff_clip = SkRect::MakeLTRB(0, 0, 15, 15); SkRect clip_bounds = SkRect::MakeLTRB(10.2, 11.3, 20.4, 25.7); - builder.clipRect(clip_bounds, ClipOp::kIntersect, false); + receiver.clipRect(clip_bounds, ClipOp::kIntersect, false); // Save initial return values for testing after kDifference clip SkRect initial_local_bounds = builder.GetLocalClipBounds(); @@ -1497,17 +1593,18 @@ TEST(DisplayList, DiffClipRectDoesNotAffectClipBounds) { ASSERT_EQ(initial_local_bounds, clip_bounds); ASSERT_EQ(initial_destination_bounds, clip_bounds); - builder.clipRect(diff_clip, ClipOp::kDifference, false); + receiver.clipRect(diff_clip, ClipOp::kDifference, false); ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds); ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds); } -TEST(DisplayList, DiffClipRRectDoesNotAffectClipBounds) { +TEST_F(DisplayListTest, DiffClipRRectDoesNotAffectClipBounds) { DisplayListBuilder builder; + DlOpReceiver& receiver = ToReceiver(builder); SkRRect diff_clip = SkRRect::MakeRectXY({0, 0, 15, 15}, 1, 1); SkRect clip_bounds = SkRect::MakeLTRB(10.2, 11.3, 20.4, 25.7); SkRRect clip = SkRRect::MakeRectXY({10.2, 11.3, 20.4, 25.7}, 3, 2); - builder.clipRRect(clip, ClipOp::kIntersect, false); + receiver.clipRRect(clip, ClipOp::kIntersect, false); // Save initial return values for testing after kDifference clip SkRect initial_local_bounds = builder.GetLocalClipBounds(); @@ -1515,17 +1612,18 @@ TEST(DisplayList, DiffClipRRectDoesNotAffectClipBounds) { ASSERT_EQ(initial_local_bounds, clip_bounds); ASSERT_EQ(initial_destination_bounds, clip_bounds); - builder.clipRRect(diff_clip, ClipOp::kDifference, false); + receiver.clipRRect(diff_clip, ClipOp::kDifference, false); ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds); ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds); } -TEST(DisplayList, DiffClipPathDoesNotAffectClipBounds) { +TEST_F(DisplayListTest, DiffClipPathDoesNotAffectClipBounds) { DisplayListBuilder builder; + DlOpReceiver& receiver = ToReceiver(builder); SkPath diff_clip = SkPath().addRect({0, 0, 15, 15}); SkPath clip = SkPath().addCircle(10.2, 11.3, 2).addCircle(20.4, 25.7, 2); SkRect clip_bounds = SkRect::MakeLTRB(8.2, 9.3, 22.4, 27.7); - builder.clipPath(clip, ClipOp::kIntersect, false); + receiver.clipPath(clip, ClipOp::kIntersect, false); // Save initial return values for testing after kDifference clip SkRect initial_local_bounds = builder.GetLocalClipBounds(); @@ -1533,40 +1631,43 @@ TEST(DisplayList, DiffClipPathDoesNotAffectClipBounds) { ASSERT_EQ(initial_local_bounds, clip_bounds); ASSERT_EQ(initial_destination_bounds, clip_bounds); - builder.clipPath(diff_clip, ClipOp::kDifference, false); + receiver.clipPath(diff_clip, ClipOp::kDifference, false); ASSERT_EQ(builder.GetLocalClipBounds(), initial_local_bounds); ASSERT_EQ(builder.GetDestinationClipBounds(), initial_destination_bounds); } -TEST(DisplayList, ClipPathWithInvertFillTypeDoesNotAffectClipBounds) { +TEST_F(DisplayListTest, ClipPathWithInvertFillTypeDoesNotAffectClipBounds) { SkRect cull_rect = SkRect::MakeLTRB(0, 0, 100.0, 100.0); DisplayListBuilder builder(cull_rect); + DlOpReceiver& receiver = ToReceiver(builder); SkPath clip = SkPath().addCircle(10.2, 11.3, 2).addCircle(20.4, 25.7, 2); clip.setFillType(SkPathFillType::kInverseWinding); - builder.clipPath(clip, ClipOp::kIntersect, false); + receiver.clipPath(clip, ClipOp::kIntersect, false); ASSERT_EQ(builder.GetLocalClipBounds(), cull_rect); ASSERT_EQ(builder.GetDestinationClipBounds(), cull_rect); } -TEST(DisplayList, DiffClipPathWithInvertFillTypeAffectsClipBounds) { +TEST_F(DisplayListTest, DiffClipPathWithInvertFillTypeAffectsClipBounds) { SkRect cull_rect = SkRect::MakeLTRB(0, 0, 100.0, 100.0); DisplayListBuilder builder(cull_rect); + DlOpReceiver& receiver = ToReceiver(builder); SkPath clip = SkPath().addCircle(10.2, 11.3, 2).addCircle(20.4, 25.7, 2); clip.setFillType(SkPathFillType::kInverseWinding); SkRect clip_bounds = SkRect::MakeLTRB(8.2, 9.3, 22.4, 27.7); - builder.clipPath(clip, ClipOp::kDifference, false); + receiver.clipPath(clip, ClipOp::kDifference, false); ASSERT_EQ(builder.GetLocalClipBounds(), clip_bounds); ASSERT_EQ(builder.GetDestinationClipBounds(), clip_bounds); } -TEST(DisplayList, FlatDrawPointsProducesBounds) { +TEST_F(DisplayListTest, FlatDrawPointsProducesBounds) { SkPoint horizontal_points[2] = {{10, 10}, {20, 10}}; SkPoint vertical_points[2] = {{10, 10}, {10, 20}}; { DisplayListBuilder builder; - builder.drawPoints(PointMode::kPolygon, 2, horizontal_points); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.drawPoints(PointMode::kPolygon, 2, horizontal_points); SkRect bounds = builder.Build()->bounds(); EXPECT_TRUE(bounds.contains(10, 10)); EXPECT_TRUE(bounds.contains(20, 10)); @@ -1574,7 +1675,8 @@ TEST(DisplayList, FlatDrawPointsProducesBounds) { } { DisplayListBuilder builder; - builder.drawPoints(PointMode::kPolygon, 2, vertical_points); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.drawPoints(PointMode::kPolygon, 2, vertical_points); SkRect bounds = builder.Build()->bounds(); EXPECT_TRUE(bounds.contains(10, 10)); EXPECT_TRUE(bounds.contains(10, 20)); @@ -1582,14 +1684,16 @@ TEST(DisplayList, FlatDrawPointsProducesBounds) { } { DisplayListBuilder builder; - builder.drawPoints(PointMode::kPoints, 1, horizontal_points); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.drawPoints(PointMode::kPoints, 1, horizontal_points); SkRect bounds = builder.Build()->bounds(); EXPECT_TRUE(bounds.contains(10, 10)); } { DisplayListBuilder builder; - builder.setStrokeWidth(2); - builder.drawPoints(PointMode::kPolygon, 2, horizontal_points); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.setStrokeWidth(2); + receiver.drawPoints(PointMode::kPolygon, 2, horizontal_points); SkRect bounds = builder.Build()->bounds(); EXPECT_TRUE(bounds.contains(10, 10)); EXPECT_TRUE(bounds.contains(20, 10)); @@ -1597,8 +1701,9 @@ TEST(DisplayList, FlatDrawPointsProducesBounds) { } { DisplayListBuilder builder; - builder.setStrokeWidth(2); - builder.drawPoints(PointMode::kPolygon, 2, vertical_points); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.setStrokeWidth(2); + receiver.drawPoints(PointMode::kPolygon, 2, vertical_points); SkRect bounds = builder.Build()->bounds(); EXPECT_TRUE(bounds.contains(10, 10)); EXPECT_TRUE(bounds.contains(10, 20)); @@ -1606,8 +1711,9 @@ TEST(DisplayList, FlatDrawPointsProducesBounds) { } { DisplayListBuilder builder; - builder.setStrokeWidth(2); - builder.drawPoints(PointMode::kPoints, 1, horizontal_points); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.setStrokeWidth(2); + receiver.drawPoints(PointMode::kPoints, 1, horizontal_points); SkRect bounds = builder.Build()->bounds(); EXPECT_TRUE(bounds.contains(10, 10)); EXPECT_EQ(bounds, SkRect::MakeLTRB(9, 9, 11, 11)); @@ -1631,10 +1737,11 @@ static void test_rtree(const sk_sp& rtree, } } -TEST(DisplayList, RTreeOfSimpleScene) { +TEST_F(DisplayListTest, RTreeOfSimpleScene) { DisplayListBuilder builder(/*prepare_rtree=*/true); - builder.drawRect({10, 10, 20, 20}); - builder.drawRect({50, 50, 60, 60}); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.drawRect({10, 10, 20, 20}); + receiver.drawRect({50, 50, 60, 60}); auto display_list = builder.Build(); auto rtree = display_list->rtree(); std::vector rects = { @@ -1658,12 +1765,13 @@ TEST(DisplayList, RTreeOfSimpleScene) { test_rtree(rtree, {19, 19, 51, 51}, rects, {0, 1}); } -TEST(DisplayList, RTreeOfSaveRestoreScene) { +TEST_F(DisplayListTest, RTreeOfSaveRestoreScene) { DisplayListBuilder builder(/*prepare_rtree=*/true); - builder.drawRect({10, 10, 20, 20}); - builder.save(); - builder.drawRect({50, 50, 60, 60}); - builder.restore(); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.drawRect({10, 10, 20, 20}); + receiver.save(); + receiver.drawRect({50, 50, 60, 60}); + receiver.restore(); auto display_list = builder.Build(); auto rtree = display_list->rtree(); std::vector rects = { @@ -1687,7 +1795,7 @@ TEST(DisplayList, RTreeOfSaveRestoreScene) { test_rtree(rtree, {19, 19, 51, 51}, rects, {0, 1}); } -TEST(DisplayList, RTreeOfSaveLayerFilterScene) { +TEST_F(DisplayListTest, RTreeOfSaveLayerFilterScene) { DisplayListBuilder builder(/*prepare_rtree=*/true); // blur filter with sigma=1 expands by 3 on all sides auto filter = DlBlurImageFilter(1.0, 1.0, DlTileMode::kClamp); @@ -1722,14 +1830,16 @@ TEST(DisplayList, RTreeOfSaveLayerFilterScene) { test_rtree(rtree, {19, 19, 51, 51}, rects, {0, 1}); } -TEST(DisplayList, NestedDisplayListRTreesAreSparse) { +TEST_F(DisplayListTest, NestedDisplayListRTreesAreSparse) { DisplayListBuilder nested_dl_builder(/**prepare_rtree=*/true); - nested_dl_builder.drawRect({10, 10, 20, 20}); - nested_dl_builder.drawRect({50, 50, 60, 60}); + DlOpReceiver& nested_dl_receiver = ToReceiver(nested_dl_builder); + nested_dl_receiver.drawRect({10, 10, 20, 20}); + nested_dl_receiver.drawRect({50, 50, 60, 60}); auto nested_display_list = nested_dl_builder.Build(); DisplayListBuilder builder(/**prepare_rtree=*/true); - builder.drawDisplayList(nested_display_list); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.drawDisplayList(nested_display_list); auto display_list = builder.Build(); auto rtree = display_list->rtree(); @@ -1742,98 +1852,106 @@ TEST(DisplayList, NestedDisplayListRTreesAreSparse) { test_rtree(rtree, {19, 19, 51, 51}, rects, {0, 1}); } -TEST(DisplayList, RemoveUnnecessarySaveRestorePairs) { +TEST_F(DisplayListTest, RemoveUnnecessarySaveRestorePairs) { { DisplayListBuilder builder; - builder.drawRect({10, 10, 20, 20}); - builder.save(); // This save op is unnecessary - builder.drawRect({50, 50, 60, 60}); - builder.restore(); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.drawRect({10, 10, 20, 20}); + receiver.save(); // This save op is unnecessary + receiver.drawRect({50, 50, 60, 60}); + receiver.restore(); DisplayListBuilder builder2; - builder2.drawRect({10, 10, 20, 20}); - builder2.drawRect({50, 50, 60, 60}); + DlOpReceiver& receiver2 = ToReceiver(builder2); + receiver2.drawRect({10, 10, 20, 20}); + receiver2.drawRect({50, 50, 60, 60}); ASSERT_TRUE(DisplayListsEQ_Verbose(builder.Build(), builder2.Build())); } { DisplayListBuilder builder; - builder.drawRect({10, 10, 20, 20}); - builder.save(); - builder.translate(1.0, 1.0); + DlOpReceiver& receiver = ToReceiver(builder); + receiver.drawRect({10, 10, 20, 20}); + receiver.save(); + receiver.translate(1.0, 1.0); { - builder.save(); // unnecessary - builder.drawRect({50, 50, 60, 60}); - builder.restore(); + receiver.save(); // unnecessary + receiver.drawRect({50, 50, 60, 60}); + receiver.restore(); } - builder.restore(); + receiver.restore(); DisplayListBuilder builder2; - builder2.drawRect({10, 10, 20, 20}); - builder2.save(); - builder2.translate(1.0, 1.0); - { builder2.drawRect({50, 50, 60, 60}); } - builder2.restore(); + DlOpReceiver& receiver2 = ToReceiver(builder2); + receiver2.drawRect({10, 10, 20, 20}); + receiver2.save(); + receiver2.translate(1.0, 1.0); + { receiver2.drawRect({50, 50, 60, 60}); } + receiver2.restore(); ASSERT_TRUE(DisplayListsEQ_Verbose(builder.Build(), builder2.Build())); } } -TEST(DisplayList, CollapseMultipleNestedSaveRestore) { +TEST_F(DisplayListTest, CollapseMultipleNestedSaveRestore) { DisplayListBuilder builder1; - builder1.save(); - builder1.save(); - builder1.save(); - builder1.translate(10, 10); - builder1.scale(2, 2); - builder1.clipRect({10, 10, 20, 20}, ClipOp::kIntersect, false); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); - builder1.restore(); - builder1.restore(); + DlOpReceiver& receiver1 = ToReceiver(builder1); + receiver1.save(); + receiver1.save(); + receiver1.save(); + receiver1.translate(10, 10); + receiver1.scale(2, 2); + receiver1.clipRect({10, 10, 20, 20}, ClipOp::kIntersect, false); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); + receiver1.restore(); + receiver1.restore(); auto display_list1 = builder1.Build(); DisplayListBuilder builder2; - builder2.save(); - builder2.translate(10, 10); - builder2.scale(2, 2); - builder2.clipRect({10, 10, 20, 20}, ClipOp::kIntersect, false); - builder2.drawRect({0, 0, 100, 100}); - builder2.restore(); + DlOpReceiver& receiver2 = ToReceiver(builder2); + receiver2.save(); + receiver2.translate(10, 10); + receiver2.scale(2, 2); + receiver2.clipRect({10, 10, 20, 20}, ClipOp::kIntersect, false); + receiver2.drawRect({0, 0, 100, 100}); + receiver2.restore(); auto display_list2 = builder2.Build(); ASSERT_TRUE(DisplayListsEQ_Verbose(display_list1, display_list2)); } -TEST(DisplayList, CollapseNestedSaveAndSaveLayerRestore) { +TEST_F(DisplayListTest, CollapseNestedSaveAndSaveLayerRestore) { DisplayListBuilder builder1; - builder1.save(); - builder1.saveLayer(nullptr, false); - builder1.drawRect({0, 0, 100, 100}); - builder1.scale(2, 2); - builder1.restore(); - builder1.restore(); + DlOpReceiver& receiver1 = ToReceiver(builder1); + receiver1.save(); + receiver1.saveLayer(nullptr, SaveLayerOptions::kNoAttributes); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.scale(2, 2); + receiver1.restore(); + receiver1.restore(); auto display_list1 = builder1.Build(); DisplayListBuilder builder2; - builder2.saveLayer(nullptr, false); - builder2.drawRect({0, 0, 100, 100}); - builder2.scale(2, 2); - builder2.restore(); + DlOpReceiver& receiver2 = ToReceiver(builder2); + receiver2.saveLayer(nullptr, SaveLayerOptions::kNoAttributes); + receiver2.drawRect({0, 0, 100, 100}); + receiver2.scale(2, 2); + receiver2.restore(); auto display_list2 = builder2.Build(); ASSERT_TRUE(DisplayListsEQ_Verbose(display_list1, display_list2)); } -TEST(DisplayList, RemoveUnnecessarySaveRestorePairsInSetPaint) { +TEST_F(DisplayListTest, RemoveUnnecessarySaveRestorePairsInSetPaint) { SkRect build_bounds = SkRect::MakeLTRB(-100, -100, 200, 200); SkRect rect = SkRect::MakeLTRB(30, 30, 70, 70); // clang-format off const float alpha_matrix[] = { - 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, - 0, 0, 1, 0, 0, - 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 1, }; // clang-format on DlMatrixColorFilter alpha_color_filter(alpha_matrix); @@ -1880,359 +1998,437 @@ TEST(DisplayList, RemoveUnnecessarySaveRestorePairsInSetPaint) { } } -TEST(DisplayList, TransformTriggersDeferredSave) { +TEST_F(DisplayListTest, TransformTriggersDeferredSave) { DisplayListBuilder builder1; - builder1.save(); - builder1.save(); - builder1.transform(SkM44::Translate(10, 100)); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); - builder1.transform(SkM44::Translate(10, 100)); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); + DlOpReceiver& receiver1 = ToReceiver(builder1); + receiver1.save(); + receiver1.save(); + receiver1.transformFullPerspective(1, 0, 0, 10, // + 0, 1, 0, 100, // + 0, 0, 1, 0, // + 0, 0, 0, 1); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); + receiver1.transformFullPerspective(1, 0, 0, 10, // + 0, 1, 0, 100, // + 0, 0, 1, 0, // + 0, 0, 0, 1); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); auto display_list1 = builder1.Build(); DisplayListBuilder builder2; - builder2.save(); - builder2.transform(SkM44::Translate(10, 100)); - builder2.drawRect({0, 0, 100, 100}); - builder2.restore(); - builder2.save(); - builder2.transform(SkM44::Translate(10, 100)); - builder2.drawRect({0, 0, 100, 100}); - builder2.restore(); + DlOpReceiver& receiver2 = ToReceiver(builder2); + receiver2.save(); + receiver2.transformFullPerspective(1, 0, 0, 10, // + 0, 1, 0, 100, // + 0, 0, 1, 0, // + 0, 0, 0, 1); + receiver2.drawRect({0, 0, 100, 100}); + receiver2.restore(); + receiver2.save(); + receiver2.transformFullPerspective(1, 0, 0, 10, // + 0, 1, 0, 100, // + 0, 0, 1, 0, // + 0, 0, 0, 1); + receiver2.drawRect({0, 0, 100, 100}); + receiver2.restore(); auto display_list2 = builder2.Build(); ASSERT_TRUE(DisplayListsEQ_Verbose(display_list1, display_list2)); } -TEST(DisplayList, Transform2DTriggersDeferredSave) { +TEST_F(DisplayListTest, Transform2DTriggersDeferredSave) { DisplayListBuilder builder1; - builder1.save(); - builder1.save(); - builder1.transform2DAffine(0, 1, 12, 1, 0, 33); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); - builder1.restore(); + DlOpReceiver& receiver1 = ToReceiver(builder1); + receiver1.save(); + receiver1.save(); + receiver1.transform2DAffine(0, 1, 12, 1, 0, 33); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); + receiver1.restore(); auto display_list1 = builder1.Build(); DisplayListBuilder builder2; - builder2.save(); - builder2.transform2DAffine(0, 1, 12, 1, 0, 33); - builder2.drawRect({0, 0, 100, 100}); - builder2.restore(); + DlOpReceiver& receiver2 = ToReceiver(builder2); + receiver2.save(); + receiver2.transform2DAffine(0, 1, 12, 1, 0, 33); + receiver2.drawRect({0, 0, 100, 100}); + receiver2.restore(); auto display_list2 = builder2.Build(); ASSERT_TRUE(DisplayListsEQ_Verbose(display_list1, display_list2)); } -TEST(DisplayList, TransformPerspectiveTriggersDeferredSave) { +TEST_F(DisplayListTest, TransformPerspectiveTriggersDeferredSave) { DisplayListBuilder builder1; - builder1.save(); - builder1.save(); - builder1.transformFullPerspective(0, 1, 0, 12, 1, 0, 0, 33, 3, 2, 5, 29, 0, 0, - 0, 12); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); - builder1.restore(); + DlOpReceiver& receiver1 = ToReceiver(builder1); + receiver1.save(); + receiver1.save(); + receiver1.transformFullPerspective(0, 1, 0, 12, // + 1, 0, 0, 33, // + 3, 2, 5, 29, // + 0, 0, 0, 12); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); + receiver1.restore(); auto display_list1 = builder1.Build(); DisplayListBuilder builder2; - builder2.save(); - builder2.transformFullPerspective(0, 1, 0, 12, 1, 0, 0, 33, 3, 2, 5, 29, 0, 0, - 0, 12); - builder2.drawRect({0, 0, 100, 100}); - builder2.restore(); + DlOpReceiver& receiver2 = ToReceiver(builder2); + receiver2.save(); + receiver2.transformFullPerspective(0, 1, 0, 12, // + 1, 0, 0, 33, // + 3, 2, 5, 29, // + 0, 0, 0, 12); + receiver2.drawRect({0, 0, 100, 100}); + receiver2.restore(); auto display_list2 = builder2.Build(); ASSERT_TRUE(DisplayListsEQ_Verbose(display_list1, display_list2)); } -TEST(DisplayList, ResetTransformTriggersDeferredSave) { +TEST_F(DisplayListTest, ResetTransformTriggersDeferredSave) { DisplayListBuilder builder1; - builder1.save(); - builder1.save(); - builder1.transformReset(); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); - builder1.restore(); + DlOpReceiver& receiver1 = ToReceiver(builder1); + receiver1.save(); + receiver1.save(); + receiver1.transformReset(); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); + receiver1.restore(); auto display_list1 = builder1.Build(); DisplayListBuilder builder2; - builder2.save(); - builder2.transformReset(); - builder2.drawRect({0, 0, 100, 100}); - builder2.restore(); + DlOpReceiver& receiver2 = ToReceiver(builder2); + receiver2.save(); + receiver2.transformReset(); + receiver2.drawRect({0, 0, 100, 100}); + receiver2.restore(); auto display_list2 = builder2.Build(); ASSERT_TRUE(DisplayListsEQ_Verbose(display_list1, display_list2)); } -TEST(DisplayList, SkewTriggersDeferredSave) { +TEST_F(DisplayListTest, SkewTriggersDeferredSave) { DisplayListBuilder builder1; - builder1.save(); - builder1.save(); - builder1.skew(10, 10); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); - builder1.restore(); + DlOpReceiver& receiver1 = ToReceiver(builder1); + receiver1.save(); + receiver1.save(); + receiver1.skew(10, 10); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); + receiver1.restore(); auto display_list1 = builder1.Build(); DisplayListBuilder builder2; - builder2.save(); - builder2.skew(10, 10); - builder2.drawRect({0, 0, 100, 100}); - builder2.restore(); + DlOpReceiver& receiver2 = ToReceiver(builder2); + receiver2.save(); + receiver2.skew(10, 10); + receiver2.drawRect({0, 0, 100, 100}); + receiver2.restore(); auto display_list2 = builder2.Build(); ASSERT_TRUE(DisplayListsEQ_Verbose(display_list1, display_list2)); } -TEST(DisplayList, TranslateTriggersDeferredSave) { +TEST_F(DisplayListTest, TranslateTriggersDeferredSave) { DisplayListBuilder builder1; - builder1.save(); - builder1.save(); - builder1.translate(10, 10); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); - builder1.restore(); + DlOpReceiver& receiver1 = ToReceiver(builder1); + receiver1.save(); + receiver1.save(); + receiver1.translate(10, 10); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); + receiver1.restore(); auto display_list1 = builder1.Build(); DisplayListBuilder builder2; - builder2.save(); - builder2.translate(10, 10); - builder2.drawRect({0, 0, 100, 100}); - builder2.restore(); + DlOpReceiver& receiver2 = ToReceiver(builder2); + receiver2.save(); + receiver2.translate(10, 10); + receiver2.drawRect({0, 0, 100, 100}); + receiver2.restore(); auto display_list2 = builder2.Build(); ASSERT_TRUE(DisplayListsEQ_Verbose(display_list1, display_list2)); } -TEST(DisplayList, ScaleTriggersDeferredSave) { +TEST_F(DisplayListTest, ScaleTriggersDeferredSave) { DisplayListBuilder builder1; - builder1.save(); - builder1.save(); - builder1.scale(0.5, 0.5); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); - builder1.restore(); + DlOpReceiver& receiver1 = ToReceiver(builder1); + receiver1.save(); + receiver1.save(); + receiver1.scale(0.5, 0.5); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); + receiver1.restore(); auto display_list1 = builder1.Build(); DisplayListBuilder builder2; - builder2.save(); - builder2.scale(0.5, 0.5); - builder2.drawRect({0, 0, 100, 100}); - builder2.restore(); + DlOpReceiver& receiver2 = ToReceiver(builder2); + receiver2.save(); + receiver2.scale(0.5, 0.5); + receiver2.drawRect({0, 0, 100, 100}); + receiver2.restore(); auto display_list2 = builder2.Build(); ASSERT_TRUE(DisplayListsEQ_Verbose(display_list1, display_list2)); } -TEST(DisplayList, ClipRectTriggersDeferredSave) { +TEST_F(DisplayListTest, ClipRectTriggersDeferredSave) { DisplayListBuilder builder1; - builder1.save(); - builder1.save(); - builder1.clipRect(SkRect::MakeLTRB(0, 0, 100, 100), ClipOp::kIntersect, true); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); - builder1.transform(SkM44()); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); + DlOpReceiver& receiver1 = ToReceiver(builder1); + receiver1.save(); + receiver1.save(); + receiver1.clipRect(SkRect::MakeLTRB(0, 0, 100, 100), ClipOp::kIntersect, + true); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); + receiver1.transformFullPerspective(1, 0, 0, 0, // + 0, 1, 0, 0, // + 0, 0, 1, 0, // + 0, 0, 0, 1); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); auto display_list1 = builder1.Build(); DisplayListBuilder builder2; - builder2.save(); - builder2.clipRect(SkRect::MakeLTRB(0, 0, 100, 100), ClipOp::kIntersect, true); - builder2.drawRect({0, 0, 100, 100}); - builder2.restore(); - builder2.transform(SkM44()); - builder2.drawRect({0, 0, 100, 100}); + DlOpReceiver& receiver2 = ToReceiver(builder2); + receiver2.save(); + receiver2.clipRect(SkRect::MakeLTRB(0, 0, 100, 100), ClipOp::kIntersect, + true); + receiver2.drawRect({0, 0, 100, 100}); + receiver2.restore(); + receiver2.transformFullPerspective(1, 0, 0, 0, // + 0, 1, 0, 0, // + 0, 0, 1, 0, // + 0, 0, 0, 1); + receiver2.drawRect({0, 0, 100, 100}); auto display_list2 = builder2.Build(); ASSERT_TRUE(DisplayListsEQ_Verbose(display_list1, display_list2)); } -TEST(DisplayList, ClipRRectTriggersDeferredSave) { +TEST_F(DisplayListTest, ClipRRectTriggersDeferredSave) { DisplayListBuilder builder1; - builder1.save(); - builder1.save(); - builder1.clipRRect(kTestRRect, ClipOp::kIntersect, true); - - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); - builder1.transform(SkM44()); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); + DlOpReceiver& receiver1 = ToReceiver(builder1); + receiver1.save(); + receiver1.save(); + receiver1.clipRRect(kTestRRect, ClipOp::kIntersect, true); + + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); + receiver1.transformFullPerspective(1, 0, 0, 0, // + 0, 1, 0, 0, // + 0, 0, 1, 0, // + 0, 0, 0, 1); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); auto display_list1 = builder1.Build(); DisplayListBuilder builder2; - builder2.save(); - builder2.clipRRect(kTestRRect, ClipOp::kIntersect, true); - - builder2.drawRect({0, 0, 100, 100}); - builder2.restore(); - builder2.transform(SkM44()); - builder2.drawRect({0, 0, 100, 100}); + DlOpReceiver& receiver2 = ToReceiver(builder2); + receiver2.save(); + receiver2.clipRRect(kTestRRect, ClipOp::kIntersect, true); + + receiver2.drawRect({0, 0, 100, 100}); + receiver2.restore(); + receiver2.transformFullPerspective(1, 0, 0, 0, // + 0, 1, 0, 0, // + 0, 0, 1, 0, // + 0, 0, 0, 1); + receiver2.drawRect({0, 0, 100, 100}); auto display_list2 = builder2.Build(); ASSERT_TRUE(DisplayListsEQ_Verbose(display_list1, display_list2)); } -TEST(DisplayList, ClipPathTriggersDeferredSave) { +TEST_F(DisplayListTest, ClipPathTriggersDeferredSave) { DisplayListBuilder builder1; - builder1.save(); - builder1.save(); - builder1.clipPath(kTestPath1, ClipOp::kIntersect, true); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); - builder1.transform(SkM44()); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); + DlOpReceiver& receiver1 = ToReceiver(builder1); + receiver1.save(); + receiver1.save(); + receiver1.clipPath(kTestPath1, ClipOp::kIntersect, true); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); + receiver1.transformFullPerspective(1, 0, 0, 0, // + 0, 1, 0, 0, // + 0, 0, 1, 0, // + 0, 0, 0, 1); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); auto display_list1 = builder1.Build(); DisplayListBuilder builder2; - builder2.save(); - builder2.clipPath(kTestPath1, ClipOp::kIntersect, true); - builder2.drawRect({0, 0, 100, 100}); - builder2.restore(); - builder2.transform(SkM44()); - builder2.drawRect({0, 0, 100, 100}); + DlOpReceiver& receiver2 = ToReceiver(builder2); + receiver2.save(); + receiver2.clipPath(kTestPath1, ClipOp::kIntersect, true); + receiver2.drawRect({0, 0, 100, 100}); + receiver2.restore(); + receiver2.transformFullPerspective(1, 0, 0, 0, // + 0, 1, 0, 0, // + 0, 0, 1, 0, // + 0, 0, 0, 1); + receiver2.drawRect({0, 0, 100, 100}); auto display_list2 = builder2.Build(); ASSERT_TRUE(DisplayListsEQ_Verbose(display_list1, display_list2)); } -TEST(DisplayList, NOPTranslateDoesNotTriggerDeferredSave) { +TEST_F(DisplayListTest, NOPTranslateDoesNotTriggerDeferredSave) { DisplayListBuilder builder1; - builder1.save(); - builder1.save(); - builder1.translate(0, 0); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); + DlOpReceiver& receiver1 = ToReceiver(builder1); + receiver1.save(); + receiver1.save(); + receiver1.translate(0, 0); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); auto display_list1 = builder1.Build(); DisplayListBuilder builder2; - builder2.drawRect({0, 0, 100, 100}); - builder2.drawRect({0, 0, 100, 100}); + DlOpReceiver& receiver2 = ToReceiver(builder2); + receiver2.drawRect({0, 0, 100, 100}); + receiver2.drawRect({0, 0, 100, 100}); auto display_list2 = builder2.Build(); ASSERT_TRUE(DisplayListsEQ_Verbose(display_list1, display_list2)); } -TEST(DisplayList, NOPScaleDoesNotTriggerDeferredSave) { +TEST_F(DisplayListTest, NOPScaleDoesNotTriggerDeferredSave) { DisplayListBuilder builder1; - builder1.save(); - builder1.save(); - builder1.scale(1.0, 1.0); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); + DlOpReceiver& receiver1 = ToReceiver(builder1); + receiver1.save(); + receiver1.save(); + receiver1.scale(1.0, 1.0); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); auto display_list1 = builder1.Build(); DisplayListBuilder builder2; - builder2.drawRect({0, 0, 100, 100}); - builder2.drawRect({0, 0, 100, 100}); + DlOpReceiver& receiver2 = ToReceiver(builder2); + receiver2.drawRect({0, 0, 100, 100}); + receiver2.drawRect({0, 0, 100, 100}); auto display_list2 = builder2.Build(); ASSERT_TRUE(DisplayListsEQ_Verbose(display_list1, display_list2)); } -TEST(DisplayList, NOPRotationDoesNotTriggerDeferredSave) { +TEST_F(DisplayListTest, NOPRotationDoesNotTriggerDeferredSave) { DisplayListBuilder builder1; - builder1.save(); - builder1.save(); - builder1.rotate(360); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); + DlOpReceiver& receiver1 = ToReceiver(builder1); + receiver1.save(); + receiver1.save(); + receiver1.rotate(360); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); auto display_list1 = builder1.Build(); DisplayListBuilder builder2; - builder2.drawRect({0, 0, 100, 100}); - builder2.drawRect({0, 0, 100, 100}); + DlOpReceiver& receiver2 = ToReceiver(builder2); + receiver2.drawRect({0, 0, 100, 100}); + receiver2.drawRect({0, 0, 100, 100}); auto display_list2 = builder2.Build(); ASSERT_TRUE(DisplayListsEQ_Verbose(display_list1, display_list2)); } -TEST(DisplayList, NOPSkewDoesNotTriggerDeferredSave) { +TEST_F(DisplayListTest, NOPSkewDoesNotTriggerDeferredSave) { DisplayListBuilder builder1; - builder1.save(); - builder1.save(); - builder1.skew(0, 0); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); + DlOpReceiver& receiver1 = ToReceiver(builder1); + receiver1.save(); + receiver1.save(); + receiver1.skew(0, 0); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); auto display_list1 = builder1.Build(); DisplayListBuilder builder2; - builder2.drawRect({0, 0, 100, 100}); - builder2.drawRect({0, 0, 100, 100}); + DlOpReceiver& receiver2 = ToReceiver(builder2); + receiver2.drawRect({0, 0, 100, 100}); + receiver2.drawRect({0, 0, 100, 100}); auto display_list2 = builder2.Build(); ASSERT_TRUE(DisplayListsEQ_Verbose(display_list1, display_list2)); } -TEST(DisplayList, NOPTransformDoesNotTriggerDeferredSave) { +TEST_F(DisplayListTest, NOPTransformDoesNotTriggerDeferredSave) { DisplayListBuilder builder1; - builder1.save(); - builder1.save(); - builder1.transform(SkM44()); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); - builder1.transform(SkM44()); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); + DlOpReceiver& receiver1 = ToReceiver(builder1); + receiver1.save(); + receiver1.save(); + receiver1.transformFullPerspective(1, 0, 0, 0, // + 0, 1, 0, 0, // + 0, 0, 1, 0, // + 0, 0, 0, 1); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); + receiver1.transformFullPerspective(1, 0, 0, 0, // + 0, 1, 0, 0, // + 0, 0, 1, 0, // + 0, 0, 0, 1); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); auto display_list1 = builder1.Build(); DisplayListBuilder builder2; - builder2.drawRect({0, 0, 100, 100}); - builder2.drawRect({0, 0, 100, 100}); + DlOpReceiver& receiver2 = ToReceiver(builder2); + receiver2.drawRect({0, 0, 100, 100}); + receiver2.drawRect({0, 0, 100, 100}); auto display_list2 = builder2.Build(); ASSERT_TRUE(DisplayListsEQ_Verbose(display_list1, display_list2)); } -TEST(DisplayList, NOPTransform2DDoesNotTriggerDeferredSave) { +TEST_F(DisplayListTest, NOPTransform2DDoesNotTriggerDeferredSave) { DisplayListBuilder builder1; - builder1.save(); - builder1.save(); - builder1.transform2DAffine(1, 0, 0, 0, 1, 0); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); + DlOpReceiver& receiver1 = ToReceiver(builder1); + receiver1.save(); + receiver1.save(); + receiver1.transform2DAffine(1, 0, 0, 0, 1, 0); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); auto display_list1 = builder1.Build(); DisplayListBuilder builder2; - builder2.drawRect({0, 0, 100, 100}); - builder2.drawRect({0, 0, 100, 100}); + DlOpReceiver& receiver2 = ToReceiver(builder2); + receiver2.drawRect({0, 0, 100, 100}); + receiver2.drawRect({0, 0, 100, 100}); auto display_list2 = builder2.Build(); ASSERT_TRUE(DisplayListsEQ_Verbose(display_list1, display_list2)); } -TEST(DisplayList, NOPTransformFullPerspectiveDoesNotTriggerDeferredSave) { +TEST_F(DisplayListTest, NOPTransformFullPerspectiveDoesNotTriggerDeferredSave) { { DisplayListBuilder builder1; - builder1.save(); - builder1.save(); - builder1.transformFullPerspective(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 1); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); + DlOpReceiver& receiver1 = ToReceiver(builder1); + receiver1.save(); + receiver1.save(); + receiver1.transformFullPerspective(1, 0, 0, 0, // + 0, 1, 0, 0, // + 0, 0, 1, 0, // + 0, 0, 0, 1); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); auto display_list1 = builder1.Build(); DisplayListBuilder builder2; - builder2.drawRect({0, 0, 100, 100}); - builder2.drawRect({0, 0, 100, 100}); + DlOpReceiver& receiver2 = ToReceiver(builder2); + receiver2.drawRect({0, 0, 100, 100}); + receiver2.drawRect({0, 0, 100, 100}); auto display_list2 = builder2.Build(); ASSERT_TRUE(DisplayListsEQ_Verbose(display_list1, display_list2)); @@ -2240,23 +2436,27 @@ TEST(DisplayList, NOPTransformFullPerspectiveDoesNotTriggerDeferredSave) { { DisplayListBuilder builder1; - builder1.save(); - builder1.save(); - builder1.transformFullPerspective(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 1); - builder1.transformReset(); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); + DlOpReceiver& receiver1 = ToReceiver(builder1); + receiver1.save(); + receiver1.save(); + receiver1.transformFullPerspective(1, 0, 0, 0, // + 0, 1, 0, 0, // + 0, 0, 1, 0, // + 0, 0, 0, 1); + receiver1.transformReset(); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); auto display_list1 = builder1.Build(); DisplayListBuilder builder2; - builder2.save(); - builder2.transformReset(); - builder2.drawRect({0, 0, 100, 100}); - builder2.restore(); - builder2.drawRect({0, 0, 100, 100}); + DlOpReceiver& receiver2 = ToReceiver(builder2); + receiver2.save(); + receiver2.transformReset(); + receiver2.drawRect({0, 0, 100, 100}); + receiver2.restore(); + receiver2.drawRect({0, 0, 100, 100}); auto display_list2 = builder2.Build(); @@ -2264,40 +2464,42 @@ TEST(DisplayList, NOPTransformFullPerspectiveDoesNotTriggerDeferredSave) { } } -TEST(DisplayList, NOPClipDoesNotTriggerDeferredSave) { +TEST_F(DisplayListTest, NOPClipDoesNotTriggerDeferredSave) { DisplayListBuilder builder1; - builder1.save(); - builder1.save(); - builder1.clipRect(SkRect::MakeLTRB(0, SK_ScalarNaN, SK_ScalarNaN, 0), - ClipOp::kIntersect, true); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); - builder1.drawRect({0, 0, 100, 100}); - builder1.restore(); + DlOpReceiver& receiver1 = ToReceiver(builder1); + receiver1.save(); + receiver1.save(); + receiver1.clipRect(SkRect::MakeLTRB(0, SK_ScalarNaN, SK_ScalarNaN, 0), + ClipOp::kIntersect, true); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); + receiver1.drawRect({0, 0, 100, 100}); + receiver1.restore(); auto display_list1 = builder1.Build(); DisplayListBuilder builder2; - builder2.drawRect({0, 0, 100, 100}); - builder2.drawRect({0, 0, 100, 100}); + DlOpReceiver& receiver2 = ToReceiver(builder2); + receiver2.drawRect({0, 0, 100, 100}); + receiver2.drawRect({0, 0, 100, 100}); auto display_list2 = builder2.Build(); ASSERT_TRUE(DisplayListsEQ_Verbose(display_list1, display_list2)); } -TEST(DisplayList, RTreeOfClippedSaveLayerFilterScene) { +TEST_F(DisplayListTest, RTreeOfClippedSaveLayerFilterScene) { DisplayListBuilder builder(/*prepare_rtree=*/true); // blur filter with sigma=1 expands by 30 on all sides auto filter = DlBlurImageFilter(10.0, 10.0, DlTileMode::kClamp); DlPaint default_paint = DlPaint(); DlPaint filter_paint = DlPaint().setImageFilter(&filter); builder.DrawRect({10, 10, 20, 20}, default_paint); - builder.clipRect({50, 50, 60, 60}, ClipOp::kIntersect, false); + builder.ClipRect({50, 50, 60, 60}, ClipOp::kIntersect, false); builder.SaveLayer(nullptr, &filter_paint); // the following rectangle will be expanded to 23,23,87,87 // by the saveLayer filter during the restore operation // but it will then be clipped to 50,50,60,60 builder.DrawRect({53, 53, 57, 57}, default_paint); - builder.restore(); + builder.Restore(); auto display_list = builder.Build(); auto rtree = display_list->rtree(); std::vector rects = { @@ -2321,12 +2523,13 @@ TEST(DisplayList, RTreeOfClippedSaveLayerFilterScene) { test_rtree(rtree, {19, 19, 51, 51}, rects, {0, 1}); } -TEST(DisplayList, RTreeRenderCulling) { +TEST_F(DisplayListTest, RTreeRenderCulling) { DisplayListBuilder main_builder(true); - main_builder.drawRect({0, 0, 10, 10}); - main_builder.drawRect({20, 0, 30, 10}); - main_builder.drawRect({0, 20, 10, 30}); - main_builder.drawRect({20, 20, 30, 30}); + DlOpReceiver& main_receiver = ToReceiver(main_builder); + main_receiver.drawRect({0, 0, 10, 10}); + main_receiver.drawRect({20, 0, 30, 10}); + main_receiver.drawRect({0, 20, 10, 30}); + main_receiver.drawRect({20, 20, 30, 30}); auto main = main_builder.Build(); { // No rects @@ -2336,7 +2539,7 @@ TEST(DisplayList, RTreeRenderCulling) { auto expected = expected_builder.Build(); DisplayListBuilder culling_builder(cull_rect); - main->RenderTo(&culling_builder); + main->Dispatch(ToReceiver(culling_builder), cull_rect); EXPECT_TRUE(DisplayListsEQ_Verbose(culling_builder.Build(), expected)); } @@ -2345,11 +2548,12 @@ TEST(DisplayList, RTreeRenderCulling) { SkRect cull_rect = {9, 9, 19, 19}; DisplayListBuilder expected_builder; - expected_builder.drawRect({0, 0, 10, 10}); + DlOpReceiver& expected_receiver = ToReceiver(expected_builder); + expected_receiver.drawRect({0, 0, 10, 10}); auto expected = expected_builder.Build(); DisplayListBuilder culling_builder(cull_rect); - main->RenderTo(&culling_builder); + main->Dispatch(ToReceiver(culling_builder), cull_rect); EXPECT_TRUE(DisplayListsEQ_Verbose(culling_builder.Build(), expected)); } @@ -2358,11 +2562,12 @@ TEST(DisplayList, RTreeRenderCulling) { SkRect cull_rect = {11, 9, 21, 19}; DisplayListBuilder expected_builder; - expected_builder.drawRect({20, 0, 30, 10}); + DlOpReceiver& expected_receiver = ToReceiver(expected_builder); + expected_receiver.drawRect({20, 0, 30, 10}); auto expected = expected_builder.Build(); DisplayListBuilder culling_builder(cull_rect); - main->RenderTo(&culling_builder); + main->Dispatch(ToReceiver(culling_builder), cull_rect); EXPECT_TRUE(DisplayListsEQ_Verbose(culling_builder.Build(), expected)); } @@ -2371,11 +2576,12 @@ TEST(DisplayList, RTreeRenderCulling) { SkRect cull_rect = {9, 11, 19, 21}; DisplayListBuilder expected_builder; - expected_builder.drawRect({0, 20, 10, 30}); + DlOpReceiver& expected_receiver = ToReceiver(expected_builder); + expected_receiver.drawRect({0, 20, 10, 30}); auto expected = expected_builder.Build(); DisplayListBuilder culling_builder(cull_rect); - main->RenderTo(&culling_builder); + main->Dispatch(ToReceiver(culling_builder), cull_rect); EXPECT_TRUE(DisplayListsEQ_Verbose(culling_builder.Build(), expected)); } @@ -2384,11 +2590,12 @@ TEST(DisplayList, RTreeRenderCulling) { SkRect cull_rect = {11, 11, 21, 21}; DisplayListBuilder expected_builder; - expected_builder.drawRect({20, 20, 30, 30}); + DlOpReceiver& expected_receiver = ToReceiver(expected_builder); + expected_receiver.drawRect({20, 20, 30, 30}); auto expected = expected_builder.Build(); DisplayListBuilder culling_builder(cull_rect); - main->RenderTo(&culling_builder); + main->Dispatch(ToReceiver(culling_builder), cull_rect); EXPECT_TRUE(DisplayListsEQ_Verbose(culling_builder.Build(), expected)); } @@ -2397,7 +2604,7 @@ TEST(DisplayList, RTreeRenderCulling) { SkRect cull_rect = {9, 9, 21, 21}; DisplayListBuilder culling_builder(cull_rect); - main->RenderTo(&culling_builder); + main->Dispatch(ToReceiver(culling_builder), cull_rect); EXPECT_TRUE(DisplayListsEQ_Verbose(culling_builder.Build(), main)); } diff --git a/display_list/display_list_utils.cc b/display_list/display_list_utils.cc index 2ffed31214ae5..e6c21d586c46a 100644 --- a/display_list/display_list_utils.cc +++ b/display_list/display_list_utils.cc @@ -4,106 +4,8 @@ #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" -#include "third_party/skia/include/core/SkPath.h" -#include "third_party/skia/include/core/SkRSXform.h" -#include "third_party/skia/include/core/SkTextBlob.h" -#include "third_party/skia/include/utils/SkShadowUtils.h" - namespace flutter { -// clang-format off -constexpr float kInvertColorMatrix[20] = { - -1.0, 0, 0, 1.0, 0, - 0, -1.0, 0, 1.0, 0, - 0, 0, -1.0, 1.0, 0, - 1.0, 1.0, 1.0, 1.0, 0 -}; -// clang-format on - -void SkPaintDispatchHelper::save_opacity(SkScalar child_opacity) { - save_stack_.emplace_back(opacity_); - set_opacity(child_opacity); -} -void SkPaintDispatchHelper::restore_opacity() { - if (save_stack_.empty()) { - return; - } - set_opacity(save_stack_.back().opacity); - save_stack_.pop_back(); -} - -void SkPaintDispatchHelper::setAntiAlias(bool aa) { - paint_.setAntiAlias(aa); -} -void SkPaintDispatchHelper::setDither(bool dither) { - paint_.setDither(dither); -} -void SkPaintDispatchHelper::setInvertColors(bool invert) { - invert_colors_ = invert; - paint_.setColorFilter(makeColorFilter()); -} -void SkPaintDispatchHelper::setStrokeCap(DlStrokeCap cap) { - paint_.setStrokeCap(ToSk(cap)); -} -void SkPaintDispatchHelper::setStrokeJoin(DlStrokeJoin join) { - paint_.setStrokeJoin(ToSk(join)); -} -void SkPaintDispatchHelper::setStyle(DlDrawStyle style) { - paint_.setStyle(ToSk(style)); -} -void SkPaintDispatchHelper::setStrokeWidth(SkScalar width) { - paint_.setStrokeWidth(width); -} -void SkPaintDispatchHelper::setStrokeMiter(SkScalar limit) { - paint_.setStrokeMiter(limit); -} -void SkPaintDispatchHelper::setColor(DlColor color) { - current_color_ = color; - paint_.setColor(color); - if (has_opacity()) { - paint_.setAlphaf(paint_.getAlphaf() * opacity()); - } -} -void SkPaintDispatchHelper::setBlendMode(DlBlendMode mode) { - paint_.setBlendMode(ToSk(mode)); -} -void SkPaintDispatchHelper::setColorSource(const DlColorSource* source) { - paint_.setShader(source ? source->skia_object() : nullptr); -} -void SkPaintDispatchHelper::setImageFilter(const DlImageFilter* filter) { - paint_.setImageFilter(filter ? filter->skia_object() : nullptr); -} -void SkPaintDispatchHelper::setColorFilter(const DlColorFilter* filter) { - color_filter_ = filter ? filter->shared() : nullptr; - paint_.setColorFilter(makeColorFilter()); -} -void SkPaintDispatchHelper::setPathEffect(const DlPathEffect* effect) { - paint_.setPathEffect(effect ? effect->skia_object() : nullptr); -} -void SkPaintDispatchHelper::setMaskFilter(const DlMaskFilter* filter) { - paint_.setMaskFilter(filter ? filter->skia_object() : nullptr); -} - -sk_sp SkPaintDispatchHelper::makeColorFilter() const { - if (!invert_colors_) { - return color_filter_ ? color_filter_->skia_object() : nullptr; - } - sk_sp invert_filter = - SkColorFilters::Matrix(kInvertColorMatrix); - if (color_filter_) { - invert_filter = invert_filter->makeComposed(color_filter_->skia_object()); - } - return invert_filter; -} - void RectBoundsAccumulator::accumulate(const SkRect& r, int index) { if (r.fLeft < r.fRight && r.fTop < r.fBottom) { rect_.accumulate(r.fLeft, r.fTop); diff --git a/display_list/display_list_utils.h b/display_list/display_list_utils.h index c2bed1440211c..ef243eacfc0ba 100644 --- a/display_list/display_list_utils.h +++ b/display_list/display_list_utils.h @@ -7,33 +7,24 @@ #include -#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_flags.h" #include "flutter/display_list/display_list_rtree.h" +#include "flutter/display_list/dl_op_receiver.h" #include "flutter/fml/logging.h" -#include "flutter/fml/macros.h" -#include "third_party/skia/include/core/SkMaskFilter.h" // This file contains various utility classes to ease implementing -// a Flutter DisplayList Dispatcher, including: +// a Flutter DisplayList DlOpReceiver, including: // // IgnoreAttributeDispatchHelper: // IgnoreClipDispatchHelper: // IgnoreTransformDispatchHelper -// Empty overrides of all of the associated methods of Dispatcher -// for dispatchers that only track some of the rendering operations -// -// SkPaintAttributeDispatchHelper: -// Tracks the attribute methods and maintains their state in an -// SkPaint object. +// Empty overrides of all of the associated methods of DlOpReceiver +// for receivers that only track some of the rendering operations namespace flutter { -// A utility class that will ignore all Dispatcher methods relating +// A utility class that will ignore all DlOpReceiver methods relating // to the setting of attributes. -class IgnoreAttributeDispatchHelper : public virtual Dispatcher { +class IgnoreAttributeDispatchHelper : public virtual DlOpReceiver { public: void setAntiAlias(bool aa) override {} void setDither(bool dither) override {} @@ -52,9 +43,9 @@ class IgnoreAttributeDispatchHelper : public virtual Dispatcher { void setMaskFilter(const DlMaskFilter* filter) override {} }; -// A utility class that will ignore all Dispatcher methods relating +// A utility class that will ignore all DlOpReceiver methods relating // to setting a clip. -class IgnoreClipDispatchHelper : public virtual Dispatcher { +class IgnoreClipDispatchHelper : public virtual DlOpReceiver { void clipRect(const SkRect& rect, DlCanvas::ClipOp clip_op, bool is_aa) override {} @@ -66,9 +57,9 @@ class IgnoreClipDispatchHelper : public virtual Dispatcher { bool is_aa) override {} }; -// A utility class that will ignore all Dispatcher methods relating +// A utility class that will ignore all DlOpReceiver methods relating // to modifying the transform. -class IgnoreTransformDispatchHelper : public virtual Dispatcher { +class IgnoreTransformDispatchHelper : public virtual DlOpReceiver { public: void translate(SkScalar tx, SkScalar ty) override {} void scale(SkScalar sx, SkScalar sy) override {} @@ -88,7 +79,7 @@ class IgnoreTransformDispatchHelper : public virtual Dispatcher { void transformReset() override {} }; -class IgnoreDrawDispatchHelper : public virtual Dispatcher { +class IgnoreDrawDispatchHelper : public virtual DlOpReceiver { public: void save() override {} void saveLayer(const SkRect* bounds, @@ -121,7 +112,7 @@ class IgnoreDrawDispatchHelper : public virtual Dispatcher { const SkRect& dst, DlImageSampling sampling, bool render_with_attributes, - SkCanvas::SrcRectConstraint constraint) override {} + bool enforce_src_edges) override {} void drawImageNine(const sk_sp image, const SkIRect& center, const SkRect& dst, @@ -136,7 +127,8 @@ class IgnoreDrawDispatchHelper : public virtual Dispatcher { DlImageSampling sampling, const SkRect* cull_rect, bool render_with_attributes) override {} - void drawDisplayList(const sk_sp display_list) override {} + void drawDisplayList(const sk_sp display_list, + SkScalar opacity) override {} void drawTextBlob(const sk_sp blob, SkScalar x, SkScalar y) override {} @@ -147,77 +139,6 @@ class IgnoreDrawDispatchHelper : public virtual Dispatcher { SkScalar dpr) override {} }; -// A utility class that will monitor the Dispatcher methods relating -// to the rendering attributes and accumulate them into an SkPaint -// which can be accessed at any time via paint(). -class SkPaintDispatchHelper : public virtual Dispatcher { - public: - SkPaintDispatchHelper(SkScalar opacity = SK_Scalar1) - : current_color_(SK_ColorBLACK), opacity_(opacity) { - if (opacity < SK_Scalar1) { - paint_.setAlphaf(opacity); - } - } - - void setAntiAlias(bool aa) override; - void setDither(bool dither) override; - void setStyle(DlDrawStyle style) override; - void setColor(DlColor color) override; - void setStrokeWidth(SkScalar width) override; - void setStrokeMiter(SkScalar limit) override; - void setStrokeCap(DlStrokeCap cap) override; - void setStrokeJoin(DlStrokeJoin join) override; - void setColorSource(const DlColorSource* source) override; - void setColorFilter(const DlColorFilter* filter) override; - void setInvertColors(bool invert) override; - void setBlendMode(DlBlendMode mode) override; - void setPathEffect(const DlPathEffect* effect) override; - void setMaskFilter(const DlMaskFilter* filter) override; - void setImageFilter(const DlImageFilter* filter) override; - - const SkPaint& paint() { return paint_; } - - /// Returns the current opacity attribute which is used to reduce - /// the alpha of all setColor calls encountered in the streeam - SkScalar opacity() { return opacity_; } - /// Returns the combined opacity that includes both the current - /// opacity attribute and the alpha of the most recent color. - /// The most recently set color will have combined the two and - /// stored the combined value in the alpha of the paint. - SkScalar combined_opacity() { return paint_.getAlphaf(); } - /// Returns true iff the current opacity attribute is not opaque, - /// irrespective of the alpha of the current color - bool has_opacity() { return opacity_ < SK_Scalar1; } - - protected: - void save_opacity(SkScalar opacity_for_children); - void restore_opacity(); - - private: - SkPaint paint_; - bool invert_colors_ = false; - std::shared_ptr color_filter_; - - sk_sp makeColorFilter() const; - - struct SaveInfo { - SaveInfo(SkScalar opacity) : opacity(opacity) {} - - SkScalar opacity; - }; - std::vector save_stack_; - - void set_opacity(SkScalar opacity) { - if (opacity_ != opacity) { - opacity_ = opacity; - setColor(current_color_); - } - } - - SkColor current_color_; - SkScalar opacity_; -}; - enum class BoundsAccumulatorType { kRect, kRTree, diff --git a/display_list/display_list_vertices.cc b/display_list/display_list_vertices.cc index 6c20c3aebef97..e6a9b72c3a7d0 100644 --- a/display_list/display_list_vertices.cc +++ b/display_list/display_list_vertices.cc @@ -176,13 +176,6 @@ DlVertices::DlVertices(DlVertexMode mode, FML_DCHECK((index_count_ != 0) == (indices() != nullptr)); } -sk_sp DlVertices::skia_object() const { - const SkColor* sk_colors = reinterpret_cast(colors()); - return SkVertices::MakeCopy(ToSk(mode_), vertex_count_, vertices(), - texture_coordinates(), sk_colors, index_count_, - indices()); -} - bool DlVertices::operator==(DlVertices const& other) const { auto lists_equal = [](auto* a, auto* b, int count) { if (a == nullptr || b == nullptr) { diff --git a/display_list/display_list_vertices.h b/display_list/display_list_vertices.h index 885ef6cfa65e8..04044baba0d72 100644 --- a/display_list/display_list_vertices.h +++ b/display_list/display_list_vertices.h @@ -30,14 +30,6 @@ enum class DlVertexMode { kTriangleFan, }; -inline SkVertices::VertexMode ToSk(DlVertexMode dl_mode) { - return static_cast(dl_mode); -} - -inline DlVertexMode ToDl(SkVertices::VertexMode sk_mode) { - return static_cast(sk_mode); -} - //------------------------------------------------------------------------------ /// @brief Holds all of the data (both required and optional) for a /// DisplayList drawVertices call. @@ -233,9 +225,6 @@ class DlVertices { return static_cast(pod(indices_offset_)); } - // Returns an equivalent sk_sp analog to this object. - sk_sp skia_object() const; - bool operator==(DlVertices const& other) const; bool operator!=(DlVertices const& other) const { return !(*this == other); } diff --git a/display_list/display_list_vertices_unittests.cc b/display_list/display_list_vertices_unittests.cc index 0323b621a53ac..5a11dc2efef3e 100644 --- a/display_list/display_list_vertices_unittests.cc +++ b/display_list/display_list_vertices_unittests.cc @@ -22,7 +22,6 @@ TEST(DisplayListVertices, MakeWithZeroAndNegativeVerticesAndIndices) { EXPECT_EQ(vertices1->colors(), nullptr); EXPECT_EQ(vertices1->index_count(), 0); EXPECT_EQ(vertices1->indices(), nullptr); - EXPECT_NE(vertices1->skia_object(), nullptr); std::shared_ptr vertices2 = DlVertices::Make( DlVertexMode::kTriangles, -1, nullptr, nullptr, nullptr, -1, nullptr); @@ -33,7 +32,6 @@ TEST(DisplayListVertices, MakeWithZeroAndNegativeVerticesAndIndices) { EXPECT_EQ(vertices2->colors(), nullptr); EXPECT_EQ(vertices2->index_count(), 0); EXPECT_EQ(vertices2->indices(), nullptr); - EXPECT_NE(vertices2->skia_object(), nullptr); TestEquals(*vertices1, *vertices2); } @@ -425,7 +423,6 @@ TEST(DisplayListVertices, BuildWithZeroAndNegativeVerticesAndIndices) { EXPECT_EQ(vertices1->colors(), nullptr); EXPECT_EQ(vertices1->index_count(), 0); EXPECT_EQ(vertices1->indices(), nullptr); - EXPECT_NE(vertices1->skia_object(), nullptr); Builder builder2(DlVertexMode::kTriangles, -1, Builder::kNone, -1); EXPECT_TRUE(builder2.is_valid()); @@ -437,7 +434,6 @@ TEST(DisplayListVertices, BuildWithZeroAndNegativeVerticesAndIndices) { EXPECT_EQ(vertices2->colors(), nullptr); EXPECT_EQ(vertices2->index_count(), 0); EXPECT_EQ(vertices2->indices(), nullptr); - EXPECT_NE(vertices2->skia_object(), nullptr); TestEquals(*vertices1, *vertices2); } diff --git a/display_list/dl_canvas.cc b/display_list/dl_canvas.cc new file mode 100644 index 0000000000000..7f9e3fce32151 --- /dev/null +++ b/display_list/dl_canvas.cc @@ -0,0 +1,23 @@ +// 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/dl_canvas.h" + +#include "third_party/skia/include/utils/SkShadowUtils.h" + +namespace flutter { + +SkRect DlCanvas::ComputeShadowBounds(const SkPath& path, + float elevation, + SkScalar dpr, + const SkMatrix& ctm) { + SkRect shadow_bounds(path.getBounds()); + SkShadowUtils::GetLocalBounds( + ctm, path, SkPoint3::Make(0, 0, dpr * elevation), + SkPoint3::Make(0, -1, 1), kShadowLightRadius / kShadowLightHeight, + SkShadowFlags::kDirectionalLight_ShadowFlag, &shadow_bounds); + return shadow_bounds; +} + +} // namespace flutter diff --git a/display_list/dl_canvas.h b/display_list/dl_canvas.h index 5d8d97eeacda8..f648b318a0970 100644 --- a/display_list/dl_canvas.h +++ b/display_list/dl_canvas.h @@ -196,6 +196,14 @@ class DlCanvas { SkScalar dpr) = 0; virtual void Flush() = 0; + + static constexpr SkScalar kShadowLightHeight = 600; + static constexpr SkScalar kShadowLightRadius = 800; + + static SkRect ComputeShadowBounds(const SkPath& path, + float elevation, + SkScalar dpr, + const SkMatrix& ctm); }; class DlAutoCanvasRestore { diff --git a/display_list/display_list_dispatcher.cc b/display_list/dl_op_receiver.cc similarity index 64% rename from display_list/display_list_dispatcher.cc rename to display_list/dl_op_receiver.cc index e321f02ea6c7f..b1b6c01967e56 100644 --- a/display_list/display_list_dispatcher.cc +++ b/display_list/dl_op_receiver.cc @@ -2,10 +2,10 @@ // 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_dispatcher.h" +#include "flutter/display_list/dl_op_receiver.h" namespace flutter { -// +// Just exists to ensure that the header can be cleanly imported. } // namespace flutter diff --git a/display_list/display_list_dispatcher.h b/display_list/dl_op_receiver.h similarity index 98% rename from display_list/display_list_dispatcher.h rename to display_list/dl_op_receiver.h index 00dc9661c1577..cca7991c288d3 100644 --- a/display_list/display_list_dispatcher.h +++ b/display_list/dl_op_receiver.h @@ -28,7 +28,7 @@ class DisplayList; /// through the DisplayListBuilder and also the methods that will be /// invoked through the DisplayList::dispatch() method. /// -class Dispatcher { +class DlOpReceiver { protected: using ClipOp = DlCanvas::ClipOp; using PointMode = DlCanvas::PointMode; @@ -224,7 +224,7 @@ class Dispatcher { const SkRect& dst, DlImageSampling sampling, bool render_with_attributes, - SkCanvas::SrcRectConstraint constraint) = 0; + bool enforce_src_edges = false) = 0; virtual void drawImageNine(const sk_sp image, const SkIRect& center, const SkRect& dst, @@ -239,7 +239,8 @@ class Dispatcher { DlImageSampling sampling, const SkRect* cull_rect, bool render_with_attributes) = 0; - virtual void drawDisplayList(const sk_sp display_list) = 0; + virtual void drawDisplayList(const sk_sp display_list, + SkScalar opacity = SK_Scalar1) = 0; virtual void drawTextBlob(const sk_sp blob, SkScalar x, SkScalar y) = 0; diff --git a/display_list/display_list_canvas_unittests.cc b/display_list/dl_rendering_unittests.cc similarity index 85% rename from display_list/display_list_canvas_unittests.cc rename to display_list/dl_rendering_unittests.cc index a6aed32248c79..6ab63fd8b8763 100644 --- a/display_list/display_list_canvas_unittests.cc +++ b/display_list/dl_rendering_unittests.cc @@ -6,15 +6,16 @@ #include "flutter/display_list/display_list.h" #include "flutter/display_list/display_list_builder.h" -#include "flutter/display_list/display_list_canvas_dispatcher.h" #include "flutter/display_list/display_list_comparable.h" #include "flutter/display_list/display_list_flags.h" #include "flutter/display_list/display_list_sampling_options.h" #include "flutter/display_list/skia/dl_sk_canvas.h" +#include "flutter/display_list/skia/dl_sk_dispatcher.h" #include "flutter/display_list/testing/dl_test_surface_provider.h" #include "flutter/fml/math.h" #include "flutter/testing/display_list_testing.h" #include "flutter/testing/testing.h" +#include "third_party/skia/include/core/SkColorFilter.h" #include "third_party/skia/include/core/SkPictureRecorder.h" #include "third_party/skia/include/core/SkSurface.h" @@ -135,6 +136,18 @@ const int kHorizontalMiterDiamondPointCount = (sizeof(kHorizontalMiterDiamondPoints) / sizeof(kHorizontalMiterDiamondPoints[0])); +class SkImageSampling { + public: + static constexpr SkSamplingOptions kNearestNeighbor = + SkSamplingOptions(SkFilterMode::kNearest); + static constexpr SkSamplingOptions kLinear = + SkSamplingOptions(SkFilterMode::kLinear); + static constexpr SkSamplingOptions kMipmapLinear = + SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear); + static constexpr SkSamplingOptions kCubic = + SkSamplingOptions(SkCubicResampler{1 / 3.0f, 1 / 3.0f}); +}; + // A class to specify how much tolerance to allow in bounds estimates. // For some attributes, the machinery must make some conservative // assumptions as to the extent of the bounds, but some of our test @@ -409,7 +422,7 @@ struct DisplayListJobRenderer : public JobRenderer { : display_list_(std::move(display_list)) {} void Render(SkCanvas* canvas, const RenderJobInfo& info) { - display_list_->RenderTo(canvas, info.opacity); + DlSkCanvasAdapter(canvas).DrawDisplayList(display_list_, info.opacity); } private: @@ -998,12 +1011,12 @@ class CanvasCompareTester { RenderEnvironment::MakeN32(env.provider()); SkSetup sk_backdrop_setup = [=](SkCanvas* cv, SkPaint& p) { SkPaint setup_p; - setup_p.setShader(kTestImageColorSource.skia_object()); + setup_p.setShader(kTestSkImageColorSource); cv->drawPaint(setup_p); }; DlSetup dl_backdrop_setup = [=](DlCanvas* cv, DlPaint& p) { DlPaint setup_p; - setup_p.setColorSource(&kTestImageColorSource); + setup_p.setColorSource(&kTestDlImageColorSource); cv->DrawPaint(setup_p); }; SkSetup sk_content_setup = [=](SkCanvas* cv, SkPaint& p) { @@ -1016,38 +1029,39 @@ class CanvasCompareTester { dl_backdrop_setup, testP.dl_renderer()); quickCompareToReference(backdrop_env, "backdrop"); - DlBlurImageFilter backdrop(5, 5, DlTileMode::kDecal); + DlBlurImageFilter dl_backdrop(5, 5, DlTileMode::kDecal); + auto sk_backdrop = + SkImageFilters::Blur(5, 5, SkTileMode::kDecal, nullptr); RenderWith(testP, backdrop_env, tolerance, CaseParameters( "saveLayer with backdrop", [=](SkCanvas* cv, SkPaint& p) { sk_backdrop_setup(cv, p); cv->saveLayer(SkCanvas::SaveLayerRec( - nullptr, nullptr, backdrop.skia_object().get(), 0)); + nullptr, nullptr, sk_backdrop.get(), 0)); sk_content_setup(cv, p); }, [=](DlCanvas* cv, DlPaint& p) { dl_backdrop_setup(cv, p); - cv->SaveLayer(nullptr, nullptr, &backdrop); + cv->SaveLayer(nullptr, nullptr, &dl_backdrop); + dl_content_setup(cv, p); + }) + .with_restore(sk_safe_restore, dl_safe_restore, true)); + RenderWith(testP, backdrop_env, tolerance, + CaseParameters( + "saveLayer with bounds and backdrop", + [=](SkCanvas* cv, SkPaint& p) { + sk_backdrop_setup(cv, p); + cv->saveLayer(SkCanvas::SaveLayerRec( + &layer_bounds, nullptr, sk_backdrop.get(), 0)); + sk_content_setup(cv, p); + }, + [=](DlCanvas* cv, DlPaint& p) { + dl_backdrop_setup(cv, p); + cv->SaveLayer(&layer_bounds, nullptr, &dl_backdrop); dl_content_setup(cv, p); }) .with_restore(sk_safe_restore, dl_safe_restore, true)); - RenderWith( - testP, backdrop_env, tolerance, - CaseParameters( - "saveLayer with bounds and backdrop", - [=](SkCanvas* cv, SkPaint& p) { - sk_backdrop_setup(cv, p); - cv->saveLayer(SkCanvas::SaveLayerRec( - &layer_bounds, nullptr, backdrop.skia_object().get(), 0)); - sk_content_setup(cv, p); - }, - [=](DlCanvas* cv, DlPaint& p) { - dl_backdrop_setup(cv, p); - cv->SaveLayer(&layer_bounds, nullptr, &backdrop); - dl_content_setup(cv, p); - }) - .with_restore(sk_safe_restore, dl_safe_restore, true)); RenderWith(testP, backdrop_env, tolerance, CaseParameters( "clipped saveLayer with backdrop", @@ -1055,13 +1069,13 @@ class CanvasCompareTester { sk_backdrop_setup(cv, p); cv->clipRect(layer_bounds); cv->saveLayer(SkCanvas::SaveLayerRec( - nullptr, nullptr, backdrop.skia_object().get(), 0)); + nullptr, nullptr, sk_backdrop.get(), 0)); sk_content_setup(cv, p); }, [=](DlCanvas* cv, DlPaint& p) { dl_backdrop_setup(cv, p); cv->ClipRect(layer_bounds); - cv->SaveLayer(nullptr, nullptr, &backdrop); + cv->SaveLayer(nullptr, nullptr, &dl_backdrop); dl_content_setup(cv, p); }) .with_restore(sk_safe_restore, dl_safe_restore, true)); @@ -1076,20 +1090,22 @@ class CanvasCompareTester { 0, 0, 0, 0.5, 0, }; // clang-format on - DlMatrixColorFilter filter(rotate_alpha_color_matrix); + DlMatrixColorFilter dl_alpha_rotate_filter(rotate_alpha_color_matrix); + auto sk_alpha_rotate_filter = + SkColorFilters::Matrix(rotate_alpha_color_matrix); { RenderWith(testP, env, tolerance, CaseParameters( "saveLayer ColorFilter, no bounds", [=](SkCanvas* cv, SkPaint& p) { SkPaint save_p; - save_p.setColorFilter(filter.skia_object()); + save_p.setColorFilter(sk_alpha_rotate_filter); cv->saveLayer(nullptr, &save_p); p.setStrokeWidth(5.0); }, [=](DlCanvas* cv, DlPaint& p) { DlPaint save_p; - save_p.setColorFilter(&filter); + save_p.setColorFilter(&dl_alpha_rotate_filter); cv->SaveLayer(nullptr, &save_p); p.setStrokeWidth(5.0); }) @@ -1101,13 +1117,13 @@ class CanvasCompareTester { "saveLayer ColorFilter and bounds", [=](SkCanvas* cv, SkPaint& p) { SkPaint save_p; - save_p.setColorFilter(filter.skia_object()); + save_p.setColorFilter(sk_alpha_rotate_filter); cv->saveLayer(kRenderBounds, &save_p); p.setStrokeWidth(5.0); }, [=](DlCanvas* cv, DlPaint& p) { DlPaint save_p; - save_p.setColorFilter(&filter); + save_p.setColorFilter(&dl_alpha_rotate_filter); cv->SaveLayer(&kRenderBounds, &save_p); p.setStrokeWidth(5.0); }) @@ -1124,21 +1140,23 @@ class CanvasCompareTester { 0, 0, 0, 1, 0, }; // clang-format on - DlMatrixColorFilter color_filter(color_matrix); - DlColorFilterImageFilter filter(color_filter); + DlMatrixColorFilter dl_color_filter(color_matrix); + DlColorFilterImageFilter dl_cf_image_filter(dl_color_filter); + auto sk_cf_image_filter = SkImageFilters::ColorFilter( + SkColorFilters::Matrix(color_matrix), nullptr); { RenderWith(testP, env, tolerance, CaseParameters( "saveLayer ImageFilter, no bounds", [=](SkCanvas* cv, SkPaint& p) { SkPaint save_p; - save_p.setImageFilter(filter.skia_object()); + save_p.setImageFilter(sk_cf_image_filter); cv->saveLayer(nullptr, &save_p); p.setStrokeWidth(5.0); }, [=](DlCanvas* cv, DlPaint& p) { DlPaint save_p; - save_p.setImageFilter(&filter); + save_p.setImageFilter(&dl_cf_image_filter); cv->SaveLayer(nullptr, &save_p); p.setStrokeWidth(5.0); }) @@ -1150,13 +1168,13 @@ class CanvasCompareTester { "saveLayer ImageFilter and bounds", [=](SkCanvas* cv, SkPaint& p) { SkPaint save_p; - save_p.setImageFilter(filter.skia_object()); + save_p.setImageFilter(sk_cf_image_filter); cv->saveLayer(kRenderBounds, &save_p); p.setStrokeWidth(5.0); }, [=](DlCanvas* cv, DlPaint& p) { DlPaint save_p; - save_p.setImageFilter(&filter); + save_p.setImageFilter(&dl_cf_image_filter); cv->SaveLayer(&kRenderBounds, &save_p); p.setStrokeWidth(5.0); }) @@ -1225,12 +1243,12 @@ class CanvasCompareTester { } else { DlColor dither_bg = DlColor::kBlack(); SkSetup sk_dither_setup = [=](SkCanvas*, SkPaint& p) { - p.setShader(kTestImageColorSource.skia_object()); + p.setShader(kTestSkImageColorSource); p.setAlpha(0xf0); p.setStrokeWidth(5.0); }; DlSetup dl_dither_setup = [=](DlCanvas*, DlPaint& p) { - p.setColorSource(&kTestImageColorSource); + p.setColorSource(&kTestDlImageColorSource); p.setAlpha(0xf0); p.setStrokeWidth(5.0); }; @@ -1316,17 +1334,19 @@ class CanvasCompareTester { // (for drawPaint) so we create a new environment for these tests. RenderEnvironment blur_env = RenderEnvironment::MakeN32(env.provider()); SkSetup sk_blur_setup = [=](SkCanvas*, SkPaint& p) { - p.setShader(kTestImageColorSource.skia_object()); + p.setShader(kTestSkImageColorSource); p.setStrokeWidth(5.0); }; DlSetup dl_blur_setup = [=](DlCanvas*, DlPaint& p) { - p.setColorSource(&kTestImageColorSource); + p.setColorSource(&kTestDlImageColorSource); p.setStrokeWidth(5.0); }; blur_env.init_ref(sk_blur_setup, testP.sk_renderer(), // dl_blur_setup, testP.dl_renderer()); quickCompareToReference(blur_env, "blur"); - DlBlurImageFilter filter_decal_5(5.0, 5.0, DlTileMode::kDecal); + DlBlurImageFilter dl_filter_decal_5(5.0, 5.0, DlTileMode::kDecal); + auto sk_filter_decal_5 = + SkImageFilters::Blur(5.0, 5.0, SkTileMode::kDecal, nullptr); BoundsTolerance blur_5_tolerance = tolerance.addBoundsPadding(4, 4); { RenderWith(testP, blur_env, blur_5_tolerance, @@ -1334,25 +1354,27 @@ class CanvasCompareTester { "ImageFilter == Decal Blur 5", [=](SkCanvas* cv, SkPaint& p) { sk_blur_setup(cv, p); - p.setImageFilter(filter_decal_5.skia_object()); + p.setImageFilter(sk_filter_decal_5); }, [=](DlCanvas* cv, DlPaint& p) { dl_blur_setup(cv, p); - p.setImageFilter(&filter_decal_5); + p.setImageFilter(&dl_filter_decal_5); })); } - DlBlurImageFilter filter_clamp_5(5.0, 5.0, DlTileMode::kClamp); + DlBlurImageFilter dl_filter_clamp_5(5.0, 5.0, DlTileMode::kClamp); + auto sk_filter_clamp_5 = + SkImageFilters::Blur(5.0, 5.0, SkTileMode::kClamp, nullptr); { RenderWith(testP, blur_env, blur_5_tolerance, CaseParameters( "ImageFilter == Clamp Blur 5", [=](SkCanvas* cv, SkPaint& p) { sk_blur_setup(cv, p); - p.setImageFilter(filter_clamp_5.skia_object()); + p.setImageFilter(sk_filter_clamp_5); }, [=](DlCanvas* cv, DlPaint& p) { dl_blur_setup(cv, p); - p.setImageFilter(&filter_clamp_5); + p.setImageFilter(&dl_filter_clamp_5); })); } } @@ -1363,27 +1385,28 @@ class CanvasCompareTester { // (for drawPaint) so we create a new environment for these tests. RenderEnvironment dilate_env = RenderEnvironment::MakeN32(env.provider()); SkSetup sk_dilate_setup = [=](SkCanvas*, SkPaint& p) { - p.setShader(kTestImageColorSource.skia_object()); + p.setShader(kTestSkImageColorSource); p.setStrokeWidth(5.0); }; DlSetup dl_dilate_setup = [=](DlCanvas*, DlPaint& p) { - p.setColorSource(&kTestImageColorSource); + p.setColorSource(&kTestDlImageColorSource); p.setStrokeWidth(5.0); }; dilate_env.init_ref(sk_dilate_setup, testP.sk_renderer(), // dl_dilate_setup, testP.dl_renderer()); quickCompareToReference(dilate_env, "dilate"); - DlDilateImageFilter filter_5(5.0, 5.0); + DlDilateImageFilter dl_dilate_filter_5(5.0, 5.0); + auto sk_dilate_filter_5 = SkImageFilters::Dilate(5.0, 5.0, nullptr); RenderWith(testP, dilate_env, tolerance, CaseParameters( "ImageFilter == Dilate 5", [=](SkCanvas* cv, SkPaint& p) { sk_dilate_setup(cv, p); - p.setImageFilter(filter_5.skia_object()); + p.setImageFilter(sk_dilate_filter_5); }, [=](DlCanvas* cv, DlPaint& p) { dl_dilate_setup(cv, p); - p.setImageFilter(&filter_5); + p.setImageFilter(&dl_dilate_filter_5); })); } @@ -1393,11 +1416,11 @@ class CanvasCompareTester { // (for drawPaint) so we create a new environment for these tests. RenderEnvironment erode_env = RenderEnvironment::MakeN32(env.provider()); SkSetup sk_erode_setup = [=](SkCanvas*, SkPaint& p) { - p.setShader(kTestImageColorSource.skia_object()); + p.setShader(kTestSkImageColorSource); p.setStrokeWidth(6.0); }; DlSetup dl_erode_setup = [=](DlCanvas*, DlPaint& p) { - p.setColorSource(&kTestImageColorSource); + p.setColorSource(&kTestDlImageColorSource); p.setStrokeWidth(6.0); }; erode_env.init_ref(sk_erode_setup, testP.sk_renderer(), // @@ -1405,17 +1428,18 @@ class CanvasCompareTester { quickCompareToReference(erode_env, "erode"); // do not erode too much, because some tests assert there are enough // pixels that are changed. - DlErodeImageFilter filter_1(1.0, 1.0); + DlErodeImageFilter dl_erode_filter_1(1.0, 1.0); + auto sk_erode_filter_1 = SkImageFilters::Erode(1.0, 1.0, nullptr); RenderWith(testP, erode_env, tolerance, CaseParameters( "ImageFilter == Erode 1", [=](SkCanvas* cv, SkPaint& p) { sk_erode_setup(cv, p); - p.setImageFilter(filter_1.skia_object()); + p.setImageFilter(sk_erode_filter_1); }, [=](DlCanvas* cv, DlPaint& p) { dl_erode_setup(cv, p); - p.setImageFilter(&filter_1); + p.setImageFilter(&dl_erode_filter_1); })); } @@ -1434,7 +1458,8 @@ class CanvasCompareTester { 1.0, 1.0, 1.0, 1.0, 0, }; // clang-format on - DlMatrixColorFilter filter(rotate_color_matrix); + DlMatrixColorFilter dl_color_filter(rotate_color_matrix); + auto sk_color_filter = SkColorFilters::Matrix(rotate_color_matrix); { DlColor bg = DlColor::kWhite(); RenderWith(testP, env, tolerance, @@ -1442,34 +1467,35 @@ class CanvasCompareTester { "ColorFilter == RotateRGB", [=](SkCanvas*, SkPaint& p) { p.setColor(DlColor::kYellow()); - p.setColorFilter(filter.skia_object()); + p.setColorFilter(sk_color_filter); }, [=](DlCanvas*, DlPaint& p) { p.setColor(DlColor::kYellow()); - p.setColorFilter(&filter); + p.setColorFilter(&dl_color_filter); }) .with_bg(bg)); } - filter = DlMatrixColorFilter(invert_color_matrix); { DlColor bg = DlColor::kWhite(); - RenderWith(testP, env, tolerance, - CaseParameters( - "ColorFilter == Invert", - [=](SkCanvas*, SkPaint& p) { - p.setColor(DlColor::kYellow()); - p.setColorFilter(filter.skia_object()); - }, - [=](DlCanvas*, DlPaint& p) { - p.setColor(DlColor::kYellow()); - p.setInvertColors(true); - }) - .with_bg(bg)); + RenderWith( + testP, env, tolerance, + CaseParameters( + "ColorFilter == Invert", + [=](SkCanvas*, SkPaint& p) { + p.setColor(DlColor::kYellow()); + p.setColorFilter(SkColorFilters::Matrix(invert_color_matrix)); + }, + [=](DlCanvas*, DlPaint& p) { + p.setColor(DlColor::kYellow()); + p.setInvertColors(true); + }) + .with_bg(bg)); } } { - const DlBlurMaskFilter filter(kNormal_SkBlurStyle, 5.0); + const DlBlurMaskFilter dl_mask_filter(kNormal_SkBlurStyle, 5.0); + auto sk_mask_filter = SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 5.0); BoundsTolerance blur_5_tolerance = tolerance.addBoundsPadding(4, 4); { // Stroked primitives need some non-trivial stroke size to be blurred @@ -1478,11 +1504,11 @@ class CanvasCompareTester { "MaskFilter == Blur 5", [=](SkCanvas*, SkPaint& p) { p.setStrokeWidth(5.0); - p.setMaskFilter(filter.skia_object()); + p.setMaskFilter(sk_mask_filter); }, [=](DlCanvas*, DlPaint& p) { p.setStrokeWidth(5.0); - p.setMaskFilter(&filter); + p.setMaskFilter(&dl_mask_filter); })); } } @@ -1492,27 +1518,33 @@ class CanvasCompareTester { SkPoint::Make(kRenderBounds.fLeft, kRenderBounds.fTop), SkPoint::Make(kRenderBounds.fRight, kRenderBounds.fBottom), }; - DlColor colors[] = { + DlColor dl_colors[] = { DlColor::kGreen(), DlColor::kYellow().withAlpha(0x7f), DlColor::kBlue(), }; + SkColor sk_colors[] = { + SK_ColorGREEN, + SkColorSetA(SK_ColorYELLOW, 0x7f), + SK_ColorBLUE, + }; float stops[] = { 0.0, 0.5, 1.0, }; - std::shared_ptr source = DlColorSource::MakeLinear( - end_points[0], end_points[1], 3, colors, stops, DlTileMode::kMirror); + auto dl_gradient = + DlColorSource::MakeLinear(end_points[0], end_points[1], 3, dl_colors, + stops, DlTileMode::kMirror); + auto sk_gradient = SkGradientShader::MakeLinear( + end_points, sk_colors, stops, 3, SkTileMode::kMirror, 0, nullptr); { RenderWith( testP, env, tolerance, CaseParameters( "LinearGradient GYB", - [=](SkCanvas*, SkPaint& p) { - p.setShader(source->skia_object()); - }, - [=](DlCanvas*, DlPaint& p) { p.setColorSource(source); })); + [=](SkCanvas*, SkPaint& p) { p.setShader(sk_gradient); }, + [=](DlCanvas*, DlPaint& p) { p.setColorSource(dl_gradient); })); } } } @@ -1697,7 +1729,8 @@ class CanvasCompareTester { { const SkScalar test_dashes_1[] = {29.0, 2.0}; const SkScalar test_dashes_2[] = {17.0, 1.5}; - auto effect = DlDashPathEffect::Make(test_dashes_1, 2, 0.0f); + auto dl_dash_effect = DlDashPathEffect::Make(test_dashes_1, 2, 0.0f); + auto sk_dash_effect = SkDashPathEffect::Make(test_dashes_1, 2, 0.0f); { RenderWith(testP, stroke_base_env, tolerance, CaseParameters( @@ -1705,12 +1738,12 @@ class CanvasCompareTester { [=](SkCanvas*, SkPaint& p) { // Provide some non-trivial stroke size to get dashed p.setStrokeWidth(5.0); - p.setPathEffect(effect->skia_object()); + p.setPathEffect(sk_dash_effect); }, [=](DlCanvas*, DlPaint& p) { // Provide some non-trivial stroke size to get dashed p.setStrokeWidth(5.0); - p.setPathEffect(effect); + p.setPathEffect(dl_dash_effect); })); } { @@ -1722,17 +1755,18 @@ class CanvasCompareTester { p.setStyle(SkPaint::kStroke_Style); // Provide some non-trivial stroke size to get dashed p.setStrokeWidth(5.0); - p.setPathEffect(effect->skia_object()); + p.setPathEffect(sk_dash_effect); }, [=](DlCanvas*, DlPaint& p) { // Need stroke style to see dashing properly p.setDrawStyle(DlDrawStyle::kStroke); // Provide some non-trivial stroke size to get dashed p.setStrokeWidth(5.0); - p.setPathEffect(effect); + p.setPathEffect(dl_dash_effect); })); } - effect = DlDashPathEffect::Make(test_dashes_2, 2, 0.0f); + dl_dash_effect = DlDashPathEffect::Make(test_dashes_2, 2, 0.0f); + sk_dash_effect = SkDashPathEffect::Make(test_dashes_2, 2, 0.0f); { RenderWith(testP, stroke_base_env, tolerance, CaseParameters( @@ -1742,14 +1776,14 @@ class CanvasCompareTester { p.setStyle(SkPaint::kStroke_Style); // Provide some non-trivial stroke size to get dashed p.setStrokeWidth(5.0); - p.setPathEffect(effect->skia_object()); + p.setPathEffect(sk_dash_effect); }, [=](DlCanvas*, DlPaint& p) { // Need stroke style to see dashing properly p.setDrawStyle(DlDrawStyle::kStroke); // Provide some non-trivial stroke size to get dashed p.setStrokeWidth(5.0); - p.setPathEffect(effect); + p.setPathEffect(dl_dash_effect); })); } } @@ -2178,6 +2212,23 @@ class CanvasCompareTester { ASSERT_GT(pixels_touched, 0) << info; } + static int countModifiedTransparentPixels(const RenderResult* ref_result, + const RenderResult* test_result) { + int count = 0; + for (int y = 0; y < kTestHeight; y++) { + const uint32_t* ref_row = ref_result->addr32(0, y); + const uint32_t* test_row = test_result->addr32(0, y); + for (int x = 0; x < kTestWidth; x++) { + if (ref_row[x] != test_row[x]) { + if (ref_row[x] == 0) { + count++; + } + } + } + } + return count; + } + static void quickCompareToReference(const RenderEnvironment& env, const std::string& info) { quickCompareToReference(env.ref_sk_result(), env.ref_dl_result(), true, @@ -2198,7 +2249,7 @@ class CanvasCompareTester { const uint32_t* test_row = test_result->addr32(0, y); for (int x = 0; x < w; x++) { if (ref_row[x] != test_row[x]) { - if (should_match) { + if (should_match && pixels_different < 5) { FML_LOG(ERROR) << std::hex << ref_row[x] << " != " << test_row[x]; } pixels_different++; @@ -2258,7 +2309,7 @@ class CanvasCompareTester { bool match = fuzzyCompares ? fuzzyCompare(test_row[x], ref_row[x], 1) : test_row[x] == ref_row[x]; if (!match) { - if (printMismatches) { + if (printMismatches && pixels_different < 5) { FML_LOG(ERROR) << "pix[" << x << ", " << y << "] mismatch: " << std::hex << test_row[x] << "(test) != (ref)" << ref_row[x] << std::dec; @@ -2347,7 +2398,8 @@ class CanvasCompareTester { return surface->makeImageSnapshot(); } - static const DlImageColorSource kTestImageColorSource; + static const DlImageColorSource kTestDlImageColorSource; + static const sk_sp kTestSkImageColorSource; static sk_sp MakeTextBlob(const std::string& string, SkScalar font_height) { @@ -2365,11 +2417,15 @@ BoundsTolerance CanvasCompareTester::DefaultTolerance = BoundsTolerance().addAbsolutePadding(1, 1); const sk_sp CanvasCompareTester::kTestImage = makeTestImage(); -const DlImageColorSource CanvasCompareTester::kTestImageColorSource( +const DlImageColorSource CanvasCompareTester::kTestDlImageColorSource( DlImage::Make(kTestImage), DlTileMode::kRepeat, DlTileMode::kRepeat, DlImageSampling::kLinear); +const sk_sp CanvasCompareTester::kTestSkImageColorSource = + kTestImage->makeShader(SkTileMode::kRepeat, + SkTileMode::kRepeat, + SkImageSampling::kLinear); // Eventually this bare bones testing::Test fixture will subsume the // CanvasCompareTester and the TestParameters could then become just @@ -2870,21 +2926,27 @@ TEST_F(DisplayListCanvas, DrawVerticesWithColors) { SkPoint::Make(kRenderLeft, kRenderCenterY), SkPoint::Make(kRenderRight, kRenderBottom), }; - const DlColor colors[6] = { + const DlColor dl_colors[6] = { + DlColor::kRed(), DlColor::kBlue(), DlColor::kGreen(), + DlColor::kCyan(), DlColor::kYellow(), DlColor::kMagenta(), + }; + const SkColor sk_colors[6] = { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN, SK_ColorCYAN, SK_ColorYELLOW, SK_ColorMAGENTA, }; - const std::shared_ptr vertices = - DlVertices::Make(DlVertexMode::kTriangles, 6, pts, nullptr, colors); + const std::shared_ptr dl_vertices = + DlVertices::Make(DlVertexMode::kTriangles, 6, pts, nullptr, dl_colors); + const auto sk_vertices = + SkVertices::MakeCopy(SkVertices::VertexMode::kTriangles_VertexMode, 6, + pts, nullptr, sk_colors); CanvasCompareTester::RenderAll( // TestParameters( [=](SkCanvas* canvas, const SkPaint& paint) { // - canvas->drawVertices(vertices->skia_object(), SkBlendMode::kSrcOver, - paint); + canvas->drawVertices(sk_vertices, SkBlendMode::kSrcOver, paint); }, [=](DlCanvas* canvas, const DlPaint& paint) { // - canvas->DrawVertices(vertices, DlBlendMode::kSrcOver, paint); + canvas->DrawVertices(dl_vertices, DlBlendMode::kSrcOver, paint); }, kDrawVerticesFlags)); } @@ -2917,27 +2979,27 @@ TEST_F(DisplayListCanvas, DrawVerticesWithImage) { SkPoint::Make(0, 0), SkPoint::Make(kRenderWidth, 0), }; - const std::shared_ptr vertices = + const std::shared_ptr dl_vertices = DlVertices::Make(DlVertexMode::kTriangles, 6, pts, tex, nullptr); + const auto sk_vertices = SkVertices::MakeCopy( + SkVertices::VertexMode::kTriangles_VertexMode, 6, pts, tex, nullptr); CanvasCompareTester::RenderAll( // TestParameters( [=](SkCanvas* canvas, const SkPaint& paint) { // SkPaint v_paint = paint; if (v_paint.getShader() == nullptr) { - v_paint.setShader( - CanvasCompareTester::kTestImageColorSource.skia_object()); + v_paint.setShader(CanvasCompareTester::kTestSkImageColorSource); } - canvas->drawVertices(vertices->skia_object(), SkBlendMode::kSrcOver, - v_paint); + canvas->drawVertices(sk_vertices, SkBlendMode::kSrcOver, v_paint); }, [=](DlCanvas* canvas, const DlPaint& paint) { // DlPaint v_paint = paint; if (v_paint.getColorSource() == nullptr) { v_paint.setColorSource( - &CanvasCompareTester::kTestImageColorSource); + &CanvasCompareTester::kTestDlImageColorSource); } - canvas->DrawVertices(vertices, DlBlendMode::kSrcOver, v_paint); + canvas->DrawVertices(dl_vertices, DlBlendMode::kSrcOver, v_paint); }, kDrawVerticesFlags)); } @@ -2948,7 +3010,7 @@ TEST_F(DisplayListCanvas, DrawImageNearest) { [=](SkCanvas* canvas, const SkPaint& paint) { // canvas->drawImage(CanvasCompareTester::kTestImage, // kRenderLeft, kRenderTop, - ToSk(DlImageSampling::kNearestNeighbor), &paint); + SkImageSampling::kNearestNeighbor, &paint); }, [=](DlCanvas* canvas, const DlPaint& paint) { canvas->DrawImage(DlImage::Make(CanvasCompareTester::kTestImage), @@ -2964,7 +3026,7 @@ TEST_F(DisplayListCanvas, DrawImageNearestNoPaint) { [=](SkCanvas* canvas, const SkPaint& paint) { // canvas->drawImage(CanvasCompareTester::kTestImage, // kRenderLeft, kRenderTop, - ToSk(DlImageSampling::kNearestNeighbor), nullptr); + SkImageSampling::kNearestNeighbor, nullptr); }, [=](DlCanvas* canvas, const DlPaint& paint) { canvas->DrawImage(DlImage::Make(CanvasCompareTester::kTestImage), @@ -2979,8 +3041,8 @@ TEST_F(DisplayListCanvas, DrawImageLinear) { TestParameters( [=](SkCanvas* canvas, const SkPaint& paint) { // canvas->drawImage(CanvasCompareTester::kTestImage, // - kRenderLeft, kRenderTop, - ToSk(DlImageSampling::kLinear), &paint); + kRenderLeft, kRenderTop, SkImageSampling::kLinear, + &paint); }, [=](DlCanvas* canvas, const DlPaint& paint) { canvas->DrawImage(DlImage::Make(CanvasCompareTester::kTestImage), @@ -2997,8 +3059,8 @@ TEST_F(DisplayListCanvas, DrawImageRectNearest) { TestParameters( [=](SkCanvas* canvas, const SkPaint& paint) { // canvas->drawImageRect(CanvasCompareTester::kTestImage, src, dst, - ToSk(DlImageSampling::kNearestNeighbor), - &paint, SkCanvas::kFast_SrcRectConstraint); + SkImageSampling::kNearestNeighbor, &paint, + SkCanvas::kFast_SrcRectConstraint); }, [=](DlCanvas* canvas, const DlPaint& paint) { // canvas->DrawImageRect( @@ -3015,8 +3077,8 @@ TEST_F(DisplayListCanvas, DrawImageRectNearestNoPaint) { TestParameters( [=](SkCanvas* canvas, const SkPaint& paint) { // canvas->drawImageRect(CanvasCompareTester::kTestImage, src, dst, - ToSk(DlImageSampling::kNearestNeighbor), - nullptr, SkCanvas::kFast_SrcRectConstraint); + SkImageSampling::kNearestNeighbor, nullptr, + SkCanvas::kFast_SrcRectConstraint); }, [=](DlCanvas* canvas, const DlPaint& paint) { // canvas->DrawImageRect( @@ -3033,7 +3095,7 @@ TEST_F(DisplayListCanvas, DrawImageRectLinear) { TestParameters( [=](SkCanvas* canvas, const SkPaint& paint) { // canvas->drawImageRect(CanvasCompareTester::kTestImage, src, dst, - ToSk(DlImageSampling::kLinear), &paint, + SkImageSampling::kLinear, &paint, SkCanvas::kFast_SrcRectConstraint); }, [=](DlCanvas* canvas, const DlPaint& paint) { // @@ -3125,17 +3187,19 @@ TEST_F(DisplayListCanvas, DrawAtlasNearest) { DlColor::kMagenta(), }; const sk_sp image = CanvasCompareTester::kTestImage; - const DlImageSampling sampling = DlImageSampling::kNearestNeighbor; + const DlImageSampling dl_sampling = DlImageSampling::kNearestNeighbor; + const SkSamplingOptions sk_sampling = SkImageSampling::kNearestNeighbor; CanvasCompareTester::RenderAll( // TestParameters( [=](SkCanvas* canvas, const SkPaint& paint) { canvas->drawAtlas(image.get(), xform, tex, sk_colors, 4, - SkBlendMode::kSrcOver, ToSk(sampling), nullptr, + SkBlendMode::kSrcOver, sk_sampling, nullptr, &paint); }, [=](DlCanvas* canvas, const DlPaint& paint) { canvas->DrawAtlas(DlImage::Make(image), xform, tex, dl_colors, 4, - DlBlendMode::kSrcOver, sampling, nullptr, &paint); + DlBlendMode::kSrcOver, dl_sampling, nullptr, + &paint); }, kDrawAtlasWithPaintFlags)); } @@ -3170,17 +3234,18 @@ TEST_F(DisplayListCanvas, DrawAtlasNearestNoPaint) { DlColor::kMagenta(), }; const sk_sp image = CanvasCompareTester::kTestImage; - const DlImageSampling sampling = DlImageSampling::kNearestNeighbor; + const DlImageSampling dl_sampling = DlImageSampling::kNearestNeighbor; + const SkSamplingOptions sk_sampling = SkImageSampling::kNearestNeighbor; CanvasCompareTester::RenderAll( // TestParameters( [=](SkCanvas* canvas, const SkPaint& paint) { canvas->drawAtlas(image.get(), xform, tex, sk_colors, 4, - SkBlendMode::kSrcOver, ToSk(sampling), // + SkBlendMode::kSrcOver, sk_sampling, // nullptr, nullptr); }, [=](DlCanvas* canvas, const DlPaint& paint) { canvas->DrawAtlas(DlImage::Make(image), xform, tex, dl_colors, 4, - DlBlendMode::kSrcOver, sampling, nullptr, + DlBlendMode::kSrcOver, dl_sampling, nullptr, nullptr); }, kDrawAtlasFlags)); @@ -3216,34 +3281,39 @@ TEST_F(DisplayListCanvas, DrawAtlasLinear) { DlColor::kMagenta(), }; const sk_sp image = CanvasCompareTester::kTestImage; - const DlImageSampling sampling = DlImageSampling::kLinear; + const DlImageSampling dl_sampling = DlImageSampling::kLinear; + const SkSamplingOptions sk_sampling = SkImageSampling::kLinear; CanvasCompareTester::RenderAll( // TestParameters( [=](SkCanvas* canvas, const SkPaint& paint) { canvas->drawAtlas(image.get(), xform, tex, sk_colors, 2, // - SkBlendMode::kSrcOver, ToSk(sampling), nullptr, + SkBlendMode::kSrcOver, sk_sampling, nullptr, &paint); }, [=](DlCanvas* canvas, const DlPaint& paint) { canvas->DrawAtlas(DlImage::Make(image), xform, tex, dl_colors, 2, - DlBlendMode::kSrcOver, sampling, nullptr, &paint); + DlBlendMode::kSrcOver, dl_sampling, nullptr, + &paint); }, kDrawAtlasWithPaintFlags)); } sk_sp makeTestDisplayList() { DisplayListBuilder builder; - builder.setStyle(DlDrawStyle::kFill); - builder.setColor(SK_ColorRED); - builder.drawRect({kRenderLeft, kRenderTop, kRenderCenterX, kRenderCenterY}); - builder.setColor(SK_ColorBLUE); - builder.drawRect({kRenderCenterX, kRenderTop, kRenderRight, kRenderCenterY}); - builder.setColor(SK_ColorGREEN); - builder.drawRect( - {kRenderLeft, kRenderCenterY, kRenderCenterX, kRenderBottom}); - builder.setColor(SK_ColorYELLOW); - builder.drawRect( - {kRenderCenterX, kRenderCenterY, kRenderRight, kRenderBottom}); + DlPaint paint; + paint.setDrawStyle(DlDrawStyle::kFill); + paint.setColor(SK_ColorRED); + builder.DrawRect({kRenderLeft, kRenderTop, kRenderCenterX, kRenderCenterY}, + paint); + paint.setColor(SK_ColorBLUE); + builder.DrawRect({kRenderCenterX, kRenderTop, kRenderRight, kRenderCenterY}, + paint); + paint.setColor(SK_ColorGREEN); + builder.DrawRect({kRenderLeft, kRenderCenterY, kRenderCenterX, kRenderBottom}, + paint); + paint.setColor(SK_ColorYELLOW); + builder.DrawRect( + {kRenderCenterX, kRenderCenterY, kRenderRight, kRenderBottom}, paint); return builder.Build(); } @@ -3252,7 +3322,7 @@ TEST_F(DisplayListCanvas, DrawDisplayList) { CanvasCompareTester::RenderAll( // TestParameters( [=](SkCanvas* canvas, const SkPaint& paint) { // - display_list->RenderTo(canvas); + DlSkCanvasAdapter(canvas).DrawDisplayList(display_list); }, [=](DlCanvas* canvas, const DlPaint& paint) { // canvas->DrawDisplayList(display_list); @@ -3310,8 +3380,8 @@ TEST_F(DisplayListCanvas, DrawShadow) { CanvasCompareTester::RenderAll( // TestParameters( [=](SkCanvas* canvas, const SkPaint& paint) { // - DisplayListCanvasDispatcher::DrawShadow(canvas, path, color, - elevation, false, 1.0); + DlSkCanvasDispatcher::DrawShadow(canvas, path, color, elevation, + false, 1.0); }, [=](DlCanvas* canvas, const DlPaint& paint) { // canvas->DrawShadow(path, color, elevation, false, 1.0); @@ -3336,8 +3406,8 @@ TEST_F(DisplayListCanvas, DrawShadowTransparentOccluder) { CanvasCompareTester::RenderAll( // TestParameters( [=](SkCanvas* canvas, const SkPaint& paint) { // - DisplayListCanvasDispatcher::DrawShadow(canvas, path, color, - elevation, true, 1.0); + DlSkCanvasDispatcher::DrawShadow(canvas, path, color, elevation, + true, 1.0); }, [=](DlCanvas* canvas, const DlPaint& paint) { // canvas->DrawShadow(path, color, elevation, true, 1.0); @@ -3362,8 +3432,8 @@ TEST_F(DisplayListCanvas, DrawShadowDpr) { CanvasCompareTester::RenderAll( // TestParameters( [=](SkCanvas* canvas, const SkPaint& paint) { // - DisplayListCanvasDispatcher::DrawShadow(canvas, path, color, - elevation, false, 1.5); + DlSkCanvasDispatcher::DrawShadow(canvas, path, color, elevation, + false, 1.5); }, [=](DlCanvas* canvas, const DlPaint& paint) { // canvas->DrawShadow(path, color, elevation, false, 1.5); @@ -3555,5 +3625,317 @@ TEST_F(DisplayListCanvas, SaveLayerConsolidation) { } } +TEST_F(DisplayListCanvas, MatrixColorFilterModifyTransparencyCheck) { + std::vector> environments; + for (auto& provider : CanvasCompareTester::kTestProviders) { + auto env = std::make_unique( + provider.get(), PixelFormat::kN32Premul_PixelFormat); + environments.push_back(std::move(env)); + } + + auto test_matrix = [&environments](int element, SkScalar value) { + // clang-format off + float matrix[] = { + 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, + }; + // clang-format on + std::string desc = + "matrix[" + std::to_string(element) + "] = " + std::to_string(value); + float original_value = matrix[element]; + matrix[element] = value; + DlMatrixColorFilter filter(matrix); + auto dl_filter = DlMatrixColorFilter::Make(matrix); + bool is_identity = (dl_filter == nullptr || original_value == value); + + DlPaint paint(0x7f7f7f7f); + DlPaint filter_save_paint = DlPaint().setColorFilter(&filter); + + DisplayListBuilder builder1; + builder1.Translate(kTestCenter.fX, kTestCenter.fY); + builder1.Rotate(45); + builder1.Translate(-kTestCenter.fX, -kTestCenter.fY); + builder1.DrawRect(kRenderBounds, paint); + auto display_list1 = builder1.Build(); + + DisplayListBuilder builder2; + builder2.Translate(kTestCenter.fX, kTestCenter.fY); + builder2.Rotate(45); + builder2.Translate(-kTestCenter.fX, -kTestCenter.fY); + builder2.SaveLayer(&kTestBounds, &filter_save_paint); + builder2.DrawRect(kRenderBounds, paint); + builder2.Restore(); + auto display_list2 = builder2.Build(); + + for (auto& env : environments) { + auto results1 = env->getResult(display_list1); + auto results2 = env->getResult(display_list2); + CanvasCompareTester::quickCompareToReference( + results1.get(), results2.get(), is_identity, + desc + " filter affects rendering"); + int modified_transparent_pixels = + CanvasCompareTester::countModifiedTransparentPixels(results1.get(), + results2.get()); + EXPECT_EQ(filter.modifies_transparent_black(), + modified_transparent_pixels != 0) + << desc; + } + }; + + // Tests identity (matrix[0] already == 1 in an identity filter) + test_matrix(0, 1); + // test_matrix(19, 1); + for (int i = 0; i < 20; i++) { + test_matrix(i, -0.25); + test_matrix(i, 0); + test_matrix(i, 0.25); + test_matrix(i, 1); + test_matrix(i, 1.25); + test_matrix(i, SK_ScalarNaN); + test_matrix(i, SK_ScalarInfinity); + test_matrix(i, -SK_ScalarInfinity); + } +} + +TEST_F(DisplayListCanvas, MatrixColorFilterOpacityCommuteCheck) { + std::vector> environments; + for (auto& provider : CanvasCompareTester::kTestProviders) { + auto env = std::make_unique( + provider.get(), PixelFormat::kN32Premul_PixelFormat); + environments.push_back(std::move(env)); + } + + auto test_matrix = [&environments](int element, SkScalar value) { + // clang-format off + float matrix[] = { + 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, + }; + // clang-format on + std::string desc = + "matrix[" + std::to_string(element) + "] = " + std::to_string(value); + matrix[element] = value; + auto filter = DlMatrixColorFilter::Make(matrix); + EXPECT_EQ(SkScalarIsFinite(value), filter != nullptr); + + DlPaint paint(0x80808080); + DlPaint opacity_save_paint = DlPaint().setOpacity(0.5); + DlPaint filter_save_paint = DlPaint().setColorFilter(filter); + + DisplayListBuilder builder1; + builder1.SaveLayer(&kTestBounds, &opacity_save_paint); + builder1.SaveLayer(&kTestBounds, &filter_save_paint); + // builder1.DrawRect(kRenderBounds.makeOffset(20, 20), DlPaint()); + builder1.DrawRect(kRenderBounds, paint); + builder1.Restore(); + builder1.Restore(); + auto display_list1 = builder1.Build(); + + DisplayListBuilder builder2; + builder2.SaveLayer(&kTestBounds, &filter_save_paint); + builder2.SaveLayer(&kTestBounds, &opacity_save_paint); + // builder1.DrawRect(kRenderBounds.makeOffset(20, 20), DlPaint()); + builder2.DrawRect(kRenderBounds, paint); + builder2.Restore(); + builder2.Restore(); + auto display_list2 = builder2.Build(); + + for (auto& env : environments) { + auto results1 = env->getResult(display_list1); + auto results2 = env->getResult(display_list2); + if (!filter || filter->can_commute_with_opacity()) { + CanvasCompareTester::compareToReference( + results2.get(), results1.get(), desc, nullptr, nullptr, + DlColor::kTransparent(), true, kTestWidth, kTestHeight, true); + } else { + CanvasCompareTester::quickCompareToReference( + results1.get(), results2.get(), false, desc); + } + } + }; + + // Tests identity (matrix[0] already == 1 in an identity filter) + test_matrix(0, 1); + // test_matrix(19, 1); + for (int i = 0; i < 20; i++) { + test_matrix(i, -0.25); + test_matrix(i, 0); + test_matrix(i, 0.25); + test_matrix(i, 1); + test_matrix(i, 1.1); + test_matrix(i, SK_ScalarNaN); + test_matrix(i, SK_ScalarInfinity); + test_matrix(i, -SK_ScalarInfinity); + } +} + +#define FOR_EACH_BLEND_MODE_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) + +TEST_F(DisplayListCanvas, BlendColorFilterModifyTransparencyCheck) { + std::vector> environments; + for (auto& provider : CanvasCompareTester::kTestProviders) { + auto env = std::make_unique( + provider.get(), PixelFormat::kN32Premul_PixelFormat); + environments.push_back(std::move(env)); + } + + auto test_mode_color = [&environments](DlBlendMode mode, DlColor color) { + std::stringstream desc_str; + desc_str << "blend[" << mode << ", " << color << "]"; + std::string desc = desc_str.str(); + DlBlendColorFilter filter(color, mode); + if (filter.modifies_transparent_black()) { + ASSERT_NE(DlBlendColorFilter::Make(color, mode), nullptr) << desc; + } + + DlPaint paint(0x7f7f7f7f); + DlPaint filter_save_paint = DlPaint().setColorFilter(&filter); + + DisplayListBuilder builder1; + builder1.Translate(kTestCenter.fX, kTestCenter.fY); + builder1.Rotate(45); + builder1.Translate(-kTestCenter.fX, -kTestCenter.fY); + builder1.DrawRect(kRenderBounds, paint); + auto display_list1 = builder1.Build(); + + DisplayListBuilder builder2; + builder2.Translate(kTestCenter.fX, kTestCenter.fY); + builder2.Rotate(45); + builder2.Translate(-kTestCenter.fX, -kTestCenter.fY); + builder2.SaveLayer(&kTestBounds, &filter_save_paint); + builder2.DrawRect(kRenderBounds, paint); + builder2.Restore(); + auto display_list2 = builder2.Build(); + + for (auto& env : environments) { + auto results1 = env->getResult(display_list1); + auto results2 = env->getResult(display_list2); + int modified_transparent_pixels = + CanvasCompareTester::countModifiedTransparentPixels(results1.get(), + results2.get()); + EXPECT_EQ(filter.modifies_transparent_black(), + modified_transparent_pixels != 0) + << desc; + } + }; + + auto test_mode = [&test_mode_color](DlBlendMode mode) { + test_mode_color(mode, DlColor::kTransparent()); + test_mode_color(mode, DlColor::kWhite()); + test_mode_color(mode, DlColor::kWhite().modulateOpacity(0.5)); + test_mode_color(mode, DlColor::kBlack()); + test_mode_color(mode, DlColor::kBlack().modulateOpacity(0.5)); + }; + +#define TEST_MODE(V) test_mode(DlBlendMode::V); + FOR_EACH_BLEND_MODE_ENUM(TEST_MODE) +#undef TEST_MODE +} + +TEST_F(DisplayListCanvas, BlendColorFilterOpacityCommuteCheck) { + std::vector> environments; + for (auto& provider : CanvasCompareTester::kTestProviders) { + auto env = std::make_unique( + provider.get(), PixelFormat::kN32Premul_PixelFormat); + environments.push_back(std::move(env)); + } + + auto test_mode_color = [&environments](DlBlendMode mode, DlColor color) { + std::stringstream desc_str; + desc_str << "blend[" << mode << ", " << color << "]"; + std::string desc = desc_str.str(); + DlBlendColorFilter filter(color, mode); + if (filter.can_commute_with_opacity()) { + // If it can commute with opacity, then it might also be a NOP, + // so we won't necessarily get a non-null return from |::Make()| + } else { + ASSERT_NE(DlBlendColorFilter::Make(color, mode), nullptr) << desc; + } + + DlPaint paint(0x80808080); + DlPaint opacity_save_paint = DlPaint().setOpacity(0.5); + DlPaint filter_save_paint = DlPaint().setColorFilter(&filter); + + DisplayListBuilder builder1; + builder1.SaveLayer(&kTestBounds, &opacity_save_paint); + builder1.SaveLayer(&kTestBounds, &filter_save_paint); + // builder1.DrawRect(kRenderBounds.makeOffset(20, 20), DlPaint()); + builder1.DrawRect(kRenderBounds, paint); + builder1.Restore(); + builder1.Restore(); + auto display_list1 = builder1.Build(); + + DisplayListBuilder builder2; + builder2.SaveLayer(&kTestBounds, &filter_save_paint); + builder2.SaveLayer(&kTestBounds, &opacity_save_paint); + // builder1.DrawRect(kRenderBounds.makeOffset(20, 20), DlPaint()); + builder2.DrawRect(kRenderBounds, paint); + builder2.Restore(); + builder2.Restore(); + auto display_list2 = builder2.Build(); + + for (auto& env : environments) { + auto results1 = env->getResult(display_list1); + auto results2 = env->getResult(display_list2); + if (filter.can_commute_with_opacity()) { + CanvasCompareTester::compareToReference( + results2.get(), results1.get(), desc, nullptr, nullptr, + DlColor::kTransparent(), true, kTestWidth, kTestHeight, true); + } else { + CanvasCompareTester::quickCompareToReference( + results1.get(), results2.get(), false, desc); + } + } + }; + + auto test_mode = [&test_mode_color](DlBlendMode mode) { + test_mode_color(mode, DlColor::kTransparent()); + test_mode_color(mode, DlColor::kWhite()); + test_mode_color(mode, DlColor::kWhite().modulateOpacity(0.5)); + test_mode_color(mode, DlColor::kBlack()); + test_mode_color(mode, DlColor::kBlack().modulateOpacity(0.5)); + }; + +#define TEST_MODE(V) test_mode(DlBlendMode::V); + FOR_EACH_BLEND_MODE_ENUM(TEST_MODE) +#undef TEST_MODE +} + +#undef FOR_EACH_ENUM + } // namespace testing } // namespace flutter diff --git a/display_list/skia/dl_sk_canvas.cc b/display_list/skia/dl_sk_canvas.cc index f7a0de8f2a5c1..6e1841c0fe408 100644 --- a/display_list/skia/dl_sk_canvas.cc +++ b/display_list/skia/dl_sk_canvas.cc @@ -4,43 +4,11 @@ #include "flutter/display_list/skia/dl_sk_canvas.h" -#include "flutter/display_list/display_list_canvas_dispatcher.h" +#include "flutter/display_list/skia/dl_sk_conversions.h" +#include "flutter/display_list/skia/dl_sk_dispatcher.h" namespace flutter { -static sk_sp ToSk(const DlColorSource* source) { - return source ? source->skia_object() : nullptr; -} - -static sk_sp ToSk(const DlImageFilter* filter) { - return filter ? filter->skia_object() : nullptr; -} - -static sk_sp ToSk(const DlColorFilter* filter) { - return filter ? filter->skia_object() : nullptr; -} - -static sk_sp ToSk(const DlMaskFilter* filter) { - return filter ? filter->skia_object() : nullptr; -} - -static sk_sp ToSk(const DlPathEffect* effect) { - return effect ? effect->skia_object() : nullptr; -} - -static SkCanvas::SrcRectConstraint ToSkConstraint(bool enforce_edges) { - return enforce_edges ? SkCanvas::kStrict_SrcRectConstraint - : SkCanvas::kFast_SrcRectConstraint; -} - -static SkClipOp ToSk(DlCanvas::ClipOp op) { - return static_cast(op); -} - -static SkCanvas::PointMode ToSk(DlCanvas::PointMode mode) { - return static_cast(mode); -} - // clang-format off constexpr float kInvertColorMatrix[20] = { -1.0, 0, 0, 1.0, 0, @@ -119,10 +87,10 @@ void DlSkCanvasAdapter::Save() { void DlSkCanvasAdapter::SaveLayer(const SkRect* bounds, const DlPaint* paint, const DlImageFilter* backdrop) { - sk_sp sk_filter = backdrop ? backdrop->skia_object() : nullptr; + sk_sp sk_backdrop = ToSk(backdrop); SkOptionalPaint sk_paint(paint); delegate_->saveLayer( - SkCanvas::SaveLayerRec{bounds, sk_paint(), sk_filter.get(), 0}); + SkCanvas::SaveLayerRec{bounds, sk_paint(), sk_backdrop.get(), 0}); } void DlSkCanvasAdapter::Restore() { @@ -309,7 +277,7 @@ void DlSkCanvasAdapter::DrawPoints(PointMode mode, void DlSkCanvasAdapter::DrawVertices(const DlVertices* vertices, DlBlendMode mode, const DlPaint& paint) { - delegate_->drawVertices(vertices->skia_object(), ToSk(mode), ToSk(paint)); + delegate_->drawVertices(ToSk(vertices), ToSk(mode), ToSk(paint)); } void DlSkCanvasAdapter::DrawImage(const sk_sp& image, @@ -363,7 +331,26 @@ void DlSkCanvasAdapter::DrawAtlas(const sk_sp& atlas, void DlSkCanvasAdapter::DrawDisplayList(const sk_sp display_list, SkScalar opacity) { - display_list->RenderTo(delegate_, opacity); + int restore_count = delegate_->getSaveCount(); + + // Figure out whether we can apply the opacity during dispatch or + // if we need a saveLayer. + if (opacity < SK_Scalar1 && !display_list->can_apply_group_opacity()) { + DlPaint save_paint = DlPaint().setOpacity(opacity); + SaveLayer(&display_list->bounds(), &save_paint); + opacity = SK_Scalar1; + } else { + Save(); + } + + DlSkCanvasDispatcher dispatcher(delegate_, opacity); + if (display_list->has_rtree()) { + display_list->Dispatch(dispatcher, delegate_->getLocalClipBounds()); + } else { + display_list->Dispatch(dispatcher); + } + + delegate_->restoreToCount(restore_count); } void DlSkCanvasAdapter::DrawTextBlob(const sk_sp& blob, @@ -378,8 +365,8 @@ void DlSkCanvasAdapter::DrawShadow(const SkPath& path, const SkScalar elevation, bool transparent_occluder, SkScalar dpr) { - DisplayListCanvasDispatcher::DrawShadow(delegate_, path, color, elevation, - transparent_occluder, dpr); + DlSkCanvasDispatcher::DrawShadow(delegate_, path, color, elevation, + transparent_occluder, dpr); } void DlSkCanvasAdapter::Flush() { diff --git a/display_list/skia/dl_sk_canvas.h b/display_list/skia/dl_sk_canvas.h index 249e5189f2276..038850de17e88 100644 --- a/display_list/skia/dl_sk_canvas.h +++ b/display_list/skia/dl_sk_canvas.h @@ -135,7 +135,7 @@ class DlSkCanvasAdapter final : public virtual DlCanvas { const SkRect* cullRect, const DlPaint* paint = nullptr) override; void DrawDisplayList(const sk_sp display_list, - SkScalar opacity) override; + SkScalar opacity = SK_Scalar1) override; void DrawTextBlob(const sk_sp& blob, SkScalar x, SkScalar y, diff --git a/display_list/skia/dl_sk_conversions.cc b/display_list/skia/dl_sk_conversions.cc new file mode 100644 index 0000000000000..7ec52f9e19f76 --- /dev/null +++ b/display_list/skia/dl_sk_conversions.cc @@ -0,0 +1,235 @@ +// 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/skia/dl_sk_conversions.h" + +namespace flutter { + +sk_sp ToSk(const DlColorSource* source) { + if (!source) { + return nullptr; + } + static auto ToSkColors = [](const DlGradientColorSourceBase* gradient) { + return reinterpret_cast(gradient->colors()); + }; + switch (source->type()) { + case DlColorSourceType::kColor: { + const DlColorColorSource* color_source = source->asColor(); + FML_DCHECK(color_source != nullptr); + return SkShaders::Color(color_source->color()); + } + case DlColorSourceType::kImage: { + const DlImageColorSource* image_source = source->asImage(); + FML_DCHECK(image_source != nullptr); + auto image = image_source->image(); + if (!image || !image->skia_image()) { + return nullptr; + } + return image->skia_image()->makeShader( + ToSk(image_source->horizontal_tile_mode()), + ToSk(image_source->vertical_tile_mode()), + ToSk(image_source->sampling()), image_source->matrix_ptr()); + } + case DlColorSourceType::kLinearGradient: { + const DlLinearGradientColorSource* linear_source = + source->asLinearGradient(); + FML_DCHECK(linear_source != nullptr); + SkPoint pts[] = {linear_source->start_point(), + linear_source->end_point()}; + return SkGradientShader::MakeLinear( + pts, ToSkColors(linear_source), linear_source->stops(), + linear_source->stop_count(), ToSk(linear_source->tile_mode()), 0, + linear_source->matrix_ptr()); + } + case DlColorSourceType::kRadialGradient: { + const DlRadialGradientColorSource* radial_source = + source->asRadialGradient(); + FML_DCHECK(radial_source != nullptr); + return SkGradientShader::MakeRadial( + radial_source->center(), radial_source->radius(), + ToSkColors(radial_source), radial_source->stops(), + radial_source->stop_count(), ToSk(radial_source->tile_mode()), 0, + radial_source->matrix_ptr()); + } + case DlColorSourceType::kConicalGradient: { + const DlConicalGradientColorSource* conical_source = + source->asConicalGradient(); + FML_DCHECK(conical_source != nullptr); + return SkGradientShader::MakeTwoPointConical( + conical_source->start_center(), conical_source->start_radius(), + conical_source->end_center(), conical_source->end_radius(), + ToSkColors(conical_source), conical_source->stops(), + conical_source->stop_count(), ToSk(conical_source->tile_mode()), 0, + conical_source->matrix_ptr()); + } + case DlColorSourceType::kSweepGradient: { + const DlSweepGradientColorSource* sweep_source = + source->asSweepGradient(); + FML_DCHECK(sweep_source != nullptr); + return SkGradientShader::MakeSweep( + sweep_source->center().x(), sweep_source->center().y(), + ToSkColors(sweep_source), sweep_source->stops(), + sweep_source->stop_count(), ToSk(sweep_source->tile_mode()), + sweep_source->start(), sweep_source->end(), 0, + sweep_source->matrix_ptr()); + } + case DlColorSourceType::kRuntimeEffect: { + const DlRuntimeEffectColorSource* runtime_source = + source->asRuntimeEffect(); + FML_DCHECK(runtime_source != nullptr); + auto runtime_effect = runtime_source->runtime_effect(); + if (!runtime_effect || !runtime_effect->skia_runtime_effect()) { + return nullptr; + } + + auto samplers = runtime_source->samplers(); + std::vector> sk_samplers(samplers.size()); + for (size_t i = 0; i < samplers.size(); i++) { + auto sampler = samplers[i]; + if (sampler == nullptr) { + return nullptr; + } + sk_samplers[i] = ToSk(sampler); + } + + auto uniform_data = runtime_source->uniform_data(); + auto ref = new std::shared_ptr>(uniform_data); + auto sk_uniform_data = SkData::MakeWithProc( + uniform_data->data(), uniform_data->size(), + [](const void* ptr, void* context) { + delete reinterpret_cast>*>( + context); + }, + ref); + + return runtime_effect->skia_runtime_effect()->makeShader( + sk_uniform_data, sk_samplers.data(), sk_samplers.size()); + } + } +} + +sk_sp ToSk(const DlImageFilter* filter) { + if (!filter) { + return nullptr; + } + switch (filter->type()) { + case DlImageFilterType::kBlur: { + const DlBlurImageFilter* blur_filter = filter->asBlur(); + FML_DCHECK(blur_filter != nullptr); + return SkImageFilters::Blur(blur_filter->sigma_x(), + blur_filter->sigma_y(), + ToSk(blur_filter->tile_mode()), nullptr); + } + case DlImageFilterType::kDilate: { + const DlDilateImageFilter* dilate_filter = filter->asDilate(); + FML_DCHECK(dilate_filter != nullptr); + return SkImageFilters::Dilate(dilate_filter->radius_x(), + dilate_filter->radius_y(), nullptr); + } + case DlImageFilterType::kErode: { + const DlErodeImageFilter* erode_filter = filter->asErode(); + FML_DCHECK(erode_filter != nullptr); + return SkImageFilters::Erode(erode_filter->radius_x(), + erode_filter->radius_y(), nullptr); + } + case DlImageFilterType::kMatrix: { + const DlMatrixImageFilter* matrix_filter = filter->asMatrix(); + FML_DCHECK(matrix_filter != nullptr); + return SkImageFilters::MatrixTransform( + matrix_filter->matrix(), ToSk(matrix_filter->sampling()), nullptr); + } + case DlImageFilterType::kCompose: { + const DlComposeImageFilter* compose_filter = filter->asCompose(); + FML_DCHECK(compose_filter != nullptr); + return SkImageFilters::Compose(ToSk(compose_filter->outer()), + ToSk(compose_filter->inner())); + } + case DlImageFilterType::kColorFilter: { + const DlColorFilterImageFilter* cf_filter = filter->asColorFilter(); + FML_DCHECK(cf_filter != nullptr); + return SkImageFilters::ColorFilter(ToSk(cf_filter->color_filter()), + nullptr); + } + case DlImageFilterType::kLocalMatrix: { + const DlLocalMatrixImageFilter* lm_filter = filter->asLocalMatrix(); + FML_DCHECK(lm_filter != nullptr); + sk_sp skia_filter = ToSk(lm_filter->image_filter()); + // The image_filter property itself might have been null, or the + // construction of the SkImageFilter might be optimized to null + // for any number of reasons. In any case, if the filter is null + // or optimizaed away, let's then optimize away this local matrix + // case by returning null. + if (!skia_filter) { + return nullptr; + } + return skia_filter->makeWithLocalMatrix(lm_filter->matrix()); + } + } +} + +sk_sp ToSk(const DlColorFilter* filter) { + if (!filter) { + return nullptr; + } + switch (filter->type()) { + case DlColorFilterType::kBlend: { + const DlBlendColorFilter* blend_filter = filter->asBlend(); + FML_DCHECK(blend_filter != nullptr); + return SkColorFilters::Blend(blend_filter->color(), + ToSk(blend_filter->mode())); + } + case DlColorFilterType::kMatrix: { + const DlMatrixColorFilter* matrix_filter = filter->asMatrix(); + FML_DCHECK(matrix_filter != nullptr); + float matrix[20]; + matrix_filter->get_matrix(matrix); + return SkColorFilters::Matrix(matrix); + } + case DlColorFilterType::kSrgbToLinearGamma: { + return SkColorFilters::SRGBToLinearGamma(); + } + case DlColorFilterType::kLinearToSrgbGamma: { + return SkColorFilters::LinearToSRGBGamma(); + } + } +} + +sk_sp ToSk(const DlMaskFilter* filter) { + if (!filter) { + return nullptr; + } + switch (filter->type()) { + case DlMaskFilterType::kBlur: { + const DlBlurMaskFilter* blur_filter = filter->asBlur(); + FML_DCHECK(blur_filter != nullptr); + return SkMaskFilter::MakeBlur(blur_filter->style(), blur_filter->sigma(), + blur_filter->respectCTM()); + } + } +} + +sk_sp ToSk(const DlPathEffect* effect) { + if (!effect) { + return nullptr; + } + switch (effect->type()) { + case DlPathEffectType::kDash: { + const DlDashPathEffect* dash_effect = effect->asDash(); + FML_DCHECK(dash_effect != nullptr); + return SkDashPathEffect::Make(dash_effect->intervals(), + dash_effect->count(), dash_effect->phase()); + } + } +} + +sk_sp ToSk(const DlVertices* vertices) { + const SkColor* sk_colors = + reinterpret_cast(vertices->colors()); + return SkVertices::MakeCopy(ToSk(vertices->mode()), vertices->vertex_count(), + vertices->vertices(), + vertices->texture_coordinates(), sk_colors, + vertices->index_count(), vertices->indices()); +} + +} // namespace flutter diff --git a/display_list/skia/dl_sk_conversions.h b/display_list/skia/dl_sk_conversions.h new file mode 100644 index 0000000000000..a8a4d472b4361 --- /dev/null +++ b/display_list/skia/dl_sk_conversions.h @@ -0,0 +1,116 @@ +// 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_SKIA_DL_SK_CONVERSIONS_H_ +#define FLUTTER_DISPLAY_LIST_SKIA_DL_SK_CONVERSIONS_H_ + +#include "flutter/display_list/dl_op_receiver.h" + +namespace flutter { + +inline SkBlendMode ToSk(DlBlendMode mode) { + return static_cast(mode); +} + +inline SkPaint::Style ToSk(DlDrawStyle style) { + return static_cast(style); +} + +inline SkPaint::Cap ToSk(DlStrokeCap cap) { + return static_cast(cap); +} + +inline SkPaint::Join ToSk(DlStrokeJoin join) { + return static_cast(join); +} + +inline SkTileMode ToSk(DlTileMode dl_mode) { + return static_cast(dl_mode); +} + +inline SkFilterMode ToSk(const DlFilterMode filter_mode) { + return static_cast(filter_mode); +} + +inline SkVertices::VertexMode ToSk(DlVertexMode dl_mode) { + return static_cast(dl_mode); +} + +inline SkSamplingOptions ToSk(DlImageSampling sampling) { + switch (sampling) { + case DlImageSampling::kCubic: + return SkSamplingOptions(SkCubicResampler{1 / 3.0f, 1 / 3.0f}); + case DlImageSampling::kLinear: + return SkSamplingOptions(SkFilterMode::kLinear); + case DlImageSampling::kMipmapLinear: + return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear); + case DlImageSampling::kNearestNeighbor: + return SkSamplingOptions(SkFilterMode::kNearest); + } +} + +inline SkCanvas::SrcRectConstraint ToSkConstraint(bool enforce_edges) { + return enforce_edges ? SkCanvas::kStrict_SrcRectConstraint + : SkCanvas::kFast_SrcRectConstraint; +} + +inline SkClipOp ToSk(DlCanvas::ClipOp op) { + return static_cast(op); +} + +inline SkCanvas::PointMode ToSk(DlCanvas::PointMode mode) { + return static_cast(mode); +} + +extern sk_sp ToSk(const DlColorSource* source); +inline sk_sp ToSk(std::shared_ptr source) { + return ToSk(source.get()); +} +inline sk_sp ToSk(const DlColorSource& source) { + return ToSk(&source); +} + +extern sk_sp ToSk(const DlImageFilter* filter); +inline sk_sp ToSk(std::shared_ptr filter) { + return ToSk(filter.get()); +} +inline sk_sp ToSk(const DlImageFilter& filter) { + return ToSk(&filter); +} + +extern sk_sp ToSk(const DlColorFilter* filter); +inline sk_sp ToSk(std::shared_ptr filter) { + return ToSk(filter.get()); +} +inline sk_sp ToSk(const DlColorFilter& filter) { + return ToSk(&filter); +} + +extern sk_sp ToSk(const DlMaskFilter* filter); +inline sk_sp ToSk(std::shared_ptr filter) { + return ToSk(filter.get()); +} +inline sk_sp ToSk(const DlMaskFilter& filter) { + return ToSk(&filter); +} + +extern sk_sp ToSk(const DlPathEffect* effect); +inline sk_sp ToSk(std::shared_ptr effect) { + return ToSk(effect.get()); +} +inline sk_sp ToSk(const DlPathEffect& effect) { + return ToSk(&effect); +} + +extern sk_sp ToSk(const DlVertices* vertices); +inline sk_sp ToSk(std::shared_ptr vertices) { + return ToSk(vertices.get()); +} +inline sk_sp ToSk(const DlVertices& vertices) { + return ToSk(&vertices); +} + +} // namespace flutter + +#endif // FLUTTER_DISPLAY_LIST_SKIA_DL_SK_CONVERSIONS_H_ diff --git a/display_list/skia/dl_sk_conversions_unittests.cc b/display_list/skia/dl_sk_conversions_unittests.cc new file mode 100644 index 0000000000000..17e6491e5545a --- /dev/null +++ b/display_list/skia/dl_sk_conversions_unittests.cc @@ -0,0 +1,260 @@ +// 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/skia/dl_sk_conversions.h" + +#include "flutter/display_list/display_list_blend_mode.h" +#include "flutter/display_list/display_list_paint.h" +#include "flutter/display_list/display_list_sampling_options.h" +#include "flutter/display_list/display_list_tile_mode.h" +#include "flutter/display_list/display_list_vertices.h" +#include "flutter/display_list/types.h" +#include "gtest/gtest.h" +#include "include/core/SkSamplingOptions.h" + +namespace flutter { +namespace testing { + +TEST(DisplayListImageFilter, LocalImageSkiaNull) { + auto blur_filter = + std::make_shared(0, 0, DlTileMode::kClamp); + DlLocalMatrixImageFilter dl_local_matrix_filter(SkMatrix::RotateDeg(45), + blur_filter); + // With sigmas set to zero on the blur filter, Skia will return a null filter. + // The local matrix filter should return nullptr instead of crashing. + ASSERT_EQ(ToSk(dl_local_matrix_filter), nullptr); +} + +TEST(DisplayListSkConversions, ToSkTileMode) { + ASSERT_EQ(ToSk(DlTileMode::kClamp), SkTileMode::kClamp); + ASSERT_EQ(ToSk(DlTileMode::kRepeat), SkTileMode::kRepeat); + ASSERT_EQ(ToSk(DlTileMode::kMirror), SkTileMode::kMirror); + ASSERT_EQ(ToSk(DlTileMode::kDecal), SkTileMode::kDecal); +} + +TEST(DisplayListSkConversions, ToSkDrawStyle) { + ASSERT_EQ(ToSk(DlDrawStyle::kFill), SkPaint::Style::kFill_Style); + ASSERT_EQ(ToSk(DlDrawStyle::kStroke), SkPaint::Style::kStroke_Style); + ASSERT_EQ(ToSk(DlDrawStyle::kStrokeAndFill), + SkPaint::Style::kStrokeAndFill_Style); +} + +TEST(DisplayListSkConversions, ToSkStrokeCap) { + ASSERT_EQ(ToSk(DlStrokeCap::kButt), SkPaint::Cap::kButt_Cap); + ASSERT_EQ(ToSk(DlStrokeCap::kRound), SkPaint::Cap::kRound_Cap); + ASSERT_EQ(ToSk(DlStrokeCap::kSquare), SkPaint::Cap::kSquare_Cap); +} + +TEST(DisplayListSkConversions, ToSkStrokeJoin) { + ASSERT_EQ(ToSk(DlStrokeJoin::kMiter), SkPaint::Join::kMiter_Join); + ASSERT_EQ(ToSk(DlStrokeJoin::kRound), SkPaint::Join::kRound_Join); + ASSERT_EQ(ToSk(DlStrokeJoin::kBevel), SkPaint::Join::kBevel_Join); +} + +TEST(DisplayListSkConversions, ToSkVertexMode) { + ASSERT_EQ(ToSk(DlVertexMode::kTriangles), + SkVertices::VertexMode::kTriangles_VertexMode); + ASSERT_EQ(ToSk(DlVertexMode::kTriangleStrip), + SkVertices::VertexMode::kTriangleStrip_VertexMode); + ASSERT_EQ(ToSk(DlVertexMode::kTriangleFan), + SkVertices::VertexMode::kTriangleFan_VertexMode); +} + +TEST(DisplayListSkConversions, ToSkFilterMode) { + ASSERT_EQ(ToSk(DlFilterMode::kLinear), SkFilterMode::kLinear); + ASSERT_EQ(ToSk(DlFilterMode::kNearest), SkFilterMode::kNearest); + ASSERT_EQ(ToSk(DlFilterMode::kLast), SkFilterMode::kLast); +} + +TEST(DisplayListSkConversions, ToSkSamplingOptions) { + ASSERT_EQ(ToSk(DlImageSampling::kLinear), + SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone)); + ASSERT_EQ(ToSk(DlImageSampling::kMipmapLinear), + SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear)); + ASSERT_EQ(ToSk(DlImageSampling::kNearestNeighbor), + SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone)); + ASSERT_EQ(ToSk(DlImageSampling::kCubic), + SkSamplingOptions(SkCubicResampler{1 / 3.0f, 1 / 3.0f})); +} + +#define FOR_EACH_BLEND_MODE_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(DisplayListSkConversions, ToSkBlendMode) { +#define CHECK_TO_SKENUM(V) ASSERT_EQ(ToSk(DlBlendMode::V), SkBlendMode::V); + FOR_EACH_BLEND_MODE_ENUM(CHECK_TO_SKENUM) +#undef CHECK_TO_SKENUM +} + +TEST(DisplayListSkConversions, BlendColorFilterModifiesTransparency) { + auto test_mode_color = [](DlBlendMode mode, DlColor color) { + std::stringstream desc_str; + desc_str << "blend[" << static_cast(mode) << ", " << color << "]"; + std::string desc = desc_str.str(); + DlBlendColorFilter filter(color, mode); + if (filter.modifies_transparent_black()) { + auto dl_filter = DlBlendColorFilter::Make(color, mode); + auto sk_filter = ToSk(filter); + ASSERT_NE(dl_filter, nullptr) << desc; + ASSERT_NE(sk_filter, nullptr) << desc; + ASSERT_TRUE(sk_filter->filterColor(0) != 0) << desc; + } else { + auto dl_filter = DlBlendColorFilter::Make(color, mode); + auto sk_filter = ToSk(filter); + EXPECT_EQ(dl_filter == nullptr, sk_filter == nullptr) << desc; + ASSERT_TRUE(sk_filter == nullptr || sk_filter->filterColor(0) == 0) + << desc; + } + }; + + auto test_mode = [&test_mode_color](DlBlendMode mode) { + test_mode_color(mode, DlColor::kTransparent()); + test_mode_color(mode, DlColor::kWhite()); + test_mode_color(mode, DlColor::kWhite().modulateOpacity(0.5)); + test_mode_color(mode, DlColor::kBlack()); + test_mode_color(mode, DlColor::kBlack().modulateOpacity(0.5)); + }; + +#define TEST_MODE(V) test_mode(DlBlendMode::V); + FOR_EACH_BLEND_MODE_ENUM(TEST_MODE) +#undef TEST_MODE +} + +#undef FOR_EACH_BLEND_MODE_ENUM + +TEST(DisplayListSkConversions, ConvertWithZeroAndNegativeVerticesAndIndices) { + std::shared_ptr vertices1 = DlVertices::Make( + DlVertexMode::kTriangles, 0, nullptr, nullptr, nullptr, 0, nullptr); + EXPECT_NE(vertices1, nullptr); + EXPECT_NE(ToSk(vertices1), nullptr); + + std::shared_ptr vertices2 = DlVertices::Make( + DlVertexMode::kTriangles, -1, nullptr, nullptr, nullptr, -1, nullptr); + EXPECT_NE(vertices2, nullptr); + EXPECT_NE(ToSk(vertices2), nullptr); +} + +TEST(DisplayListVertices, ConvertWithZeroAndNegativeVerticesAndIndices) { + DlVertices::Builder builder1(DlVertexMode::kTriangles, 0, + DlVertices::Builder::kNone, 0); + EXPECT_TRUE(builder1.is_valid()); + std::shared_ptr vertices1 = builder1.build(); + EXPECT_NE(vertices1, nullptr); + EXPECT_NE(ToSk(vertices1), nullptr); + + DlVertices::Builder builder2(DlVertexMode::kTriangles, -1, + DlVertices::Builder::kNone, -1); + EXPECT_TRUE(builder2.is_valid()); + std::shared_ptr vertices2 = builder2.build(); + EXPECT_NE(vertices2, nullptr); + EXPECT_NE(ToSk(vertices2), nullptr); +} + +TEST(DisplayListColorSource, ConvertRuntimeEffect) { + const sk_sp kTestRuntimeEffect1 = DlRuntimeEffect::MakeSkia( + SkRuntimeEffect::MakeForShader( + SkString("vec4 main(vec2 p) { return vec4(0); }")) + .effect); + const sk_sp kTestRuntimeEffect2 = DlRuntimeEffect::MakeSkia( + SkRuntimeEffect::MakeForShader( + SkString("vec4 main(vec2 p) { return vec4(1); }")) + .effect); + std::shared_ptr source1 = + DlColorSource::MakeRuntimeEffect( + kTestRuntimeEffect1, {}, std::make_shared>()); + std::shared_ptr source2 = + DlColorSource::MakeRuntimeEffect( + kTestRuntimeEffect2, {}, std::make_shared>()); + std::shared_ptr source3 = + DlColorSource::MakeRuntimeEffect( + nullptr, {}, std::make_shared>()); + + ASSERT_NE(ToSk(source1), nullptr); + ASSERT_NE(ToSk(source2), nullptr); + ASSERT_EQ(ToSk(source3), nullptr); +} + +TEST(DisplayListColorSource, ConvertRuntimeEffectWithNullSampler) { + const sk_sp kTestRuntimeEffect1 = DlRuntimeEffect::MakeSkia( + SkRuntimeEffect::MakeForShader( + SkString("vec4 main(vec2 p) { return vec4(0); }")) + .effect); + std::shared_ptr source1 = + DlColorSource::MakeRuntimeEffect( + kTestRuntimeEffect1, {nullptr}, + std::make_shared>()); + + ASSERT_EQ(ToSk(source1), nullptr); +} + +TEST(DisplayListSkConversions, MatrixColorFilterModifiesTransparency) { + auto test_matrix = [](int element, SkScalar value) { + // clang-format off + float matrix[] = { + 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, + }; + // clang-format on + std::string desc = + "matrix[" + std::to_string(element) + "] = " + std::to_string(value); + matrix[element] = value; + DlMatrixColorFilter filter(matrix); + auto dl_filter = DlMatrixColorFilter::Make(matrix); + auto sk_filter = ToSk(filter); + EXPECT_EQ(dl_filter == nullptr, sk_filter == nullptr); + EXPECT_EQ(filter.modifies_transparent_black(), + sk_filter && sk_filter->filterColor(0) != 0); + }; + + // Tests identity (matrix[0] already == 1 in an identity filter) + test_matrix(0, 1); + // test_matrix(19, 1); + for (int i = 0; i < 20; i++) { + test_matrix(i, -0.25); + test_matrix(i, 0); + test_matrix(i, 0.25); + test_matrix(i, 1); + test_matrix(i, 1.25); + test_matrix(i, SK_ScalarNaN); + test_matrix(i, SK_ScalarInfinity); + test_matrix(i, -SK_ScalarInfinity); + } +} + +} // namespace testing +} // namespace flutter diff --git a/display_list/skia/dl_sk_dispatcher.cc b/display_list/skia/dl_sk_dispatcher.cc new file mode 100644 index 0000000000000..199a6b7cae352 --- /dev/null +++ b/display_list/skia/dl_sk_dispatcher.cc @@ -0,0 +1,305 @@ +// 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/skia/dl_sk_dispatcher.h" + +#include "flutter/display_list/display_list_blend_mode.h" +#include "flutter/display_list/skia/dl_sk_conversions.h" +#include "flutter/fml/trace_event.h" +#include "third_party/skia/include/utils/SkShadowUtils.h" + +namespace flutter { + +const SkPaint* DlSkCanvasDispatcher::safe_paint(bool use_attributes) { + if (use_attributes) { + // The accumulated SkPaint object will already have incorporated + // any attribute overrides. + return &paint(); + } else if (has_opacity()) { + temp_paint_.setAlphaf(opacity()); + return &temp_paint_; + } else { + return nullptr; + } +} + +void DlSkCanvasDispatcher::save() { + canvas_->save(); + // save has no impact on attributes, but it needs to register a record + // on the restore stack so that the eventual call to restore() will + // know what to do at that time. We could annotate the restore record + // with a flag that the record came from a save call, but it is simpler + // to just pass in the current opacity value as the value to be used by + // the children and let the utility calls notice that it didn't change. + save_opacity(opacity()); +} +void DlSkCanvasDispatcher::restore() { + canvas_->restore(); + restore_opacity(); +} +void DlSkCanvasDispatcher::saveLayer(const SkRect* bounds, + const SaveLayerOptions options, + const DlImageFilter* backdrop) { + if (bounds == nullptr && options.can_distribute_opacity() && + backdrop == nullptr) { + // We know that: + // - no bounds is needed for clipping here + // - no backdrop filter is used to initialize the layer + // - the current attributes only have an alpha + // - the children are compatible with individually rendering with + // an inherited opacity + // Therefore we can just use a save instead of a saveLayer and pass the + // intended opacity to the children. + canvas_->save(); + // If the saveLayer does not use attributes, the children should continue + // to render with the inherited opacity unmodified. If attributes are to + // be applied, the children should render with the combination of the + // inherited opacity combined with the alpha from the current color. + save_opacity(options.renders_with_attributes() ? combined_opacity() + : opacity()); + } else { + TRACE_EVENT0("flutter", "Canvas::saveLayer"); + const SkPaint* paint = safe_paint(options.renders_with_attributes()); + const sk_sp sk_backdrop = ToSk(backdrop); + canvas_->saveLayer( + SkCanvas::SaveLayerRec(bounds, paint, sk_backdrop.get(), 0)); + // saveLayer will apply the current opacity on behalf of the children + // so they will inherit an opaque opacity. + save_opacity(SK_Scalar1); + } +} + +void DlSkCanvasDispatcher::translate(SkScalar tx, SkScalar ty) { + canvas_->translate(tx, ty); +} +void DlSkCanvasDispatcher::scale(SkScalar sx, SkScalar sy) { + canvas_->scale(sx, sy); +} +void DlSkCanvasDispatcher::rotate(SkScalar degrees) { + canvas_->rotate(degrees); +} +void DlSkCanvasDispatcher::skew(SkScalar sx, SkScalar sy) { + canvas_->skew(sx, sy); +} +// clang-format off +// 2x3 2D affine subset of a 4x4 transform in row major order +void DlSkCanvasDispatcher::transform2DAffine( + SkScalar mxx, SkScalar mxy, SkScalar mxt, + SkScalar myx, SkScalar myy, SkScalar myt) { + // Internally concat(SkMatrix) gets redirected to concat(SkM44) + // so we just jump directly to the SkM44 version + canvas_->concat(SkM44(mxx, mxy, 0, mxt, + myx, myy, 0, myt, + 0, 0, 1, 0, + 0, 0, 0, 1)); +} +// full 4x4 transform in row major order +void DlSkCanvasDispatcher::transformFullPerspective( + SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt, + SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt, + SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt, + SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt) { + canvas_->concat(SkM44(mxx, mxy, mxz, mxt, + myx, myy, myz, myt, + mzx, mzy, mzz, mzt, + mwx, mwy, mwz, mwt)); +} +// clang-format on +void DlSkCanvasDispatcher::transformReset() { + canvas_->setMatrix(original_transform_); +} + +void DlSkCanvasDispatcher::clipRect(const SkRect& rect, + ClipOp clip_op, + bool is_aa) { + canvas_->clipRect(rect, ToSk(clip_op), is_aa); +} +void DlSkCanvasDispatcher::clipRRect(const SkRRect& rrect, + ClipOp clip_op, + bool is_aa) { + canvas_->clipRRect(rrect, ToSk(clip_op), is_aa); +} +void DlSkCanvasDispatcher::clipPath(const SkPath& path, + ClipOp clip_op, + bool is_aa) { + canvas_->clipPath(path, ToSk(clip_op), is_aa); +} + +void DlSkCanvasDispatcher::drawPaint() { + const SkPaint& sk_paint = paint(); + SkImageFilter* filter = sk_paint.getImageFilter(); + if (filter && !filter->asColorFilter(nullptr)) { + // drawPaint does an implicit saveLayer if an SkImageFilter is + // present that cannot be replaced by an SkColorFilter. + TRACE_EVENT0("flutter", "Canvas::saveLayer"); + } + canvas_->drawPaint(sk_paint); +} +void DlSkCanvasDispatcher::drawColor(DlColor 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, ToSk(mode)); +} +void DlSkCanvasDispatcher::drawLine(const SkPoint& p0, const SkPoint& p1) { + canvas_->drawLine(p0, p1, paint()); +} +void DlSkCanvasDispatcher::drawRect(const SkRect& rect) { + canvas_->drawRect(rect, paint()); +} +void DlSkCanvasDispatcher::drawOval(const SkRect& bounds) { + canvas_->drawOval(bounds, paint()); +} +void DlSkCanvasDispatcher::drawCircle(const SkPoint& center, SkScalar radius) { + canvas_->drawCircle(center, radius, paint()); +} +void DlSkCanvasDispatcher::drawRRect(const SkRRect& rrect) { + canvas_->drawRRect(rrect, paint()); +} +void DlSkCanvasDispatcher::drawDRRect(const SkRRect& outer, + const SkRRect& inner) { + canvas_->drawDRRect(outer, inner, paint()); +} +void DlSkCanvasDispatcher::drawPath(const SkPath& path) { + canvas_->drawPath(path, paint()); +} +void DlSkCanvasDispatcher::drawArc(const SkRect& bounds, + SkScalar start, + SkScalar sweep, + bool useCenter) { + canvas_->drawArc(bounds, start, sweep, useCenter, paint()); +} +void DlSkCanvasDispatcher::drawPoints(PointMode mode, + uint32_t count, + const SkPoint pts[]) { + canvas_->drawPoints(ToSk(mode), count, pts, paint()); +} +void DlSkCanvasDispatcher::drawVertices(const DlVertices* vertices, + DlBlendMode mode) { + canvas_->drawVertices(ToSk(vertices), ToSk(mode), paint()); +} +void DlSkCanvasDispatcher::drawImage(const sk_sp image, + const SkPoint point, + DlImageSampling sampling, + bool render_with_attributes) { + canvas_->drawImage(image ? image->skia_image() : nullptr, point.fX, point.fY, + ToSk(sampling), safe_paint(render_with_attributes)); +} +void DlSkCanvasDispatcher::drawImageRect(const sk_sp image, + const SkRect& src, + const SkRect& dst, + DlImageSampling sampling, + bool render_with_attributes, + bool enforce_src_edges) { + canvas_->drawImageRect(image ? image->skia_image() : nullptr, src, dst, + ToSk(sampling), safe_paint(render_with_attributes), + ToSkConstraint(enforce_src_edges)); +} +void DlSkCanvasDispatcher::drawImageNine(const sk_sp image, + const SkIRect& center, + const SkRect& dst, + DlFilterMode filter, + bool render_with_attributes) { + if (!image) { + return; + } + auto skia_image = image->skia_image(); + if (!skia_image) { + return; + } + canvas_->drawImageNine(skia_image.get(), center, dst, ToSk(filter), + safe_paint(render_with_attributes)); +} +void DlSkCanvasDispatcher::drawAtlas(const sk_sp atlas, + const SkRSXform xform[], + const SkRect tex[], + const DlColor colors[], + int count, + DlBlendMode mode, + DlImageSampling sampling, + const SkRect* cullRect, + bool render_with_attributes) { + if (!atlas) { + return; + } + auto skia_atlas = atlas->skia_image(); + if (!skia_atlas) { + return; + } + const SkColor* sk_colors = reinterpret_cast(colors); + canvas_->drawAtlas(skia_atlas.get(), xform, tex, sk_colors, count, ToSk(mode), + ToSk(sampling), cullRect, + safe_paint(render_with_attributes)); +} +void DlSkCanvasDispatcher::drawDisplayList( + const sk_sp display_list, + SkScalar opacity) { + int restore_count; + + // Compute combined opacity and figure out whether we can apply it + // during dispatch or if we need a saveLayer. + SkScalar combined_opacity = opacity * this->opacity(); + if (combined_opacity < SK_Scalar1 && + !display_list->can_apply_group_opacity()) { + SkPaint save_paint; + save_paint.setAlphaf(combined_opacity); + restore_count = canvas_->saveLayer(display_list->bounds(), &save_paint); + combined_opacity = SK_Scalar1; + } else { + restore_count = canvas_->save(); + } + + // Create a new CanvasDispatcher to isolate the actions of the + // display_list from the current environment. + DlSkCanvasDispatcher dispatcher(canvas_, combined_opacity); + if (display_list->rtree()) { + display_list->Dispatch(dispatcher, canvas_->getLocalClipBounds()); + } else { + display_list->Dispatch(dispatcher); + } + + // Restore canvas state to what it was before dispatching. + canvas_->restoreToCount(restore_count); +} +void DlSkCanvasDispatcher::drawTextBlob(const sk_sp blob, + SkScalar x, + SkScalar y) { + canvas_->drawTextBlob(blob, x, y, paint()); +} + +void DlSkCanvasDispatcher::DrawShadow(SkCanvas* canvas, + const SkPath& path, + DlColor color, + float elevation, + bool transparentOccluder, + SkScalar dpr) { + const SkScalar kAmbientAlpha = 0.039f; + const SkScalar kSpotAlpha = 0.25f; + + uint32_t flags = transparentOccluder + ? SkShadowFlags::kTransparentOccluder_ShadowFlag + : SkShadowFlags::kNone_ShadowFlag; + flags |= SkShadowFlags::kDirectionalLight_ShadowFlag; + SkColor in_ambient = SkColorSetA(color, kAmbientAlpha * SkColorGetA(color)); + SkColor in_spot = SkColorSetA(color, kSpotAlpha * SkColorGetA(color)); + SkColor ambient_color, spot_color; + SkShadowUtils::ComputeTonalColors(in_ambient, in_spot, &ambient_color, + &spot_color); + SkShadowUtils::DrawShadow( + canvas, path, SkPoint3::Make(0, 0, dpr * elevation), + SkPoint3::Make(0, -1, 1), + DlCanvas::kShadowLightRadius / DlCanvas::kShadowLightHeight, + ambient_color, spot_color, flags); +} + +void DlSkCanvasDispatcher::drawShadow(const SkPath& path, + const DlColor color, + const SkScalar elevation, + bool transparent_occluder, + SkScalar dpr) { + DrawShadow(canvas_, path, color, elevation, transparent_occluder, dpr); +} + +} // namespace flutter diff --git a/display_list/display_list_canvas_dispatcher.h b/display_list/skia/dl_sk_dispatcher.h similarity index 85% rename from display_list/display_list_canvas_dispatcher.h rename to display_list/skia/dl_sk_dispatcher.h index 993b5b4da2117..725ab585585db 100644 --- a/display_list/display_list_canvas_dispatcher.h +++ b/display_list/skia/dl_sk_dispatcher.h @@ -6,9 +6,8 @@ #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/display_list/dl_op_receiver.h" +#include "flutter/display_list/skia/dl_sk_utils.h" #include "flutter/fml/macros.h" namespace flutter { @@ -19,11 +18,10 @@ namespace flutter { /// /// Receives all methods on Dispatcher and sends them to an SkCanvas /// -class DisplayListCanvasDispatcher : public virtual Dispatcher, - public SkPaintDispatchHelper { +class DlSkCanvasDispatcher : public virtual DlOpReceiver, + public SkPaintDispatchHelper { public: - explicit DisplayListCanvasDispatcher(SkCanvas* canvas, - SkScalar opacity = SK_Scalar1) + explicit DlSkCanvasDispatcher(SkCanvas* canvas, SkScalar opacity = SK_Scalar1) : SkPaintDispatchHelper(opacity), canvas_(canvas), original_transform_(canvas->getLocalToDevice()) {} @@ -81,7 +79,7 @@ class DisplayListCanvasDispatcher : public virtual Dispatcher, const SkRect& dst, DlImageSampling sampling, bool render_with_attributes, - SkCanvas::SrcRectConstraint constraint) override; + bool enforce_src_edges) override; void drawImageNine(const sk_sp image, const SkIRect& center, const SkRect& dst, @@ -96,7 +94,8 @@ class DisplayListCanvasDispatcher : public virtual Dispatcher, DlImageSampling sampling, const SkRect* cullRect, bool render_with_attributes) override; - void drawDisplayList(const sk_sp display_list) override; + void drawDisplayList(const sk_sp display_list, + SkScalar opacity) override; void drawTextBlob(const sk_sp blob, SkScalar x, SkScalar y) override; @@ -106,11 +105,6 @@ class DisplayListCanvasDispatcher : public virtual Dispatcher, bool transparent_occluder, SkScalar dpr) override; - static SkRect ComputeShadowBounds(const SkPath& path, - float elevation, - SkScalar dpr, - const SkMatrix& ctm); - static void DrawShadow(SkCanvas* canvas, const SkPath& path, DlColor color, diff --git a/display_list/skia/dl_sk_utils.cc b/display_list/skia/dl_sk_utils.cc new file mode 100644 index 0000000000000..3476ab3f5139d --- /dev/null +++ b/display_list/skia/dl_sk_utils.cc @@ -0,0 +1,102 @@ +// 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/skia/dl_sk_utils.h" + +#include +#include +#include + +#include "flutter/display_list/display_list_blend_mode.h" +#include "flutter/display_list/skia/dl_sk_conversions.h" +#include "flutter/fml/logging.h" + +namespace flutter { + +// clang-format off +constexpr float kInvertColorMatrix[20] = { + -1.0, 0, 0, 1.0, 0, + 0, -1.0, 0, 1.0, 0, + 0, 0, -1.0, 1.0, 0, + 1.0, 1.0, 1.0, 1.0, 0 +}; +// clang-format on + +void SkPaintDispatchHelper::save_opacity(SkScalar child_opacity) { + save_stack_.emplace_back(opacity_); + set_opacity(child_opacity); +} +void SkPaintDispatchHelper::restore_opacity() { + if (save_stack_.empty()) { + return; + } + set_opacity(save_stack_.back().opacity); + save_stack_.pop_back(); +} + +void SkPaintDispatchHelper::setAntiAlias(bool aa) { + paint_.setAntiAlias(aa); +} +void SkPaintDispatchHelper::setDither(bool dither) { + paint_.setDither(dither); +} +void SkPaintDispatchHelper::setInvertColors(bool invert) { + invert_colors_ = invert; + paint_.setColorFilter(makeColorFilter()); +} +void SkPaintDispatchHelper::setStrokeCap(DlStrokeCap cap) { + paint_.setStrokeCap(ToSk(cap)); +} +void SkPaintDispatchHelper::setStrokeJoin(DlStrokeJoin join) { + paint_.setStrokeJoin(ToSk(join)); +} +void SkPaintDispatchHelper::setStyle(DlDrawStyle style) { + paint_.setStyle(ToSk(style)); +} +void SkPaintDispatchHelper::setStrokeWidth(SkScalar width) { + paint_.setStrokeWidth(width); +} +void SkPaintDispatchHelper::setStrokeMiter(SkScalar limit) { + paint_.setStrokeMiter(limit); +} +void SkPaintDispatchHelper::setColor(DlColor color) { + current_color_ = color; + paint_.setColor(color); + if (has_opacity()) { + paint_.setAlphaf(paint_.getAlphaf() * opacity()); + } +} +void SkPaintDispatchHelper::setBlendMode(DlBlendMode mode) { + paint_.setBlendMode(ToSk(mode)); +} +void SkPaintDispatchHelper::setColorSource(const DlColorSource* source) { + paint_.setShader(ToSk(source)); +} +void SkPaintDispatchHelper::setImageFilter(const DlImageFilter* filter) { + paint_.setImageFilter(ToSk(filter)); +} +void SkPaintDispatchHelper::setColorFilter(const DlColorFilter* filter) { + sk_color_filter_ = ToSk(filter); + paint_.setColorFilter(makeColorFilter()); +} +void SkPaintDispatchHelper::setPathEffect(const DlPathEffect* effect) { + paint_.setPathEffect(ToSk(effect)); +} +void SkPaintDispatchHelper::setMaskFilter(const DlMaskFilter* filter) { + paint_.setMaskFilter(ToSk(filter)); +} + +sk_sp SkPaintDispatchHelper::makeColorFilter() const { + if (!invert_colors_) { + return sk_color_filter_; + } + sk_sp invert_filter = + SkColorFilters::Matrix(kInvertColorMatrix); + if (sk_color_filter_) { + invert_filter = invert_filter->makeComposed(sk_color_filter_); + } + return invert_filter; +} + +} // namespace flutter diff --git a/display_list/skia/dl_sk_utils.h b/display_list/skia/dl_sk_utils.h new file mode 100644 index 0000000000000..e61848d1a6cd4 --- /dev/null +++ b/display_list/skia/dl_sk_utils.h @@ -0,0 +1,85 @@ +// 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_SKIA_DL_SK_UTILS_H_ +#define FLUTTER_DISPLAY_LIST_SKIA_DL_SK_UTILS_H_ + +#include "flutter/display_list/dl_op_receiver.h" + +namespace flutter { + +// A utility class that will monitor the DlOpReceiver methods relating +// to the rendering attributes and accumulate them into an SkPaint +// which can be accessed at any time via paint(). +class SkPaintDispatchHelper : public virtual DlOpReceiver { + public: + SkPaintDispatchHelper(SkScalar opacity = SK_Scalar1) + : current_color_(SK_ColorBLACK), opacity_(opacity) { + if (opacity < SK_Scalar1) { + paint_.setAlphaf(opacity); + } + } + + void setAntiAlias(bool aa) override; + void setDither(bool dither) override; + void setStyle(DlDrawStyle style) override; + void setColor(DlColor color) override; + void setStrokeWidth(SkScalar width) override; + void setStrokeMiter(SkScalar limit) override; + void setStrokeCap(DlStrokeCap cap) override; + void setStrokeJoin(DlStrokeJoin join) override; + void setColorSource(const DlColorSource* source) override; + void setColorFilter(const DlColorFilter* filter) override; + void setInvertColors(bool invert) override; + void setBlendMode(DlBlendMode mode) override; + void setPathEffect(const DlPathEffect* effect) override; + void setMaskFilter(const DlMaskFilter* filter) override; + void setImageFilter(const DlImageFilter* filter) override; + + const SkPaint& paint() { return paint_; } + + /// Returns the current opacity attribute which is used to reduce + /// the alpha of all setColor calls encountered in the streeam + SkScalar opacity() { return opacity_; } + /// Returns the combined opacity that includes both the current + /// opacity attribute and the alpha of the most recent color. + /// The most recently set color will have combined the two and + /// stored the combined value in the alpha of the paint. + SkScalar combined_opacity() { return paint_.getAlphaf(); } + /// Returns true iff the current opacity attribute is not opaque, + /// irrespective of the alpha of the current color + bool has_opacity() { return opacity_ < SK_Scalar1; } + + protected: + void save_opacity(SkScalar opacity_for_children); + void restore_opacity(); + + private: + SkPaint paint_; + bool invert_colors_ = false; + sk_sp sk_color_filter_; + + sk_sp makeColorFilter() const; + + struct SaveInfo { + SaveInfo(SkScalar opacity) : opacity(opacity) {} + + SkScalar opacity; + }; + std::vector save_stack_; + + void set_opacity(SkScalar opacity) { + if (opacity_ != opacity) { + opacity_ = opacity; + setColor(current_color_); + } + } + + SkColor current_color_; + SkScalar opacity_; +}; + +} // namespace flutter + +#endif // FLUTTER_DISPLAY_LIST_SKIA_DL_SK_UTILS_H_ diff --git a/display_list/display_list_utils_unittests.cc b/display_list/skia/dl_sk_utils_unittests.cc similarity index 90% rename from display_list/display_list_utils_unittests.cc rename to display_list/skia/dl_sk_utils_unittests.cc index 9f77c949b861e..ccab201117af3 100644 --- a/display_list/display_list_utils_unittests.cc +++ b/display_list/skia/dl_sk_utils_unittests.cc @@ -3,12 +3,13 @@ // found in the LICENSE file. #include "flutter/display_list/display_list_utils.h" +#include "flutter/display_list/skia/dl_sk_utils.h" #include "gtest/gtest.h" namespace flutter { namespace testing { -class MockDispatchHelper final : public virtual Dispatcher, +class MockDispatchHelper final : public virtual DlOpReceiver, public SkPaintDispatchHelper, public IgnoreClipDispatchHelper, public IgnoreTransformDispatchHelper, diff --git a/display_list/testing/dl_test_snippets.cc b/display_list/testing/dl_test_snippets.cc index 741b0dbb5b10a..c1a0d75f031c5 100644 --- a/display_list/testing/dl_test_snippets.cc +++ b/display_list/testing/dl_test_snippets.cc @@ -4,34 +4,35 @@ #include "flutter/display_list/testing/dl_test_snippets.h" #include "flutter/display_list/display_list_builder.h" +#include "flutter/display_list/dl_op_receiver.h" namespace flutter { namespace testing { sk_sp GetSampleDisplayList() { DisplayListBuilder builder(SkRect::MakeWH(150, 100)); - builder.setColor(SK_ColorRED); - builder.drawRect(SkRect::MakeXYWH(10, 10, 80, 80)); + builder.DrawRect(SkRect::MakeXYWH(10, 10, 80, 80), DlPaint(DlColor::kRed())); return builder.Build(); } sk_sp GetSampleNestedDisplayList() { DisplayListBuilder builder(SkRect::MakeWH(150, 100)); + DlPaint paint; for (int y = 10; y <= 60; y += 10) { for (int x = 10; x <= 60; x += 10) { - builder.setColor(((x + y) % 20) == 10 ? SK_ColorRED : SK_ColorBLUE); - builder.drawRect(SkRect::MakeXYWH(x, y, 80, 80)); + paint.setColor(((x + y) % 20) == 10 ? SK_ColorRED : SK_ColorBLUE); + builder.DrawRect(SkRect::MakeXYWH(x, y, 80, 80), paint); } } DisplayListBuilder outer_builder(SkRect::MakeWH(150, 100)); - outer_builder.drawDisplayList(builder.Build()); + outer_builder.DrawDisplayList(builder.Build()); return outer_builder.Build(); } sk_sp GetSampleDisplayList(int ops) { DisplayListBuilder builder(SkRect::MakeWH(150, 100)); for (int i = 0; i < ops; i++) { - builder.drawColor(SK_ColorRED, DlBlendMode::kSrc); + builder.DrawColor(DlColor::kRed(), DlBlendMode::kSrc); } return builder.Build(); } @@ -44,192 +45,148 @@ std::vector CreateAllAttributesOps() { return { {"SetAntiAlias", { - {0, 8, 0, 0, [](DisplayListBuilder& b) { b.setAntiAlias(true); }}, - {0, 0, 0, 0, [](DisplayListBuilder& b) { b.setAntiAlias(false); }}, + {0, 8, 0, 0, [](DlOpReceiver& r) { r.setAntiAlias(true); }}, + {0, 0, 0, 0, [](DlOpReceiver& r) { r.setAntiAlias(false); }}, }}, {"SetDither", { - {0, 8, 0, 0, [](DisplayListBuilder& b) { b.setDither(true); }}, - {0, 0, 0, 0, [](DisplayListBuilder& b) { b.setDither(false); }}, + {0, 8, 0, 0, [](DlOpReceiver& r) { r.setDither(true); }}, + {0, 0, 0, 0, [](DlOpReceiver& r) { r.setDither(false); }}, }}, {"SetInvertColors", { - {0, 8, 0, 0, [](DisplayListBuilder& b) { b.setInvertColors(true); }}, - {0, 0, 0, 0, - [](DisplayListBuilder& b) { b.setInvertColors(false); }}, + {0, 8, 0, 0, [](DlOpReceiver& r) { r.setInvertColors(true); }}, + {0, 0, 0, 0, [](DlOpReceiver& r) { r.setInvertColors(false); }}, }}, {"SetStrokeCap", { {0, 8, 0, 0, - [](DisplayListBuilder& b) { b.setStrokeCap(DlStrokeCap::kRound); }}, + [](DlOpReceiver& r) { r.setStrokeCap(DlStrokeCap::kRound); }}, {0, 8, 0, 0, - [](DisplayListBuilder& b) { - b.setStrokeCap(DlStrokeCap::kSquare); - }}, + [](DlOpReceiver& r) { r.setStrokeCap(DlStrokeCap::kSquare); }}, {0, 0, 0, 0, - [](DisplayListBuilder& b) { b.setStrokeCap(DlStrokeCap::kButt); }}, + [](DlOpReceiver& r) { r.setStrokeCap(DlStrokeCap::kButt); }}, }}, {"SetStrokeJoin", { {0, 8, 0, 0, - [](DisplayListBuilder& b) { - b.setStrokeJoin(DlStrokeJoin::kBevel); - }}, + [](DlOpReceiver& r) { r.setStrokeJoin(DlStrokeJoin::kBevel); }}, {0, 8, 0, 0, - [](DisplayListBuilder& b) { - b.setStrokeJoin(DlStrokeJoin::kRound); - }}, + [](DlOpReceiver& r) { r.setStrokeJoin(DlStrokeJoin::kRound); }}, {0, 0, 0, 0, - [](DisplayListBuilder& b) { - b.setStrokeJoin(DlStrokeJoin::kMiter); - }}, + [](DlOpReceiver& r) { r.setStrokeJoin(DlStrokeJoin::kMiter); }}, }}, {"SetStyle", { {0, 8, 0, 0, - [](DisplayListBuilder& b) { b.setStyle(DlDrawStyle::kStroke); }}, + [](DlOpReceiver& r) { r.setStyle(DlDrawStyle::kStroke); }}, {0, 8, 0, 0, - [](DisplayListBuilder& b) { - b.setStyle(DlDrawStyle::kStrokeAndFill); - }}, + [](DlOpReceiver& r) { r.setStyle(DlDrawStyle::kStrokeAndFill); }}, {0, 0, 0, 0, - [](DisplayListBuilder& b) { b.setStyle(DlDrawStyle::kFill); }}, + [](DlOpReceiver& r) { r.setStyle(DlDrawStyle::kFill); }}, }}, {"SetStrokeWidth", { - {0, 8, 0, 0, [](DisplayListBuilder& b) { b.setStrokeWidth(1.0); }}, - {0, 8, 0, 0, [](DisplayListBuilder& b) { b.setStrokeWidth(5.0); }}, - {0, 0, 0, 0, [](DisplayListBuilder& b) { b.setStrokeWidth(0.0); }}, + {0, 8, 0, 0, [](DlOpReceiver& r) { r.setStrokeWidth(1.0); }}, + {0, 8, 0, 0, [](DlOpReceiver& r) { r.setStrokeWidth(5.0); }}, + {0, 0, 0, 0, [](DlOpReceiver& r) { r.setStrokeWidth(0.0); }}, }}, {"SetStrokeMiter", { - {0, 8, 0, 0, [](DisplayListBuilder& b) { b.setStrokeMiter(0.0); }}, - {0, 8, 0, 0, [](DisplayListBuilder& b) { b.setStrokeMiter(5.0); }}, - {0, 0, 0, 0, [](DisplayListBuilder& b) { b.setStrokeMiter(4.0); }}, + {0, 8, 0, 0, [](DlOpReceiver& r) { r.setStrokeMiter(0.0); }}, + {0, 8, 0, 0, [](DlOpReceiver& r) { r.setStrokeMiter(5.0); }}, + {0, 0, 0, 0, [](DlOpReceiver& r) { r.setStrokeMiter(4.0); }}, }}, {"SetColor", { - {0, 8, 0, 0, - [](DisplayListBuilder& b) { b.setColor(SK_ColorGREEN); }}, - {0, 8, 0, 0, - [](DisplayListBuilder& b) { b.setColor(SK_ColorBLUE); }}, - {0, 0, 0, 0, - [](DisplayListBuilder& b) { b.setColor(SK_ColorBLACK); }}, + {0, 8, 0, 0, [](DlOpReceiver& r) { r.setColor(SK_ColorGREEN); }}, + {0, 8, 0, 0, [](DlOpReceiver& r) { r.setColor(SK_ColorBLUE); }}, + {0, 0, 0, 0, [](DlOpReceiver& r) { r.setColor(SK_ColorBLACK); }}, }}, {"SetBlendMode", { {0, 8, 0, 0, - [](DisplayListBuilder& b) { b.setBlendMode(DlBlendMode::kSrcIn); }}, + [](DlOpReceiver& r) { r.setBlendMode(DlBlendMode::kSrcIn); }}, {0, 8, 0, 0, - [](DisplayListBuilder& b) { b.setBlendMode(DlBlendMode::kDstIn); }}, + [](DlOpReceiver& r) { r.setBlendMode(DlBlendMode::kDstIn); }}, {0, 0, 0, 0, - [](DisplayListBuilder& b) { - b.setBlendMode(DlBlendMode::kSrcOver); - }}, + [](DlOpReceiver& r) { r.setBlendMode(DlBlendMode::kSrcOver); }}, }}, {"SetColorSource", { {0, 96, 0, 0, - [](DisplayListBuilder& b) { b.setColorSource(&kTestSource1); }}, + [](DlOpReceiver& r) { r.setColorSource(&kTestSource1); }}, // stop_count * (sizeof(float) + sizeof(uint32_t)) = 80 {0, 80 + 6 * 4, 0, 0, - [](DisplayListBuilder& b) { - b.setColorSource(kTestSource2.get()); - }}, + [](DlOpReceiver& r) { r.setColorSource(kTestSource2.get()); }}, {0, 80 + 6 * 4, 0, 0, - [](DisplayListBuilder& b) { - b.setColorSource(kTestSource3.get()); - }}, + [](DlOpReceiver& r) { r.setColorSource(kTestSource3.get()); }}, {0, 88 + 6 * 4, 0, 0, - [](DisplayListBuilder& b) { - b.setColorSource(kTestSource4.get()); - }}, + [](DlOpReceiver& r) { r.setColorSource(kTestSource4.get()); }}, {0, 80 + 6 * 4, 0, 0, - [](DisplayListBuilder& b) { - b.setColorSource(kTestSource5.get()); - }}, - {0, 0, 0, 0, - [](DisplayListBuilder& b) { b.setColorSource(nullptr); }}, + [](DlOpReceiver& r) { r.setColorSource(kTestSource5.get()); }}, + {0, 0, 0, 0, [](DlOpReceiver& r) { r.setColorSource(nullptr); }}, }}, {"SetImageFilter", { {0, 32, 0, 0, - [](DisplayListBuilder& b) { - b.setImageFilter(&kTestBlurImageFilter1); - }}, + [](DlOpReceiver& r) { r.setImageFilter(&kTestBlurImageFilter1); }}, {0, 32, 0, 0, - [](DisplayListBuilder& b) { - b.setImageFilter(&kTestBlurImageFilter2); - }}, + [](DlOpReceiver& r) { r.setImageFilter(&kTestBlurImageFilter2); }}, {0, 32, 0, 0, - [](DisplayListBuilder& b) { - b.setImageFilter(&kTestBlurImageFilter3); - }}, + [](DlOpReceiver& r) { r.setImageFilter(&kTestBlurImageFilter3); }}, {0, 32, 0, 0, - [](DisplayListBuilder& b) { - b.setImageFilter(&kTestBlurImageFilter4); - }}, + [](DlOpReceiver& r) { r.setImageFilter(&kTestBlurImageFilter4); }}, {0, 24, 0, 0, - [](DisplayListBuilder& b) { - b.setImageFilter(&kTestDilateImageFilter1); + [](DlOpReceiver& r) { + r.setImageFilter(&kTestDilateImageFilter1); }}, {0, 24, 0, 0, - [](DisplayListBuilder& b) { - b.setImageFilter(&kTestDilateImageFilter2); + [](DlOpReceiver& r) { + r.setImageFilter(&kTestDilateImageFilter2); }}, {0, 24, 0, 0, - [](DisplayListBuilder& b) { - b.setImageFilter(&kTestDilateImageFilter3); + [](DlOpReceiver& r) { + r.setImageFilter(&kTestDilateImageFilter3); }}, {0, 24, 0, 0, - [](DisplayListBuilder& b) { - b.setImageFilter(&kTestErodeImageFilter1); - }}, + [](DlOpReceiver& r) { r.setImageFilter(&kTestErodeImageFilter1); }}, {0, 24, 0, 0, - [](DisplayListBuilder& b) { - b.setImageFilter(&kTestErodeImageFilter2); - }}, + [](DlOpReceiver& r) { r.setImageFilter(&kTestErodeImageFilter2); }}, {0, 24, 0, 0, - [](DisplayListBuilder& b) { - b.setImageFilter(&kTestErodeImageFilter3); - }}, + [](DlOpReceiver& r) { r.setImageFilter(&kTestErodeImageFilter3); }}, {0, 64, 0, 0, - [](DisplayListBuilder& b) { - b.setImageFilter(&kTestMatrixImageFilter1); + [](DlOpReceiver& r) { + r.setImageFilter(&kTestMatrixImageFilter1); }}, {0, 64, 0, 0, - [](DisplayListBuilder& b) { - b.setImageFilter(&kTestMatrixImageFilter2); + [](DlOpReceiver& r) { + r.setImageFilter(&kTestMatrixImageFilter2); }}, {0, 64, 0, 0, - [](DisplayListBuilder& b) { - b.setImageFilter(&kTestMatrixImageFilter3); + [](DlOpReceiver& r) { + r.setImageFilter(&kTestMatrixImageFilter3); }}, {0, 24, 0, 0, - [](DisplayListBuilder& b) { - b.setImageFilter(&kTestComposeImageFilter1); + [](DlOpReceiver& r) { + r.setImageFilter(&kTestComposeImageFilter1); }}, {0, 24, 0, 0, - [](DisplayListBuilder& b) { - b.setImageFilter(&kTestComposeImageFilter2); + [](DlOpReceiver& r) { + r.setImageFilter(&kTestComposeImageFilter2); }}, {0, 24, 0, 0, - [](DisplayListBuilder& b) { - b.setImageFilter(&kTestComposeImageFilter3); + [](DlOpReceiver& r) { + r.setImageFilter(&kTestComposeImageFilter3); }}, {0, 24, 0, 0, - [](DisplayListBuilder& b) { - b.setImageFilter(&kTestCFImageFilter1); - }}, + [](DlOpReceiver& r) { r.setImageFilter(&kTestCFImageFilter1); }}, {0, 24, 0, 0, - [](DisplayListBuilder& b) { - b.setImageFilter(&kTestCFImageFilter2); - }}, - {0, 0, 0, 0, - [](DisplayListBuilder& b) { b.setImageFilter(nullptr); }}, + [](DlOpReceiver& r) { r.setImageFilter(&kTestCFImageFilter2); }}, + {0, 0, 0, 0, [](DlOpReceiver& r) { r.setImageFilter(nullptr); }}, {0, 24, 0, 0, - [](DisplayListBuilder& b) { - b.setImageFilter( + [](DlOpReceiver& r) { + r.setImageFilter( kTestBlurImageFilter1 .makeWithLocalMatrix(SkMatrix::Translate(2, 2)) .get()); @@ -238,64 +195,51 @@ std::vector CreateAllAttributesOps() { {"SetColorFilter", { {0, 24, 0, 0, - [](DisplayListBuilder& b) { - b.setColorFilter(&kTestBlendColorFilter1); - }}, + [](DlOpReceiver& r) { r.setColorFilter(&kTestBlendColorFilter1); }}, {0, 24, 0, 0, - [](DisplayListBuilder& b) { - b.setColorFilter(&kTestBlendColorFilter2); - }}, + [](DlOpReceiver& r) { r.setColorFilter(&kTestBlendColorFilter2); }}, {0, 24, 0, 0, - [](DisplayListBuilder& b) { - b.setColorFilter(&kTestBlendColorFilter3); - }}, + [](DlOpReceiver& r) { r.setColorFilter(&kTestBlendColorFilter3); }}, {0, 96, 0, 0, - [](DisplayListBuilder& b) { - b.setColorFilter(&kTestMatrixColorFilter1); + [](DlOpReceiver& r) { + r.setColorFilter(&kTestMatrixColorFilter1); }}, {0, 96, 0, 0, - [](DisplayListBuilder& b) { - b.setColorFilter(&kTestMatrixColorFilter2); + [](DlOpReceiver& r) { + r.setColorFilter(&kTestMatrixColorFilter2); }}, {0, 16, 0, 0, - [](DisplayListBuilder& b) { - b.setColorFilter(DlSrgbToLinearGammaColorFilter::instance.get()); + [](DlOpReceiver& r) { + r.setColorFilter(DlSrgbToLinearGammaColorFilter::instance.get()); }}, {0, 16, 0, 0, - [](DisplayListBuilder& b) { - b.setColorFilter(DlLinearToSrgbGammaColorFilter::instance.get()); + [](DlOpReceiver& r) { + r.setColorFilter(DlLinearToSrgbGammaColorFilter::instance.get()); }}, - {0, 0, 0, 0, - [](DisplayListBuilder& b) { b.setColorFilter(nullptr); }}, + {0, 0, 0, 0, [](DlOpReceiver& r) { r.setColorFilter(nullptr); }}, }}, {"SetPathEffect", { // sizeof(DlDashPathEffect) + 2 * sizeof(SkScalar) {0, 32, 0, 0, - [](DisplayListBuilder& b) { - b.setPathEffect(kTestPathEffect1.get()); - }}, + [](DlOpReceiver& r) { r.setPathEffect(kTestPathEffect1.get()); }}, {0, 32, 0, 0, - [](DisplayListBuilder& b) { - b.setPathEffect(kTestPathEffect2.get()); - }}, - {0, 0, 0, 0, - [](DisplayListBuilder& b) { b.setPathEffect(nullptr); }}, + [](DlOpReceiver& r) { r.setPathEffect(kTestPathEffect2.get()); }}, + {0, 0, 0, 0, [](DlOpReceiver& r) { r.setPathEffect(nullptr); }}, }}, {"SetMaskFilter", { {0, 32, 0, 0, - [](DisplayListBuilder& b) { b.setMaskFilter(&kTestMaskFilter1); }}, + [](DlOpReceiver& r) { r.setMaskFilter(&kTestMaskFilter1); }}, {0, 32, 0, 0, - [](DisplayListBuilder& b) { b.setMaskFilter(&kTestMaskFilter2); }}, + [](DlOpReceiver& r) { r.setMaskFilter(&kTestMaskFilter2); }}, {0, 32, 0, 0, - [](DisplayListBuilder& b) { b.setMaskFilter(&kTestMaskFilter3); }}, + [](DlOpReceiver& r) { r.setMaskFilter(&kTestMaskFilter3); }}, {0, 32, 0, 0, - [](DisplayListBuilder& b) { b.setMaskFilter(&kTestMaskFilter4); }}, + [](DlOpReceiver& r) { r.setMaskFilter(&kTestMaskFilter4); }}, {0, 32, 0, 0, - [](DisplayListBuilder& b) { b.setMaskFilter(&kTestMaskFilter5); }}, - {0, 0, 0, 0, - [](DisplayListBuilder& b) { b.setMaskFilter(nullptr); }}, + [](DlOpReceiver& r) { r.setMaskFilter(&kTestMaskFilter5); }}, + {0, 0, 0, 0, [](DlOpReceiver& r) { r.setMaskFilter(nullptr); }}, }}, }; } @@ -305,13 +249,13 @@ std::vector CreateAllSaveRestoreOps() { {"Save(Layer)+Restore", { {5, 112, 5, 112, - [](DisplayListBuilder& b) { - b.saveLayer(nullptr, SaveLayerOptions::kNoAttributes, + [](DlOpReceiver& r) { + r.saveLayer(nullptr, SaveLayerOptions::kNoAttributes, &kTestCFImageFilter1); - b.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true); - b.drawRect({5, 5, 15, 15}); - b.drawRect({10, 10, 20, 20}); - b.restore(); + r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true); + r.drawRect({5, 5, 15, 15}); + r.drawRect({10, 10, 20, 20}); + r.restore(); }}, // There are many reasons that save and restore can elide content, // including whether or not there are any draw operations between @@ -321,80 +265,80 @@ std::vector CreateAllSaveRestoreOps() { // cases we include at least one clip operation and 2 overlapping // rendering primitives between each save/restore pair. {5, 96, 5, 96, - [](DisplayListBuilder& b) { - b.save(); - b.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true); - b.drawRect({5, 5, 15, 15}); - b.drawRect({10, 10, 20, 20}); - b.restore(); + [](DlOpReceiver& r) { + r.save(); + r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true); + r.drawRect({5, 5, 15, 15}); + r.drawRect({10, 10, 20, 20}); + r.restore(); }}, {5, 96, 5, 96, - [](DisplayListBuilder& b) { - b.saveLayer(nullptr, false); - b.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true); - b.drawRect({5, 5, 15, 15}); - b.drawRect({10, 10, 20, 20}); - b.restore(); + [](DlOpReceiver& r) { + r.saveLayer(nullptr, SaveLayerOptions::kNoAttributes); + r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true); + r.drawRect({5, 5, 15, 15}); + r.drawRect({10, 10, 20, 20}); + r.restore(); }}, {5, 96, 5, 96, - [](DisplayListBuilder& b) { - b.saveLayer(nullptr, true); - b.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true); - b.drawRect({5, 5, 15, 15}); - b.drawRect({10, 10, 20, 20}); - b.restore(); + [](DlOpReceiver& r) { + r.saveLayer(nullptr, SaveLayerOptions::kWithAttributes); + r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true); + r.drawRect({5, 5, 15, 15}); + r.drawRect({10, 10, 20, 20}); + r.restore(); }}, {5, 112, 5, 112, - [](DisplayListBuilder& b) { - b.saveLayer(&kTestBounds, false); - b.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true); - b.drawRect({5, 5, 15, 15}); - b.drawRect({10, 10, 20, 20}); - b.restore(); + [](DlOpReceiver& r) { + r.saveLayer(&kTestBounds, SaveLayerOptions::kNoAttributes); + r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true); + r.drawRect({5, 5, 15, 15}); + r.drawRect({10, 10, 20, 20}); + r.restore(); }}, {5, 112, 5, 112, - [](DisplayListBuilder& b) { - b.saveLayer(&kTestBounds, true); - b.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true); - b.drawRect({5, 5, 15, 15}); - b.drawRect({10, 10, 20, 20}); - b.restore(); + [](DlOpReceiver& r) { + r.saveLayer(&kTestBounds, SaveLayerOptions::kWithAttributes); + r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true); + r.drawRect({5, 5, 15, 15}); + r.drawRect({10, 10, 20, 20}); + r.restore(); }}, // backdrop variants - using the TestCFImageFilter because it can be // reconstituted in the DL->SkCanvas->DL stream - // {5, 104, 5, 104, [](DisplayListBuilder& b) { - // b.saveLayer(nullptr, SaveLayerOptions::kNoAttributes, - // &kTestCFImageFilter1); b.clipRect({0, 0, 25, 25}, - // SkClipOp::kIntersect, true); b.drawRect({5, 5, 15, 15}); - // b.drawRect({10, 10, 20, 20}); - // b.restore(); + // {5, 104, 5, 104, [](DlOpReceiver& r) { + // r.saveLayer(nullptr, SaveLayerOptions::kNoAttributes, + // &kTestCFImageFilter1); r.clipRect({0, 0, 25, 25}, + // SkClipOp::kIntersect, true); r.drawRect({5, 5, 15, 15}); + // r.drawRect({10, 10, 20, 20}); + // r.restore(); // }}, {5, 112, 5, 112, - [](DisplayListBuilder& b) { - b.saveLayer(nullptr, SaveLayerOptions::kWithAttributes, + [](DlOpReceiver& r) { + r.saveLayer(nullptr, SaveLayerOptions::kWithAttributes, &kTestCFImageFilter1); - b.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true); - b.drawRect({5, 5, 15, 15}); - b.drawRect({10, 10, 20, 20}); - b.restore(); + r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true); + r.drawRect({5, 5, 15, 15}); + r.drawRect({10, 10, 20, 20}); + r.restore(); }}, {5, 128, 5, 128, - [](DisplayListBuilder& b) { - b.saveLayer(&kTestBounds, SaveLayerOptions::kNoAttributes, + [](DlOpReceiver& r) { + r.saveLayer(&kTestBounds, SaveLayerOptions::kNoAttributes, &kTestCFImageFilter1); - b.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true); - b.drawRect({5, 5, 15, 15}); - b.drawRect({10, 10, 20, 20}); - b.restore(); + r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true); + r.drawRect({5, 5, 15, 15}); + r.drawRect({10, 10, 20, 20}); + r.restore(); }}, {5, 128, 5, 128, - [](DisplayListBuilder& b) { - b.saveLayer(&kTestBounds, SaveLayerOptions::kWithAttributes, + [](DlOpReceiver& r) { + r.saveLayer(&kTestBounds, SaveLayerOptions::kWithAttributes, &kTestCFImageFilter1); - b.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true); - b.drawRect({5, 5, 15, 15}); - b.drawRect({10, 10, 20, 20}); - b.restore(); + r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true); + r.drawRect({5, 5, 15, 15}); + r.drawRect({10, 10, 20, 20}); + r.restore(); }}, }}, }; @@ -405,65 +349,61 @@ std::vector CreateAllTransformOps() { {"Translate", { // cv.translate(0, 0) is ignored - {1, 16, 1, 16, [](DisplayListBuilder& b) { b.translate(10, 10); }}, - {1, 16, 1, 16, [](DisplayListBuilder& b) { b.translate(10, 15); }}, - {1, 16, 1, 16, [](DisplayListBuilder& b) { b.translate(15, 10); }}, - {0, 0, 0, 0, [](DisplayListBuilder& b) { b.translate(0, 0); }}, + {1, 16, 1, 16, [](DlOpReceiver& r) { r.translate(10, 10); }}, + {1, 16, 1, 16, [](DlOpReceiver& r) { r.translate(10, 15); }}, + {1, 16, 1, 16, [](DlOpReceiver& r) { r.translate(15, 10); }}, + {0, 0, 0, 0, [](DlOpReceiver& r) { r.translate(0, 0); }}, }}, {"Scale", { // cv.scale(1, 1) is ignored - {1, 16, 1, 16, [](DisplayListBuilder& b) { b.scale(2, 2); }}, - {1, 16, 1, 16, [](DisplayListBuilder& b) { b.scale(2, 3); }}, - {1, 16, 1, 16, [](DisplayListBuilder& b) { b.scale(3, 2); }}, - {0, 0, 0, 0, [](DisplayListBuilder& b) { b.scale(1, 1); }}, + {1, 16, 1, 16, [](DlOpReceiver& r) { r.scale(2, 2); }}, + {1, 16, 1, 16, [](DlOpReceiver& r) { r.scale(2, 3); }}, + {1, 16, 1, 16, [](DlOpReceiver& r) { r.scale(3, 2); }}, + {0, 0, 0, 0, [](DlOpReceiver& r) { r.scale(1, 1); }}, }}, {"Rotate", { // cv.rotate(0) is ignored, otherwise expressed as concat(rotmatrix) - {1, 8, 1, 32, [](DisplayListBuilder& b) { b.rotate(30); }}, - {1, 8, 1, 32, [](DisplayListBuilder& b) { b.rotate(45); }}, - {0, 0, 0, 0, [](DisplayListBuilder& b) { b.rotate(0); }}, - {0, 0, 0, 0, [](DisplayListBuilder& b) { b.rotate(360); }}, + {1, 8, 1, 32, [](DlOpReceiver& r) { r.rotate(30); }}, + {1, 8, 1, 32, [](DlOpReceiver& r) { r.rotate(45); }}, + {0, 0, 0, 0, [](DlOpReceiver& r) { r.rotate(0); }}, + {0, 0, 0, 0, [](DlOpReceiver& r) { r.rotate(360); }}, }}, {"Skew", { // cv.skew(0, 0) is ignored, otherwise expressed as // concat(skewmatrix) - {1, 16, 1, 32, [](DisplayListBuilder& b) { b.skew(0.1, 0.1); }}, - {1, 16, 1, 32, [](DisplayListBuilder& b) { b.skew(0.1, 0.2); }}, - {1, 16, 1, 32, [](DisplayListBuilder& b) { b.skew(0.2, 0.1); }}, - {0, 0, 0, 0, [](DisplayListBuilder& b) { b.skew(0, 0); }}, + {1, 16, 1, 32, [](DlOpReceiver& r) { r.skew(0.1, 0.1); }}, + {1, 16, 1, 32, [](DlOpReceiver& r) { r.skew(0.1, 0.2); }}, + {1, 16, 1, 32, [](DlOpReceiver& r) { r.skew(0.2, 0.1); }}, + {0, 0, 0, 0, [](DlOpReceiver& r) { r.skew(0, 0); }}, }}, {"Transform2DAffine", { {1, 32, 1, 32, - [](DisplayListBuilder& b) { - b.transform2DAffine(0, 1, 12, 1, 0, 33); - }}, - // b.transform(identity) is ignored + [](DlOpReceiver& r) { r.transform2DAffine(0, 1, 12, 1, 0, 33); }}, + // r.transform(identity) is ignored {0, 0, 0, 0, - [](DisplayListBuilder& b) { - b.transform2DAffine(1, 0, 0, 0, 1, 0); - }}, + [](DlOpReceiver& r) { r.transform2DAffine(1, 0, 0, 0, 1, 0); }}, }}, {"TransformFullPerspective", { {1, 72, 1, 72, - [](DisplayListBuilder& b) { - b.transformFullPerspective(0, 1, 0, 12, 1, 0, 0, 33, 3, 2, 5, 29, + [](DlOpReceiver& r) { + r.transformFullPerspective(0, 1, 0, 12, 1, 0, 0, 33, 3, 2, 5, 29, 0, 0, 0, 12); }}, - // b.transform(2D affine) is reduced to 2x3 + // r.transform(2D affine) is reduced to 2x3 {1, 32, 1, 32, - [](DisplayListBuilder& b) { - b.transformFullPerspective(2, 1, 0, 4, 1, 3, 0, 5, 0, 0, 1, 0, 0, + [](DlOpReceiver& r) { + r.transformFullPerspective(2, 1, 0, 4, 1, 3, 0, 5, 0, 0, 1, 0, 0, 0, 0, 1); }}, - // b.transform(identity) is ignored + // r.transform(identity) is ignored {0, 0, 0, 0, - [](DisplayListBuilder& b) { - b.transformFullPerspective(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, + [](DlOpReceiver& r) { + r.transformFullPerspective(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }}, }}, @@ -475,86 +415,86 @@ std::vector CreateAllClipOps() { {"ClipRect", { {1, 24, 1, 24, - [](DisplayListBuilder& b) { - b.clipRect(kTestBounds, DlCanvas::ClipOp::kIntersect, true); + [](DlOpReceiver& r) { + r.clipRect(kTestBounds, DlCanvas::ClipOp::kIntersect, true); }}, {1, 24, 1, 24, - [](DisplayListBuilder& b) { - b.clipRect(kTestBounds.makeOffset(1, 1), + [](DlOpReceiver& r) { + r.clipRect(kTestBounds.makeOffset(1, 1), DlCanvas::ClipOp::kIntersect, true); }}, {1, 24, 1, 24, - [](DisplayListBuilder& b) { - b.clipRect(kTestBounds, DlCanvas::ClipOp::kIntersect, false); + [](DlOpReceiver& r) { + r.clipRect(kTestBounds, DlCanvas::ClipOp::kIntersect, false); }}, {1, 24, 1, 24, - [](DisplayListBuilder& b) { - b.clipRect(kTestBounds, DlCanvas::ClipOp::kDifference, true); + [](DlOpReceiver& r) { + r.clipRect(kTestBounds, DlCanvas::ClipOp::kDifference, true); }}, {1, 24, 1, 24, - [](DisplayListBuilder& b) { - b.clipRect(kTestBounds, DlCanvas::ClipOp::kDifference, false); + [](DlOpReceiver& r) { + r.clipRect(kTestBounds, DlCanvas::ClipOp::kDifference, false); }}, }}, {"ClipRRect", { {1, 64, 1, 64, - [](DisplayListBuilder& b) { - b.clipRRect(kTestRRect, DlCanvas::ClipOp::kIntersect, true); + [](DlOpReceiver& r) { + r.clipRRect(kTestRRect, DlCanvas::ClipOp::kIntersect, true); }}, {1, 64, 1, 64, - [](DisplayListBuilder& b) { - b.clipRRect(kTestRRect.makeOffset(1, 1), + [](DlOpReceiver& r) { + r.clipRRect(kTestRRect.makeOffset(1, 1), DlCanvas::ClipOp::kIntersect, true); }}, {1, 64, 1, 64, - [](DisplayListBuilder& b) { - b.clipRRect(kTestRRect, DlCanvas::ClipOp::kIntersect, false); + [](DlOpReceiver& r) { + r.clipRRect(kTestRRect, DlCanvas::ClipOp::kIntersect, false); }}, {1, 64, 1, 64, - [](DisplayListBuilder& b) { - b.clipRRect(kTestRRect, DlCanvas::ClipOp::kDifference, true); + [](DlOpReceiver& r) { + r.clipRRect(kTestRRect, DlCanvas::ClipOp::kDifference, true); }}, {1, 64, 1, 64, - [](DisplayListBuilder& b) { - b.clipRRect(kTestRRect, DlCanvas::ClipOp::kDifference, false); + [](DlOpReceiver& r) { + r.clipRRect(kTestRRect, DlCanvas::ClipOp::kDifference, false); }}, }}, {"ClipPath", { {1, 24, 1, 24, - [](DisplayListBuilder& b) { - b.clipPath(kTestPath1, DlCanvas::ClipOp::kIntersect, true); + [](DlOpReceiver& r) { + r.clipPath(kTestPath1, DlCanvas::ClipOp::kIntersect, true); }}, {1, 24, 1, 24, - [](DisplayListBuilder& b) { - b.clipPath(kTestPath2, DlCanvas::ClipOp::kIntersect, true); + [](DlOpReceiver& r) { + r.clipPath(kTestPath2, DlCanvas::ClipOp::kIntersect, true); }}, {1, 24, 1, 24, - [](DisplayListBuilder& b) { - b.clipPath(kTestPath3, DlCanvas::ClipOp::kIntersect, true); + [](DlOpReceiver& r) { + r.clipPath(kTestPath3, DlCanvas::ClipOp::kIntersect, true); }}, {1, 24, 1, 24, - [](DisplayListBuilder& b) { - b.clipPath(kTestPath1, DlCanvas::ClipOp::kIntersect, false); + [](DlOpReceiver& r) { + r.clipPath(kTestPath1, DlCanvas::ClipOp::kIntersect, false); }}, {1, 24, 1, 24, - [](DisplayListBuilder& b) { - b.clipPath(kTestPath1, DlCanvas::ClipOp::kDifference, true); + [](DlOpReceiver& r) { + r.clipPath(kTestPath1, DlCanvas::ClipOp::kDifference, true); }}, {1, 24, 1, 24, - [](DisplayListBuilder& b) { - b.clipPath(kTestPath1, DlCanvas::ClipOp::kDifference, false); + [](DlOpReceiver& r) { + r.clipPath(kTestPath1, DlCanvas::ClipOp::kDifference, false); }}, // clipPath(rect) becomes clipRect {1, 24, 1, 24, - [](DisplayListBuilder& b) { - b.clipPath(kTestPathRect, DlCanvas::ClipOp::kIntersect, true); + [](DlOpReceiver& r) { + r.clipPath(kTestPathRect, DlCanvas::ClipOp::kIntersect, true); }}, // clipPath(oval) becomes clipRRect {1, 64, 1, 64, - [](DisplayListBuilder& b) { - b.clipPath(kTestPathOval, DlCanvas::ClipOp::kIntersect, true); + [](DlOpReceiver& r) { + r.clipPath(kTestPathOval, DlCanvas::ClipOp::kIntersect, true); }}, }}, }; @@ -564,268 +504,256 @@ std::vector CreateAllRenderingOps() { return { {"DrawPaint", { - {1, 8, 1, 8, [](DisplayListBuilder& b) { b.drawPaint(); }}, + {1, 8, 1, 8, [](DlOpReceiver& r) { r.drawPaint(); }}, }}, {"DrawColor", { // cv.drawColor becomes cv.drawPaint(paint) {1, 16, 1, 24, - [](DisplayListBuilder& b) { - b.drawColor(SK_ColorBLUE, DlBlendMode::kSrcIn); + [](DlOpReceiver& r) { + r.drawColor(SK_ColorBLUE, DlBlendMode::kSrcIn); }}, {1, 16, 1, 24, - [](DisplayListBuilder& b) { - b.drawColor(SK_ColorBLUE, DlBlendMode::kDstIn); + [](DlOpReceiver& r) { + r.drawColor(SK_ColorBLUE, DlBlendMode::kDstIn); }}, {1, 16, 1, 24, - [](DisplayListBuilder& b) { - b.drawColor(SK_ColorCYAN, DlBlendMode::kSrcIn); + [](DlOpReceiver& r) { + r.drawColor(SK_ColorCYAN, DlBlendMode::kSrcIn); }}, }}, {"DrawLine", { {1, 24, 1, 24, - [](DisplayListBuilder& b) { - b.drawLine({0, 0}, {10, 10}); + [](DlOpReceiver& r) { + r.drawLine({0, 0}, {10, 10}); }}, {1, 24, 1, 24, - [](DisplayListBuilder& b) { - b.drawLine({0, 1}, {10, 10}); + [](DlOpReceiver& r) { + r.drawLine({0, 1}, {10, 10}); }}, {1, 24, 1, 24, - [](DisplayListBuilder& b) { - b.drawLine({0, 0}, {20, 10}); + [](DlOpReceiver& r) { + r.drawLine({0, 0}, {20, 10}); }}, {1, 24, 1, 24, - [](DisplayListBuilder& b) { - b.drawLine({0, 0}, {10, 20}); + [](DlOpReceiver& r) { + r.drawLine({0, 0}, {10, 20}); }}, }}, {"DrawRect", { {1, 24, 1, 24, - [](DisplayListBuilder& b) { - b.drawRect({0, 0, 10, 10}); + [](DlOpReceiver& r) { + r.drawRect({0, 0, 10, 10}); }}, {1, 24, 1, 24, - [](DisplayListBuilder& b) { - b.drawRect({0, 1, 10, 10}); + [](DlOpReceiver& r) { + r.drawRect({0, 1, 10, 10}); }}, {1, 24, 1, 24, - [](DisplayListBuilder& b) { - b.drawRect({0, 0, 20, 10}); + [](DlOpReceiver& r) { + r.drawRect({0, 0, 20, 10}); }}, {1, 24, 1, 24, - [](DisplayListBuilder& b) { - b.drawRect({0, 0, 10, 20}); + [](DlOpReceiver& r) { + r.drawRect({0, 0, 10, 20}); }}, }}, {"DrawOval", { {1, 24, 1, 24, - [](DisplayListBuilder& b) { - b.drawOval({0, 0, 10, 10}); + [](DlOpReceiver& r) { + r.drawOval({0, 0, 10, 10}); }}, {1, 24, 1, 24, - [](DisplayListBuilder& b) { - b.drawOval({0, 1, 10, 10}); + [](DlOpReceiver& r) { + r.drawOval({0, 1, 10, 10}); }}, {1, 24, 1, 24, - [](DisplayListBuilder& b) { - b.drawOval({0, 0, 20, 10}); + [](DlOpReceiver& r) { + r.drawOval({0, 0, 20, 10}); }}, {1, 24, 1, 24, - [](DisplayListBuilder& b) { - b.drawOval({0, 0, 10, 20}); + [](DlOpReceiver& r) { + r.drawOval({0, 0, 10, 20}); }}, }}, {"DrawCircle", { // cv.drawCircle becomes cv.drawOval {1, 16, 1, 24, - [](DisplayListBuilder& b) { - b.drawCircle({0, 0}, 10); + [](DlOpReceiver& r) { + r.drawCircle({0, 0}, 10); }}, {1, 16, 1, 24, - [](DisplayListBuilder& b) { - b.drawCircle({0, 5}, 10); + [](DlOpReceiver& r) { + r.drawCircle({0, 5}, 10); }}, {1, 16, 1, 24, - [](DisplayListBuilder& b) { - b.drawCircle({0, 0}, 20); + [](DlOpReceiver& r) { + r.drawCircle({0, 0}, 20); }}, }}, {"DrawRRect", { + {1, 56, 1, 56, [](DlOpReceiver& r) { r.drawRRect(kTestRRect); }}, {1, 56, 1, 56, - [](DisplayListBuilder& b) { b.drawRRect(kTestRRect); }}, - {1, 56, 1, 56, - [](DisplayListBuilder& b) { - b.drawRRect(kTestRRect.makeOffset(5, 5)); - }}, + [](DlOpReceiver& r) { r.drawRRect(kTestRRect.makeOffset(5, 5)); }}, }}, {"DrawDRRect", { {1, 112, 1, 112, - [](DisplayListBuilder& b) { - b.drawDRRect(kTestRRect, kTestInnerRRect); - }}, + [](DlOpReceiver& r) { r.drawDRRect(kTestRRect, kTestInnerRRect); }}, {1, 112, 1, 112, - [](DisplayListBuilder& b) { - b.drawDRRect(kTestRRect.makeOffset(5, 5), + [](DlOpReceiver& r) { + r.drawDRRect(kTestRRect.makeOffset(5, 5), kTestInnerRRect.makeOffset(4, 4)); }}, }}, {"DrawPath", { - {1, 24, 1, 24, - [](DisplayListBuilder& b) { b.drawPath(kTestPath1); }}, - {1, 24, 1, 24, - [](DisplayListBuilder& b) { b.drawPath(kTestPath2); }}, - {1, 24, 1, 24, - [](DisplayListBuilder& b) { b.drawPath(kTestPath3); }}, - {1, 24, 1, 24, - [](DisplayListBuilder& b) { b.drawPath(kTestPathRect); }}, - {1, 24, 1, 24, - [](DisplayListBuilder& b) { b.drawPath(kTestPathOval); }}, + {1, 24, 1, 24, [](DlOpReceiver& r) { r.drawPath(kTestPath1); }}, + {1, 24, 1, 24, [](DlOpReceiver& r) { r.drawPath(kTestPath2); }}, + {1, 24, 1, 24, [](DlOpReceiver& r) { r.drawPath(kTestPath3); }}, + {1, 24, 1, 24, [](DlOpReceiver& r) { r.drawPath(kTestPathRect); }}, + {1, 24, 1, 24, [](DlOpReceiver& r) { r.drawPath(kTestPathOval); }}, }}, {"DrawArc", { {1, 32, 1, 32, - [](DisplayListBuilder& b) { - b.drawArc(kTestBounds, 45, 270, false); - }}, + [](DlOpReceiver& r) { r.drawArc(kTestBounds, 45, 270, false); }}, {1, 32, 1, 32, - [](DisplayListBuilder& b) { - b.drawArc(kTestBounds.makeOffset(1, 1), 45, 270, false); + [](DlOpReceiver& r) { + r.drawArc(kTestBounds.makeOffset(1, 1), 45, 270, false); }}, {1, 32, 1, 32, - [](DisplayListBuilder& b) { - b.drawArc(kTestBounds, 30, 270, false); - }}, + [](DlOpReceiver& r) { r.drawArc(kTestBounds, 30, 270, false); }}, {1, 32, 1, 32, - [](DisplayListBuilder& b) { - b.drawArc(kTestBounds, 45, 260, false); - }}, + [](DlOpReceiver& r) { r.drawArc(kTestBounds, 45, 260, false); }}, {1, 32, 1, 32, - [](DisplayListBuilder& b) { - b.drawArc(kTestBounds, 45, 270, true); - }}, + [](DlOpReceiver& r) { r.drawArc(kTestBounds, 45, 270, true); }}, }}, {"DrawPoints", { {1, 8 + TestPointCount * 8, 1, 8 + TestPointCount * 8, - [](DisplayListBuilder& b) { - b.drawPoints(DlCanvas::PointMode::kPoints, TestPointCount, + [](DlOpReceiver& r) { + r.drawPoints(DlCanvas::PointMode::kPoints, TestPointCount, TestPoints); }}, {1, 8 + (TestPointCount - 1) * 8, 1, 8 + (TestPointCount - 1) * 8, - [](DisplayListBuilder& b) { - b.drawPoints(DlCanvas::PointMode::kPoints, TestPointCount - 1, + [](DlOpReceiver& r) { + r.drawPoints(DlCanvas::PointMode::kPoints, TestPointCount - 1, TestPoints); }}, {1, 8 + TestPointCount * 8, 1, 8 + TestPointCount * 8, - [](DisplayListBuilder& b) { - b.drawPoints(DlCanvas::PointMode::kLines, TestPointCount, + [](DlOpReceiver& r) { + r.drawPoints(DlCanvas::PointMode::kLines, TestPointCount, TestPoints); }}, {1, 8 + TestPointCount * 8, 1, 8 + TestPointCount * 8, - [](DisplayListBuilder& b) { - b.drawPoints(DlCanvas::PointMode::kPolygon, TestPointCount, + [](DlOpReceiver& r) { + r.drawPoints(DlCanvas::PointMode::kPolygon, TestPointCount, TestPoints); }}, }}, {"DrawVertices", { {1, 112, 1, 16, - [](DisplayListBuilder& b) { - b.drawVertices(TestVertices1, DlBlendMode::kSrcIn); + [](DlOpReceiver& r) { + r.drawVertices(TestVertices1.get(), DlBlendMode::kSrcIn); }}, {1, 112, 1, 16, - [](DisplayListBuilder& b) { - b.drawVertices(TestVertices1, DlBlendMode::kDstIn); + [](DlOpReceiver& r) { + r.drawVertices(TestVertices1.get(), DlBlendMode::kDstIn); }}, {1, 112, 1, 16, - [](DisplayListBuilder& b) { - b.drawVertices(TestVertices2, DlBlendMode::kSrcIn); + [](DlOpReceiver& r) { + r.drawVertices(TestVertices2.get(), DlBlendMode::kSrcIn); }}, }}, {"DrawImage", { {1, 24, -1, 48, - [](DisplayListBuilder& b) { - b.drawImage(TestImage1, {10, 10}, kNearestSampling, false); + [](DlOpReceiver& r) { + r.drawImage(TestImage1, {10, 10}, kNearestSampling, false); }}, {1, 24, -1, 48, - [](DisplayListBuilder& b) { - b.drawImage(TestImage1, {10, 10}, kNearestSampling, true); + [](DlOpReceiver& r) { + r.drawImage(TestImage1, {10, 10}, kNearestSampling, true); }}, {1, 24, -1, 48, - [](DisplayListBuilder& b) { - b.drawImage(TestImage1, {20, 10}, kNearestSampling, false); + [](DlOpReceiver& r) { + r.drawImage(TestImage1, {20, 10}, kNearestSampling, false); }}, {1, 24, -1, 48, - [](DisplayListBuilder& b) { - b.drawImage(TestImage1, {10, 20}, kNearestSampling, false); + [](DlOpReceiver& r) { + r.drawImage(TestImage1, {10, 20}, kNearestSampling, false); }}, {1, 24, -1, 48, - [](DisplayListBuilder& b) { - b.drawImage(TestImage1, {10, 10}, kLinearSampling, false); + [](DlOpReceiver& r) { + r.drawImage(TestImage1, {10, 10}, kLinearSampling, false); }}, {1, 24, -1, 48, - [](DisplayListBuilder& b) { - b.drawImage(TestImage2, {10, 10}, kNearestSampling, false); + [](DlOpReceiver& r) { + r.drawImage(TestImage2, {10, 10}, kNearestSampling, false); }}, {1, 24, -1, 48, - [](DisplayListBuilder& b) { + [](DlOpReceiver& r) { auto dl_image = DlImage::Make(TestSkImage); - b.drawImage(dl_image, {10, 10}, kNearestSampling, false); + r.drawImage(dl_image, {10, 10}, kNearestSampling, false); }}, }}, {"DrawImageRect", { {1, 56, -1, 80, - [](DisplayListBuilder& b) { - b.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, - kNearestSampling, false); + [](DlOpReceiver& r) { + r.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, + kNearestSampling, false, + SkCanvas::kFast_SrcRectConstraint); }}, {1, 56, -1, 80, - [](DisplayListBuilder& b) { - b.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, - kNearestSampling, true); + [](DlOpReceiver& r) { + r.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, + kNearestSampling, true, + SkCanvas::kFast_SrcRectConstraint); }}, {1, 56, -1, 80, - [](DisplayListBuilder& b) { - b.drawImageRect( - TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, - kNearestSampling, false, - SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint); + [](DlOpReceiver& r) { + r.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, + kNearestSampling, false, + SkCanvas::kStrict_SrcRectConstraint); }}, {1, 56, -1, 80, - [](DisplayListBuilder& b) { - b.drawImageRect(TestImage1, {10, 10, 25, 20}, {10, 10, 80, 80}, - kNearestSampling, false); + [](DlOpReceiver& r) { + r.drawImageRect(TestImage1, {10, 10, 25, 20}, {10, 10, 80, 80}, + kNearestSampling, false, + SkCanvas::kFast_SrcRectConstraint); }}, {1, 56, -1, 80, - [](DisplayListBuilder& b) { - b.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 85, 80}, - kNearestSampling, false); + [](DlOpReceiver& r) { + r.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 85, 80}, + kNearestSampling, false, + SkCanvas::kFast_SrcRectConstraint); }}, {1, 56, -1, 80, - [](DisplayListBuilder& b) { - b.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, - kLinearSampling, false); + [](DlOpReceiver& r) { + r.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, + kLinearSampling, false, + SkCanvas::kFast_SrcRectConstraint); }}, {1, 56, -1, 80, - [](DisplayListBuilder& b) { - b.drawImageRect(TestImage2, {10, 10, 15, 15}, {10, 10, 80, 80}, - kNearestSampling, false); + [](DlOpReceiver& r) { + r.drawImageRect(TestImage2, {10, 10, 15, 15}, {10, 10, 80, 80}, + kNearestSampling, false, + SkCanvas::kFast_SrcRectConstraint); }}, {1, 56, -1, 80, - [](DisplayListBuilder& b) { + [](DlOpReceiver& r) { auto dl_image = DlImage::Make(TestSkImage); - b.drawImageRect(dl_image, {10, 10, 15, 15}, {10, 10, 80, 80}, - kNearestSampling, false); + r.drawImageRect(dl_image, {10, 10, 15, 15}, {10, 10, 80, 80}, + kNearestSampling, false, + SkCanvas::kFast_SrcRectConstraint); }}, }}, {"DrawImageNine", @@ -833,124 +761,124 @@ std::vector CreateAllRenderingOps() { // SkCanvas::drawImageNine is immediately converted to // drawImageLattice {1, 48, -1, 80, - [](DisplayListBuilder& b) { - b.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, + [](DlOpReceiver& r) { + r.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, DlFilterMode::kNearest, false); }}, {1, 48, -1, 80, - [](DisplayListBuilder& b) { - b.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, + [](DlOpReceiver& r) { + r.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, DlFilterMode::kNearest, true); }}, {1, 48, -1, 80, - [](DisplayListBuilder& b) { - b.drawImageNine(TestImage1, {10, 10, 25, 20}, {10, 10, 80, 80}, + [](DlOpReceiver& r) { + r.drawImageNine(TestImage1, {10, 10, 25, 20}, {10, 10, 80, 80}, DlFilterMode::kNearest, false); }}, {1, 48, -1, 80, - [](DisplayListBuilder& b) { - b.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 85, 80}, + [](DlOpReceiver& r) { + r.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 85, 80}, DlFilterMode::kNearest, false); }}, {1, 48, -1, 80, - [](DisplayListBuilder& b) { - b.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, + [](DlOpReceiver& r) { + r.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, DlFilterMode::kLinear, false); }}, {1, 48, -1, 80, - [](DisplayListBuilder& b) { - b.drawImageNine(TestImage2, {10, 10, 15, 15}, {10, 10, 80, 80}, + [](DlOpReceiver& r) { + r.drawImageNine(TestImage2, {10, 10, 15, 15}, {10, 10, 80, 80}, DlFilterMode::kNearest, false); }}, {1, 48, -1, 80, - [](DisplayListBuilder& b) { + [](DlOpReceiver& r) { auto dl_image = DlImage::Make(TestSkImage); - b.drawImageNine(dl_image, {10, 10, 15, 15}, {10, 10, 80, 80}, + r.drawImageNine(dl_image, {10, 10, 15, 15}, {10, 10, 80, 80}, DlFilterMode::kNearest, false); }}, }}, {"DrawAtlas", { {1, 48 + 32 + 8, -1, 48 + 32 + 32, - [](DisplayListBuilder& b) { + [](DlOpReceiver& r) { 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, + r.drawAtlas(TestImage1, xforms, texs, nullptr, 2, DlBlendMode::kSrcIn, kNearestSampling, nullptr, false); }}, {1, 48 + 32 + 8, -1, 48 + 32 + 32, - [](DisplayListBuilder& b) { + [](DlOpReceiver& r) { 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, + r.drawAtlas(TestImage1, xforms, texs, nullptr, 2, DlBlendMode::kSrcIn, kNearestSampling, nullptr, true); }}, {1, 48 + 32 + 8, -1, 48 + 32 + 32, - [](DisplayListBuilder& b) { + [](DlOpReceiver& r) { 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, + r.drawAtlas(TestImage1, xforms, texs, nullptr, 2, DlBlendMode::kSrcIn, kNearestSampling, nullptr, false); }}, {1, 48 + 32 + 8, -1, 48 + 32 + 32, - [](DisplayListBuilder& b) { + [](DlOpReceiver& r) { 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, + r.drawAtlas(TestImage1, xforms, texs, nullptr, 2, DlBlendMode::kSrcIn, kNearestSampling, nullptr, false); }}, {1, 48 + 32 + 8, -1, 48 + 32 + 32, - [](DisplayListBuilder& b) { + [](DlOpReceiver& r) { 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, + r.drawAtlas(TestImage1, xforms, texs, nullptr, 2, DlBlendMode::kSrcIn, kLinearSampling, nullptr, false); }}, {1, 48 + 32 + 8, -1, 48 + 32 + 32, - [](DisplayListBuilder& b) { + [](DlOpReceiver& r) { 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, + r.drawAtlas(TestImage1, xforms, texs, nullptr, 2, DlBlendMode::kDstIn, kNearestSampling, nullptr, false); }}, {1, 64 + 32 + 8, -1, 64 + 32 + 32, - [](DisplayListBuilder& b) { + [](DlOpReceiver& r) { static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}}; static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}}; static SkRect cull_rect = {0, 0, 200, 200}; - b.drawAtlas(TestImage2, xforms, texs, nullptr, 2, + r.drawAtlas(TestImage2, xforms, texs, nullptr, 2, DlBlendMode::kSrcIn, kNearestSampling, &cull_rect, false); }}, {1, 48 + 32 + 8 + 8, -1, 48 + 32 + 32 + 8, - [](DisplayListBuilder& b) { + [](DlOpReceiver& r) { static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}}; static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}}; static DlColor colors[] = {DlColor::kBlue(), DlColor::kGreen()}; - b.drawAtlas(TestImage1, xforms, texs, colors, 2, + r.drawAtlas(TestImage1, xforms, texs, colors, 2, DlBlendMode::kSrcIn, kNearestSampling, nullptr, false); }}, {1, 64 + 32 + 8 + 8, -1, 64 + 32 + 32 + 8, - [](DisplayListBuilder& b) { + [](DlOpReceiver& r) { static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}}; static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}}; static DlColor colors[] = {DlColor::kBlue(), DlColor::kGreen()}; static SkRect cull_rect = {0, 0, 200, 200}; - b.drawAtlas(TestImage1, xforms, texs, colors, 2, + r.drawAtlas(TestImage1, xforms, texs, colors, 2, DlBlendMode::kSrcIn, kNearestSampling, &cull_rect, false); }}, {1, 48 + 32 + 8, -1, 48 + 32 + 32, - [](DisplayListBuilder& b) { + [](DlOpReceiver& r) { auto dl_image = DlImage::Make(TestSkImage); static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}}; static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}}; - b.drawAtlas(dl_image, xforms, texs, nullptr, 2, + r.drawAtlas(dl_image, xforms, texs, nullptr, 2, DlBlendMode::kSrcIn, kNearestSampling, nullptr, false); }}, @@ -959,24 +887,26 @@ std::vector CreateAllRenderingOps() { { // cv.drawDL does not exist {1, 16, -1, 16, - [](DisplayListBuilder& b) { b.drawDisplayList(TestDisplayList1); }}, + [](DlOpReceiver& r) { r.drawDisplayList(TestDisplayList1, 1.0); }}, + {1, 16, -1, 16, + [](DlOpReceiver& r) { r.drawDisplayList(TestDisplayList1, 0.5); }}, {1, 16, -1, 16, - [](DisplayListBuilder& b) { b.drawDisplayList(TestDisplayList2); }}, + [](DlOpReceiver& r) { r.drawDisplayList(TestDisplayList2, 1.0); }}, {1, 16, -1, 16, - [](DisplayListBuilder& b) { - b.drawDisplayList(MakeTestDisplayList(10, 10, SK_ColorRED)); + [](DlOpReceiver& r) { + r.drawDisplayList(MakeTestDisplayList(10, 10, SK_ColorRED), 1.0); }}, }}, {"DrawTextBlob", { {1, 24, 1, 24, - [](DisplayListBuilder& b) { b.drawTextBlob(TestBlob1, 10, 10); }}, + [](DlOpReceiver& r) { r.drawTextBlob(TestBlob1, 10, 10); }}, {1, 24, 1, 24, - [](DisplayListBuilder& b) { b.drawTextBlob(TestBlob1, 20, 10); }}, + [](DlOpReceiver& r) { r.drawTextBlob(TestBlob1, 20, 10); }}, {1, 24, 1, 24, - [](DisplayListBuilder& b) { b.drawTextBlob(TestBlob1, 10, 20); }}, + [](DlOpReceiver& r) { r.drawTextBlob(TestBlob1, 10, 20); }}, {1, 24, 1, 24, - [](DisplayListBuilder& b) { b.drawTextBlob(TestBlob2, 10, 10); }}, + [](DlOpReceiver& r) { r.drawTextBlob(TestBlob2, 10, 10); }}, }}, // The -1 op counts below are to indicate to the framework not to test // SkCanvas conversion of these ops as it converts the operation into a @@ -988,28 +918,28 @@ std::vector CreateAllRenderingOps() { // cv shadows are turned into an opaque ShadowRec which is not // exposed {1, 32, -1, 32, - [](DisplayListBuilder& b) { - b.drawShadow(kTestPath1, SK_ColorGREEN, 1.0, false, 1.0); + [](DlOpReceiver& r) { + r.drawShadow(kTestPath1, SK_ColorGREEN, 1.0, false, 1.0); }}, {1, 32, -1, 32, - [](DisplayListBuilder& b) { - b.drawShadow(kTestPath2, SK_ColorGREEN, 1.0, false, 1.0); + [](DlOpReceiver& r) { + r.drawShadow(kTestPath2, SK_ColorGREEN, 1.0, false, 1.0); }}, {1, 32, -1, 32, - [](DisplayListBuilder& b) { - b.drawShadow(kTestPath1, SK_ColorBLUE, 1.0, false, 1.0); + [](DlOpReceiver& r) { + r.drawShadow(kTestPath1, SK_ColorBLUE, 1.0, false, 1.0); }}, {1, 32, -1, 32, - [](DisplayListBuilder& b) { - b.drawShadow(kTestPath1, SK_ColorGREEN, 2.0, false, 1.0); + [](DlOpReceiver& r) { + r.drawShadow(kTestPath1, SK_ColorGREEN, 2.0, false, 1.0); }}, {1, 32, -1, 32, - [](DisplayListBuilder& b) { - b.drawShadow(kTestPath1, SK_ColorGREEN, 1.0, true, 1.0); + [](DlOpReceiver& r) { + r.drawShadow(kTestPath1, SK_ColorGREEN, 1.0, true, 1.0); }}, {1, 32, -1, 32, - [](DisplayListBuilder& b) { - b.drawShadow(kTestPath1, SK_ColorGREEN, 1.0, false, 2.5); + [](DlOpReceiver& r) { + r.drawShadow(kTestPath1, SK_ColorGREEN, 1.0, false, 2.5); }}, }}, }; diff --git a/display_list/testing/dl_test_snippets.h b/display_list/testing/dl_test_snippets.h index 35278db751810..69bab82538bc5 100644 --- a/display_list/testing/dl_test_snippets.h +++ b/display_list/testing/dl_test_snippets.h @@ -20,7 +20,7 @@ sk_sp GetSampleDisplayList(); sk_sp GetSampleDisplayList(int ops); sk_sp GetSampleNestedDisplayList(); -typedef const std::function DlInvoker; +typedef const std::function DlInvoker; constexpr SkPoint kEndPoints[] = { {0, 0}, @@ -214,8 +214,7 @@ static std::shared_ptr TestVertices2 = static sk_sp MakeTestDisplayList(int w, int h, SkColor color) { DisplayListBuilder builder; - builder.setColor(color); - builder.drawRect(SkRect::MakeWH(w, h)); + builder.DrawRect(SkRect::MakeWH(w, h), DlPaint(color)); return builder.Build(); } static sk_sp TestDisplayList1 = @@ -271,13 +270,13 @@ struct DisplayListInvocation { // through an SkCanvas interface, comparable to |DisplayList.byte_count(). size_t sk_byte_count() { return sizeof(DisplayList) + sk_byte_count_; } - void Invoke(DisplayListBuilder& builder) { invoker(builder); } + void Invoke(DlOpReceiver& builder) { invoker(builder); } - sk_sp Build() { - DisplayListBuilder builder; - invoker(builder); - return builder.Build(); - } + // sk_sp Build() { + // DisplayListBuilder builder; + // invoker(builder.asReceiver()); + // return builder.Build(); + // } }; struct DisplayListInvocationGroup { diff --git a/display_list/types.h b/display_list/types.h index dbe04aa3983e9..b8737f5d1d336 100644 --- a/display_list/types.h +++ b/display_list/types.h @@ -28,5 +28,4 @@ #include "third_party/skia/include/effects/SkDashPathEffect.h" #include "third_party/skia/include/effects/SkDiscretePathEffect.h" #include "third_party/skia/include/gpu/GrTypes.h" -#include "third_party/skia/include/utils/SkShadowUtils.h" #endif // FLUTTER_DISPLAY_LIST_TYPES_H_ diff --git a/flow/layers/checkerboard_layertree_unittests.cc b/flow/layers/checkerboard_layertree_unittests.cc index d54abf924f921..7917b5eff3390 100644 --- a/flow/layers/checkerboard_layertree_unittests.cc +++ b/flow/layers/checkerboard_layertree_unittests.cc @@ -2,7 +2,6 @@ // 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_canvas_dispatcher.h" #include "flutter/flow/layers/clip_path_layer.h" #include "flutter/flow/layers/clip_rect_layer.h" #include "flutter/flow/layers/clip_rrect_layer.h" @@ -235,8 +234,8 @@ TEST_F(CheckerBoardLayerTest, PhysicalSaveLayerCheckBoard) { // The Fuchsia system compositor handles all elevated PhysicalShapeLayers and // their shadows , so we do not do any painting there. EXPECT_EQ(layer->paint_bounds(), - DisplayListCanvasDispatcher::ComputeShadowBounds( - layer_path, initial_elevation, 1.0f, SkMatrix())); + DlCanvas::ComputeShadowBounds(layer_path, initial_elevation, 1.0f, + SkMatrix())); EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(layer->elevation(), initial_elevation); diff --git a/flow/layers/clip_path_layer_unittests.cc b/flow/layers/clip_path_layer_unittests.cc index 4f07f8c8fa66c..1012a4ca72fee 100644 --- a/flow/layers/clip_path_layer_unittests.cc +++ b/flow/layers/clip_path_layer_unittests.cc @@ -424,7 +424,7 @@ TEST_F(ClipPathLayerTest, OpacityInheritancePainting) { { expected_builder.Translate(offset.fX, offset.fY); /* ClipRectLayer::Paint() */ { - expected_builder.save(); + expected_builder.Save(); expected_builder.ClipPath(layer_clip, ClipOp::kIntersect, true); /* child layer1 paint */ { expected_builder.DrawPath(path1, DlPaint().setAlpha(opacity_alpha)); @@ -472,25 +472,24 @@ TEST_F(ClipPathLayerTest, OpacityInheritanceSaveLayerPainting) { DisplayListBuilder expected_builder; /* OpacityLayer::Paint() */ { - expected_builder.save(); + expected_builder.Save(); { - expected_builder.translate(offset.fX, offset.fY); + expected_builder.Translate(offset.fX, offset.fY); /* ClipRectLayer::Paint() */ { - expected_builder.save(); - expected_builder.clipPath(layer_clip, ClipOp::kIntersect, true); - expected_builder.setColor(opacity_alpha << 24); - expected_builder.saveLayer(&children_bounds, true); + expected_builder.Save(); + expected_builder.ClipPath(layer_clip, ClipOp::kIntersect, true); + expected_builder.SaveLayer(&children_bounds, + &DlPaint().setAlpha(opacity_alpha)); /* child layer1 paint */ { - expected_builder.setColor(0xFF000000); - expected_builder.drawPath(path1); + expected_builder.DrawPath(path1, DlPaint()); } /* child layer2 paint */ { // - expected_builder.drawPath(path2); + expected_builder.DrawPath(path2, DlPaint()); } - expected_builder.restore(); + expected_builder.Restore(); } } - expected_builder.restore(); + expected_builder.Restore(); } opacity_layer->Paint(display_list_paint_context()); diff --git a/flow/layers/clip_rect_layer_unittests.cc b/flow/layers/clip_rect_layer_unittests.cc index 728e487c38856..6ddb9076ddce5 100644 --- a/flow/layers/clip_rect_layer_unittests.cc +++ b/flow/layers/clip_rect_layer_unittests.cc @@ -454,25 +454,24 @@ TEST_F(ClipRectLayerTest, OpacityInheritanceSaveLayerPainting) { DisplayListBuilder expected_builder; /* OpacityLayer::Paint() */ { - expected_builder.save(); + expected_builder.Save(); { - expected_builder.translate(offset.fX, offset.fY); + expected_builder.Translate(offset.fX, offset.fY); /* ClipRectLayer::Paint() */ { - expected_builder.save(); - expected_builder.clipRect(clip_rect, ClipOp::kIntersect, true); - expected_builder.setColor(opacity_alpha << 24); - expected_builder.saveLayer(&children_bounds, true); + expected_builder.Save(); + expected_builder.ClipRect(clip_rect, ClipOp::kIntersect, true); + expected_builder.SaveLayer(&children_bounds, + &DlPaint().setAlpha(opacity_alpha)); /* child layer1 paint */ { - expected_builder.setColor(0xFF000000); - expected_builder.drawPath(path1); + expected_builder.DrawPath(path1, DlPaint()); } /* child layer2 paint */ { // - expected_builder.drawPath(path2); + expected_builder.DrawPath(path2, DlPaint()); } - expected_builder.restore(); + expected_builder.Restore(); } } - expected_builder.restore(); + expected_builder.Restore(); } opacity_layer->Paint(display_list_paint_context()); diff --git a/flow/layers/clip_rrect_layer_unittests.cc b/flow/layers/clip_rrect_layer_unittests.cc index 9e789cee4f82b..75ca41c3e4863 100644 --- a/flow/layers/clip_rrect_layer_unittests.cc +++ b/flow/layers/clip_rrect_layer_unittests.cc @@ -467,25 +467,24 @@ TEST_F(ClipRRectLayerTest, OpacityInheritanceSaveLayerPainting) { DisplayListBuilder expected_builder; /* OpacityLayer::Paint() */ { - expected_builder.save(); + expected_builder.Save(); { - expected_builder.translate(offset.fX, offset.fY); + expected_builder.Translate(offset.fX, offset.fY); /* ClipRectLayer::Paint() */ { - expected_builder.save(); - expected_builder.clipRRect(clip_rrect, ClipOp::kIntersect, true); - expected_builder.setColor(opacity_alpha << 24); - expected_builder.saveLayer(&children_bounds, true); + expected_builder.Save(); + expected_builder.ClipRRect(clip_rrect, ClipOp::kIntersect, true); + expected_builder.SaveLayer(&children_bounds, + &DlPaint().setAlpha(opacity_alpha)); /* child layer1 paint */ { - expected_builder.setColor(0xFF000000); - expected_builder.drawPath(path1); + expected_builder.DrawPath(path1, DlPaint()); } /* child layer2 paint */ { // - expected_builder.drawPath(path2); + expected_builder.DrawPath(path2, DlPaint()); } - expected_builder.restore(); + expected_builder.Restore(); } } - expected_builder.restore(); + expected_builder.Restore(); } opacity_layer->Paint(display_list_paint_context()); diff --git a/flow/layers/display_list_layer_unittests.cc b/flow/layers/display_list_layer_unittests.cc index 5d4b633d7eba8..1b2ad31ec118d 100644 --- a/flow/layers/display_list_layer_unittests.cc +++ b/flow/layers/display_list_layer_unittests.cc @@ -32,7 +32,7 @@ TEST_F(DisplayListLayerTest, PaintBeforePrerollDies) { const SkPoint layer_offset = SkPoint::Make(0.0f, 0.0f); const SkRect picture_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f); DisplayListBuilder builder; - builder.drawRect(picture_bounds); + builder.DrawRect(picture_bounds, DlPaint()); auto display_list = builder.Build(); auto layer = std::make_shared( layer_offset, SkiaGPUObject(display_list, unref_queue()), @@ -47,7 +47,7 @@ TEST_F(DisplayListLayerTest, PaintingEmptyLayerDies) { const SkPoint layer_offset = SkPoint::Make(0.0f, 0.0f); const SkRect picture_bounds = SkRect::MakeEmpty(); DisplayListBuilder builder; - builder.drawRect(picture_bounds); + builder.DrawRect(picture_bounds, DlPaint()); auto display_list = builder.Build(); auto layer = std::make_shared( layer_offset, SkiaGPUObject(display_list, unref_queue()), @@ -77,7 +77,7 @@ TEST_F(DisplayListLayerTest, SimpleDisplayList) { SkMatrix::Translate(layer_offset.fX, layer_offset.fY); const SkRect picture_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f); DisplayListBuilder builder; - builder.drawRect(picture_bounds); + builder.DrawRect(picture_bounds, DlPaint()); auto display_list = builder.Build(); auto layer = std::make_shared( layer_offset, SkiaGPUObject(display_list, unref_queue()), false, false); @@ -102,7 +102,7 @@ TEST_F(DisplayListLayerTest, SimpleDisplayList) { TEST_F(DisplayListLayerTest, CachingDoesNotChangeCullRect) { const SkPoint layer_offset = SkPoint::Make(10, 10); DisplayListBuilder builder; - builder.drawRect({10, 10, 20, 20}); + builder.DrawRect({10, 10, 20, 20}, DlPaint()); auto display_list = builder.Build(); auto layer = std::make_shared( layer_offset, SkiaGPUObject(display_list, unref_queue()), true, false); @@ -118,7 +118,7 @@ TEST_F(DisplayListLayerTest, SimpleDisplayListOpacityInheritance) { const SkPoint layer_offset = SkPoint::Make(1.5f, -0.5f); const SkRect picture_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f); DisplayListBuilder builder; - builder.drawRect(picture_bounds); + builder.DrawRect(picture_bounds, DlPaint()); auto display_list = builder.Build(); auto display_list_layer = std::make_shared( layer_offset, SkiaGPUObject(display_list, unref_queue()), false, false); @@ -130,6 +130,7 @@ TEST_F(DisplayListLayerTest, SimpleDisplayListOpacityInheritance) { LayerStateStack::kCallerCanApplyOpacity); int opacity_alpha = 0x7F; + SkScalar opacity = opacity_alpha / 255.0; SkPoint opacity_offset = SkPoint::Make(10, 10); auto opacity_layer = std::make_shared(opacity_alpha, opacity_offset); @@ -138,30 +139,24 @@ TEST_F(DisplayListLayerTest, SimpleDisplayListOpacityInheritance) { EXPECT_TRUE(opacity_layer->children_can_accept_opacity()); DisplayListBuilder child_builder; - child_builder.drawRect(picture_bounds); + child_builder.DrawRect(picture_bounds, DlPaint()); auto child_display_list = child_builder.Build(); DisplayListBuilder expected_builder; /* opacity_layer::Paint() */ { - expected_builder.save(); + expected_builder.Save(); { - expected_builder.translate(opacity_offset.fX, opacity_offset.fY); + expected_builder.Translate(opacity_offset.fX, opacity_offset.fY); /* display_list_layer::Paint() */ { - expected_builder.save(); + expected_builder.Save(); { - expected_builder.translate(layer_offset.fX, layer_offset.fY); - expected_builder.setColor(opacity_alpha << 24); - expected_builder.saveLayer(&picture_bounds, true); - /* display_list contents */ { // - expected_builder.drawDisplayList(child_display_list); - } - expected_builder.restore(); - expected_builder.setColor(DlColor::kBlack()); + expected_builder.Translate(layer_offset.fX, layer_offset.fY); + expected_builder.DrawDisplayList(child_display_list, opacity); } - expected_builder.restore(); + expected_builder.Restore(); } } - expected_builder.restore(); + expected_builder.Restore(); } opacity_layer->Paint(display_list_paint_context()); @@ -174,8 +169,8 @@ TEST_F(DisplayListLayerTest, IncompatibleDisplayListOpacityInheritance) { const SkRect picture1_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f); const SkRect picture2_bounds = SkRect::MakeLTRB(10.0f, 15.0f, 30.0f, 35.0f); DisplayListBuilder builder; - builder.drawRect(picture1_bounds); - builder.drawRect(picture2_bounds); + builder.DrawRect(picture1_bounds, DlPaint()); + builder.DrawRect(picture2_bounds, DlPaint()); auto display_list = builder.Build(); auto display_list_layer = std::make_shared( layer_offset, SkiaGPUObject(display_list, unref_queue()), false, false); @@ -194,8 +189,8 @@ TEST_F(DisplayListLayerTest, IncompatibleDisplayListOpacityInheritance) { EXPECT_FALSE(opacity_layer->children_can_accept_opacity()); DisplayListBuilder child_builder; - child_builder.drawRect(picture1_bounds); - child_builder.drawRect(picture2_bounds); + child_builder.DrawRect(picture1_bounds, DlPaint()); + child_builder.DrawRect(picture2_bounds, DlPaint()); auto child_display_list = child_builder.Build(); auto display_list_bounds = picture1_bounds; @@ -204,24 +199,24 @@ TEST_F(DisplayListLayerTest, IncompatibleDisplayListOpacityInheritance) { display_list_bounds.makeOffset(layer_offset.fX, layer_offset.fY); DisplayListBuilder expected_builder; /* opacity_layer::Paint() */ { - expected_builder.save(); + expected_builder.Save(); { - expected_builder.translate(opacity_offset.fX, opacity_offset.fY); - expected_builder.setColor(opacity_alpha << 24); - expected_builder.saveLayer(&save_layer_bounds, true); + expected_builder.Translate(opacity_offset.fX, opacity_offset.fY); + expected_builder.SaveLayer(&save_layer_bounds, + &DlPaint().setAlpha(opacity_alpha)); { /* display_list_layer::Paint() */ { - expected_builder.save(); + expected_builder.Save(); { - expected_builder.translate(layer_offset.fX, layer_offset.fY); - expected_builder.drawDisplayList(child_display_list); + expected_builder.Translate(layer_offset.fX, layer_offset.fY); + expected_builder.DrawDisplayList(child_display_list); } - expected_builder.restore(); + expected_builder.Restore(); } } - expected_builder.restore(); + expected_builder.Restore(); } - expected_builder.restore(); + expected_builder.Restore(); } opacity_layer->Paint(display_list_paint_context()); @@ -234,8 +229,8 @@ TEST_F(DisplayListLayerTest, CachedIncompatibleDisplayListOpacityInheritance) { const SkRect picture1_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f); const SkRect picture2_bounds = SkRect::MakeLTRB(10.0f, 15.0f, 30.0f, 35.0f); DisplayListBuilder builder; - builder.drawRect(picture1_bounds); - builder.drawRect(picture2_bounds); + builder.DrawRect(picture1_bounds, DlPaint()); + builder.DrawRect(picture2_bounds, DlPaint()); auto display_list = builder.Build(); auto display_list_layer = std::make_shared( layer_offset, SkiaGPUObject(display_list, unref_queue()), true, false); @@ -386,7 +381,7 @@ TEST_F(DisplayListLayerTest, LayerTreeSnapshotsWhenEnabled) { const SkPoint layer_offset = SkPoint::Make(1.5f, -0.5f); const SkRect picture_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f); DisplayListBuilder builder; - builder.drawRect(picture_bounds); + builder.DrawRect(picture_bounds, DlPaint()); auto display_list = builder.Build(); auto layer = std::make_shared( layer_offset, SkiaGPUObject(display_list, unref_queue()), false, false); @@ -405,7 +400,7 @@ TEST_F(DisplayListLayerTest, NoLayerTreeSnapshotsWhenDisabledByDefault) { const SkPoint layer_offset = SkPoint::Make(1.5f, -0.5f); const SkRect picture_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f); DisplayListBuilder builder; - builder.drawRect(picture_bounds); + builder.DrawRect(picture_bounds, DlPaint()); auto display_list = builder.Build(); auto layer = std::make_shared( layer_offset, SkiaGPUObject(display_list, unref_queue()), false, false); @@ -423,7 +418,7 @@ TEST_F(DisplayListLayerTest, DisplayListAccessCountDependsOnVisibility) { const SkRect missed_cull_rect = SkRect::MakeLTRB(100, 100, 200, 200); const SkRect hit_cull_rect = SkRect::MakeLTRB(0, 0, 200, 200); DisplayListBuilder builder; - builder.drawRect(picture_bounds); + builder.DrawRect(picture_bounds, DlPaint()); auto display_list = builder.Build(); auto layer = std::make_shared( layer_offset, SkiaGPUObject(display_list, unref_queue()), true, false); @@ -524,8 +519,8 @@ TEST_F(DisplayListLayerTest, OverflowCachedDisplayListOpacityInheritance) { std::shared_ptr layers[layer_count]; for (int i = 0; i < layer_count; i++) { DisplayListBuilder builder(false); - builder.drawRect({0, 0, 100, 100}); - builder.drawRect({50, 50, 100, 100}); + builder.DrawRect({0, 0, 100, 100}, DlPaint()); + builder.DrawRect({50, 50, 100, 100}, DlPaint()); auto display_list = builder.Build(); ASSERT_FALSE(display_list->can_apply_group_opacity()); SkPoint offset = {i * 200.0f, 0}; diff --git a/flow/layers/image_filter_layer_unittests.cc b/flow/layers/image_filter_layer_unittests.cc index 77789a9b6af30..bb5ced3e00b0c 100644 --- a/flow/layers/image_filter_layer_unittests.cc +++ b/flow/layers/image_filter_layer_unittests.cc @@ -248,7 +248,7 @@ TEST_F(ImageFilterLayerTest, MultipleChildren) { } } } - expected_builder.restore(); + expected_builder.Restore(); auto expected_display_list = expected_builder.Build(); layer->Paint(display_list_paint_context()); diff --git a/flow/layers/opacity_layer_unittests.cc b/flow/layers/opacity_layer_unittests.cc index a5e72e056d720..1be70be8007ed 100644 --- a/flow/layers/opacity_layer_unittests.cc +++ b/flow/layers/opacity_layer_unittests.cc @@ -606,24 +606,23 @@ TEST_F(OpacityLayerTest, OpacityInheritanceNestedWithIncompatibleChild) { DisplayListBuilder expected_builder; /* opacity_layer_1::Paint */ { - expected_builder.save(); + expected_builder.Save(); { - expected_builder.translate(offset1.fX, offset1.fY); + expected_builder.Translate(offset1.fX, offset1.fY); /* opacity_layer_2::Paint */ { - expected_builder.save(); + expected_builder.Save(); { - expected_builder.translate(offset2.fX, offset2.fY); - expected_builder.setColor(savelayer_paint.getAlpha() << 24); - expected_builder.saveLayer(&mock_layer->paint_bounds(), true); + expected_builder.Translate(offset2.fX, offset2.fY); + expected_builder.SaveLayer(&mock_layer->paint_bounds(), + &savelayer_paint); /* mock_layer::Paint */ { - expected_builder.setColor(0xFF000000); - expected_builder.drawPath(mock_path); + expected_builder.DrawPath(mock_path, DlPaint()); } } - expected_builder.restore(); + expected_builder.Restore(); } } - expected_builder.restore(); + expected_builder.Restore(); } opacity_layer_1->Paint(display_list_paint_context()); diff --git a/flow/layers/physical_shape_layer.cc b/flow/layers/physical_shape_layer.cc index 61b31995c2620..c23711453bf38 100644 --- a/flow/layers/physical_shape_layer.cc +++ b/flow/layers/physical_shape_layer.cc @@ -4,7 +4,6 @@ #include "flutter/flow/layers/physical_shape_layer.h" -#include "flutter/display_list/display_list_canvas_dispatcher.h" #include "flutter/flow/paint_utils.h" namespace flutter { @@ -36,9 +35,9 @@ void PhysicalShapeLayer::Diff(DiffContext* context, const Layer* old_layer) { if (elevation_ == 0) { bounds = path_.getBounds(); } else { - bounds = DisplayListCanvasDispatcher::ComputeShadowBounds( - path_, elevation_, context->frame_device_pixel_ratio(), - context->GetTransform3x3()); + bounds = DlCanvas::ComputeShadowBounds(path_, elevation_, + context->frame_device_pixel_ratio(), + context->GetTransform3x3()); } context->AddLayerBounds(bounds); @@ -65,7 +64,7 @@ void PhysicalShapeLayer::Preroll(PrerollContext* context) { } else { // We will draw the shadow in Paint(), so add some margin to the paint // bounds to leave space for the shadow. - paint_bounds = DisplayListCanvasDispatcher::ComputeShadowBounds( + paint_bounds = DlCanvas::ComputeShadowBounds( path_, elevation_, context->frame_device_pixel_ratio, context->state_stack.transform_3x3()); } diff --git a/flow/layers/physical_shape_layer_unittests.cc b/flow/layers/physical_shape_layer_unittests.cc index daae0907f4412..6c97b455783a9 100644 --- a/flow/layers/physical_shape_layer_unittests.cc +++ b/flow/layers/physical_shape_layer_unittests.cc @@ -4,7 +4,6 @@ #include "flutter/flow/layers/physical_shape_layer.h" -#include "flutter/display_list/display_list_canvas_dispatcher.h" #include "flutter/flow/testing/diff_context_test.h" #include "flutter/flow/testing/layer_test.h" #include "flutter/flow/testing/mock_layer.h" @@ -214,8 +213,8 @@ TEST_F(PhysicalShapeLayerTest, ElevationSimple) { // The Fuchsia system compositor handles all elevated PhysicalShapeLayers and // their shadows , so we do not do any painting there. EXPECT_EQ(layer->paint_bounds(), - DisplayListCanvasDispatcher::ComputeShadowBounds( - layer_path, initial_elevation, 1.0f, SkMatrix())); + DlCanvas::ComputeShadowBounds(layer_path, initial_elevation, 1.0f, + SkMatrix())); EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(layer->elevation(), initial_elevation); @@ -264,7 +263,7 @@ TEST_F(PhysicalShapeLayerTest, ElevationComplex) { // On Fuchsia, the system compositor handles all elevated // PhysicalShapeLayers and their shadows , so we do not do any painting // there. - SkRect paint_bounds = DisplayListCanvasDispatcher::ComputeShadowBounds( + SkRect paint_bounds = DlCanvas::ComputeShadowBounds( layer_path, initial_elevations[i], 1.0f /* pixel_ratio */, SkMatrix()); // Without clipping the children will be painted as well @@ -313,15 +312,15 @@ TEST_F(PhysicalShapeLayerTest, ShadowNotDependsCtm) { path.addRect(0, 0, 8, 8).close(); for (SkScalar elevation : elevations) { - SkRect baseline_bounds = DisplayListCanvasDispatcher::ComputeShadowBounds( - path, elevation, 1.0f, SkMatrix()); + SkRect baseline_bounds = + DlCanvas::ComputeShadowBounds(path, elevation, 1.0f, SkMatrix()); for (SkScalar scale : scales) { for (SkScalar translate_x : translates) { for (SkScalar translate_y : translates) { SkMatrix ctm; ctm.setScaleTranslate(scale, scale, translate_x, translate_y); - SkRect bounds = DisplayListCanvasDispatcher::ComputeShadowBounds( - path, elevation, scale, ctm); + SkRect bounds = + DlCanvas::ComputeShadowBounds(path, elevation, scale, ctm); EXPECT_FLOAT_EQ(bounds.fLeft, baseline_bounds.fLeft); EXPECT_FLOAT_EQ(bounds.fTop, baseline_bounds.fTop); EXPECT_FLOAT_EQ(bounds.fRight, baseline_bounds.fRight); @@ -377,14 +376,14 @@ TEST_F(PhysicalShapeLayerTest, ShadowNotDependsPathSize) { [=](SkCanvas* canvas) { SkPath path; path.addRect(test_case[0]).close(); - DisplayListCanvasDispatcher::DrawShadow( - canvas, path, DlColor::kBlack(), 1.0f, false, 1.0f); + DlSkCanvasAdapter(canvas).DrawShadow( + path, DlColor::kBlack(), 1.0f, false, 1.0f); }, [=](SkCanvas* canvas) { SkPath path; path.addRect(test_case[1]).close(); - DisplayListCanvasDispatcher::DrawShadow( - canvas, path, DlColor::kBlack(), 1.0f, false, 1.0f); + DlSkCanvasAdapter(canvas).DrawShadow( + path, DlColor::kBlack(), 1.0f, false, 1.0f); }, SkSize::Make(100, 100)), 0); diff --git a/flow/layers/shader_mask_layer_unittests.cc b/flow/layers/shader_mask_layer_unittests.cc index 886f0d00de198..b08d73cf9cdf5 100644 --- a/flow/layers/shader_mask_layer_unittests.cc +++ b/flow/layers/shader_mask_layer_unittests.cc @@ -383,7 +383,7 @@ TEST_F(ShaderMaskLayerTest, OpacityInheritance) { /* child layer paint */ { expected_builder.DrawPath(child_path, DlPaint()); } - expected_builder.translate(mask_rect.fLeft, mask_rect.fTop); + expected_builder.Translate(mask_rect.fLeft, mask_rect.fTop); expected_builder.DrawRect( SkRect::MakeWH(mask_rect.width(), mask_rect.height()), DlPaint().setBlendMode(DlBlendMode::kSrc)); diff --git a/flow/raster_cache_unittests.cc b/flow/raster_cache_unittests.cc index 7fc8a5c7f8fce..7f1c5182995fd 100644 --- a/flow/raster_cache_unittests.cc +++ b/flow/raster_cache_unittests.cc @@ -449,8 +449,7 @@ TEST(RasterCache, DeviceRectRoundOutForDisplayList) { SkRect logical_rect = SkRect::MakeLTRB(28, 0, 354.56731, 310.288); DisplayListBuilder builder(logical_rect); - builder.setColor(SK_ColorRED); - builder.drawRect(logical_rect); + builder.DrawRect(logical_rect, DlPaint(DlColor::kRed())); sk_sp display_list = builder.Build(); SkMatrix ctm = SkMatrix::MakeAll(1.3312, 0, 233, 0, 1.3312, 206, 0, 0, 1); diff --git a/flow/testing/diff_context_test.cc b/flow/testing/diff_context_test.cc index 888923af483ca..61629eb133abc 100644 --- a/flow/testing/diff_context_test.cc +++ b/flow/testing/diff_context_test.cc @@ -35,8 +35,7 @@ Damage DiffContextTest::DiffLayerTree(MockLayerTree& layer_tree, sk_sp DiffContextTest::CreateDisplayList(const SkRect& bounds, SkColor color) { DisplayListBuilder builder; - builder.setColor(color); - builder.drawRect(bounds); + builder.DrawRect(bounds, DlPaint().setColor(color)); return builder.Build(); } diff --git a/impeller/display_list/display_list_dispatcher.cc b/impeller/display_list/display_list_dispatcher.cc index afe8e8422722c..66d543d710842 100644 --- a/impeller/display_list/display_list_dispatcher.cc +++ b/impeller/display_list/display_list_dispatcher.cc @@ -180,12 +180,12 @@ static Matrix ToMatrix(const SkMatrix& m) { }; } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::setAntiAlias(bool aa) { // Nothing to do because AA is implicit. } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::setDither(bool dither) {} static Paint::Style ToStyle(flutter::DlDrawStyle style) { @@ -201,12 +201,12 @@ static Paint::Style ToStyle(flutter::DlDrawStyle style) { return Paint::Style::kFill; } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::setStyle(flutter::DlDrawStyle style) { paint_.style = ToStyle(style); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::setColor(flutter::DlColor color) { paint_.color = { color.getRedF(), @@ -216,17 +216,17 @@ void DisplayListDispatcher::setColor(flutter::DlColor color) { }; } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::setStrokeWidth(SkScalar width) { paint_.stroke_width = width; } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::setStrokeMiter(SkScalar limit) { paint_.stroke_miter = limit; } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::setStrokeCap(flutter::DlStrokeCap cap) { switch (cap) { case flutter::DlStrokeCap::kButt: @@ -241,7 +241,7 @@ void DisplayListDispatcher::setStrokeCap(flutter::DlStrokeCap cap) { } } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::setStrokeJoin(flutter::DlStrokeJoin join) { switch (join) { case flutter::DlStrokeJoin::kMiter: @@ -345,7 +345,7 @@ static std::optional ToColorSourceType( } } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::setColorSource( const flutter::DlColorSource* source) { if (!source) { @@ -583,24 +583,24 @@ static std::optional ToColorFilterProc( return std::nullopt; } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::setColorFilter( const flutter::DlColorFilter* filter) { // Needs https://github.com/flutter/flutter/issues/95434 paint_.color_filter = ToColorFilterProc(filter); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::setInvertColors(bool invert) { paint_.invert_colors = invert; } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::setBlendMode(flutter::DlBlendMode dl_mode) { paint_.blend_mode = ToBlendMode(dl_mode); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::setPathEffect(const flutter::DlPathEffect* effect) { // Needs https://github.com/flutter/flutter/issues/95434 UNIMPLEMENTED; @@ -619,7 +619,7 @@ static FilterContents::BlurStyle ToBlurStyle(SkBlurStyle blur_style) { } } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::setMaskFilter(const flutter::DlMaskFilter* filter) { // Needs https://github.com/flutter/flutter/issues/95434 if (filter == nullptr) { @@ -704,7 +704,7 @@ static std::optional ToImageFilterProc( }; break; } - case flutter::DlImageFilterType::kComposeFilter: { + case flutter::DlImageFilterType::kCompose: { auto compose = filter->asCompose(); FML_DCHECK(compose); auto outer = compose->outer(); @@ -741,7 +741,7 @@ static std::optional ToImageFilterProc( }; break; } - case flutter::DlImageFilterType::kLocalMatrixFilter: { + case flutter::DlImageFilterType::kLocalMatrix: { auto local_matrix_filter = filter->asLocalMatrix(); FML_DCHECK(local_matrix_filter); auto internal_filter = local_matrix_filter->image_filter(); @@ -766,13 +766,13 @@ static std::optional ToImageFilterProc( } } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::setImageFilter( const flutter::DlImageFilter* filter) { paint_.image_filter = ToImageFilterProc(filter); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::save() { canvas_.Save(); } @@ -792,7 +792,7 @@ static std::vector ToRects(const SkRect tex[], int count) { return result; } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::saveLayer(const SkRect* bounds, const flutter::SaveLayerOptions options, const flutter::DlImageFilter* backdrop) { @@ -800,32 +800,32 @@ void DisplayListDispatcher::saveLayer(const SkRect* bounds, canvas_.SaveLayer(paint, ToRect(bounds), ToImageFilterProc(backdrop)); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::restore() { canvas_.Restore(); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::translate(SkScalar tx, SkScalar ty) { canvas_.Translate({tx, ty, 0.0}); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::scale(SkScalar sx, SkScalar sy) { canvas_.Scale({sx, sy, 1.0}); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::rotate(SkScalar degrees) { canvas_.Rotate(Degrees{degrees}); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::skew(SkScalar sx, SkScalar sy) { canvas_.Skew(sx, sy); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::transform2DAffine(SkScalar mxx, SkScalar mxy, SkScalar mxt, @@ -842,7 +842,7 @@ void DisplayListDispatcher::transform2DAffine(SkScalar mxx, // clang-format on } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::transformFullPerspective(SkScalar mxx, SkScalar mxy, SkScalar mxz, @@ -872,7 +872,7 @@ void DisplayListDispatcher::transformFullPerspective(SkScalar mxx, canvas_.Transform(xformation); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::transformReset() { canvas_.ResetTransform(); canvas_.Transform(initial_matrix_); @@ -892,7 +892,7 @@ static Entity::ClipOperation ToClipOperation( } } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::clipRect(const SkRect& rect, ClipOp clip_op, bool is_aa) { @@ -979,7 +979,7 @@ static Path ToPath(const SkPath& path) { case SkPathFillType::kInverseWinding: case SkPathFillType::kInverseEvenOdd: // Flutter doesn't expose these path fill types. These are only visible - // via the dispatcher interface. We should never get here. + // via the receiver interface. We should never get here. fill_type = FillType::kNonZero; break; } @@ -992,21 +992,21 @@ static Path ToPath(const SkRRect& rrect) { .TakePath(); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::clipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) { canvas_.ClipPath(ToPath(rrect), ToClipOperation(clip_op)); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::clipPath(const SkPath& path, ClipOp clip_op, bool is_aa) { canvas_.ClipPath(ToPath(path), ToClipOperation(clip_op)); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::drawColor(flutter::DlColor color, flutter::DlBlendMode dl_mode) { Paint paint; @@ -1015,12 +1015,12 @@ void DisplayListDispatcher::drawColor(flutter::DlColor color, canvas_.DrawPaint(paint); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::drawPaint() { canvas_.DrawPaint(paint_); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::drawLine(const SkPoint& p0, const SkPoint& p1) { auto path = PathBuilder{}.AddLine(ToPoint(p0), ToPoint(p1)).TakePath(); Paint paint = paint_; @@ -1028,12 +1028,12 @@ void DisplayListDispatcher::drawLine(const SkPoint& p0, const SkPoint& p1) { canvas_.DrawPath(path, paint); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::drawRect(const SkRect& rect) { canvas_.DrawRect(ToRect(rect), paint_); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::drawOval(const SkRect& bounds) { if (bounds.width() == bounds.height()) { canvas_.DrawCircle(ToPoint(bounds.center()), bounds.width() * 0.5, paint_); @@ -1043,12 +1043,12 @@ void DisplayListDispatcher::drawOval(const SkRect& bounds) { } } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::drawCircle(const SkPoint& center, SkScalar radius) { canvas_.DrawCircle(ToPoint(center), radius, paint_); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::drawRRect(const SkRRect& rrect) { if (rrect.isSimple()) { canvas_.DrawRRect(ToRect(rrect.rect()), rrect.getSimpleRadii().fX, paint_); @@ -1057,7 +1057,7 @@ void DisplayListDispatcher::drawRRect(const SkRRect& rrect) { } } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::drawDRRect(const SkRRect& outer, const SkRRect& inner) { PathBuilder builder; @@ -1066,12 +1066,12 @@ void DisplayListDispatcher::drawDRRect(const SkRRect& outer, canvas_.DrawPath(builder.TakePath(FillType::kOdd), paint_); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::drawPath(const SkPath& path) { canvas_.DrawPath(ToPath(path), paint_); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::drawArc(const SkRect& oval_bounds, SkScalar start_degrees, SkScalar sweep_degrees, @@ -1082,7 +1082,7 @@ void DisplayListDispatcher::drawArc(const SkRect& oval_bounds, canvas_.DrawPath(builder.TakePath(), paint_); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::drawPoints(PointMode mode, uint32_t count, const SkPoint points[]) { @@ -1121,14 +1121,14 @@ void DisplayListDispatcher::drawPoints(PointMode mode, } } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::drawVertices(const flutter::DlVertices* vertices, flutter::DlBlendMode dl_mode) { canvas_.DrawVertices(DLVerticesGeometry::MakeVertices(vertices), ToBlendMode(dl_mode), paint_); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::drawImage(const sk_sp image, const SkPoint point, flutter::DlImageSampling sampling, @@ -1157,14 +1157,13 @@ void DisplayListDispatcher::drawImage(const sk_sp image, ); } -// |flutter::Dispatcher| -void DisplayListDispatcher::drawImageRect( - const sk_sp image, - const SkRect& src, - const SkRect& dst, - flutter::DlImageSampling sampling, - bool render_with_attributes, - SkCanvas::SrcRectConstraint constraint) { +// |flutter::DlOpReceiver| +void DisplayListDispatcher::drawImageRect(const sk_sp image, + const SkRect& src, + const SkRect& dst, + flutter::DlImageSampling sampling, + bool render_with_attributes, + bool enforce_src_edges) { canvas_.DrawImageRect( std::make_shared(image->impeller_texture()), // image ToRect(src), // source rect @@ -1174,7 +1173,7 @@ void DisplayListDispatcher::drawImageRect( ); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::drawImageNine(const sk_sp image, const SkIRect& center, const SkRect& dst, @@ -1187,7 +1186,7 @@ void DisplayListDispatcher::drawImageNine(const sk_sp image, ToRect(dst), ToSamplerDescriptor(filter), &canvas_, &paint_); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::drawAtlas(const sk_sp atlas, const SkRSXform xform[], const SkRect tex[], @@ -1203,21 +1202,43 @@ void DisplayListDispatcher::drawAtlas(const sk_sp atlas, ToSamplerDescriptor(sampling), ToRect(cull_rect), paint_); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::drawDisplayList( - const sk_sp display_list) { - int saveCount = canvas_.GetSaveCount(); - Paint savePaint = paint_; - Matrix saveMatrix = initial_matrix_; - paint_ = Paint(); + const sk_sp display_list, + SkScalar opacity) { + // Save all values that must remain untouched after the operation. + Paint saved_paint = paint_; + Matrix saved_initial_matrix = initial_matrix_; + int restore_count = canvas_.GetSaveCount(); + + // Establish a new baseline for interpreting the new DL. + // Matrix and clip are left untouched, the current + // transform is saved as the new base matrix, and paint + // values are reset to defaults. initial_matrix_ = canvas_.GetCurrentTransformation(); + paint_ = Paint(); + + // Handle passed opacity in the most brute-force way by using + // a SaveLayer. If the display_list is able to inherit the + // opacity, this could also be handled by modulating all of its + // attribute settings (for example, color), by the indicated + // opacity. + if (opacity < SK_Scalar1) { + Paint save_paint; + save_paint.color = Color(0, 0, 0, opacity); + canvas_.SaveLayer(save_paint); + } + display_list->Dispatch(*this); - paint_ = savePaint; - initial_matrix_ = saveMatrix; - canvas_.RestoreToCount(saveCount); + + // Restore all saved state back to what it was before we interpreted + // the display_list + canvas_.RestoreToCount(restore_count); + initial_matrix_ = saved_initial_matrix; + paint_ = saved_paint; } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::drawTextBlob(const sk_sp blob, SkScalar x, SkScalar y) { @@ -1228,7 +1249,7 @@ void DisplayListDispatcher::drawTextBlob(const sk_sp blob, ); } -// |flutter::Dispatcher| +// |flutter::DlOpReceiver| void DisplayListDispatcher::drawShadow(const SkPath& path, const flutter::DlColor color, const SkScalar elevation, diff --git a/impeller/display_list/display_list_dispatcher.h b/impeller/display_list/display_list_dispatcher.h index 2f462f9741c39..9f45fed2a70b2 100644 --- a/impeller/display_list/display_list_dispatcher.h +++ b/impeller/display_list/display_list_dispatcher.h @@ -7,14 +7,14 @@ #include "display_list/display_list_path_effect.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/dl_op_receiver.h" #include "flutter/fml/macros.h" #include "impeller/aiks/canvas.h" #include "impeller/aiks/paint.h" namespace impeller { -class DisplayListDispatcher final : public flutter::Dispatcher { +class DisplayListDispatcher final : public flutter::DlOpReceiver { public: DisplayListDispatcher(); @@ -22,75 +22,75 @@ class DisplayListDispatcher final : public flutter::Dispatcher { Picture EndRecordingAsPicture(); - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void setAntiAlias(bool aa) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void setDither(bool dither) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void setStyle(flutter::DlDrawStyle style) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void setColor(flutter::DlColor color) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void setStrokeWidth(SkScalar width) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void setStrokeMiter(SkScalar limit) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void setStrokeCap(flutter::DlStrokeCap cap) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void setStrokeJoin(flutter::DlStrokeJoin join) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void setColorSource(const flutter::DlColorSource* source) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void setColorFilter(const flutter::DlColorFilter* filter) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void setInvertColors(bool invert) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void setBlendMode(flutter::DlBlendMode mode) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void setPathEffect(const flutter::DlPathEffect* effect) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void setMaskFilter(const flutter::DlMaskFilter* filter) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void setImageFilter(const flutter::DlImageFilter* filter) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void save() override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void saveLayer(const SkRect* bounds, const flutter::SaveLayerOptions options, const flutter::DlImageFilter* backdrop) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void restore() override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void translate(SkScalar tx, SkScalar ty) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void scale(SkScalar sx, SkScalar sy) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void rotate(SkScalar degrees) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void skew(SkScalar sx, SkScalar sy) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void transform2DAffine(SkScalar mxx, SkScalar mxy, SkScalar mxt, @@ -98,7 +98,7 @@ class DisplayListDispatcher final : public flutter::Dispatcher { SkScalar myy, SkScalar myt) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void transformFullPerspective(SkScalar mxx, SkScalar mxy, SkScalar mxz, @@ -116,82 +116,82 @@ class DisplayListDispatcher final : public flutter::Dispatcher { SkScalar mwz, SkScalar mwt) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void transformReset() override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void clipRect(const SkRect& rect, ClipOp clip_op, bool is_aa) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void clipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void clipPath(const SkPath& path, ClipOp clip_op, bool is_aa) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void drawColor(flutter::DlColor color, flutter::DlBlendMode mode) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void drawPaint() override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void drawLine(const SkPoint& p0, const SkPoint& p1) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void drawRect(const SkRect& rect) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void drawOval(const SkRect& bounds) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void drawCircle(const SkPoint& center, SkScalar radius) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void drawRRect(const SkRRect& rrect) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void drawDRRect(const SkRRect& outer, const SkRRect& inner) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void drawPath(const SkPath& path) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void drawArc(const SkRect& oval_bounds, SkScalar start_degrees, SkScalar sweep_degrees, bool use_center) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void drawPoints(PointMode mode, uint32_t count, const SkPoint points[]) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void drawVertices(const flutter::DlVertices* vertices, flutter::DlBlendMode dl_mode) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void drawImage(const sk_sp image, const SkPoint point, flutter::DlImageSampling sampling, bool render_with_attributes) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void drawImageRect(const sk_sp image, const SkRect& src, const SkRect& dst, flutter::DlImageSampling sampling, bool render_with_attributes, - SkCanvas::SrcRectConstraint constraint) override; + bool enforce_src_edges) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void drawImageNine(const sk_sp image, const SkIRect& center, const SkRect& dst, flutter::DlFilterMode filter, bool render_with_attributes) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void drawAtlas(const sk_sp atlas, const SkRSXform xform[], const SkRect tex[], @@ -202,15 +202,16 @@ class DisplayListDispatcher final : public flutter::Dispatcher { const SkRect* cull_rect, bool render_with_attributes) override; - // |flutter::Dispatcher| - void drawDisplayList(const sk_sp display_list) override; + // |flutter::DlOpReceiver| + void drawDisplayList(const sk_sp display_list, + SkScalar opacity) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void drawTextBlob(const sk_sp blob, SkScalar x, SkScalar y) override; - // |flutter::Dispatcher| + // |flutter::DlOpReceiver| void drawShadow(const SkPath& path, const flutter::DlColor color, const SkScalar elevation, diff --git a/impeller/display_list/display_list_unittests.cc b/impeller/display_list/display_list_unittests.cc index 0ba6f7a38e9fc..fb94821ecd3a5 100644 --- a/impeller/display_list/display_list_unittests.cc +++ b/impeller/display_list/display_list_unittests.cc @@ -44,85 +44,83 @@ INSTANTIATE_PLAYGROUND_SUITE(DisplayListTest); TEST_P(DisplayListTest, CanDrawRect) { flutter::DisplayListBuilder builder; - builder.setColor(SK_ColorBLUE); - builder.drawRect(SkRect::MakeXYWH(10, 10, 100, 100)); + builder.DrawRect(SkRect::MakeXYWH(10, 10, 100, 100), + flutter::DlPaint(flutter::DlColor::kBlue())); ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } TEST_P(DisplayListTest, CanDrawTextBlob) { flutter::DisplayListBuilder builder; - builder.setColor(SK_ColorBLUE); - builder.drawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()), - 100, 100); + builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()), + 100, 100, flutter::DlPaint(flutter::DlColor::kBlue())); ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } TEST_P(DisplayListTest, CanDrawTextWithSaveLayer) { flutter::DisplayListBuilder builder; - builder.setColor(SK_ColorRED); - builder.drawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()), - 100, 100); + builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()), + 100, 100, flutter::DlPaint(flutter::DlColor::kRed())); flutter::DlPaint save_paint; float alpha = 0.5; save_paint.setAlpha(static_cast(255 * alpha)); builder.SaveLayer(nullptr, &save_paint); - builder.setColor(SK_ColorRED); - builder.drawTextBlob(SkTextBlob::MakeFromString("Hello with half alpha", + builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello with half alpha", CreateTestFontOfSize(100)), - 100, 300); - builder.restore(); + 100, 300, flutter::DlPaint(flutter::DlColor::kRed())); + builder.Restore(); ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } TEST_P(DisplayListTest, CanDrawImage) { auto texture = CreateTextureForFixture("embarcadero.jpg"); flutter::DisplayListBuilder builder; - builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100), - flutter::DlImageSampling::kNearestNeighbor, true); + builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100), + flutter::DlImageSampling::kNearestNeighbor, nullptr); ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } TEST_P(DisplayListTest, CanDrawCapsAndJoins) { flutter::DisplayListBuilder builder; + flutter::DlPaint paint; - builder.setStyle(flutter::DlDrawStyle::kStroke); - builder.setStrokeWidth(30); - builder.setColor(SK_ColorRED); + paint.setDrawStyle(flutter::DlDrawStyle::kStroke); + paint.setStrokeWidth(30); + paint.setColor(SK_ColorRED); auto path = SkPathBuilder{}.moveTo(-50, 0).lineTo(0, -50).lineTo(50, 0).snapshot(); - builder.translate(100, 100); + builder.Translate(100, 100); { - builder.setStrokeCap(flutter::DlStrokeCap::kButt); - builder.setStrokeJoin(flutter::DlStrokeJoin::kMiter); - builder.setStrokeMiter(4); - builder.drawPath(path); + paint.setStrokeCap(flutter::DlStrokeCap::kButt); + paint.setStrokeJoin(flutter::DlStrokeJoin::kMiter); + paint.setStrokeMiter(4); + builder.DrawPath(path, paint); } { - builder.save(); - builder.translate(0, 100); + builder.Save(); + builder.Translate(0, 100); // The joint in the path is 45 degrees. A miter length of 1 convert to a // bevel in this case. - builder.setStrokeMiter(1); - builder.drawPath(path); - builder.restore(); + paint.setStrokeMiter(1); + builder.DrawPath(path, paint); + builder.Restore(); } - builder.translate(150, 0); + builder.Translate(150, 0); { - builder.setStrokeCap(flutter::DlStrokeCap::kSquare); - builder.setStrokeJoin(flutter::DlStrokeJoin::kBevel); - builder.drawPath(path); + paint.setStrokeCap(flutter::DlStrokeCap::kSquare); + paint.setStrokeJoin(flutter::DlStrokeJoin::kBevel); + builder.DrawPath(path, paint); } - builder.translate(150, 0); + builder.Translate(150, 0); { - builder.setStrokeCap(flutter::DlStrokeCap::kRound); - builder.setStrokeJoin(flutter::DlStrokeJoin::kRound); - builder.drawPath(path); + paint.setStrokeCap(flutter::DlStrokeCap::kRound); + paint.setStrokeJoin(flutter::DlStrokeJoin::kRound); + builder.DrawPath(path, paint); } ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); @@ -167,20 +165,21 @@ TEST_P(DisplayListTest, CanDrawArc) { Point(200, 200), Point(400, 400), 20, Color::White(), Color::White()); flutter::DisplayListBuilder builder; + flutter::DlPaint paint; Vector2 scale = GetContentScale(); - builder.scale(scale.x, scale.y); - builder.setStyle(flutter::DlDrawStyle::kStroke); - builder.setStrokeCap(cap); - builder.setStrokeJoin(flutter::DlStrokeJoin::kMiter); - builder.setStrokeMiter(10); + builder.Scale(scale.x, scale.y); + paint.setDrawStyle(flutter::DlDrawStyle::kStroke); + paint.setStrokeCap(cap); + paint.setStrokeJoin(flutter::DlStrokeJoin::kMiter); + paint.setStrokeMiter(10); auto rect = SkRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y); - builder.setColor(SK_ColorGREEN); - builder.setStrokeWidth(2); - builder.drawRect(rect); - builder.setColor(SK_ColorRED); - builder.setStrokeWidth(stroke_width); - builder.drawArc(rect, start_angle, sweep_angle, use_center); + paint.setColor(SK_ColorGREEN); + paint.setStrokeWidth(2); + builder.DrawRect(rect, paint); + paint.setColor(SK_ColorRED); + paint.setStrokeWidth(stroke_width); + builder.DrawArc(rect, start_angle, sweep_angle, use_center, paint); return builder.Build(); }; @@ -189,45 +188,48 @@ TEST_P(DisplayListTest, CanDrawArc) { TEST_P(DisplayListTest, StrokedPathsDrawCorrectly) { flutter::DisplayListBuilder builder; - builder.setColor(SK_ColorRED); - builder.setStyle(flutter::DlDrawStyle::kStroke); - builder.setStrokeWidth(10); + flutter::DlPaint paint; + + paint.setColor(SK_ColorRED); + paint.setDrawStyle(flutter::DlDrawStyle::kStroke); + paint.setStrokeWidth(10); // Rectangle - builder.translate(100, 100); - builder.drawRect(SkRect::MakeSize({100, 100})); + builder.Translate(100, 100); + builder.DrawRect(SkRect::MakeSize({100, 100}), paint); // Rounded rectangle - builder.translate(150, 0); - builder.drawRRect(SkRRect::MakeRectXY(SkRect::MakeSize({100, 50}), 10, 10)); + builder.Translate(150, 0); + builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeSize({100, 50}), 10, 10), + paint); // Double rounded rectangle - builder.translate(150, 0); - builder.drawDRRect( + builder.Translate(150, 0); + builder.DrawDRRect( SkRRect::MakeRectXY(SkRect::MakeSize({100, 50}), 10, 10), - SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 10, 80, 30), 10, 10)); + SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 10, 80, 30), 10, 10), paint); // Contour with duplicate join points { - builder.translate(150, 0); + builder.Translate(150, 0); SkPath path; path.lineTo({100, 0}); path.lineTo({100, 0}); path.lineTo({100, 100}); - builder.drawPath(path); + builder.DrawPath(path, paint); } // Contour with duplicate end points { - builder.setStrokeCap(flutter::DlStrokeCap::kRound); - builder.translate(150, 0); + paint.setStrokeCap(flutter::DlStrokeCap::kRound); + builder.Translate(150, 0); SkPath path; path.moveTo(0, 0); path.lineTo({0, 0}); path.lineTo({50, 50}); path.lineTo({100, 0}); path.lineTo({100, 0}); - builder.drawPath(path); + builder.DrawPath(path, paint); } ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); @@ -235,15 +237,17 @@ TEST_P(DisplayListTest, StrokedPathsDrawCorrectly) { TEST_P(DisplayListTest, CanDrawWithOddPathWinding) { flutter::DisplayListBuilder builder; - builder.setColor(SK_ColorRED); - builder.setStyle(flutter::DlDrawStyle::kFill); + flutter::DlPaint paint; - builder.translate(300, 300); + paint.setColor(SK_ColorRED); + paint.setDrawStyle(flutter::DlDrawStyle::kFill); + + builder.Translate(300, 300); SkPath path; path.setFillType(SkPathFillType::kEvenOdd); path.addCircle(0, 0, 100); path.addCircle(0, 0, 50); - builder.drawPath(path); + builder.DrawPath(path, paint); ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } @@ -251,29 +255,31 @@ TEST_P(DisplayListTest, CanDrawWithOddPathWinding) { TEST_P(DisplayListTest, CanDrawWithMaskBlur) { auto texture = CreateTextureForFixture("embarcadero.jpg"); flutter::DisplayListBuilder builder; + flutter::DlPaint paint; // Mask blurred image. { auto filter = flutter::DlBlurMaskFilter(kNormal_SkBlurStyle, 10.0f); - builder.setMaskFilter(&filter); - builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100), - flutter::DlImageSampling::kNearestNeighbor, true); + paint.setMaskFilter(&filter); + builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100), + flutter::DlImageSampling::kNearestNeighbor, &paint); } // Mask blurred filled path. { - builder.setColor(SK_ColorYELLOW); + paint.setColor(SK_ColorYELLOW); auto filter = flutter::DlBlurMaskFilter(kOuter_SkBlurStyle, 10.0f); - builder.setMaskFilter(&filter); - builder.drawArc(SkRect::MakeXYWH(410, 110, 100, 100), 45, 270, true); + paint.setMaskFilter(&filter); + builder.DrawArc(SkRect::MakeXYWH(410, 110, 100, 100), 45, 270, true, paint); } // Mask blurred text. { auto filter = flutter::DlBlurMaskFilter(kSolid_SkBlurStyle, 10.0f); - builder.setMaskFilter(&filter); - builder.drawTextBlob( - SkTextBlob::MakeFromString("Testing", CreateTestFont()), 220, 170); + paint.setMaskFilter(&filter); + builder.DrawTextBlob( + SkTextBlob::MakeFromString("Testing", CreateTestFont()), 220, 170, + paint); } ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); @@ -295,23 +301,24 @@ TEST_P(DisplayListTest, IgnoreMaskFilterWhenSavingLayer) { TEST_P(DisplayListTest, CanDrawWithBlendColorFilter) { auto texture = CreateTextureForFixture("embarcadero.jpg"); flutter::DisplayListBuilder builder; + flutter::DlPaint paint; // Pipeline blended image. { auto filter = flutter::DlBlendColorFilter(SK_ColorYELLOW, flutter::DlBlendMode::kModulate); - builder.setColorFilter(&filter); - builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100), - flutter::DlImageSampling::kNearestNeighbor, true); + paint.setColorFilter(&filter); + builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100), + flutter::DlImageSampling::kNearestNeighbor, &paint); } // Advanced blended image. { auto filter = flutter::DlBlendColorFilter(SK_ColorRED, flutter::DlBlendMode::kScreen); - builder.setColorFilter(&filter); - builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(250, 250), - flutter::DlImageSampling::kNearestNeighbor, true); + paint.setColorFilter(&filter); + builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(250, 250), + flutter::DlImageSampling::kNearestNeighbor, &paint); } ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); @@ -326,18 +333,21 @@ TEST_P(DisplayListTest, CanDrawWithColorFilterImageFilter) { }; auto texture = CreateTextureForFixture("boston.jpg"); flutter::DisplayListBuilder builder; + flutter::DlPaint paint; + auto color_filter = std::make_shared(invert_color_matrix); auto image_filter = std::make_shared(color_filter); - builder.setImageFilter(image_filter.get()); - builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100), - flutter::DlImageSampling::kNearestNeighbor, true); - - builder.translate(0, 700); - builder.setColorFilter(color_filter.get()); - builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100), - flutter::DlImageSampling::kNearestNeighbor, true); + + paint.setImageFilter(image_filter.get()); + builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100), + flutter::DlImageSampling::kNearestNeighbor, &paint); + + builder.Translate(0, 700); + paint.setColorFilter(color_filter.get()); + builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100), + flutter::DlImageSampling::kNearestNeighbor, &paint); ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } @@ -352,12 +362,13 @@ TEST_P(DisplayListTest, CanDrawWithImageBlurFilter) { ImGui::End(); flutter::DisplayListBuilder builder; + flutter::DlPaint paint; auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1], flutter::DlTileMode::kClamp); - builder.setImageFilter(&filter); - builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200), - flutter::DlImageSampling::kNearestNeighbor, true); + paint.setImageFilter(&filter); + builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200), + flutter::DlImageSampling::kNearestNeighbor, &paint); return builder.Build(); }; @@ -368,17 +379,20 @@ TEST_P(DisplayListTest, CanDrawWithImageBlurFilter) { TEST_P(DisplayListTest, CanDrawWithComposeImageFilter) { auto texture = CreateTextureForFixture("boston.jpg"); flutter::DisplayListBuilder builder; + flutter::DlPaint paint; + auto dilate = std::make_shared(10.0, 10.0); auto erode = std::make_shared(10.0, 10.0); auto open = std::make_shared(dilate, erode); auto close = std::make_shared(erode, dilate); - builder.setImageFilter(open.get()); - builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100), - flutter::DlImageSampling::kNearestNeighbor, true); - builder.translate(0, 700); - builder.setImageFilter(close.get()); - builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100), - flutter::DlImageSampling::kNearestNeighbor, true); + + paint.setImageFilter(open.get()); + builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100), + flutter::DlImageSampling::kNearestNeighbor, &paint); + builder.Translate(0, 700); + paint.setImageFilter(close.get()); + builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100), + flutter::DlImageSampling::kNearestNeighbor, &paint); ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } @@ -407,9 +421,10 @@ TEST_P(DisplayListTest, CanClampTheResultingColorOfColorMatrixFilter) { auto compose = std::make_shared(outer, inner); flutter::DisplayListBuilder builder; - builder.setImageFilter(compose.get()); - builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100), - flutter::DlImageSampling::kNearestNeighbor, true); + flutter::DlPaint paint; + paint.setImageFilter(compose.get()); + builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100), + flutter::DlImageSampling::kNearestNeighbor, &paint); ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } @@ -543,7 +558,7 @@ TEST_P(DisplayListTest, CanDrawBackdropFilter) { flutter::DisplayListBuilder builder; Vector2 scale = ctm_scale * GetContentScale(); - builder.scale(scale.x, scale.y); + builder.Scale(scale.x, scale.y); auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1], flutter::DlTileMode::kClamp); @@ -558,25 +573,26 @@ TEST_P(DisplayListTest, CanDrawBackdropFilter) { // Insert a clip to test that the backdrop filter handles stencil depths > 0 // correctly. if (add_clip) { - builder.clipRect(SkRect::MakeLTRB(0, 0, 99999, 99999), + builder.ClipRect(SkRect::MakeLTRB(0, 0, 99999, 99999), flutter::DlCanvas::ClipOp::kIntersect, true); } - builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200), - flutter::DlImageSampling::kNearestNeighbor, true); - builder.saveLayer(bounds.has_value() ? &bounds.value() : nullptr, nullptr, + builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200), + flutter::DlImageSampling::kNearestNeighbor, nullptr); + builder.SaveLayer(bounds.has_value() ? &bounds.value() : nullptr, nullptr, &filter); if (draw_circle) { auto circle_center = IMPELLER_PLAYGROUND_POINT(Point(500, 400), 20, Color::Red()); - builder.setStyle(flutter::DlDrawStyle::kStroke); - builder.setStrokeCap(flutter::DlStrokeCap::kButt); - builder.setStrokeJoin(flutter::DlStrokeJoin::kBevel); - builder.setStrokeWidth(10); - builder.setColor(flutter::DlColor::kRed().withAlpha(100)); - builder.drawCircle({circle_center.x, circle_center.y}, 100); + flutter::DlPaint paint; + paint.setDrawStyle(flutter::DlDrawStyle::kStroke); + paint.setStrokeCap(flutter::DlStrokeCap::kButt); + paint.setStrokeJoin(flutter::DlStrokeJoin::kBevel); + paint.setStrokeWidth(10); + paint.setColor(flutter::DlColor::kRed().withAlpha(100)); + builder.DrawCircle({circle_center.x, circle_center.y}, 100, paint); } return builder.Build(); @@ -590,12 +606,12 @@ TEST_P(DisplayListTest, CanDrawNinePatchImage) { auto texture = CreateTextureForFixture("embarcadero.jpg"); flutter::DisplayListBuilder builder; auto size = texture->GetSize(); - builder.drawImageNine( + builder.DrawImageNine( DlImageImpeller::Make(texture), SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4, size.height * 3 / 4), SkRect::MakeLTRB(0, 0, size.width * 2, size.height * 2), - flutter::DlFilterMode::kNearest, true); + flutter::DlFilterMode::kNearest, nullptr); ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } @@ -606,12 +622,12 @@ TEST_P(DisplayListTest, CanDrawNinePatchImageCenterWidthBiggerThanDest) { auto texture = CreateTextureForFixture("embarcadero.jpg"); flutter::DisplayListBuilder builder; auto size = texture->GetSize(); - builder.drawImageNine( + builder.DrawImageNine( DlImageImpeller::Make(texture), SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4, size.height * 3 / 4), SkRect::MakeLTRB(0, 0, size.width / 2, size.height), - flutter::DlFilterMode::kNearest, true); + flutter::DlFilterMode::kNearest, nullptr); ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } @@ -622,12 +638,12 @@ TEST_P(DisplayListTest, CanDrawNinePatchImageCenterHeightBiggerThanDest) { auto texture = CreateTextureForFixture("embarcadero.jpg"); flutter::DisplayListBuilder builder; auto size = texture->GetSize(); - builder.drawImageNine( + builder.DrawImageNine( DlImageImpeller::Make(texture), SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4, size.height * 3 / 4), SkRect::MakeLTRB(0, 0, size.width, size.height / 2), - flutter::DlFilterMode::kNearest, true); + flutter::DlFilterMode::kNearest, nullptr); ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } @@ -637,12 +653,12 @@ TEST_P(DisplayListTest, CanDrawNinePatchImageCenterBiggerThanDest) { auto texture = CreateTextureForFixture("embarcadero.jpg"); flutter::DisplayListBuilder builder; auto size = texture->GetSize(); - builder.drawImageNine( + builder.DrawImageNine( DlImageImpeller::Make(texture), SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4, size.height * 3 / 4), SkRect::MakeLTRB(0, 0, size.width / 2, size.height / 2), - flutter::DlFilterMode::kNearest, true); + flutter::DlFilterMode::kNearest, nullptr); ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } @@ -652,12 +668,12 @@ TEST_P(DisplayListTest, CanDrawNinePatchImageCornersScaledDown) { auto texture = CreateTextureForFixture("embarcadero.jpg"); flutter::DisplayListBuilder builder; auto size = texture->GetSize(); - builder.drawImageNine( + builder.DrawImageNine( DlImageImpeller::Make(texture), SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4, size.height * 3 / 4), SkRect::MakeLTRB(0, 0, size.width / 4, size.height / 4), - flutter::DlFilterMode::kNearest, true); + flutter::DlFilterMode::kNearest, nullptr); ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } @@ -722,9 +738,10 @@ TEST_P(DisplayListTest, CanDrawZeroLengthLine) { TEST_P(DisplayListTest, CanDrawShadow) { flutter::DisplayListBuilder builder; + flutter::DlPaint paint; auto content_scale = GetContentScale() * 0.8; - builder.scale(content_scale.x, content_scale.y); + builder.Scale(content_scale.x, content_scale.y); constexpr size_t star_spikes = 5; constexpr SkScalar half_spike_rotation = kPi / star_spikes; @@ -749,20 +766,20 @@ TEST_P(DisplayListTest, CanDrawShadow) { SkPath{}.addCircle(100, 50, 50), SkPath{}.addPoly(star.data(), star.size(), true), }; - builder.setColor(flutter::DlColor::kWhite()); - builder.drawPaint(); - builder.setColor(flutter::DlColor::kCyan()); - builder.translate(100, 50); + paint.setColor(flutter::DlColor::kWhite()); + builder.DrawPaint(paint); + paint.setColor(flutter::DlColor::kCyan()); + builder.Translate(100, 50); for (size_t x = 0; x < paths.size(); x++) { - builder.save(); + builder.Save(); for (size_t y = 0; y < 6; y++) { - builder.drawShadow(paths[x], flutter::DlColor::kBlack(), 3 + y * 8, false, + builder.DrawShadow(paths[x], flutter::DlColor::kBlack(), 3 + y * 8, false, 1); - builder.drawPath(paths[x]); - builder.translate(0, 150); + builder.DrawPath(paths[x], paint); + builder.Translate(0, 150); } - builder.restore(); - builder.translate(250, 0); + builder.Restore(); + builder.Translate(250, 0); } ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); @@ -878,20 +895,21 @@ TEST_P(DisplayListTest, CanDrawWithMatrixFilter) { ImGui::End(); flutter::DisplayListBuilder builder; - SkPaint paint; + flutter::DlPaint paint; + if (enable_savelayer) { builder.SaveLayer(nullptr, nullptr); } { auto content_scale = GetContentScale(); - builder.scale(content_scale.x, content_scale.y); + builder.Scale(content_scale.x, content_scale.y); // Set the current transform auto ctm_matrix = SkMatrix::MakeAll(ctm_scale[0], ctm_skew[0], ctm_translation[0], // ctm_skew[1], ctm_scale[1], ctm_translation[1], // 0, 0, 1); - builder.transform(ctm_matrix); + builder.Transform(ctm_matrix); // Set the matrix filter auto filter_matrix = @@ -904,7 +922,7 @@ TEST_P(DisplayListTest, CanDrawWithMatrixFilter) { case 0: { auto filter = flutter::DlMatrixImageFilter( filter_matrix, flutter::DlImageSampling::kLinear); - builder.setImageFilter(&filter); + paint.setImageFilter(&filter); break; } case 1: { @@ -913,17 +931,17 @@ TEST_P(DisplayListTest, CanDrawWithMatrixFilter) { .shared(); auto filter = flutter::DlLocalMatrixImageFilter(filter_matrix, internal_filter); - builder.setImageFilter(&filter); + paint.setImageFilter(&filter); break; } } } - builder.drawImage(DlImageImpeller::Make(boston), {}, - flutter::DlImageSampling::kLinear, true); + builder.DrawImage(DlImageImpeller::Make(boston), {}, + flutter::DlImageSampling::kLinear, &paint); } if (enable_savelayer) { - builder.restore(); + builder.Restore(); } return builder.Build(); diff --git a/lib/ui/painting/canvas.cc b/lib/ui/painting/canvas.cc index 92f7043d2d090..b802adbaefa91 100644 --- a/lib/ui/painting/canvas.cc +++ b/lib/ui/painting/canvas.cc @@ -47,7 +47,7 @@ Canvas::~Canvas() {} void Canvas::save() { if (display_list_builder_) { - builder()->save(); + builder()->Save(); } } @@ -57,11 +57,11 @@ void Canvas::saveLayerWithoutBounds(Dart_Handle paint_objects, FML_DCHECK(paint.isNotNull()); if (display_list_builder_) { - bool restore_with_paint = - paint.sync_to(builder(), kSaveLayerWithPaintFlags); - FML_DCHECK(restore_with_paint); + DlPaint dl_paint; + const DlPaint* save_paint = paint.paint(dl_paint, kSaveLayerWithPaintFlags); + FML_DCHECK(save_paint); TRACE_EVENT0("flutter", "ui.Canvas::saveLayer (Recorded)"); - builder()->saveLayer(nullptr, restore_with_paint); + builder()->SaveLayer(nullptr, save_paint); } } @@ -76,17 +76,17 @@ void Canvas::saveLayer(double left, FML_DCHECK(paint.isNotNull()); SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom); if (display_list_builder_) { - bool restore_with_paint = - paint.sync_to(builder(), kSaveLayerWithPaintFlags); - FML_DCHECK(restore_with_paint); + DlPaint dl_paint; + const DlPaint* save_paint = paint.paint(dl_paint, kSaveLayerWithPaintFlags); + FML_DCHECK(save_paint); TRACE_EVENT0("flutter", "ui.Canvas::saveLayer (Recorded)"); - builder()->saveLayer(&bounds, restore_with_paint); + builder()->SaveLayer(&bounds, save_paint); } } void Canvas::restore() { if (display_list_builder_) { - builder()->restore(); + builder()->Restore(); } } @@ -100,31 +100,31 @@ int Canvas::getSaveCount() { void Canvas::restoreToCount(int count) { if (display_list_builder_ && count < getSaveCount()) { - builder()->restoreToCount(count); + builder()->RestoreToCount(count); } } void Canvas::translate(double dx, double dy) { if (display_list_builder_) { - builder()->translate(dx, dy); + builder()->Translate(dx, dy); } } void Canvas::scale(double sx, double sy) { if (display_list_builder_) { - builder()->scale(sx, sy); + builder()->Scale(sx, sy); } } void Canvas::rotate(double radians) { if (display_list_builder_) { - builder()->rotate(radians * 180.0 / M_PI); + builder()->Rotate(radians * 180.0 / M_PI); } } void Canvas::skew(double sx, double sy) { if (display_list_builder_) { - builder()->skew(sx, sy); + builder()->Skew(sx, sy); } } @@ -133,7 +133,7 @@ void Canvas::transform(const tonic::Float64List& matrix4) { // Both DisplayList and SkM44 constructor take row-major matrix order if (display_list_builder_) { // clang-format off - builder()->transformFullPerspective( + builder()->TransformFullPerspective( matrix4[ 0], matrix4[ 4], matrix4[ 8], matrix4[12], matrix4[ 1], matrix4[ 5], matrix4[ 9], matrix4[13], matrix4[ 2], matrix4[ 6], matrix4[10], matrix4[14], @@ -162,14 +162,14 @@ void Canvas::clipRect(double left, DlCanvas::ClipOp clipOp, bool doAntiAlias) { if (display_list_builder_) { - builder()->clipRect(SkRect::MakeLTRB(left, top, right, bottom), clipOp, + builder()->ClipRect(SkRect::MakeLTRB(left, top, right, bottom), clipOp, doAntiAlias); } } void Canvas::clipRRect(const RRect& rrect, bool doAntiAlias) { if (display_list_builder_) { - builder()->clipRRect(rrect.sk_rrect, DlCanvas::ClipOp::kIntersect, + builder()->ClipRRect(rrect.sk_rrect, DlCanvas::ClipOp::kIntersect, doAntiAlias); } } @@ -181,7 +181,7 @@ void Canvas::clipPath(const CanvasPath* path, bool doAntiAlias) { return; } if (display_list_builder_) { - builder()->clipPath(path->path(), DlCanvas::ClipOp::kIntersect, + builder()->ClipPath(path->path(), DlCanvas::ClipOp::kIntersect, doAntiAlias); } } @@ -210,7 +210,7 @@ void Canvas::getLocalClipBounds(Dart_Handle rect_handle) { void Canvas::drawColor(SkColor color, DlBlendMode blend_mode) { if (display_list_builder_) { - builder()->drawColor(color, blend_mode); + builder()->DrawColor(color, blend_mode); } } @@ -224,8 +224,9 @@ void Canvas::drawLine(double x1, FML_DCHECK(paint.isNotNull()); if (display_list_builder_) { - paint.sync_to(builder(), kDrawLineFlags); - builder()->drawLine(SkPoint::Make(x1, y1), SkPoint::Make(x2, y2)); + DlPaint dl_paint; + paint.paint(dl_paint, kDrawLineFlags); + builder()->DrawLine(SkPoint::Make(x1, y1), SkPoint::Make(x2, y2), dl_paint); } } @@ -234,14 +235,15 @@ void Canvas::drawPaint(Dart_Handle paint_objects, Dart_Handle paint_data) { FML_DCHECK(paint.isNotNull()); if (display_list_builder_) { - paint.sync_to(builder(), kDrawPaintFlags); - std::shared_ptr filter = builder()->getImageFilter(); + DlPaint dl_paint; + paint.paint(dl_paint, kDrawPaintFlags); + std::shared_ptr filter = dl_paint.getImageFilter(); if (filter && !filter->asColorFilter()) { // drawPaint does an implicit saveLayer if an SkImageFilter is // present that cannot be replaced by an SkColorFilter. TRACE_EVENT0("flutter", "ui.Canvas::saveLayer (Recorded)"); } - builder()->drawPaint(); + builder()->DrawPaint(dl_paint); } } @@ -255,8 +257,9 @@ void Canvas::drawRect(double left, FML_DCHECK(paint.isNotNull()); if (display_list_builder_) { - paint.sync_to(builder(), kDrawRectFlags); - builder()->drawRect(SkRect::MakeLTRB(left, top, right, bottom)); + DlPaint dl_paint; + paint.paint(dl_paint, kDrawRectFlags); + builder()->DrawRect(SkRect::MakeLTRB(left, top, right, bottom), dl_paint); } } @@ -267,8 +270,9 @@ void Canvas::drawRRect(const RRect& rrect, FML_DCHECK(paint.isNotNull()); if (display_list_builder_) { - paint.sync_to(builder(), kDrawRRectFlags); - builder()->drawRRect(rrect.sk_rrect); + DlPaint dl_paint; + paint.paint(dl_paint, kDrawRRectFlags); + builder()->DrawRRect(rrect.sk_rrect, dl_paint); } } @@ -280,8 +284,9 @@ void Canvas::drawDRRect(const RRect& outer, FML_DCHECK(paint.isNotNull()); if (display_list_builder_) { - paint.sync_to(builder(), kDrawDRRectFlags); - builder()->drawDRRect(outer.sk_rrect, inner.sk_rrect); + DlPaint dl_paint; + paint.paint(dl_paint, kDrawDRRectFlags); + builder()->DrawDRRect(outer.sk_rrect, inner.sk_rrect, dl_paint); } } @@ -295,8 +300,9 @@ void Canvas::drawOval(double left, FML_DCHECK(paint.isNotNull()); if (display_list_builder_) { - paint.sync_to(builder(), kDrawOvalFlags); - builder()->drawOval(SkRect::MakeLTRB(left, top, right, bottom)); + DlPaint dl_paint; + paint.paint(dl_paint, kDrawOvalFlags); + builder()->DrawOval(SkRect::MakeLTRB(left, top, right, bottom), dl_paint); } } @@ -309,8 +315,9 @@ void Canvas::drawCircle(double x, FML_DCHECK(paint.isNotNull()); if (display_list_builder_) { - paint.sync_to(builder(), kDrawCircleFlags); - builder()->drawCircle(SkPoint::Make(x, y), radius); + DlPaint dl_paint; + paint.paint(dl_paint, kDrawCircleFlags); + builder()->DrawCircle(SkPoint::Make(x, y), radius, dl_paint); } } @@ -327,13 +334,13 @@ void Canvas::drawArc(double left, FML_DCHECK(paint.isNotNull()); if (display_list_builder_) { - paint.sync_to(builder(), - useCenter // - ? kDrawArcWithCenterFlags - : kDrawArcNoCenterFlags); - builder()->drawArc(SkRect::MakeLTRB(left, top, right, bottom), + DlPaint dl_paint; + paint.paint(dl_paint, useCenter // + ? kDrawArcWithCenterFlags + : kDrawArcNoCenterFlags); + builder()->DrawArc(SkRect::MakeLTRB(left, top, right, bottom), startAngle * 180.0 / M_PI, sweepAngle * 180.0 / M_PI, - useCenter); + useCenter, dl_paint); } } @@ -349,8 +356,9 @@ void Canvas::drawPath(const CanvasPath* path, return; } if (display_list_builder_) { - paint.sync_to(builder(), kDrawPathFlags); - builder()->drawPath(path->path()); + DlPaint dl_paint; + paint.paint(dl_paint, kDrawPathFlags); + builder()->DrawPath(path->path(), dl_paint); } } @@ -378,9 +386,9 @@ Dart_Handle Canvas::drawImage(const CanvasImage* image, auto sampling = ImageFilter::SamplingFromIndex(filterQualityIndex); if (display_list_builder_) { - bool with_attributes = paint.sync_to(builder(), kDrawImageWithPaintFlags); - builder()->drawImage(dl_image, SkPoint::Make(x, y), sampling, - with_attributes); + DlPaint dl_paint; + const DlPaint* opt_paint = paint.paint(dl_paint, kDrawImageWithPaintFlags); + builder()->DrawImage(dl_image, SkPoint::Make(x, y), sampling, opt_paint); } return Dart_Null(); } @@ -417,9 +425,10 @@ Dart_Handle Canvas::drawImageRect(const CanvasImage* image, SkRect dst = SkRect::MakeLTRB(dst_left, dst_top, dst_right, dst_bottom); auto sampling = ImageFilter::SamplingFromIndex(filterQualityIndex); if (display_list_builder_) { - bool with_attributes = - paint.sync_to(builder(), kDrawImageRectWithPaintFlags); - builder()->drawImageRect(dl_image, src, dst, sampling, with_attributes, + DlPaint dl_paint; + const DlPaint* opt_paint = + paint.paint(dl_paint, kDrawImageRectWithPaintFlags); + builder()->DrawImageRect(dl_image, src, dst, sampling, opt_paint, SkCanvas::kFast_SrcRectConstraint); } return Dart_Null(); @@ -459,9 +468,10 @@ Dart_Handle Canvas::drawImageNine(const CanvasImage* image, SkRect dst = SkRect::MakeLTRB(dst_left, dst_top, dst_right, dst_bottom); auto filter = ImageFilter::FilterModeFromIndex(bitmapSamplingIndex); if (display_list_builder_) { - bool with_attributes = - paint.sync_to(builder(), kDrawImageNineWithPaintFlags); - builder()->drawImageNine(dl_image, icenter, dst, filter, with_attributes); + DlPaint dl_paint; + const DlPaint* opt_paint = + paint.paint(dl_paint, kDrawImageNineWithPaintFlags); + builder()->DrawImageNine(dl_image, icenter, dst, filter, opt_paint); } return Dart_Null(); } @@ -474,7 +484,7 @@ void Canvas::drawPicture(Picture* picture) { } if (picture->display_list()) { if (display_list_builder_) { - builder()->drawDisplayList(picture->display_list()); + builder()->DrawDisplayList(picture->display_list()); } } else { FML_DCHECK(false); @@ -492,20 +502,22 @@ void Canvas::drawPoints(Dart_Handle paint_objects, FML_DCHECK(paint.isNotNull()); if (display_list_builder_) { + DlPaint dl_paint; switch (point_mode) { case DlCanvas::PointMode::kPoints: - paint.sync_to(builder(), kDrawPointsAsPointsFlags); + paint.paint(dl_paint, kDrawPointsAsPointsFlags); break; case DlCanvas::PointMode::kLines: - paint.sync_to(builder(), kDrawPointsAsLinesFlags); + paint.paint(dl_paint, kDrawPointsAsLinesFlags); break; case DlCanvas::PointMode::kPolygon: - paint.sync_to(builder(), kDrawPointsAsPolygonFlags); + paint.paint(dl_paint, kDrawPointsAsPolygonFlags); break; } - builder()->drawPoints(point_mode, + builder()->DrawPoints(point_mode, points.num_elements() / 2, // SkPoints have 2 floats - reinterpret_cast(points.data())); + reinterpret_cast(points.data()), + dl_paint); } } @@ -522,8 +534,9 @@ void Canvas::drawVertices(const Vertices* vertices, } FML_DCHECK(paint.isNotNull()); if (display_list_builder_) { - paint.sync_to(builder(), kDrawVerticesFlags); - builder()->drawVertices(vertices->vertices(), blend_mode); + DlPaint dl_paint; + paint.paint(dl_paint, kDrawVerticesFlags); + builder()->DrawVertices(vertices->vertices(), blend_mode, dl_paint); } } @@ -564,14 +577,15 @@ Dart_Handle Canvas::drawAtlas(Dart_Handle paint_objects, tonic::Int32List colors(colors_handle); tonic::Float32List cull_rect(cull_rect_handle); - bool with_attributes = paint.sync_to(builder(), kDrawAtlasWithPaintFlags); - builder()->drawAtlas( + DlPaint dl_paint; + const DlPaint* opt_paint = paint.paint(dl_paint, kDrawAtlasWithPaintFlags); + builder()->DrawAtlas( dl_image, 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()), - with_attributes); + opt_paint); } return Dart_Null(); } @@ -598,7 +612,7 @@ void Canvas::drawShadow(const CanvasPath* path, // that situation we bypass the canvas interface and inject the // shadow parameters directly into the underlying DisplayList. // See: https://bugs.chromium.org/p/skia/issues/detail?id=12125 - builder()->drawShadow(path->path(), color, elevation, transparentOccluder, + builder()->DrawShadow(path->path(), color, elevation, transparentOccluder, dpr); } } diff --git a/lib/ui/painting/color_filter.cc b/lib/ui/painting/color_filter.cc index 12b0db95892df..06d421b377369 100644 --- a/lib/ui/painting/color_filter.cc +++ b/lib/ui/painting/color_filter.cc @@ -23,8 +23,8 @@ void ColorFilter::Create(Dart_Handle wrapper) { } void ColorFilter::initMode(int color, int blend_mode) { - filter_ = std::make_shared( - static_cast(color), static_cast(blend_mode)); + filter_ = DlBlendColorFilter::Make(static_cast(color), + static_cast(blend_mode)); } void ColorFilter::initMatrix(const tonic::Float32List& color_matrix) { @@ -39,7 +39,7 @@ void ColorFilter::initMatrix(const tonic::Float32List& color_matrix) { matrix[9] *= 1.0f / 255; matrix[14] *= 1.0f / 255; matrix[19] *= 1.0f / 255; - filter_ = std::make_shared(matrix); + filter_ = DlMatrixColorFilter::Make(matrix); } void ColorFilter::initLinearToSrgbGamma() { diff --git a/lib/ui/painting/color_filter.h b/lib/ui/painting/color_filter.h index f80c48d96fe2f..b7aa2e2bc7016 100644 --- a/lib/ui/painting/color_filter.h +++ b/lib/ui/painting/color_filter.h @@ -31,9 +31,6 @@ class ColorFilter : public RefCountedDartWrappable { ~ColorFilter() override; const std::shared_ptr filter() const { return filter_; } - const DlColorFilter* dl_filter() const { - return (filter_ && filter_->skia_object()) ? filter_.get() : nullptr; - } private: std::shared_ptr filter_; diff --git a/lib/ui/painting/gradient.cc b/lib/ui/painting/gradient.cc index 9651982c183c4..5f586a384dc7b 100644 --- a/lib/ui/painting/gradient.cc +++ b/lib/ui/painting/gradient.cc @@ -25,7 +25,7 @@ void CanvasGradient::Create(Dart_Handle wrapper) { void CanvasGradient::initLinear(const tonic::Float32List& end_points, const tonic::Int32List& colors, const tonic::Float32List& color_stops, - SkTileMode tile_mode, + DlTileMode tile_mode, const tonic::Float64List& matrix4) { FML_DCHECK(end_points.num_elements() == 4); FML_DCHECK(colors.num_elements() == color_stops.num_elements() || @@ -48,7 +48,7 @@ void CanvasGradient::initLinear(const tonic::Float32List& end_points, dl_shader_ = DlColorSource::MakeLinear( p0, p1, colors.num_elements(), colors_array, color_stops.data(), - ToDl(tile_mode), has_matrix ? &sk_matrix : nullptr); + tile_mode, has_matrix ? &sk_matrix : nullptr); } void CanvasGradient::initRadial(double center_x, @@ -56,7 +56,7 @@ void CanvasGradient::initRadial(double center_x, double radius, const tonic::Int32List& colors, const tonic::Float32List& color_stops, - SkTileMode tile_mode, + DlTileMode tile_mode, const tonic::Float64List& matrix4) { FML_DCHECK(colors.num_elements() == color_stops.num_elements() || color_stops.data() == nullptr); @@ -74,7 +74,7 @@ void CanvasGradient::initRadial(double center_x, dl_shader_ = DlColorSource::MakeRadial( SkPoint::Make(center_x, center_y), radius, colors.num_elements(), - colors_array, color_stops.data(), ToDl(tile_mode), + colors_array, color_stops.data(), tile_mode, has_matrix ? &sk_matrix : nullptr); } @@ -82,7 +82,7 @@ void CanvasGradient::initSweep(double center_x, double center_y, const tonic::Int32List& colors, const tonic::Float32List& color_stops, - SkTileMode tile_mode, + DlTileMode tile_mode, double start_angle, double end_angle, const tonic::Float64List& matrix4) { @@ -103,7 +103,7 @@ void CanvasGradient::initSweep(double center_x, dl_shader_ = DlColorSource::MakeSweep( SkPoint::Make(center_x, center_y), start_angle * 180.0 / M_PI, end_angle * 180.0 / M_PI, colors.num_elements(), colors_array, - color_stops.data(), ToDl(tile_mode), has_matrix ? &sk_matrix : nullptr); + color_stops.data(), tile_mode, has_matrix ? &sk_matrix : nullptr); } void CanvasGradient::initTwoPointConical(double start_x, @@ -114,7 +114,7 @@ void CanvasGradient::initTwoPointConical(double start_x, double end_radius, const tonic::Int32List& colors, const tonic::Float32List& color_stops, - SkTileMode tile_mode, + DlTileMode tile_mode, const tonic::Float64List& matrix4) { FML_DCHECK(colors.num_elements() == color_stops.num_elements() || color_stops.data() == nullptr); @@ -134,7 +134,7 @@ void CanvasGradient::initTwoPointConical(double start_x, SkPoint::Make(start_x, start_y), start_radius, // SkPoint::Make(end_x, end_y), end_radius, // colors.num_elements(), colors_array, color_stops.data(), // - ToDl(tile_mode), has_matrix ? &sk_matrix : nullptr); + tile_mode, has_matrix ? &sk_matrix : nullptr); } CanvasGradient::CanvasGradient() = default; diff --git a/lib/ui/painting/gradient.h b/lib/ui/painting/gradient.h index 5041ab27426f3..9222fb83634e6 100644 --- a/lib/ui/painting/gradient.h +++ b/lib/ui/painting/gradient.h @@ -12,9 +12,6 @@ namespace flutter { -// TODO: update this if/when Skia adds Decal mode skbug.com/7638 -static_assert(kSkTileModeCount >= 3, "Need to update tile mode enum"); - class CanvasGradient : public Shader { DEFINE_WRAPPERTYPEINFO(); FML_FRIEND_MAKE_REF_COUNTED(CanvasGradient); @@ -26,7 +23,7 @@ class CanvasGradient : public Shader { void initLinear(const tonic::Float32List& end_points, const tonic::Int32List& colors, const tonic::Float32List& color_stops, - SkTileMode tile_mode, + DlTileMode tile_mode, const tonic::Float64List& matrix4); void initRadial(double center_x, @@ -34,14 +31,14 @@ class CanvasGradient : public Shader { double radius, const tonic::Int32List& colors, const tonic::Float32List& color_stops, - SkTileMode tile_mode, + DlTileMode tile_mode, const tonic::Float64List& matrix4); void initSweep(double center_x, double center_y, const tonic::Int32List& colors, const tonic::Float32List& color_stops, - SkTileMode tile_mode, + DlTileMode tile_mode, double start_angle, double end_angle, const tonic::Float64List& matrix4); @@ -54,7 +51,7 @@ class CanvasGradient : public Shader { double end_radius, const tonic::Int32List& colors, const tonic::Float32List& color_stops, - SkTileMode tile_mode, + DlTileMode tile_mode, const tonic::Float64List& matrix4); std::shared_ptr shader(DlImageSampling sampling) override { diff --git a/lib/ui/painting/image_filter.cc b/lib/ui/painting/image_filter.cc index 665d3b0372b77..d92db00f550b0 100644 --- a/lib/ui/painting/image_filter.cc +++ b/lib/ui/painting/image_filter.cc @@ -52,45 +52,32 @@ ImageFilter::~ImageFilter() {} void ImageFilter::initBlur(double sigma_x, double sigma_y, - SkTileMode tile_mode) { - filter_ = - std::make_shared(sigma_x, sigma_y, ToDl(tile_mode)); + DlTileMode tile_mode) { + filter_ = DlBlurImageFilter::Make(sigma_x, sigma_y, tile_mode); } void ImageFilter::initDilate(double radius_x, double radius_y) { - filter_ = std::make_shared(radius_x, radius_y); + filter_ = DlDilateImageFilter::Make(radius_x, radius_y); } void ImageFilter::initErode(double radius_x, double radius_y) { - filter_ = std::make_shared(radius_x, radius_y); + filter_ = DlErodeImageFilter::Make(radius_x, radius_y); } void ImageFilter::initMatrix(const tonic::Float64List& matrix4, int filterQualityIndex) { auto sampling = ImageFilter::SamplingFromIndex(filterQualityIndex); - filter_ = - std::make_shared(ToSkMatrix(matrix4), sampling); + filter_ = DlMatrixImageFilter::Make(ToSkMatrix(matrix4), sampling); } void ImageFilter::initColorFilter(ColorFilter* colorFilter) { FML_DCHECK(colorFilter); - auto dl_filter = colorFilter->dl_filter(); - // Skia may return nullptr if the colorfilter is a no-op. - if (dl_filter) { - filter_ = std::make_shared(dl_filter); - } + filter_ = DlColorFilterImageFilter::Make(colorFilter->filter()); } void ImageFilter::initComposeFilter(ImageFilter* outer, ImageFilter* inner) { FML_DCHECK(outer && inner); - if (!outer->dl_filter()) { - filter_ = inner->filter(); - } else if (!inner->dl_filter()) { - filter_ = outer->filter(); - } else { - filter_ = std::make_shared(outer->dl_filter(), - inner->dl_filter()); - } + filter_ = DlComposeImageFilter::Make(outer->filter(), inner->filter()); } } // namespace flutter diff --git a/lib/ui/painting/image_filter.h b/lib/ui/painting/image_filter.h index 67d97385e702d..66e30121ad206 100644 --- a/lib/ui/painting/image_filter.h +++ b/lib/ui/painting/image_filter.h @@ -30,7 +30,7 @@ class ImageFilter : public RefCountedDartWrappable { static DlImageSampling SamplingFromIndex(int filterQualityIndex); static DlFilterMode FilterModeFromIndex(int index); - void initBlur(double sigma_x, double sigma_y, SkTileMode tile_mode); + void initBlur(double sigma_x, double sigma_y, DlTileMode tile_mode); void initDilate(double radius_x, double radius_y); void initErode(double radius_x, double radius_y); void initMatrix(const tonic::Float64List& matrix4, int filter_quality_index); @@ -38,9 +38,6 @@ class ImageFilter : public RefCountedDartWrappable { void initComposeFilter(ImageFilter* outer, ImageFilter* inner); const std::shared_ptr filter() const { return filter_; } - const DlImageFilter* dl_filter() const { - return (filter_ && filter_->skia_object()) ? filter_.get() : nullptr; - } static void RegisterNatives(tonic::DartLibraryNatives* natives); diff --git a/lib/ui/painting/image_shader.cc b/lib/ui/painting/image_shader.cc index bd00fd1766e78..e2cdae7dfb308 100644 --- a/lib/ui/painting/image_shader.cc +++ b/lib/ui/painting/image_shader.cc @@ -24,8 +24,8 @@ void ImageShader::Create(Dart_Handle wrapper) { } Dart_Handle ImageShader::initWithImage(CanvasImage* image, - SkTileMode tmx, - SkTileMode tmy, + DlTileMode tmx, + DlTileMode tmy, int filter_quality_index, Dart_Handle matrix_handle) { if (!image) { @@ -41,7 +41,7 @@ Dart_Handle ImageShader::initWithImage(CanvasImage* image, sampling_is_locked_ ? ImageFilter::SamplingFromIndex(filter_quality_index) : DlImageSampling::kLinear; cached_shader_ = UIDartState::CreateGPUObject(sk_make_sp( - image_, ToDl(tmx), ToDl(tmy), sampling, &local_matrix)); + image_, tmx, tmy, sampling, &local_matrix)); return Dart_Null(); } diff --git a/lib/ui/painting/image_shader.h b/lib/ui/painting/image_shader.h index d130c5d53c390..7c69d1389bd89 100644 --- a/lib/ui/painting/image_shader.h +++ b/lib/ui/painting/image_shader.h @@ -25,8 +25,8 @@ class ImageShader : public Shader { static void Create(Dart_Handle wrapper); Dart_Handle initWithImage(CanvasImage* image, - SkTileMode tmx, - SkTileMode tmy, + DlTileMode tmx, + DlTileMode tmy, int filter_quality_index, Dart_Handle matrix_handle); diff --git a/lib/ui/painting/paint.cc b/lib/ui/painting/paint.cc index 2849526ca00a4..f4beac1abbed6 100644 --- a/lib/ui/painting/paint.cc +++ b/lib/ui/painting/paint.cc @@ -53,148 +53,17 @@ constexpr uint32_t kBlendModeDefault = // default SkPaintDefaults_MiterLimit in Skia (which is not in a public header). constexpr double kStrokeMiterLimitDefault = 4.0; -// A color matrix which inverts colors. -// clang-format off -constexpr float kInvertColors[20] = { - -1.0, 0, 0, 1.0, 0, - 0, -1.0, 0, 1.0, 0, - 0, 0, -1.0, 1.0, 0, - 1.0, 1.0, 1.0, 1.0, 0 -}; -// clang-format on - // Must be kept in sync with the MaskFilter private constants in painting.dart. enum MaskFilterType { kNull, kBlur }; Paint::Paint(Dart_Handle paint_objects, Dart_Handle paint_data) : paint_objects_(paint_objects), paint_data_(paint_data) {} -const SkPaint* Paint::paint(SkPaint& paint) const { +const DlPaint* Paint::paint(DlPaint& paint, + const DisplayListAttributeFlags& flags) const { if (isNull()) { return nullptr; } - FML_DCHECK(paint == SkPaint()); - - tonic::DartByteData byte_data(paint_data_); - FML_CHECK(byte_data.length_in_bytes() == kDataByteCount); - - const uint32_t* uint_data = static_cast(byte_data.data()); - const float* float_data = static_cast(byte_data.data()); - - Dart_Handle values[kObjectCount]; - if (!Dart_IsNull(paint_objects_)) { - FML_DCHECK(Dart_IsList(paint_objects_)); - intptr_t length = 0; - Dart_ListLength(paint_objects_, &length); - - FML_CHECK(length == kObjectCount); - if (Dart_IsError( - Dart_ListGetRange(paint_objects_, 0, kObjectCount, values))) { - return nullptr; - } - - Dart_Handle shader = values[kShaderIndex]; - if (!Dart_IsNull(shader)) { - if (Shader* decoded = tonic::DartConverter::FromDart(shader)) { - auto sampling = - ImageFilter::SamplingFromIndex(uint_data[kFilterQualityIndex]); - auto color_source = decoded->shader(sampling); - // TODO(dnfield): Remove this restriction. - // This currently is only used by paragraph code. Once SkParagraph does - // not need to take an SkPaint, we won't be restricted in this way - // because we will not need to access the shader on the UI task runner. - if (color_source->owning_context() != DlImage::OwningContext::kRaster) { - paint.setShader(color_source->skia_object()); - } - } - } - - Dart_Handle color_filter = values[kColorFilterIndex]; - if (!Dart_IsNull(color_filter)) { - ColorFilter* decoded = - tonic::DartConverter::FromDart(color_filter); - paint.setColorFilter(decoded->filter()->skia_object()); - } - - Dart_Handle image_filter = values[kImageFilterIndex]; - if (!Dart_IsNull(image_filter)) { - ImageFilter* decoded = - tonic::DartConverter::FromDart(image_filter); - paint.setImageFilter(decoded->filter()->skia_object()); - } - } - - paint.setAntiAlias(uint_data[kIsAntiAliasIndex] == 0); - - uint32_t encoded_color = uint_data[kColorIndex]; - if (encoded_color) { - SkColor color = encoded_color ^ kColorDefault; - paint.setColor(color); - } - - uint32_t encoded_blend_mode = uint_data[kBlendModeIndex]; - if (encoded_blend_mode) { - uint32_t blend_mode = encoded_blend_mode ^ kBlendModeDefault; - paint.setBlendMode(static_cast(blend_mode)); - } - - uint32_t style = uint_data[kStyleIndex]; - if (style) { - paint.setStyle(static_cast(style)); - } - - float stroke_width = float_data[kStrokeWidthIndex]; - if (stroke_width != 0.0) { - paint.setStrokeWidth(stroke_width); - } - - uint32_t stroke_cap = uint_data[kStrokeCapIndex]; - if (stroke_cap) { - paint.setStrokeCap(static_cast(stroke_cap)); - } - - uint32_t stroke_join = uint_data[kStrokeJoinIndex]; - if (stroke_join) { - paint.setStrokeJoin(static_cast(stroke_join)); - } - - float stroke_miter_limit = float_data[kStrokeMiterLimitIndex]; - if (stroke_miter_limit != 0.0) { - paint.setStrokeMiter(stroke_miter_limit + kStrokeMiterLimitDefault); - } - - if (uint_data[kInvertColorIndex]) { - sk_sp invert_filter = SkColorFilters::Matrix(kInvertColors); - sk_sp current_filter = paint.refColorFilter(); - if (current_filter) { - invert_filter = invert_filter->makeComposed(current_filter); - } - paint.setColorFilter(invert_filter); - } - - if (uint_data[kDitherIndex]) { - paint.setDither(true); - } - - switch (uint_data[kMaskFilterIndex]) { - case kNull: - break; - case kBlur: - SkBlurStyle blur_style = - static_cast(uint_data[kMaskFilterBlurStyleIndex]); - double sigma = float_data[kMaskFilterSigmaIndex]; - paint.setMaskFilter(SkMaskFilter::MakeBlur(blur_style, sigma)); - break; - } - - return &paint; -} - -bool Paint::sync_to(DisplayListBuilder* builder, - const DisplayListAttributeFlags& flags) const { - if (isNull()) { - return false; - } tonic::DartByteData byte_data(paint_data_); FML_CHECK(byte_data.length_in_bytes() == kDataByteCount); @@ -204,13 +73,13 @@ bool Paint::sync_to(DisplayListBuilder* builder, Dart_Handle values[kObjectCount]; if (Dart_IsNull(paint_objects_)) { if (flags.applies_shader()) { - builder->setColorSource(nullptr); + paint.setColorSource(nullptr); } if (flags.applies_color_filter()) { - builder->setColorFilter(nullptr); + paint.setColorFilter(nullptr); } if (flags.applies_image_filter()) { - builder->setImageFilter(nullptr); + paint.setImageFilter(nullptr); } } else { FML_DCHECK(Dart_IsList(paint_objects_)); @@ -220,20 +89,20 @@ bool Paint::sync_to(DisplayListBuilder* builder, FML_CHECK(length == kObjectCount); if (Dart_IsError( Dart_ListGetRange(paint_objects_, 0, kObjectCount, values))) { - return false; + return nullptr; } if (flags.applies_shader()) { Dart_Handle shader = values[kShaderIndex]; if (Dart_IsNull(shader)) { - builder->setColorSource(nullptr); + paint.setColorSource(nullptr); } else { if (Shader* decoded = tonic::DartConverter::FromDart(shader)) { auto sampling = ImageFilter::SamplingFromIndex(uint_data[kFilterQualityIndex]); - builder->setColorSource(decoded->shader(sampling).get()); + paint.setColorSource(decoded->shader(sampling).get()); } else { - builder->setColorSource(nullptr); + paint.setColorSource(nullptr); } } } @@ -241,94 +110,89 @@ bool Paint::sync_to(DisplayListBuilder* builder, if (flags.applies_color_filter()) { Dart_Handle color_filter = values[kColorFilterIndex]; if (Dart_IsNull(color_filter)) { - builder->setColorFilter(nullptr); + paint.setColorFilter(nullptr); } else { ColorFilter* decoded = tonic::DartConverter::FromDart(color_filter); - builder->setColorFilter(decoded->dl_filter()); + paint.setColorFilter(decoded->filter()); } } if (flags.applies_image_filter()) { Dart_Handle image_filter = values[kImageFilterIndex]; if (Dart_IsNull(image_filter)) { - builder->setImageFilter(nullptr); + paint.setImageFilter(nullptr); } else { ImageFilter* decoded = tonic::DartConverter::FromDart(image_filter); - builder->setImageFilter(decoded->dl_filter()); + paint.setImageFilter(decoded->filter()); } } } if (flags.applies_anti_alias()) { - builder->setAntiAlias(uint_data[kIsAntiAliasIndex] == 0); + paint.setAntiAlias(uint_data[kIsAntiAliasIndex] == 0); } if (flags.applies_alpha_or_color()) { uint32_t encoded_color = uint_data[kColorIndex]; - builder->setColor(encoded_color ^ kColorDefault); + paint.setColor(encoded_color ^ kColorDefault); } 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)); + paint.setBlendMode(static_cast(blend_mode)); } if (flags.applies_style()) { uint32_t style = uint_data[kStyleIndex]; - builder->setStyle(static_cast(style)); + paint.setDrawStyle(static_cast(style)); } - if (flags.is_stroked(builder->getStyle())) { + if (flags.is_stroked(paint.getDrawStyle())) { float stroke_width = float_data[kStrokeWidthIndex]; - builder->setStrokeWidth(stroke_width); + paint.setStrokeWidth(stroke_width); float stroke_miter_limit = float_data[kStrokeMiterLimitIndex]; - builder->setStrokeMiter(stroke_miter_limit + kStrokeMiterLimitDefault); + paint.setStrokeMiter(stroke_miter_limit + kStrokeMiterLimitDefault); uint32_t stroke_cap = uint_data[kStrokeCapIndex]; - builder->setStrokeCap(static_cast(stroke_cap)); + paint.setStrokeCap(static_cast(stroke_cap)); uint32_t stroke_join = uint_data[kStrokeJoinIndex]; - builder->setStrokeJoin(static_cast(stroke_join)); + paint.setStrokeJoin(static_cast(stroke_join)); } if (flags.applies_color_filter()) { - builder->setInvertColors(uint_data[kInvertColorIndex] != 0); + paint.setInvertColors(uint_data[kInvertColorIndex] != 0); } if (flags.applies_dither()) { - builder->setDither(uint_data[kDitherIndex] != 0); + paint.setDither(uint_data[kDitherIndex] != 0); } if (flags.applies_path_effect()) { // The paint API exposed to Dart does not support path effects. But other // operations such as text may set a path effect, which must be cleared. - builder->setPathEffect(nullptr); + paint.setPathEffect(nullptr); } if (flags.applies_mask_filter()) { switch (uint_data[kMaskFilterIndex]) { case kNull: - builder->setMaskFilter(nullptr); + paint.setMaskFilter(nullptr); break; case kBlur: SkBlurStyle blur_style = static_cast(uint_data[kMaskFilterBlurStyleIndex]); double sigma = float_data[kMaskFilterSigmaIndex]; - DlBlurMaskFilter dl_filter(blur_style, sigma); - if (dl_filter.skia_object()) { - builder->setMaskFilter(&dl_filter); - } else { - builder->setMaskFilter(nullptr); - } + paint.setMaskFilter(DlBlurMaskFilter::Make(blur_style, sigma)); break; } } - return true; + return &paint; } void Paint::toDlPaint(DlPaint& paint) const { @@ -414,11 +278,14 @@ void Paint::toDlPaint(DlPaint& paint) const { SkBlurStyle blur_style = static_cast(uint_data[kMaskFilterBlurStyleIndex]); double sigma = float_data[kMaskFilterSigmaIndex]; - std::shared_ptr dl_filter = - std::make_shared(blur_style, sigma); - if (dl_filter->skia_object()) { - paint.setMaskFilter(dl_filter); - } + // Make could return a nullptr here if the values are NOP or + // do not make sense. We could interpret that as if there was + // no value passed from Dart at all (i.e. don't change the + // setting in the paint object as in the kNull branch right + // above here), but the maskfilter flag was actually set + // indicating that the developer "tried" to set a mask, so we + // should set the null value rather than do nothing. + paint.setMaskFilter(DlBlurMaskFilter::Make(blur_style, sigma)); break; } } diff --git a/lib/ui/painting/paint.h b/lib/ui/painting/paint.h index 6e74535dbe726..466f26ad680ce 100644 --- a/lib/ui/painting/paint.h +++ b/lib/ui/painting/paint.h @@ -17,19 +17,11 @@ class Paint { Paint() = default; Paint(Dart_Handle paint_objects, Dart_Handle paint_data); - const SkPaint* paint(SkPaint& paint) const; + const DlPaint* paint(DlPaint& paint, + const DisplayListAttributeFlags& flags) const; void toDlPaint(DlPaint& paint) const; - /// Synchronize the Dart properties to the display list according - /// to the attribute flags that indicate which properties are needed. - /// The return value indicates if the paint was non-null and can - /// either be DCHECKed or used to indicate to the DisplayList - /// draw operation whether or not to use the synchronized attributes - /// (mainly the drawImage and saveLayer methods). - bool sync_to(DisplayListBuilder* builder, - const DisplayListAttributeFlags& flags) const; - bool isNull() const { return Dart_IsNull(paint_data_); } bool isNotNull() const { return !Dart_IsNull(paint_data_); } diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index e1b1789dad1be..ebd2ff29ee724 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -270,9 +270,9 @@ std::unique_ptr MakeBitmapImage( }; sk_sp surface = SkSurface::MakeRaster(image_info); - SkCanvas* canvas = surface->getCanvas(); - canvas->clear(SK_ColorTRANSPARENT); - display_list->RenderTo(canvas); + auto canvas = DlSkCanvasAdapter(surface->getCanvas()); + canvas.Clear(DlColor::kTransparent()); + canvas.DrawDisplayList(display_list); sk_sp image = surface->makeImageSnapshot(); return std::make_unique( @@ -335,9 +335,9 @@ std::unique_ptr Rasterizer::MakeSkiaGpuImage( return; } - SkCanvas* canvas = sk_surface->getCanvas(); - canvas->clear(SK_ColorTRANSPARENT); - display_list->RenderTo(canvas); + auto canvas = DlSkCanvasAdapter(sk_surface->getCanvas()); + canvas.Clear(DlColor::kTransparent()); + canvas.DrawDisplayList(display_list); result = std::make_unique( texture, sk_ref_sp(context), nullptr, ""); diff --git a/shell/common/snapshot_controller_skia.cc b/shell/common/snapshot_controller_skia.cc index 27b67008e417d..0e2fdea910451 100644 --- a/shell/common/snapshot_controller_skia.cc +++ b/shell/common/snapshot_controller_skia.cc @@ -126,7 +126,7 @@ sk_sp SnapshotControllerSkia::MakeRasterSnapshot( sk_sp display_list, SkISize size) { return DoMakeRasterSnapshot(size, [display_list](SkCanvas* canvas) { - display_list->RenderTo(canvas); + DlSkCanvasAdapter(canvas).DrawDisplayList(display_list); }); } diff --git a/testing/display_list_testing.cc b/testing/display_list_testing.cc index 2caadcb7245ad..122e9008639df 100644 --- a/testing/display_list_testing.cc +++ b/testing/display_list_testing.cc @@ -448,7 +448,7 @@ void DisplayListStreamDispatcher::setColorSource(const DlColorSource* source) { break; } default: - os_ << "DlUnknownColorSource(" << source->skia_object().get() << ")"; + os_ << "?DlUnknownColorSource?()"; break; } os_ << ");" << std::endl; @@ -490,7 +490,7 @@ void DisplayListStreamDispatcher::out(const DlColorFilter& filter) { break; } default: - os_ << "DlUnknownColorFilter(" << filter.skia_object().get() << ")"; + os_ << "?DlUnknownColorFilter?()"; break; } } @@ -530,7 +530,7 @@ void DisplayListStreamDispatcher::setMaskFilter(const DlMaskFilter* filter) { break; } default: - os_ << "DlUnknownMaskFilter(" << filter->skia_object().get() << ")"; + os_ << "?DlUnknownMaskFilter?()"; break; } os_ << ");" << std::endl; @@ -563,7 +563,7 @@ void DisplayListStreamDispatcher::out(const DlImageFilter& filter) { os_ << "DlMatrixImageFilter(" << matrix->matrix() << ", " << matrix->sampling() << ")"; break; } - case DlImageFilterType::kComposeFilter: { + case DlImageFilterType::kCompose: { const DlComposeImageFilter* compose = filter.asCompose(); FML_DCHECK(compose); os_ << "DlComposeImageFilter(" << std::endl; @@ -590,7 +590,7 @@ void DisplayListStreamDispatcher::out(const DlImageFilter& filter) { os_ << ")"; break; } - case DlImageFilterType::kLocalMatrixFilter: { + case DlImageFilterType::kLocalMatrix: { const DlLocalMatrixImageFilter* local_matrix = filter.asLocalMatrix(); FML_DCHECK(local_matrix); os_ << "DlLocalMatrixImageFilter(" << local_matrix->matrix(); @@ -810,13 +810,13 @@ void DisplayListStreamDispatcher::drawImageRect(const sk_sp image, const SkRect& dst, DlImageSampling sampling, bool render_with_attributes, - SkCanvas::SrcRectConstraint constraint) { + bool enforce_src_edges) { startl() << "drawImageRect(" << image.get() << "," << std::endl; startl() << " src: " << src << "," << std::endl; startl() << " dst: " << dst << "," << std::endl; startl() << " " << sampling << ", " << "with attributes: " << render_with_attributes << ", " - << constraint + << "enforce src edges: " << enforce_src_edges << ");" << std::endl; } void DisplayListStreamDispatcher::drawImageNine(const sk_sp image, @@ -849,8 +849,12 @@ void DisplayListStreamDispatcher::drawAtlas(const sk_sp atlas, << ");" << std::endl; } void DisplayListStreamDispatcher::drawDisplayList( - const sk_sp display_list) { - startl() << "drawDisplayList(ID: " << display_list->unique_id() << ", bounds: " << display_list->bounds() << ");" << std::endl; + const sk_sp display_list, SkScalar opacity) { + startl() << "drawDisplayList(" + << "ID: " << display_list->unique_id() << ", " + << "bounds: " << display_list->bounds() << ", " + << "opacity: " << opacity + << ");" << std::endl; } void DisplayListStreamDispatcher::drawTextBlob(const sk_sp blob, SkScalar x, diff --git a/testing/display_list_testing.h b/testing/display_list_testing.h index 26d5af0329940..54b698033fb2b 100644 --- a/testing/display_list_testing.h +++ b/testing/display_list_testing.h @@ -8,8 +8,8 @@ #include #include "flutter/display_list/display_list.h" -#include "flutter/display_list/display_list_dispatcher.h" #include "flutter/display_list/display_list_path_effect.h" +#include "flutter/display_list/dl_op_receiver.h" namespace flutter { namespace testing { @@ -47,7 +47,7 @@ extern std::ostream& operator<<(std::ostream& os, const DlVertexMode& mode); extern std::ostream& operator<<(std::ostream& os, const DlTileMode& mode); extern std::ostream& operator<<(std::ostream& os, const DlImage* image); -class DisplayListStreamDispatcher final : public Dispatcher { +class DisplayListStreamDispatcher final : public DlOpReceiver { public: DisplayListStreamDispatcher(std::ostream& os, int cur_indent = 2, @@ -121,7 +121,7 @@ class DisplayListStreamDispatcher final : public Dispatcher { const SkRect& dst, DlImageSampling sampling, bool render_with_attributes, - SkCanvas::SrcRectConstraint constraint) override; + bool enforce_src_edges) override; void drawImageNine(const sk_sp image, const SkIRect& center, const SkRect& dst, @@ -136,7 +136,8 @@ class DisplayListStreamDispatcher final : public Dispatcher { DlImageSampling sampling, const SkRect* cull_rect, bool render_with_attributes) override; - void drawDisplayList(const sk_sp display_list) override; + void drawDisplayList(const sk_sp display_list, + SkScalar opacity) override; void drawTextBlob(const sk_sp blob, SkScalar x, SkScalar y) override; From 03a95cf5220bce9a9b49c08010e8bb691cb8ad81 Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Tue, 7 Mar 2023 09:49:49 +1300 Subject: [PATCH 3/9] Fix incorrect response to platform SystemSound.play (#39992) * Fix incorrect response to platform SystemSound.play * Add tests for FlPlatformPlugin --- ci/licenses_golden/licenses_flutter | 2 + shell/platform/linux/BUILD.gn | 1 + shell/platform/linux/fl_platform_plugin.cc | 2 +- .../platform/linux/fl_platform_plugin_test.cc | 47 +++++++++++++++++++ 4 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 shell/platform/linux/fl_platform_plugin_test.cc diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 40f7e6f9f7533..6e21e8a07522f 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -2927,6 +2927,7 @@ ORIGIN: ../../../flutter/shell/platform/linux/fl_pixel_buffer_texture_private.h ORIGIN: ../../../flutter/shell/platform/linux/fl_pixel_buffer_texture_test.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/linux/fl_platform_plugin.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/linux/fl_platform_plugin.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/linux/fl_platform_plugin_test.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/linux/fl_plugin_registrar.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/linux/fl_plugin_registrar_private.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/linux/fl_plugin_registrar_test.cc + ../../../flutter/LICENSE @@ -5480,6 +5481,7 @@ FILE: ../../../flutter/shell/platform/linux/fl_pixel_buffer_texture_private.h FILE: ../../../flutter/shell/platform/linux/fl_pixel_buffer_texture_test.cc FILE: ../../../flutter/shell/platform/linux/fl_platform_plugin.cc FILE: ../../../flutter/shell/platform/linux/fl_platform_plugin.h +FILE: ../../../flutter/shell/platform/linux/fl_platform_plugin_test.cc FILE: ../../../flutter/shell/platform/linux/fl_plugin_registrar.cc FILE: ../../../flutter/shell/platform/linux/fl_plugin_registrar_private.h FILE: ../../../flutter/shell/platform/linux/fl_plugin_registrar_test.cc diff --git a/shell/platform/linux/BUILD.gn b/shell/platform/linux/BUILD.gn index 2b6a0cf95e8e4..5cb9f2839aaa8 100644 --- a/shell/platform/linux/BUILD.gn +++ b/shell/platform/linux/BUILD.gn @@ -212,6 +212,7 @@ executable("flutter_linux_unittests") { "fl_method_codec_test.cc", "fl_method_response_test.cc", "fl_pixel_buffer_texture_test.cc", + "fl_platform_plugin_test.cc", "fl_plugin_registrar_test.cc", "fl_scrolling_manager_test.cc", "fl_settings_plugin_test.cc", diff --git a/shell/platform/linux/fl_platform_plugin.cc b/shell/platform/linux/fl_platform_plugin.cc index 86fee31da8d79..15076266cb190 100644 --- a/shell/platform/linux/fl_platform_plugin.cc +++ b/shell/platform/linux/fl_platform_plugin.cc @@ -160,7 +160,7 @@ static FlMethodResponse* system_sound_play(FlPlatformPlugin* self, g_warning("Ignoring unknown sound type %s in SystemSound.play.\n", type); } - return FL_METHOD_RESPONSE(fl_method_not_implemented_response_new()); + return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr)); } // Called when Flutter wants to quit the application. diff --git a/shell/platform/linux/fl_platform_plugin_test.cc b/shell/platform/linux/fl_platform_plugin_test.cc new file mode 100644 index 0000000000000..88051e829443c --- /dev/null +++ b/shell/platform/linux/fl_platform_plugin_test.cc @@ -0,0 +1,47 @@ +// 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/shell/platform/linux/fl_platform_plugin.h" +#include "flutter/shell/platform/linux/fl_binary_messenger_private.h" +#include "flutter/shell/platform/linux/fl_method_codec_private.h" +#include "flutter/shell/platform/linux/public/flutter_linux/fl_json_method_codec.h" +#include "flutter/shell/platform/linux/public/flutter_linux/fl_method_codec.h" +#include "flutter/shell/platform/linux/testing/fl_test.h" +#include "flutter/shell/platform/linux/testing/mock_binary_messenger.h" +#include "flutter/testing/testing.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +MATCHER_P(SuccessResponse, result, "") { + g_autoptr(FlJsonMethodCodec) codec = fl_json_method_codec_new(); + g_autoptr(FlMethodResponse) response = + fl_method_codec_decode_response(FL_METHOD_CODEC(codec), arg, nullptr); + if (fl_value_equal(fl_method_response_get_result(response, nullptr), + result)) { + return true; + } + *result_listener << ::testing::PrintToString(response); + return false; +} + +TEST(FlPlatformPluginTest, PlaySound) { + ::testing::NiceMock messenger; + + g_autoptr(FlPlatformPlugin) plugin = fl_platform_plugin_new(messenger); + EXPECT_NE(plugin, nullptr); + + g_autoptr(FlValue) args = fl_value_new_string("SystemSoundType.alert"); + g_autoptr(FlJsonMethodCodec) codec = fl_json_method_codec_new(); + g_autoptr(GBytes) message = fl_method_codec_encode_method_call( + FL_METHOD_CODEC(codec), "SystemSound.play", args, nullptr); + + g_autoptr(FlValue) null = fl_value_new_null(); + EXPECT_CALL(messenger, fl_binary_messenger_send_response( + ::testing::Eq(messenger), + ::testing::_, SuccessResponse(null), ::testing::_)) + .WillOnce(::testing::Return(true)); + + messenger.ReceiveMessage("flutter/platform", message); +} From 6e9ccf7a7f25570a3da2dbadf2e71a459c847579 Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Mon, 6 Mar 2023 16:08:47 -0500 Subject: [PATCH 4/9] Roll Skia from 7e1756b42f94 to fd380c7801f8 (4 revisions) (#40095) Roll Skia from 7e1756b42f94 to fd380c7801f8 (4 revisions) --- DEPS | 2 +- ci/licenses_golden/licenses_skia | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DEPS b/DEPS index 8787180931125..23e8c1ef1dead 100644 --- a/DEPS +++ b/DEPS @@ -18,7 +18,7 @@ vars = { 'llvm_git': 'https://llvm.googlesource.com', # OCMock is for testing only so there is no google clone 'ocmock_git': 'https://github.com/erikdoe/ocmock.git', - 'skia_revision': '7e1756b42f945c66056e57829936fabc920b08a0', + 'skia_revision': 'fd380c7801f8c06e37604e7bf2682fb5e1cc564b', # WARNING: DO NOT EDIT canvaskit_cipd_instance MANUALLY # See `lib/web_ui/README.md` for how to roll CanvasKit to a new version. diff --git a/ci/licenses_golden/licenses_skia b/ci/licenses_golden/licenses_skia index ccc7209dd4fd7..b60c8245d6a23 100644 --- a/ci/licenses_golden/licenses_skia +++ b/ci/licenses_golden/licenses_skia @@ -1,4 +1,4 @@ -Signature: 15f3e16b2daae95bb96d3d2941979561 +Signature: 5e5c7d6075e9c2d070ba73226ee6ed5d ==================================================================================================== LIBRARY: etc1 From 0aa657800da8e4a72f8ae62bf17e235798fd8599 Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Mon, 6 Mar 2023 16:13:14 -0500 Subject: [PATCH 5/9] Roll Fuchsia Mac SDK from lO7cFvQ7UoYqKRDnV... to YHXIOcHEIEtyHcNG4... (#40094) Roll Fuchsia Mac SDK from lO7cFvQ7UoYqKRDnV... to YHXIOcHEIEtyHcNG4... --- DEPS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEPS b/DEPS index 23e8c1ef1dead..da1412402ca56 100644 --- a/DEPS +++ b/DEPS @@ -829,7 +829,7 @@ deps = { 'packages': [ { 'package': 'fuchsia/sdk/core/mac-amd64', - 'version': 'lO7cFvQ7UoYqKRDnVU-XVeCUrJeNEfdtAfZ-MF2BUhcC' + 'version': 'YHXIOcHEIEtyHcNG43f2QX-AdDA8b9Sf6-PYqnyDNUkC' } ], 'condition': 'host_os == "mac" and not download_fuchsia_sdk', From 6045e6e566a9867fde94682889d9e721a5de8233 Mon Sep 17 00:00:00 2001 From: Jackson Gardner Date: Mon, 6 Mar 2023 14:27:48 -0800 Subject: [PATCH 6/9] Compile skwasm with better space saving flags. (#40093) Compile skwasm with better space saving flags. --- lib/web_ui/skwasm/BUILD.gn | 5 +++-- lib/web_ui/skwasm/helpers.h | 6 ++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/web_ui/skwasm/BUILD.gn b/lib/web_ui/skwasm/BUILD.gn index 8745b6a064d62..2d962dc8a0dc0 100644 --- a/lib/web_ui/skwasm/BUILD.gn +++ b/lib/web_ui/skwasm/BUILD.gn @@ -26,6 +26,7 @@ wasm_lib("skwasm") { "-sPTHREAD_POOL_SIZE=1", "-sALLOW_MEMORY_GROWTH", "-sUSE_PTHREADS=1", + "-lexports.js", ] cflags = [ "-pthread" ] @@ -40,8 +41,8 @@ wasm_lib("skwasm") { ] } else { ldflags += [ - "-O1", - "--closure=0", + "-Oz", + "--closure=1", "-flto", "-sEXPORTED_FUNCTIONS=[stackAlloc]", ] diff --git a/lib/web_ui/skwasm/helpers.h b/lib/web_ui/skwasm/helpers.h index 89b00beefa2af..f32055f9e44cc 100644 --- a/lib/web_ui/skwasm/helpers.h +++ b/lib/web_ui/skwasm/helpers.h @@ -15,10 +15,8 @@ inline SkMatrix createMatrix(const SkScalar* f) { } inline SkRRect createRRect(const SkScalar* f) { - const SkScalar* twelveFloats = reinterpret_cast(f); - const SkRect* rect = reinterpret_cast(twelveFloats); - const SkVector* radiiValues = - reinterpret_cast(twelveFloats + 4); + const SkRect* rect = reinterpret_cast(f); + const SkVector* radiiValues = reinterpret_cast(f + 4); SkRRect rr; rr.setRectRadii(*rect, radiiValues); From 00a9958174324fd8b464dfdccc4ad76025e024a7 Mon Sep 17 00:00:00 2001 From: Jia Hao Date: Tue, 7 Mar 2023 08:14:48 +0800 Subject: [PATCH 7/9] Optimize search for the default bundle (#39975) Optimize search for the default bundle --- .../framework/Source/FlutterDartProject.mm | 48 ++++++++++++++++++- .../Source/FlutterDartProjectTest.mm | 13 +++++ .../Source/FlutterDartProject_Internal.h | 2 + 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm index ccf89a746b020..3c6f8550f4887 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm @@ -32,6 +32,50 @@ static const char* kApplicationKernelSnapshotFileName = "kernel_blob.bin"; +// Finds a bundle with the named `bundleID` within `searchURL`. +// +// Returns `nil` if the bundle cannot be found or if errors are encountered. +NSBundle* FLTFrameworkBundleInternal(NSString* bundleID, NSURL* searchURL) { + NSDirectoryEnumerator* frameworkEnumerator = [NSFileManager.defaultManager + enumeratorAtURL:searchURL + includingPropertiesForKeys:nil + options:NSDirectoryEnumerationSkipsSubdirectoryDescendants | + NSDirectoryEnumerationSkipsHiddenFiles + // Skip directories where errors are encountered. + errorHandler:nil]; + + for (NSURL* candidate in frameworkEnumerator) { + NSBundle* bundle = [NSBundle bundleWithURL:candidate]; + if ([bundle.bundleIdentifier isEqualToString:bundleID]) { + return bundle; + } + } + return nil; +} + +// Finds a bundle with the named `bundleID`. +// +// `+[NSBundle bundleWithIdentifier:]` is slow, and can take in the order of +// tens of milliseconds in a minimal flutter app, and closer to 100 milliseconds +// in a medium sized Flutter app on an iPhone 13. It is likely that the slowness +// comes from having to traverse and load all bundles known to the process. +// Using `+[NSBundle allframeworks]` and filtering also suffers from the same +// problem. +// +// This implementation is an optimization to first limit the search space to +// `+[NSBundle privateFrameworksURL]` of the main bundle, which is usually where +// frameworks used by this file are placed. If the desired bundle cannot be +// found here, the implementation falls back to +// `+[NSBundle bundleWithIdentifier:]`. +NS_INLINE NSBundle* FLTFrameworkBundleWithIdentifier(NSString* bundleID) { + NSBundle* bundle = FLTFrameworkBundleInternal(bundleID, NSBundle.mainBundle.privateFrameworksURL); + if (bundle != nil) { + return bundle; + } + // Fallback to slow implementation. + return [NSBundle bundleWithIdentifier:bundleID]; +} + flutter::Settings FLTDefaultSettingsForBundle(NSBundle* bundle) { auto command_line = flutter::CommandLineFromNSProcessInfo(); @@ -46,7 +90,7 @@ bool hasExplicitBundle = bundle != nil; if (bundle == nil) { - bundle = [NSBundle bundleWithIdentifier:[FlutterDartProject defaultBundleIdentifier]]; + bundle = FLTFrameworkBundleWithIdentifier([FlutterDartProject defaultBundleIdentifier]); } if (bundle == nil) { bundle = mainBundle; @@ -317,7 +361,7 @@ - (instancetype)initWithSettings:(const flutter::Settings&)settings { + (NSString*)flutterAssetsName:(NSBundle*)bundle { if (bundle == nil) { - bundle = [NSBundle bundleWithIdentifier:[FlutterDartProject defaultBundleIdentifier]]; + bundle = FLTFrameworkBundleWithIdentifier([FlutterDartProject defaultBundleIdentifier]); } if (bundle == nil) { bundle = [NSBundle mainBundle]; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterDartProjectTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterDartProjectTest.mm index 3eb89543995fb..8de0007868b65 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterDartProjectTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterDartProjectTest.mm @@ -60,6 +60,19 @@ - (void)testLeakDartVMSettingsAreCorrectlyParsed { XCTAssertEqual(settings.leak_vm, NO); } +- (void)testFLTFrameworkBundleInternalWhenBundleIsNotPresent { + NSBundle* found = + FLTFrameworkBundleInternal(@"doesNotExist", NSBundle.mainBundle.privateFrameworksURL); + XCTAssertNil(found); +} + +- (void)testFLTFrameworkBundleInternalWhenBundleIsPresent { + NSString* presentBundleID = @"io.flutter.flutter"; + NSBundle* found = + FLTFrameworkBundleInternal(presentBundleID, NSBundle.mainBundle.privateFrameworksURL); + XCTAssertNotNil(found); +} + - (void)testEnableImpellerSettingIsCorrectlyParsed { // The FLTEnableImpeller's value is defined in Info.plist NSBundle* mainBundle = [NSBundle mainBundle]; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h index c741a53478bab..50a42fe77f318 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h @@ -12,6 +12,8 @@ NS_ASSUME_NONNULL_BEGIN +NSBundle* FLTFrameworkBundleInternal(NSString* bundleID, NSURL* searchURL); + flutter::Settings FLTDefaultSettingsForBundle(NSBundle* bundle = nil); @interface FlutterDartProject () From 8885149cf97a9a97bcc54aa4c58a654a190411de Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Mon, 6 Mar 2023 19:19:41 -0500 Subject: [PATCH 8/9] Roll Skia from fd380c7801f8 to 3e38c84ce48e (1 revision) (#40096) Roll Skia from fd380c7801f8 to 3e38c84ce48e (1 revision) --- DEPS | 2 +- ci/licenses_golden/licenses_skia | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DEPS b/DEPS index da1412402ca56..94cda41c89c22 100644 --- a/DEPS +++ b/DEPS @@ -18,7 +18,7 @@ vars = { 'llvm_git': 'https://llvm.googlesource.com', # OCMock is for testing only so there is no google clone 'ocmock_git': 'https://github.com/erikdoe/ocmock.git', - 'skia_revision': 'fd380c7801f8c06e37604e7bf2682fb5e1cc564b', + 'skia_revision': '3e38c84ce48e931637f34438ef423eb0dd9218ca', # WARNING: DO NOT EDIT canvaskit_cipd_instance MANUALLY # See `lib/web_ui/README.md` for how to roll CanvasKit to a new version. diff --git a/ci/licenses_golden/licenses_skia b/ci/licenses_golden/licenses_skia index b60c8245d6a23..c8673973ab65f 100644 --- a/ci/licenses_golden/licenses_skia +++ b/ci/licenses_golden/licenses_skia @@ -1,4 +1,4 @@ -Signature: 5e5c7d6075e9c2d070ba73226ee6ed5d +Signature: 229cb5ce3248302838a4d974d87834d4 ==================================================================================================== LIBRARY: etc1 From 0f62c2379c377fec82f8aff292f54ef4edc90f9c Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Mon, 6 Mar 2023 19:41:18 -0500 Subject: [PATCH 9/9] Manual roll Dart SDK from b1016d8f293a to 1ae877e6c3d3 (5 revisions) (#40089) Manual roll Dart SDK from b1016d8f293a to 1ae877e6c3d3 (5 revisions) --- DEPS | 2 +- ci/licenses_golden/licenses_third_party | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DEPS b/DEPS index 94cda41c89c22..36777715cefbd 100644 --- a/DEPS +++ b/DEPS @@ -48,7 +48,7 @@ vars = { # Dart is: https://github.com/dart-lang/sdk/blob/main/DEPS # You can use //tools/dart/create_updated_flutter_deps.py to produce # updated revision list of existing dependencies. - 'dart_revision': 'b1016d8f293a723c83adb84e7839e7a4ad3bec22', + 'dart_revision': '1ae877e6c3d33ba6888213fdcc1e910324512c36', # WARNING: DO NOT EDIT MANUALLY # The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py diff --git a/ci/licenses_golden/licenses_third_party b/ci/licenses_golden/licenses_third_party index f99640ca8353b..b387e31831f9e 100644 --- a/ci/licenses_golden/licenses_third_party +++ b/ci/licenses_golden/licenses_third_party @@ -1,4 +1,4 @@ -Signature: 3feccd13ac097176c4f3f0454625899a +Signature: 5e1563c4dd9d9a18358dec9bcdeabab7 ==================================================================================================== LIBRARY: angle