Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 1 | // Copyright 2013 The Flutter Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Jim Graham | ee6969d | 2023-03-20 19:34:48 -0700 | [diff] [blame] | 5 | #include "flutter/display_list/dl_builder.h" |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 6 | |
JsouLiang | ac81750 | 2022-08-11 15:48:40 +0800 | [diff] [blame] | 7 | #include "flutter/display_list/display_list.h" |
Jim Graham | ee6969d | 2023-03-20 19:34:48 -0700 | [diff] [blame] | 8 | #include "flutter/display_list/dl_blend_mode.h" |
| 9 | #include "flutter/display_list/dl_op_records.h" |
| 10 | #include "flutter/display_list/effects/dl_color_source.h" |
| 11 | #include "flutter/display_list/utils/dl_bounds_accumulator.h" |
Brandon DeRosier | 716bb91 | 2023-01-09 20:25:59 -0800 | [diff] [blame] | 12 | #include "fml/logging.h" |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 13 | |
| 14 | namespace flutter { |
| 15 | |
| 16 | #define DL_BUILDER_PAGE 4096 |
| 17 | |
| 18 | // CopyV(dst, src,n, src,n, ...) copies any number of typed srcs into dst. |
| 19 | static void CopyV(void* dst) {} |
| 20 | |
| 21 | template <typename S, typename... Rest> |
| 22 | static void CopyV(void* dst, const S* src, int n, Rest&&... rest) { |
| 23 | FML_DCHECK(((uintptr_t)dst & (alignof(S) - 1)) == 0) |
| 24 | << "Expected " << dst << " to be aligned for at least " << alignof(S) |
| 25 | << " bytes."; |
Kevin Lubick | 2722c54 | 2023-01-18 12:58:59 -0500 | [diff] [blame] | 26 | // If n is 0, there is nothing to copy into dst from src. |
| 27 | if (n > 0) { |
| 28 | memcpy(dst, src, n * sizeof(S)); |
| 29 | dst = reinterpret_cast<void*>(reinterpret_cast<uint8_t*>(dst) + |
| 30 | n * sizeof(S)); |
| 31 | } |
| 32 | // Repeat for the next items, if any |
| 33 | CopyV(dst, std::forward<Rest>(rest)...); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 34 | } |
| 35 | |
Kevin Lubick | 4f0cdcd | 2023-01-09 19:22:33 -0600 | [diff] [blame] | 36 | static constexpr inline bool is_power_of_two(int value) { |
| 37 | return (value & (value - 1)) == 0; |
| 38 | } |
| 39 | |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 40 | template <typename T, typename... Args> |
Jim Graham | 147ac7d | 2022-12-22 02:16:25 -0800 | [diff] [blame] | 41 | void* DisplayListBuilder::Push(size_t pod, int render_op_inc, Args&&... args) { |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 42 | size_t size = SkAlignPtr(sizeof(T) + pod); |
| 43 | FML_DCHECK(size < (1 << 24)); |
| 44 | if (used_ + size > allocated_) { |
Kevin Lubick | 4f0cdcd | 2023-01-09 19:22:33 -0600 | [diff] [blame] | 45 | static_assert(is_power_of_two(DL_BUILDER_PAGE), |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 46 | "This math needs updating for non-pow2."); |
| 47 | // Next greater multiple of DL_BUILDER_PAGE. |
| 48 | allocated_ = (used_ + size + DL_BUILDER_PAGE) & ~(DL_BUILDER_PAGE - 1); |
| 49 | storage_.realloc(allocated_); |
| 50 | FML_DCHECK(storage_.get()); |
| 51 | memset(storage_.get() + used_, 0, allocated_ - used_); |
| 52 | } |
| 53 | FML_DCHECK(used_ + size <= allocated_); |
| 54 | auto op = reinterpret_cast<T*>(storage_.get() + used_); |
| 55 | used_ += size; |
| 56 | new (op) T{std::forward<Args>(args)...}; |
| 57 | op->type = T::kType; |
| 58 | op->size = size; |
Jim Graham | 147ac7d | 2022-12-22 02:16:25 -0800 | [diff] [blame] | 59 | render_op_count_ += render_op_inc; |
| 60 | op_index_++; |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 61 | return op + 1; |
| 62 | } |
| 63 | |
| 64 | sk_sp<DisplayList> DisplayListBuilder::Build() { |
| 65 | while (layer_stack_.size() > 1) { |
| 66 | restore(); |
| 67 | } |
Jim Graham | ff04d2f | 2023-05-25 14:56:25 -0700 | [diff] [blame] | 68 | |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 69 | size_t bytes = used_; |
Jim Graham | 147ac7d | 2022-12-22 02:16:25 -0800 | [diff] [blame] | 70 | int count = render_op_count_; |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 71 | size_t nested_bytes = nested_bytes_; |
| 72 | int nested_count = nested_op_count_; |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 73 | bool compatible = layer_stack_.back().is_group_opacity_compatible(); |
Jim Graham | ff04d2f | 2023-05-25 14:56:25 -0700 | [diff] [blame] | 74 | bool is_safe = is_ui_thread_safe_; |
| 75 | |
Jim Graham | 147ac7d | 2022-12-22 02:16:25 -0800 | [diff] [blame] | 76 | used_ = allocated_ = render_op_count_ = op_index_ = 0; |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 77 | nested_bytes_ = nested_op_count_ = 0; |
| 78 | storage_.realloc(bytes); |
Jim Graham | ff04d2f | 2023-05-25 14:56:25 -0700 | [diff] [blame] | 79 | layer_stack_.pop_back(); |
| 80 | layer_stack_.emplace_back(); |
| 81 | tracker_.reset(); |
| 82 | current_ = DlPaint(); |
| 83 | |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 84 | return sk_sp<DisplayList>( |
| 85 | new DisplayList(std::move(storage_), bytes, count, nested_bytes, |
| 86 | nested_count, bounds(), compatible, is_safe, rtree())); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 87 | } |
| 88 | |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 89 | DisplayListBuilder::DisplayListBuilder(const SkRect& cull_rect, |
ColdPaleLight | 6b7ed78 | 2022-12-20 18:05:40 +0800 | [diff] [blame] | 90 | bool prepare_rtree) |
| 91 | : tracker_(cull_rect, SkMatrix::I()) { |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 92 | if (prepare_rtree) { |
| 93 | accumulator_ = std::make_unique<RTreeBoundsAccumulator>(); |
| 94 | } else { |
| 95 | accumulator_ = std::make_unique<RectBoundsAccumulator>(); |
| 96 | } |
| 97 | |
ColdPaleLight | 6b7ed78 | 2022-12-20 18:05:40 +0800 | [diff] [blame] | 98 | layer_stack_.emplace_back(); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 99 | current_layer_ = &layer_stack_.back(); |
| 100 | } |
| 101 | |
| 102 | DisplayListBuilder::~DisplayListBuilder() { |
| 103 | uint8_t* ptr = storage_.get(); |
| 104 | if (ptr) { |
| 105 | DisplayList::DisposeOps(ptr, ptr + used_); |
| 106 | } |
| 107 | } |
| 108 | |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 109 | SkISize DisplayListBuilder::GetBaseLayerSize() const { |
| 110 | return tracker_.base_device_cull_rect().roundOut().size(); |
| 111 | } |
| 112 | |
| 113 | SkImageInfo DisplayListBuilder::GetImageInfo() const { |
| 114 | SkISize size = GetBaseLayerSize(); |
| 115 | return SkImageInfo::MakeUnknown(size.width(), size.height()); |
| 116 | } |
| 117 | |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 118 | void DisplayListBuilder::onSetAntiAlias(bool aa) { |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 119 | current_.setAntiAlias(aa); |
| 120 | Push<SetAntiAliasOp>(0, 0, aa); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 121 | } |
| 122 | void DisplayListBuilder::onSetDither(bool dither) { |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 123 | current_.setDither(dither); |
| 124 | Push<SetDitherOp>(0, 0, dither); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 125 | } |
| 126 | void DisplayListBuilder::onSetInvertColors(bool invert) { |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 127 | current_.setInvertColors(invert); |
| 128 | Push<SetInvertColorsOp>(0, 0, invert); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 129 | UpdateCurrentOpacityCompatibility(); |
| 130 | } |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 131 | void DisplayListBuilder::onSetStrokeCap(DlStrokeCap cap) { |
| 132 | current_.setStrokeCap(cap); |
| 133 | Push<SetStrokeCapOp>(0, 0, cap); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 134 | } |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 135 | void DisplayListBuilder::onSetStrokeJoin(DlStrokeJoin join) { |
| 136 | current_.setStrokeJoin(join); |
| 137 | Push<SetStrokeJoinOp>(0, 0, join); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 138 | } |
Jim Graham | ff04d2f | 2023-05-25 14:56:25 -0700 | [diff] [blame] | 139 | void DisplayListBuilder::onSetDrawStyle(DlDrawStyle style) { |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 140 | current_.setDrawStyle(style); |
| 141 | Push<SetStyleOp>(0, 0, style); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 142 | } |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 143 | void DisplayListBuilder::onSetStrokeWidth(float width) { |
| 144 | current_.setStrokeWidth(width); |
| 145 | Push<SetStrokeWidthOp>(0, 0, width); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 146 | } |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 147 | void DisplayListBuilder::onSetStrokeMiter(float limit) { |
| 148 | current_.setStrokeMiter(limit); |
| 149 | Push<SetStrokeMiterOp>(0, 0, limit); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 150 | } |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 151 | void DisplayListBuilder::onSetColor(DlColor color) { |
| 152 | current_.setColor(color); |
| 153 | Push<SetColorOp>(0, 0, color); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 154 | } |
JsouLiang | 1aa5255 | 2022-03-20 05:10:07 +0800 | [diff] [blame] | 155 | void DisplayListBuilder::onSetBlendMode(DlBlendMode mode) { |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 156 | current_.setBlendMode(mode); |
| 157 | Push<SetBlendModeOp>(0, 0, mode); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 158 | UpdateCurrentOpacityCompatibility(); |
| 159 | } |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 160 | |
Jim Graham | dc22c4c | 2022-03-15 16:55:04 -0700 | [diff] [blame] | 161 | void DisplayListBuilder::onSetColorSource(const DlColorSource* source) { |
| 162 | if (source == nullptr) { |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 163 | current_.setColorSource(nullptr); |
Jim Graham | dc22c4c | 2022-03-15 16:55:04 -0700 | [diff] [blame] | 164 | Push<ClearColorSourceOp>(0, 0); |
| 165 | } else { |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 166 | current_.setColorSource(source->shared()); |
Jim Graham | 35833e7 | 2023-04-17 16:47:20 -0700 | [diff] [blame] | 167 | is_ui_thread_safe_ = is_ui_thread_safe_ && source->isUIThreadSafe(); |
Jim Graham | dc22c4c | 2022-03-15 16:55:04 -0700 | [diff] [blame] | 168 | switch (source->type()) { |
| 169 | case DlColorSourceType::kColor: { |
| 170 | const DlColorColorSource* color_source = source->asColor(); |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 171 | current_.setColorSource(nullptr); |
Jim Graham | dc22c4c | 2022-03-15 16:55:04 -0700 | [diff] [blame] | 172 | setColor(color_source->color()); |
| 173 | break; |
| 174 | } |
| 175 | case DlColorSourceType::kImage: { |
| 176 | const DlImageColorSource* image_source = source->asImage(); |
| 177 | FML_DCHECK(image_source); |
| 178 | Push<SetImageColorSourceOp>(0, 0, image_source); |
| 179 | break; |
| 180 | } |
| 181 | case DlColorSourceType::kLinearGradient: { |
| 182 | const DlLinearGradientColorSource* linear = source->asLinearGradient(); |
| 183 | FML_DCHECK(linear); |
| 184 | void* pod = Push<SetPodColorSourceOp>(linear->size(), 0); |
| 185 | new (pod) DlLinearGradientColorSource(linear); |
| 186 | break; |
| 187 | } |
| 188 | case DlColorSourceType::kRadialGradient: { |
| 189 | const DlRadialGradientColorSource* radial = source->asRadialGradient(); |
| 190 | FML_DCHECK(radial); |
| 191 | void* pod = Push<SetPodColorSourceOp>(radial->size(), 0); |
| 192 | new (pod) DlRadialGradientColorSource(radial); |
| 193 | break; |
| 194 | } |
| 195 | case DlColorSourceType::kConicalGradient: { |
| 196 | const DlConicalGradientColorSource* conical = |
| 197 | source->asConicalGradient(); |
| 198 | FML_DCHECK(conical); |
| 199 | void* pod = Push<SetPodColorSourceOp>(conical->size(), 0); |
| 200 | new (pod) DlConicalGradientColorSource(conical); |
| 201 | break; |
| 202 | } |
| 203 | case DlColorSourceType::kSweepGradient: { |
| 204 | const DlSweepGradientColorSource* sweep = source->asSweepGradient(); |
| 205 | FML_DCHECK(sweep); |
| 206 | void* pod = Push<SetPodColorSourceOp>(sweep->size(), 0); |
| 207 | new (pod) DlSweepGradientColorSource(sweep); |
| 208 | break; |
| 209 | } |
Dan Field | 4fbe41d | 2022-08-18 16:12:11 -0700 | [diff] [blame] | 210 | case DlColorSourceType::kRuntimeEffect: { |
| 211 | const DlRuntimeEffectColorSource* effect = source->asRuntimeEffect(); |
| 212 | FML_DCHECK(effect); |
| 213 | Push<SetRuntimeEffectColorSourceOp>(0, 0, effect); |
| 214 | break; |
| 215 | } |
Brandon DeRosier | 716bb91 | 2023-01-09 20:25:59 -0800 | [diff] [blame] | 216 | #ifdef IMPELLER_ENABLE_3D |
| 217 | case DlColorSourceType::kScene: { |
| 218 | const DlSceneColorSource* scene = source->asScene(); |
| 219 | FML_DCHECK(scene); |
| 220 | Push<SetSceneColorSourceOp>(0, 0, scene); |
| 221 | break; |
| 222 | } |
| 223 | #endif // IMPELLER_ENABLE_3D |
Jim Graham | dc22c4c | 2022-03-15 16:55:04 -0700 | [diff] [blame] | 224 | } |
| 225 | } |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 226 | } |
Jim Graham | 3f2750c | 2022-03-21 13:55:08 -0700 | [diff] [blame] | 227 | void DisplayListBuilder::onSetImageFilter(const DlImageFilter* filter) { |
| 228 | if (filter == nullptr) { |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 229 | current_.setImageFilter(nullptr); |
Jim Graham | 3f2750c | 2022-03-21 13:55:08 -0700 | [diff] [blame] | 230 | Push<ClearImageFilterOp>(0, 0); |
| 231 | } else { |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 232 | current_.setImageFilter(filter->shared()); |
Jim Graham | 3f2750c | 2022-03-21 13:55:08 -0700 | [diff] [blame] | 233 | switch (filter->type()) { |
| 234 | case DlImageFilterType::kBlur: { |
| 235 | const DlBlurImageFilter* blur_filter = filter->asBlur(); |
| 236 | FML_DCHECK(blur_filter); |
| 237 | void* pod = Push<SetPodImageFilterOp>(blur_filter->size(), 0); |
| 238 | new (pod) DlBlurImageFilter(blur_filter); |
| 239 | break; |
| 240 | } |
fzyzcjy | 9b3117a | 2022-04-05 04:01:02 +0800 | [diff] [blame] | 241 | case DlImageFilterType::kDilate: { |
| 242 | const DlDilateImageFilter* dilate_filter = filter->asDilate(); |
| 243 | FML_DCHECK(dilate_filter); |
| 244 | void* pod = Push<SetPodImageFilterOp>(dilate_filter->size(), 0); |
| 245 | new (pod) DlDilateImageFilter(dilate_filter); |
| 246 | break; |
| 247 | } |
| 248 | case DlImageFilterType::kErode: { |
| 249 | const DlErodeImageFilter* erode_filter = filter->asErode(); |
| 250 | FML_DCHECK(erode_filter); |
| 251 | void* pod = Push<SetPodImageFilterOp>(erode_filter->size(), 0); |
| 252 | new (pod) DlErodeImageFilter(erode_filter); |
| 253 | break; |
| 254 | } |
Jim Graham | 3f2750c | 2022-03-21 13:55:08 -0700 | [diff] [blame] | 255 | case DlImageFilterType::kMatrix: { |
| 256 | const DlMatrixImageFilter* matrix_filter = filter->asMatrix(); |
| 257 | FML_DCHECK(matrix_filter); |
| 258 | void* pod = Push<SetPodImageFilterOp>(matrix_filter->size(), 0); |
| 259 | new (pod) DlMatrixImageFilter(matrix_filter); |
| 260 | break; |
| 261 | } |
Jim Graham | 25514ec | 2023-03-19 15:59:17 -0700 | [diff] [blame] | 262 | case DlImageFilterType::kCompose: |
| 263 | case DlImageFilterType::kLocalMatrix: |
Jim Graham | 3f2750c | 2022-03-21 13:55:08 -0700 | [diff] [blame] | 264 | case DlImageFilterType::kColorFilter: { |
| 265 | Push<SetSharedImageFilterOp>(0, 0, filter); |
| 266 | break; |
| 267 | } |
Jim Graham | 3f2750c | 2022-03-21 13:55:08 -0700 | [diff] [blame] | 268 | } |
| 269 | } |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 270 | } |
Jim Graham | 70c1173 | 2022-02-17 11:19:11 -0800 | [diff] [blame] | 271 | void DisplayListBuilder::onSetColorFilter(const DlColorFilter* filter) { |
| 272 | if (filter == nullptr) { |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 273 | current_.setColorFilter(nullptr); |
Jim Graham | 70c1173 | 2022-02-17 11:19:11 -0800 | [diff] [blame] | 274 | Push<ClearColorFilterOp>(0, 0); |
| 275 | } else { |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 276 | current_.setColorFilter(filter->shared()); |
Jim Graham | 70c1173 | 2022-02-17 11:19:11 -0800 | [diff] [blame] | 277 | switch (filter->type()) { |
Jim Graham | eef4f8e | 2022-02-25 11:51:02 -0800 | [diff] [blame] | 278 | case DlColorFilterType::kBlend: { |
Jim Graham | 70c1173 | 2022-02-17 11:19:11 -0800 | [diff] [blame] | 279 | const DlBlendColorFilter* blend_filter = filter->asBlend(); |
| 280 | FML_DCHECK(blend_filter); |
Jim Graham | dc22c4c | 2022-03-15 16:55:04 -0700 | [diff] [blame] | 281 | void* pod = Push<SetPodColorFilterOp>(blend_filter->size(), 0); |
Jim Graham | 70c1173 | 2022-02-17 11:19:11 -0800 | [diff] [blame] | 282 | new (pod) DlBlendColorFilter(blend_filter); |
| 283 | break; |
| 284 | } |
Jim Graham | eef4f8e | 2022-02-25 11:51:02 -0800 | [diff] [blame] | 285 | case DlColorFilterType::kMatrix: { |
Jim Graham | 70c1173 | 2022-02-17 11:19:11 -0800 | [diff] [blame] | 286 | const DlMatrixColorFilter* matrix_filter = filter->asMatrix(); |
| 287 | FML_DCHECK(matrix_filter); |
Jim Graham | dc22c4c | 2022-03-15 16:55:04 -0700 | [diff] [blame] | 288 | void* pod = Push<SetPodColorFilterOp>(matrix_filter->size(), 0); |
Jim Graham | 70c1173 | 2022-02-17 11:19:11 -0800 | [diff] [blame] | 289 | new (pod) DlMatrixColorFilter(matrix_filter); |
| 290 | break; |
| 291 | } |
Jim Graham | eef4f8e | 2022-02-25 11:51:02 -0800 | [diff] [blame] | 292 | case DlColorFilterType::kSrgbToLinearGamma: { |
Jim Graham | dc22c4c | 2022-03-15 16:55:04 -0700 | [diff] [blame] | 293 | void* pod = Push<SetPodColorFilterOp>(filter->size(), 0); |
Jim Graham | 70c1173 | 2022-02-17 11:19:11 -0800 | [diff] [blame] | 294 | new (pod) DlSrgbToLinearGammaColorFilter(); |
| 295 | break; |
| 296 | } |
Jim Graham | eef4f8e | 2022-02-25 11:51:02 -0800 | [diff] [blame] | 297 | case DlColorFilterType::kLinearToSrgbGamma: { |
Jim Graham | dc22c4c | 2022-03-15 16:55:04 -0700 | [diff] [blame] | 298 | void* pod = Push<SetPodColorFilterOp>(filter->size(), 0); |
Jim Graham | 70c1173 | 2022-02-17 11:19:11 -0800 | [diff] [blame] | 299 | new (pod) DlLinearToSrgbGammaColorFilter(); |
| 300 | break; |
| 301 | } |
Jim Graham | 70c1173 | 2022-02-17 11:19:11 -0800 | [diff] [blame] | 302 | } |
| 303 | } |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 304 | UpdateCurrentOpacityCompatibility(); |
| 305 | } |
JsouLiang | b8ca6a5 | 2022-05-12 09:45:30 +0800 | [diff] [blame] | 306 | void DisplayListBuilder::onSetPathEffect(const DlPathEffect* effect) { |
| 307 | if (effect == nullptr) { |
| 308 | current_.setPathEffect(nullptr); |
| 309 | Push<ClearPathEffectOp>(0, 0); |
| 310 | } else { |
| 311 | current_.setPathEffect(effect->shared()); |
| 312 | switch (effect->type()) { |
| 313 | case DlPathEffectType::kDash: { |
| 314 | const DlDashPathEffect* dash_effect = effect->asDash(); |
| 315 | void* pod = Push<SetPodPathEffectOp>(dash_effect->size(), 0); |
| 316 | new (pod) DlDashPathEffect(dash_effect); |
| 317 | break; |
| 318 | } |
JsouLiang | b8ca6a5 | 2022-05-12 09:45:30 +0800 | [diff] [blame] | 319 | } |
| 320 | } |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 321 | } |
Jim Graham | d1fbb63 | 2022-02-18 09:19:09 -0800 | [diff] [blame] | 322 | void DisplayListBuilder::onSetMaskFilter(const DlMaskFilter* filter) { |
| 323 | if (filter == nullptr) { |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 324 | current_.setMaskFilter(nullptr); |
Jim Graham | d1fbb63 | 2022-02-18 09:19:09 -0800 | [diff] [blame] | 325 | Push<ClearMaskFilterOp>(0, 0); |
| 326 | } else { |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 327 | current_.setMaskFilter(filter->shared()); |
Jim Graham | d1fbb63 | 2022-02-18 09:19:09 -0800 | [diff] [blame] | 328 | switch (filter->type()) { |
Jim Graham | eef4f8e | 2022-02-25 11:51:02 -0800 | [diff] [blame] | 329 | case DlMaskFilterType::kBlur: { |
Jim Graham | d1fbb63 | 2022-02-18 09:19:09 -0800 | [diff] [blame] | 330 | const DlBlurMaskFilter* blur_filter = filter->asBlur(); |
| 331 | FML_DCHECK(blur_filter); |
Jim Graham | dc22c4c | 2022-03-15 16:55:04 -0700 | [diff] [blame] | 332 | void* pod = Push<SetPodMaskFilterOp>(blur_filter->size(), 0); |
Jim Graham | d1fbb63 | 2022-02-18 09:19:09 -0800 | [diff] [blame] | 333 | new (pod) DlBlurMaskFilter(blur_filter); |
| 334 | break; |
| 335 | } |
Jim Graham | d1fbb63 | 2022-02-18 09:19:09 -0800 | [diff] [blame] | 336 | } |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 337 | } |
| 338 | } |
| 339 | |
Jim Graham | de9093d | 2023-02-24 17:42:20 -0800 | [diff] [blame] | 340 | void DisplayListBuilder::SetAttributesFromPaint( |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 341 | const DlPaint& paint, |
| 342 | const DisplayListAttributeFlags flags) { |
| 343 | if (flags.applies_anti_alias()) { |
| 344 | setAntiAlias(paint.isAntiAlias()); |
| 345 | } |
| 346 | if (flags.applies_dither()) { |
| 347 | setDither(paint.isDither()); |
| 348 | } |
| 349 | if (flags.applies_alpha_or_color()) { |
| 350 | setColor(paint.getColor().argb); |
| 351 | } |
| 352 | if (flags.applies_blend()) { |
| 353 | setBlendMode(paint.getBlendMode()); |
| 354 | } |
| 355 | if (flags.applies_style()) { |
Jim Graham | ff04d2f | 2023-05-25 14:56:25 -0700 | [diff] [blame] | 356 | setDrawStyle(paint.getDrawStyle()); |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 357 | } |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 358 | if (flags.is_stroked(paint.getDrawStyle())) { |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 359 | setStrokeWidth(paint.getStrokeWidth()); |
| 360 | setStrokeMiter(paint.getStrokeMiter()); |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 361 | setStrokeCap(paint.getStrokeCap()); |
| 362 | setStrokeJoin(paint.getStrokeJoin()); |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 363 | } |
| 364 | if (flags.applies_shader()) { |
| 365 | setColorSource(paint.getColorSource().get()); |
| 366 | } |
| 367 | if (flags.applies_color_filter()) { |
| 368 | setInvertColors(paint.isInvertColors()); |
| 369 | setColorFilter(paint.getColorFilter().get()); |
| 370 | } |
| 371 | if (flags.applies_image_filter()) { |
| 372 | setImageFilter(paint.getImageFilter().get()); |
| 373 | } |
Jason Simmons | 623d2d9 | 2022-10-10 15:29:19 -0700 | [diff] [blame] | 374 | if (flags.applies_path_effect()) { |
| 375 | setPathEffect(paint.getPathEffect().get()); |
| 376 | } |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 377 | if (flags.applies_mask_filter()) { |
| 378 | setMaskFilter(paint.getMaskFilter().get()); |
| 379 | } |
| 380 | } |
| 381 | |
JsouLiang | ac81750 | 2022-08-11 15:48:40 +0800 | [diff] [blame] | 382 | void DisplayListBuilder::checkForDeferredSave() { |
| 383 | if (current_layer_->has_deferred_save_op_) { |
Jim Graham | 147ac7d | 2022-12-22 02:16:25 -0800 | [diff] [blame] | 384 | size_t save_offset_ = used_; |
JsouLiang | ac81750 | 2022-08-11 15:48:40 +0800 | [diff] [blame] | 385 | Push<SaveOp>(0, 1); |
Jim Graham | 147ac7d | 2022-12-22 02:16:25 -0800 | [diff] [blame] | 386 | current_layer_->save_offset_ = save_offset_; |
JsouLiang | ac81750 | 2022-08-11 15:48:40 +0800 | [diff] [blame] | 387 | current_layer_->has_deferred_save_op_ = false; |
| 388 | } |
| 389 | } |
| 390 | |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 391 | void DisplayListBuilder::Save() { |
ColdPaleLight | 6b7ed78 | 2022-12-20 18:05:40 +0800 | [diff] [blame] | 392 | layer_stack_.emplace_back(); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 393 | current_layer_ = &layer_stack_.back(); |
JsouLiang | ac81750 | 2022-08-11 15:48:40 +0800 | [diff] [blame] | 394 | current_layer_->has_deferred_save_op_ = true; |
ColdPaleLight | 6b7ed78 | 2022-12-20 18:05:40 +0800 | [diff] [blame] | 395 | tracker_.save(); |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 396 | accumulator()->save(); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 397 | } |
JsouLiang | ac81750 | 2022-08-11 15:48:40 +0800 | [diff] [blame] | 398 | |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 399 | void DisplayListBuilder::Restore() { |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 400 | if (layer_stack_.size() > 1) { |
Jim Graham | 147ac7d | 2022-12-22 02:16:25 -0800 | [diff] [blame] | 401 | SaveOpBase* op = reinterpret_cast<SaveOpBase*>( |
| 402 | storage_.get() + current_layer_->save_offset()); |
JsouLiang | ac81750 | 2022-08-11 15:48:40 +0800 | [diff] [blame] | 403 | if (!current_layer_->has_deferred_save_op_) { |
Jim Graham | 147ac7d | 2022-12-22 02:16:25 -0800 | [diff] [blame] | 404 | op->restore_index = op_index_; |
JsouLiang | ac81750 | 2022-08-11 15:48:40 +0800 | [diff] [blame] | 405 | Push<RestoreOp>(0, 1); |
| 406 | } |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 407 | // Grab the current layer info before we push the restore |
| 408 | // on the stack. |
| 409 | LayerInfo layer_info = layer_stack_.back(); |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 410 | |
ColdPaleLight | 6b7ed78 | 2022-12-20 18:05:40 +0800 | [diff] [blame] | 411 | tracker_.restore(); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 412 | layer_stack_.pop_back(); |
| 413 | current_layer_ = &layer_stack_.back(); |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 414 | bool is_unbounded = layer_info.is_unbounded(); |
| 415 | |
| 416 | // Before we pop_back we will get the current layer bounds from the |
| 417 | // current accumulator and adjust it as required based on the filter. |
| 418 | std::shared_ptr<const DlImageFilter> filter = layer_info.filter(); |
| 419 | if (filter) { |
ColdPaleLight | 6b7ed78 | 2022-12-20 18:05:40 +0800 | [diff] [blame] | 420 | const SkRect clip = tracker_.device_cull_rect(); |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 421 | if (!accumulator()->restore( |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 422 | [filter = filter, matrix = GetTransform()](const SkRect& input, |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 423 | SkRect& output) { |
| 424 | SkIRect output_bounds; |
| 425 | bool ret = filter->map_device_bounds(input.roundOut(), matrix, |
| 426 | output_bounds); |
| 427 | output.set(output_bounds); |
| 428 | return ret; |
| 429 | }, |
ColdPaleLight | 6b7ed78 | 2022-12-20 18:05:40 +0800 | [diff] [blame] | 430 | &clip)) { |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 431 | is_unbounded = true; |
| 432 | } |
| 433 | } else { |
| 434 | accumulator()->restore(); |
| 435 | } |
| 436 | |
| 437 | if (is_unbounded) { |
| 438 | AccumulateUnbounded(); |
| 439 | } |
| 440 | |
| 441 | if (layer_info.has_layer()) { |
Jim Graham | 147ac7d | 2022-12-22 02:16:25 -0800 | [diff] [blame] | 442 | // Layers are never deferred for now, we need to update the |
| 443 | // following code if we ever do saveLayer culling... |
| 444 | FML_DCHECK(!layer_info.has_deferred_save_op_); |
Jim Graham | dbe4cc8 | 2022-02-04 00:45:10 -0800 | [diff] [blame] | 445 | if (layer_info.is_group_opacity_compatible()) { |
| 446 | // We are now going to go back and modify the matching saveLayer |
| 447 | // call to add the option indicating it can distribute an opacity |
| 448 | // value to its children. |
| 449 | // |
| 450 | // Note that this operation cannot and does not change the size |
| 451 | // or structure of the SaveLayerOp record. It only sets an option |
| 452 | // flag on an existing field. |
| 453 | // |
| 454 | // Note that these kinds of modification operations on data already |
| 455 | // in the DisplayList are only allowed *during* the build phase. |
| 456 | // Once built, the DisplayList records must remain read only to |
| 457 | // ensure consistency of rendering and |Equals()| behavior. |
Jim Graham | dbe4cc8 | 2022-02-04 00:45:10 -0800 | [diff] [blame] | 458 | op->options = op->options.with_can_distribute_opacity(); |
| 459 | } |
| 460 | } else { |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 461 | // For regular save() ops there was no protecting layer so we have to |
| 462 | // accumulate the values into the enclosing layer. |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 463 | if (layer_info.cannot_inherit_opacity()) { |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 464 | current_layer_->mark_incompatible(); |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 465 | } else if (layer_info.has_compatible_op()) { |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 466 | current_layer_->add_compatible_op(); |
| 467 | } |
| 468 | } |
| 469 | } |
| 470 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 471 | void DisplayListBuilder::RestoreToCount(int restore_count) { |
| 472 | FML_DCHECK(restore_count <= GetSaveCount()); |
| 473 | while (restore_count < GetSaveCount() && GetSaveCount() > 1) { |
Jim Graham | 8ab4124 | 2022-04-22 16:19:04 -0700 | [diff] [blame] | 474 | restore(); |
| 475 | } |
| 476 | } |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 477 | void DisplayListBuilder::saveLayer(const SkRect* bounds, |
Jim Graham | 0f2870c | 2022-06-06 15:23:06 -0700 | [diff] [blame] | 478 | const SaveLayerOptions in_options, |
| 479 | const DlImageFilter* backdrop) { |
Jim Graham | dbe4cc8 | 2022-02-04 00:45:10 -0800 | [diff] [blame] | 480 | SaveLayerOptions options = in_options.without_optimizations(); |
Jim Graham | eb57d70 | 2023-07-14 15:34:50 -0700 | [diff] [blame] | 481 | size_t save_layer_offset = used_; |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 482 | if (backdrop) { |
| 483 | bounds // |
| 484 | ? Push<SaveLayerBackdropBoundsOp>(0, 1, options, *bounds, backdrop) |
| 485 | : Push<SaveLayerBackdropOp>(0, 1, options, backdrop); |
| 486 | } else { |
| 487 | bounds // |
| 488 | ? Push<SaveLayerBoundsOp>(0, 1, options, *bounds) |
| 489 | : Push<SaveLayerOp>(0, 1, options); |
| 490 | } |
| 491 | CheckLayerOpacityCompatibility(options.renders_with_attributes()); |
| 492 | |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 493 | if (options.renders_with_attributes()) { |
| 494 | // The actual flood of the outer layer clip will occur after the |
| 495 | // (eventual) corresponding restore is called, but rather than |
| 496 | // remember this information in the LayerInfo until the restore |
| 497 | // method is processed, we just mark the unbounded state up front. |
Jim Graham | 147ac7d | 2022-12-22 02:16:25 -0800 | [diff] [blame] | 498 | // Another reason to accumulate the clip here rather than in |
| 499 | // restore is so that this savelayer will be tagged in the rtree |
| 500 | // with its full bounds and the right op_index so that it doesn't |
| 501 | // get culled during rendering. |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 502 | if (!paint_nops_on_transparency()) { |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 503 | // We will fill the clip of the outer layer when we restore |
| 504 | AccumulateUnbounded(); |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 505 | } |
ColdPaleLight | 6b7ed78 | 2022-12-20 18:05:40 +0800 | [diff] [blame] | 506 | layer_stack_.emplace_back(save_layer_offset, true, |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 507 | current_.getImageFilter()); |
| 508 | } else { |
ColdPaleLight | 6b7ed78 | 2022-12-20 18:05:40 +0800 | [diff] [blame] | 509 | layer_stack_.emplace_back(save_layer_offset, true, nullptr); |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 510 | } |
ColdPaleLight | 6b7ed78 | 2022-12-20 18:05:40 +0800 | [diff] [blame] | 511 | tracker_.save(); |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 512 | accumulator()->save(); |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 513 | current_layer_ = &layer_stack_.back(); |
Jim Graham | dbe4cc8 | 2022-02-04 00:45:10 -0800 | [diff] [blame] | 514 | if (options.renders_with_attributes()) { |
| 515 | // |current_opacity_compatibility_| does not take an ImageFilter into |
| 516 | // account because an individual primitive with an ImageFilter can apply |
| 517 | // opacity on top of it. But, if the layer is applying the ImageFilter |
| 518 | // then it cannot pass the opacity on. |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 519 | if (!current_opacity_compatibility_ || |
| 520 | current_.getImageFilter() != nullptr) { |
Jim Graham | dbe4cc8 | 2022-02-04 00:45:10 -0800 | [diff] [blame] | 521 | UpdateLayerOpacityCompatibility(false); |
| 522 | } |
| 523 | } |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 524 | |
| 525 | // Even though Skia claims that the bounds are only a hint, they actually |
| 526 | // use them as the temporary layer bounds during rendering the layer, so |
| 527 | // we set them as if a clip operation were performed. |
| 528 | if (bounds) { |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 529 | tracker_.clipRect(*bounds, ClipOp::kIntersect, false); |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 530 | } |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 531 | if (backdrop) { |
| 532 | // A backdrop will affect up to the entire surface, bounded by the clip |
| 533 | AccumulateUnbounded(); |
| 534 | } |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 535 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 536 | void DisplayListBuilder::SaveLayer(const SkRect* bounds, |
Jim Graham | 0f2870c | 2022-06-06 15:23:06 -0700 | [diff] [blame] | 537 | const DlPaint* paint, |
| 538 | const DlImageFilter* backdrop) { |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 539 | if (paint != nullptr) { |
Jim Graham | de9093d | 2023-02-24 17:42:20 -0800 | [diff] [blame] | 540 | SetAttributesFromPaint(*paint, |
| 541 | DisplayListOpFlags::kSaveLayerWithPaintFlags); |
Jim Graham | 0f2870c | 2022-06-06 15:23:06 -0700 | [diff] [blame] | 542 | saveLayer(bounds, SaveLayerOptions::kWithAttributes, backdrop); |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 543 | } else { |
Jim Graham | 0f2870c | 2022-06-06 15:23:06 -0700 | [diff] [blame] | 544 | saveLayer(bounds, SaveLayerOptions::kNoAttributes, backdrop); |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 545 | } |
| 546 | } |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 547 | |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 548 | void DisplayListBuilder::Translate(SkScalar tx, SkScalar ty) { |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 549 | if (SkScalarIsFinite(tx) && SkScalarIsFinite(ty) && |
| 550 | (tx != 0.0 || ty != 0.0)) { |
JsouLiang | ac81750 | 2022-08-11 15:48:40 +0800 | [diff] [blame] | 551 | checkForDeferredSave(); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 552 | Push<TranslateOp>(0, 1, tx, ty); |
ColdPaleLight | 6b7ed78 | 2022-12-20 18:05:40 +0800 | [diff] [blame] | 553 | tracker_.translate(tx, ty); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 554 | } |
| 555 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 556 | void DisplayListBuilder::Scale(SkScalar sx, SkScalar sy) { |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 557 | if (SkScalarIsFinite(sx) && SkScalarIsFinite(sy) && |
| 558 | (sx != 1.0 || sy != 1.0)) { |
JsouLiang | ac81750 | 2022-08-11 15:48:40 +0800 | [diff] [blame] | 559 | checkForDeferredSave(); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 560 | Push<ScaleOp>(0, 1, sx, sy); |
ColdPaleLight | 6b7ed78 | 2022-12-20 18:05:40 +0800 | [diff] [blame] | 561 | tracker_.scale(sx, sy); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 562 | } |
| 563 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 564 | void DisplayListBuilder::Rotate(SkScalar degrees) { |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 565 | if (SkScalarMod(degrees, 360.0) != 0.0) { |
JsouLiang | ac81750 | 2022-08-11 15:48:40 +0800 | [diff] [blame] | 566 | checkForDeferredSave(); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 567 | Push<RotateOp>(0, 1, degrees); |
ColdPaleLight | 6b7ed78 | 2022-12-20 18:05:40 +0800 | [diff] [blame] | 568 | tracker_.rotate(degrees); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 569 | } |
| 570 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 571 | void DisplayListBuilder::Skew(SkScalar sx, SkScalar sy) { |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 572 | if (SkScalarIsFinite(sx) && SkScalarIsFinite(sy) && |
| 573 | (sx != 0.0 || sy != 0.0)) { |
JsouLiang | ac81750 | 2022-08-11 15:48:40 +0800 | [diff] [blame] | 574 | checkForDeferredSave(); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 575 | Push<SkewOp>(0, 1, sx, sy); |
ColdPaleLight | 6b7ed78 | 2022-12-20 18:05:40 +0800 | [diff] [blame] | 576 | tracker_.skew(sx, sy); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 577 | } |
| 578 | } |
| 579 | |
| 580 | // clang-format off |
| 581 | |
| 582 | // 2x3 2D affine subset of a 4x4 transform in row major order |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 583 | void DisplayListBuilder::Transform2DAffine( |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 584 | SkScalar mxx, SkScalar mxy, SkScalar mxt, |
| 585 | SkScalar myx, SkScalar myy, SkScalar myt) { |
| 586 | if (SkScalarsAreFinite(mxx, myx) && |
| 587 | SkScalarsAreFinite(mxy, myy) && |
Jim Graham | 8dbffe5 | 2023-05-10 12:00:18 -0700 | [diff] [blame] | 588 | SkScalarsAreFinite(mxt, myt)) { |
| 589 | if (mxx == 1 && mxy == 0 && |
| 590 | myx == 0 && myy == 1) { |
| 591 | Translate(mxt, myt); |
| 592 | } else { |
| 593 | checkForDeferredSave(); |
| 594 | Push<Transform2DAffineOp>(0, 1, |
| 595 | mxx, mxy, mxt, |
| 596 | myx, myy, myt); |
| 597 | tracker_.transform2DAffine(mxx, mxy, mxt, |
| 598 | myx, myy, myt); |
| 599 | } |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 600 | } |
| 601 | } |
| 602 | // full 4x4 transform in row major order |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 603 | void DisplayListBuilder::TransformFullPerspective( |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 604 | SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt, |
| 605 | SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt, |
| 606 | SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt, |
| 607 | SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt) { |
| 608 | if ( mxz == 0 && |
| 609 | myz == 0 && |
| 610 | mzx == 0 && mzy == 0 && mzz == 1 && mzt == 0 && |
| 611 | mwx == 0 && mwy == 0 && mwz == 0 && mwt == 1) { |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 612 | Transform2DAffine(mxx, mxy, mxt, |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 613 | myx, myy, myt); |
| 614 | } else if (SkScalarsAreFinite(mxx, mxy) && SkScalarsAreFinite(mxz, mxt) && |
| 615 | SkScalarsAreFinite(myx, myy) && SkScalarsAreFinite(myz, myt) && |
| 616 | SkScalarsAreFinite(mzx, mzy) && SkScalarsAreFinite(mzz, mzt) && |
| 617 | SkScalarsAreFinite(mwx, mwy) && SkScalarsAreFinite(mwz, mwt)) { |
JsouLiang | ac81750 | 2022-08-11 15:48:40 +0800 | [diff] [blame] | 618 | checkForDeferredSave(); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 619 | Push<TransformFullPerspectiveOp>(0, 1, |
| 620 | mxx, mxy, mxz, mxt, |
| 621 | myx, myy, myz, myt, |
| 622 | mzx, mzy, mzz, mzt, |
| 623 | mwx, mwy, mwz, mwt); |
ColdPaleLight | 6b7ed78 | 2022-12-20 18:05:40 +0800 | [diff] [blame] | 624 | tracker_.transformFullPerspective(mxx, mxy, mxz, mxt, |
| 625 | myx, myy, myz, myt, |
| 626 | mzx, mzy, mzz, mzt, |
| 627 | mwx, mwy, mwz, mwt); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 628 | } |
| 629 | } |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 630 | // clang-format on |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 631 | void DisplayListBuilder::TransformReset() { |
JsouLiang | ac81750 | 2022-08-11 15:48:40 +0800 | [diff] [blame] | 632 | checkForDeferredSave(); |
Chinmay Garde | 81547d1 | 2022-03-16 12:40:24 -0700 | [diff] [blame] | 633 | Push<TransformResetOp>(0, 0); |
ColdPaleLight | 6b7ed78 | 2022-12-20 18:05:40 +0800 | [diff] [blame] | 634 | tracker_.setIdentity(); |
Chinmay Garde | 81547d1 | 2022-03-16 12:40:24 -0700 | [diff] [blame] | 635 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 636 | void DisplayListBuilder::Transform(const SkMatrix* matrix) { |
Jim Graham | 1ef3f75 | 2022-04-19 23:04:03 -0700 | [diff] [blame] | 637 | if (matrix != nullptr) { |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 638 | Transform(SkM44(*matrix)); |
Jim Graham | 1ef3f75 | 2022-04-19 23:04:03 -0700 | [diff] [blame] | 639 | } |
| 640 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 641 | void DisplayListBuilder::Transform(const SkM44* m44) { |
Jim Graham | 1ef3f75 | 2022-04-19 23:04:03 -0700 | [diff] [blame] | 642 | if (m44 != nullptr) { |
| 643 | transformFullPerspective( |
| 644 | m44->rc(0, 0), m44->rc(0, 1), m44->rc(0, 2), m44->rc(0, 3), |
| 645 | m44->rc(1, 0), m44->rc(1, 1), m44->rc(1, 2), m44->rc(1, 3), |
| 646 | m44->rc(2, 0), m44->rc(2, 1), m44->rc(2, 2), m44->rc(2, 3), |
| 647 | m44->rc(3, 0), m44->rc(3, 1), m44->rc(3, 2), m44->rc(3, 3)); |
| 648 | } |
| 649 | } |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 650 | |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 651 | void DisplayListBuilder::ClipRect(const SkRect& rect, |
| 652 | ClipOp clip_op, |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 653 | bool is_aa) { |
JsouLiang | ac81750 | 2022-08-11 15:48:40 +0800 | [diff] [blame] | 654 | if (!rect.isFinite()) { |
| 655 | return; |
| 656 | } |
| 657 | checkForDeferredSave(); |
Jim Graham | 45de099 | 2022-06-14 18:53:06 -0700 | [diff] [blame] | 658 | switch (clip_op) { |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 659 | case ClipOp::kIntersect: |
Jim Graham | 45de099 | 2022-06-14 18:53:06 -0700 | [diff] [blame] | 660 | Push<ClipIntersectRectOp>(0, 1, rect, is_aa); |
Jim Graham | 45de099 | 2022-06-14 18:53:06 -0700 | [diff] [blame] | 661 | break; |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 662 | case ClipOp::kDifference: |
Jim Graham | 45de099 | 2022-06-14 18:53:06 -0700 | [diff] [blame] | 663 | Push<ClipDifferenceRectOp>(0, 1, rect, is_aa); |
| 664 | break; |
| 665 | } |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 666 | tracker_.clipRect(rect, clip_op, is_aa); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 667 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 668 | void DisplayListBuilder::ClipRRect(const SkRRect& rrect, |
| 669 | ClipOp clip_op, |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 670 | bool is_aa) { |
| 671 | if (rrect.isRect()) { |
| 672 | clipRect(rrect.rect(), clip_op, is_aa); |
| 673 | } else { |
JsouLiang | ac81750 | 2022-08-11 15:48:40 +0800 | [diff] [blame] | 674 | checkForDeferredSave(); |
Jim Graham | 45de099 | 2022-06-14 18:53:06 -0700 | [diff] [blame] | 675 | switch (clip_op) { |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 676 | case ClipOp::kIntersect: |
Jim Graham | 45de099 | 2022-06-14 18:53:06 -0700 | [diff] [blame] | 677 | Push<ClipIntersectRRectOp>(0, 1, rrect, is_aa); |
Jim Graham | 45de099 | 2022-06-14 18:53:06 -0700 | [diff] [blame] | 678 | break; |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 679 | case ClipOp::kDifference: |
Jim Graham | 45de099 | 2022-06-14 18:53:06 -0700 | [diff] [blame] | 680 | Push<ClipDifferenceRRectOp>(0, 1, rrect, is_aa); |
| 681 | break; |
| 682 | } |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 683 | tracker_.clipRRect(rrect, clip_op, is_aa); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 684 | } |
| 685 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 686 | void DisplayListBuilder::ClipPath(const SkPath& path, |
| 687 | ClipOp clip_op, |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 688 | bool is_aa) { |
| 689 | if (!path.isInverseFillType()) { |
| 690 | SkRect rect; |
| 691 | if (path.isRect(&rect)) { |
| 692 | this->clipRect(rect, clip_op, is_aa); |
| 693 | return; |
| 694 | } |
| 695 | SkRRect rrect; |
| 696 | if (path.isOval(&rect)) { |
| 697 | rrect.setOval(rect); |
| 698 | this->clipRRect(rrect, clip_op, is_aa); |
| 699 | return; |
| 700 | } |
| 701 | if (path.isRRect(&rrect)) { |
| 702 | this->clipRRect(rrect, clip_op, is_aa); |
| 703 | return; |
| 704 | } |
| 705 | } |
JsouLiang | ac81750 | 2022-08-11 15:48:40 +0800 | [diff] [blame] | 706 | checkForDeferredSave(); |
Jim Graham | 45de099 | 2022-06-14 18:53:06 -0700 | [diff] [blame] | 707 | switch (clip_op) { |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 708 | case ClipOp::kIntersect: |
Jim Graham | 45de099 | 2022-06-14 18:53:06 -0700 | [diff] [blame] | 709 | Push<ClipIntersectPathOp>(0, 1, path, is_aa); |
Jim Graham | 45de099 | 2022-06-14 18:53:06 -0700 | [diff] [blame] | 710 | break; |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 711 | case ClipOp::kDifference: |
Jim Graham | 45de099 | 2022-06-14 18:53:06 -0700 | [diff] [blame] | 712 | Push<ClipDifferencePathOp>(0, 1, path, is_aa); |
| 713 | break; |
| 714 | } |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 715 | tracker_.clipPath(path, clip_op, is_aa); |
Jim Graham | 5b31f4f | 2022-11-17 11:34:19 -0800 | [diff] [blame] | 716 | } |
| 717 | |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 718 | bool DisplayListBuilder::QuickReject(const SkRect& bounds) const { |
ColdPaleLight | 6b7ed78 | 2022-12-20 18:05:40 +0800 | [diff] [blame] | 719 | return tracker_.content_culled(bounds); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 720 | } |
| 721 | |
| 722 | void DisplayListBuilder::drawPaint() { |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 723 | Push<DrawPaintOp>(0, 1); |
| 724 | CheckLayerOpacityCompatibility(); |
| 725 | AccumulateUnbounded(); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 726 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 727 | void DisplayListBuilder::DrawPaint(const DlPaint& paint) { |
Jim Graham | de9093d | 2023-02-24 17:42:20 -0800 | [diff] [blame] | 728 | SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawPaintFlags); |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 729 | drawPaint(); |
| 730 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 731 | void DisplayListBuilder::DrawColor(DlColor color, DlBlendMode mode) { |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 732 | Push<DrawColorOp>(0, 1, color, mode); |
| 733 | CheckLayerOpacityCompatibility(mode); |
| 734 | AccumulateUnbounded(); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 735 | } |
| 736 | void DisplayListBuilder::drawLine(const SkPoint& p0, const SkPoint& p1) { |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 737 | Push<DrawLineOp>(0, 1, p0, p1); |
| 738 | CheckLayerOpacityCompatibility(); |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 739 | SkRect bounds = SkRect::MakeLTRB(p0.fX, p0.fY, p1.fX, p1.fY).makeSorted(); |
| 740 | DisplayListAttributeFlags flags = |
| 741 | (bounds.width() > 0.0f && bounds.height() > 0.0f) ? kDrawLineFlags |
| 742 | : kDrawHVLineFlags; |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 743 | AccumulateOpBounds(bounds, flags); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 744 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 745 | void DisplayListBuilder::DrawLine(const SkPoint& p0, |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 746 | const SkPoint& p1, |
| 747 | const DlPaint& paint) { |
Jim Graham | de9093d | 2023-02-24 17:42:20 -0800 | [diff] [blame] | 748 | SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawLineFlags); |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 749 | drawLine(p0, p1); |
| 750 | } |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 751 | void DisplayListBuilder::drawRect(const SkRect& rect) { |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 752 | Push<DrawRectOp>(0, 1, rect); |
| 753 | CheckLayerOpacityCompatibility(); |
| 754 | AccumulateOpBounds(rect.makeSorted(), kDrawRectFlags); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 755 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 756 | void DisplayListBuilder::DrawRect(const SkRect& rect, const DlPaint& paint) { |
Jim Graham | de9093d | 2023-02-24 17:42:20 -0800 | [diff] [blame] | 757 | SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawRectFlags); |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 758 | drawRect(rect); |
| 759 | } |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 760 | void DisplayListBuilder::drawOval(const SkRect& bounds) { |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 761 | Push<DrawOvalOp>(0, 1, bounds); |
| 762 | CheckLayerOpacityCompatibility(); |
| 763 | AccumulateOpBounds(bounds.makeSorted(), kDrawOvalFlags); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 764 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 765 | void DisplayListBuilder::DrawOval(const SkRect& bounds, const DlPaint& paint) { |
Jim Graham | de9093d | 2023-02-24 17:42:20 -0800 | [diff] [blame] | 766 | SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawOvalFlags); |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 767 | drawOval(bounds); |
| 768 | } |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 769 | void DisplayListBuilder::drawCircle(const SkPoint& center, SkScalar radius) { |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 770 | Push<DrawCircleOp>(0, 1, center, radius); |
| 771 | CheckLayerOpacityCompatibility(); |
| 772 | AccumulateOpBounds(SkRect::MakeLTRB(center.fX - radius, center.fY - radius, |
| 773 | center.fX + radius, center.fY + radius), |
| 774 | kDrawCircleFlags); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 775 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 776 | void DisplayListBuilder::DrawCircle(const SkPoint& center, |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 777 | SkScalar radius, |
| 778 | const DlPaint& paint) { |
Jim Graham | de9093d | 2023-02-24 17:42:20 -0800 | [diff] [blame] | 779 | SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawCircleFlags); |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 780 | drawCircle(center, radius); |
| 781 | } |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 782 | void DisplayListBuilder::drawRRect(const SkRRect& rrect) { |
| 783 | if (rrect.isRect()) { |
| 784 | drawRect(rrect.rect()); |
| 785 | } else if (rrect.isOval()) { |
| 786 | drawOval(rrect.rect()); |
| 787 | } else { |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 788 | Push<DrawRRectOp>(0, 1, rrect); |
| 789 | CheckLayerOpacityCompatibility(); |
| 790 | AccumulateOpBounds(rrect.getBounds(), kDrawRRectFlags); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 791 | } |
| 792 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 793 | void DisplayListBuilder::DrawRRect(const SkRRect& rrect, const DlPaint& paint) { |
Jim Graham | de9093d | 2023-02-24 17:42:20 -0800 | [diff] [blame] | 794 | SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawRRectFlags); |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 795 | drawRRect(rrect); |
| 796 | } |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 797 | void DisplayListBuilder::drawDRRect(const SkRRect& outer, |
| 798 | const SkRRect& inner) { |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 799 | Push<DrawDRRectOp>(0, 1, outer, inner); |
| 800 | CheckLayerOpacityCompatibility(); |
| 801 | AccumulateOpBounds(outer.getBounds(), kDrawDRRectFlags); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 802 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 803 | void DisplayListBuilder::DrawDRRect(const SkRRect& outer, |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 804 | const SkRRect& inner, |
| 805 | const DlPaint& paint) { |
Jim Graham | de9093d | 2023-02-24 17:42:20 -0800 | [diff] [blame] | 806 | SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawDRRectFlags); |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 807 | drawDRRect(outer, inner); |
| 808 | } |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 809 | void DisplayListBuilder::drawPath(const SkPath& path) { |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 810 | Push<DrawPathOp>(0, 1, path); |
| 811 | CheckLayerOpacityHairlineCompatibility(); |
| 812 | if (path.isInverseFillType()) { |
| 813 | AccumulateUnbounded(); |
| 814 | } else { |
| 815 | AccumulateOpBounds(path.getBounds(), kDrawPathFlags); |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 816 | } |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 817 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 818 | void DisplayListBuilder::DrawPath(const SkPath& path, const DlPaint& paint) { |
Jim Graham | de9093d | 2023-02-24 17:42:20 -0800 | [diff] [blame] | 819 | SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawPathFlags); |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 820 | drawPath(path); |
| 821 | } |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 822 | |
| 823 | void DisplayListBuilder::drawArc(const SkRect& bounds, |
| 824 | SkScalar start, |
| 825 | SkScalar sweep, |
| 826 | bool useCenter) { |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 827 | Push<DrawArcOp>(0, 1, bounds, start, sweep, useCenter); |
| 828 | if (useCenter) { |
| 829 | CheckLayerOpacityHairlineCompatibility(); |
| 830 | } else { |
| 831 | CheckLayerOpacityCompatibility(); |
| 832 | } |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 833 | // This could be tighter if we compute where the start and end |
| 834 | // angles are and then also consider the quadrants swept and |
| 835 | // the center if specified. |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 836 | AccumulateOpBounds(bounds, |
| 837 | useCenter // |
| 838 | ? kDrawArcWithCenterFlags |
| 839 | : kDrawArcNoCenterFlags); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 840 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 841 | void DisplayListBuilder::DrawArc(const SkRect& bounds, |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 842 | SkScalar start, |
| 843 | SkScalar sweep, |
| 844 | bool useCenter, |
| 845 | const DlPaint& paint) { |
Jim Graham | de9093d | 2023-02-24 17:42:20 -0800 | [diff] [blame] | 846 | SetAttributesFromPaint( |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 847 | paint, useCenter ? kDrawArcWithCenterFlags : kDrawArcNoCenterFlags); |
| 848 | drawArc(bounds, start, sweep, useCenter); |
| 849 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 850 | void DisplayListBuilder::drawPoints(PointMode mode, |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 851 | uint32_t count, |
| 852 | const SkPoint pts[]) { |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 853 | if (count == 0) { |
| 854 | return; |
| 855 | } |
| 856 | |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 857 | void* data_ptr; |
Jim Graham | 25514ec | 2023-03-19 15:59:17 -0700 | [diff] [blame] | 858 | FML_DCHECK(count < DlOpReceiver::kMaxDrawPointsCount); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 859 | int bytes = count * sizeof(SkPoint); |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 860 | RectBoundsAccumulator ptBounds; |
| 861 | for (size_t i = 0; i < count; i++) { |
| 862 | ptBounds.accumulate(pts[i]); |
| 863 | } |
| 864 | SkRect point_bounds = ptBounds.bounds(); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 865 | switch (mode) { |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 866 | case PointMode::kPoints: |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 867 | data_ptr = Push<DrawPointsOp>(bytes, 1, count); |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 868 | AccumulateOpBounds(point_bounds, kDrawPointsAsPointsFlags); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 869 | break; |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 870 | case PointMode::kLines: |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 871 | data_ptr = Push<DrawLinesOp>(bytes, 1, count); |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 872 | AccumulateOpBounds(point_bounds, kDrawPointsAsLinesFlags); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 873 | break; |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 874 | case PointMode::kPolygon: |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 875 | data_ptr = Push<DrawPolygonOp>(bytes, 1, count); |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 876 | AccumulateOpBounds(point_bounds, kDrawPointsAsPolygonFlags); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 877 | break; |
| 878 | default: |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 879 | FML_DCHECK(false); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 880 | return; |
| 881 | } |
| 882 | CopyV(data_ptr, pts, count); |
| 883 | // drawPoints treats every point or line (or segment of a polygon) |
| 884 | // as a completely separate operation meaning we cannot ensure |
| 885 | // distribution of group opacity without analyzing the mode and the |
| 886 | // bounds of every sub-primitive. |
| 887 | // See: https://fiddle.skia.org/c/228459001d2de8db117ce25ef5cedb0c |
| 888 | UpdateLayerOpacityCompatibility(false); |
| 889 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 890 | void DisplayListBuilder::DrawPoints(PointMode mode, |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 891 | uint32_t count, |
| 892 | const SkPoint pts[], |
| 893 | const DlPaint& paint) { |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 894 | const DisplayListAttributeFlags* flags; |
| 895 | switch (mode) { |
| 896 | case PointMode::kPoints: |
| 897 | flags = &DisplayListOpFlags::kDrawPointsAsPointsFlags; |
| 898 | break; |
| 899 | case PointMode::kLines: |
| 900 | flags = &DisplayListOpFlags::kDrawPointsAsLinesFlags; |
| 901 | break; |
| 902 | case PointMode::kPolygon: |
| 903 | flags = &DisplayListOpFlags::kDrawPointsAsPolygonFlags; |
| 904 | break; |
| 905 | default: |
| 906 | FML_DCHECK(false); |
| 907 | return; |
| 908 | } |
| 909 | SetAttributesFromPaint(paint, *flags); |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 910 | drawPoints(mode, count, pts); |
| 911 | } |
Jim Graham | e4f9ee1 | 2022-03-31 00:15:04 -0700 | [diff] [blame] | 912 | void DisplayListBuilder::drawVertices(const DlVertices* vertices, |
JsouLiang | 1aa5255 | 2022-03-20 05:10:07 +0800 | [diff] [blame] | 913 | DlBlendMode mode) { |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 914 | void* pod = Push<DrawVerticesOp>(vertices->size(), 1, mode); |
| 915 | new (pod) DlVertices(vertices); |
| 916 | // DrawVertices applies its colors to the paint so we have no way |
| 917 | // of controlling opacity using the current paint attributes. |
| 918 | // Although, examination of the |mode| might find some predictable |
| 919 | // cases. |
| 920 | UpdateLayerOpacityCompatibility(false); |
| 921 | AccumulateOpBounds(vertices->bounds(), kDrawVerticesFlags); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 922 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 923 | void DisplayListBuilder::DrawVertices(const DlVertices* vertices, |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 924 | DlBlendMode mode, |
| 925 | const DlPaint& paint) { |
Jim Graham | de9093d | 2023-02-24 17:42:20 -0800 | [diff] [blame] | 926 | SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawVerticesFlags); |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 927 | drawVertices(vertices, mode); |
| 928 | } |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 929 | |
Chinmay Garde | 6dd43e6 | 2022-03-30 13:31:37 -0700 | [diff] [blame] | 930 | void DisplayListBuilder::drawImage(const sk_sp<DlImage> image, |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 931 | const SkPoint point, |
JsouLiang | e25d1ce | 2022-06-18 03:26:04 +0800 | [diff] [blame] | 932 | DlImageSampling sampling, |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 933 | bool render_with_attributes) { |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 934 | render_with_attributes |
| 935 | ? Push<DrawImageWithAttrOp>(0, 1, image, point, sampling) |
| 936 | : Push<DrawImageOp>(0, 1, image, point, sampling); |
| 937 | CheckLayerOpacityCompatibility(render_with_attributes); |
| 938 | is_ui_thread_safe_ = is_ui_thread_safe_ && image->isUIThreadSafe(); |
| 939 | SkRect bounds = SkRect::MakeXYWH(point.fX, point.fY, // |
| 940 | image->width(), image->height()); |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 941 | DisplayListAttributeFlags flags = render_with_attributes // |
| 942 | ? kDrawImageWithPaintFlags |
| 943 | : kDrawImageFlags; |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 944 | AccumulateOpBounds(bounds, flags); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 945 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 946 | void DisplayListBuilder::DrawImage(const sk_sp<DlImage>& image, |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 947 | const SkPoint point, |
JsouLiang | e25d1ce | 2022-06-18 03:26:04 +0800 | [diff] [blame] | 948 | DlImageSampling sampling, |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 949 | const DlPaint* paint) { |
| 950 | if (paint != nullptr) { |
Jim Graham | de9093d | 2023-02-24 17:42:20 -0800 | [diff] [blame] | 951 | SetAttributesFromPaint(*paint, |
| 952 | DisplayListOpFlags::kDrawImageWithPaintFlags); |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 953 | drawImage(image, point, sampling, true); |
| 954 | } else { |
| 955 | drawImage(image, point, sampling, false); |
| 956 | } |
| 957 | } |
Chinmay Garde | 6dd43e6 | 2022-03-30 13:31:37 -0700 | [diff] [blame] | 958 | void DisplayListBuilder::drawImageRect(const sk_sp<DlImage> image, |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 959 | const SkRect& src, |
| 960 | const SkRect& dst, |
JsouLiang | e25d1ce | 2022-06-18 03:26:04 +0800 | [diff] [blame] | 961 | DlImageSampling sampling, |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 962 | bool render_with_attributes, |
Jim Graham | 25514ec | 2023-03-19 15:59:17 -0700 | [diff] [blame] | 963 | SrcRectConstraint constraint) { |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 964 | Push<DrawImageRectOp>(0, 1, image, src, dst, sampling, render_with_attributes, |
| 965 | constraint); |
| 966 | CheckLayerOpacityCompatibility(render_with_attributes); |
| 967 | is_ui_thread_safe_ = is_ui_thread_safe_ && image->isUIThreadSafe(); |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 968 | DisplayListAttributeFlags flags = render_with_attributes |
| 969 | ? kDrawImageRectWithPaintFlags |
| 970 | : kDrawImageRectFlags; |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 971 | AccumulateOpBounds(dst, flags); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 972 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 973 | void DisplayListBuilder::DrawImageRect(const sk_sp<DlImage>& image, |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 974 | const SkRect& src, |
| 975 | const SkRect& dst, |
JsouLiang | e25d1ce | 2022-06-18 03:26:04 +0800 | [diff] [blame] | 976 | DlImageSampling sampling, |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 977 | const DlPaint* paint, |
Jim Graham | 25514ec | 2023-03-19 15:59:17 -0700 | [diff] [blame] | 978 | SrcRectConstraint constraint) { |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 979 | if (paint != nullptr) { |
Jim Graham | de9093d | 2023-02-24 17:42:20 -0800 | [diff] [blame] | 980 | SetAttributesFromPaint(*paint, |
| 981 | DisplayListOpFlags::kDrawImageRectWithPaintFlags); |
Jason Simmons | b3e314e | 2023-03-06 18:58:49 -0800 | [diff] [blame] | 982 | drawImageRect(image, src, dst, sampling, true, constraint); |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 983 | } else { |
Jason Simmons | b3e314e | 2023-03-06 18:58:49 -0800 | [diff] [blame] | 984 | drawImageRect(image, src, dst, sampling, false, constraint); |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 985 | } |
| 986 | } |
Chinmay Garde | 6dd43e6 | 2022-03-30 13:31:37 -0700 | [diff] [blame] | 987 | void DisplayListBuilder::drawImageNine(const sk_sp<DlImage> image, |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 988 | const SkIRect& center, |
| 989 | const SkRect& dst, |
JsouLiang | e25d1ce | 2022-06-18 03:26:04 +0800 | [diff] [blame] | 990 | DlFilterMode filter, |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 991 | bool render_with_attributes) { |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 992 | render_with_attributes |
| 993 | ? Push<DrawImageNineWithAttrOp>(0, 1, image, center, dst, filter) |
| 994 | : Push<DrawImageNineOp>(0, 1, image, center, dst, filter); |
| 995 | CheckLayerOpacityCompatibility(render_with_attributes); |
| 996 | is_ui_thread_safe_ = is_ui_thread_safe_ && image->isUIThreadSafe(); |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 997 | DisplayListAttributeFlags flags = render_with_attributes |
| 998 | ? kDrawImageNineWithPaintFlags |
| 999 | : kDrawImageNineFlags; |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 1000 | AccumulateOpBounds(dst, flags); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 1001 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 1002 | void DisplayListBuilder::DrawImageNine(const sk_sp<DlImage>& image, |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 1003 | const SkIRect& center, |
| 1004 | const SkRect& dst, |
JsouLiang | e25d1ce | 2022-06-18 03:26:04 +0800 | [diff] [blame] | 1005 | DlFilterMode filter, |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 1006 | const DlPaint* paint) { |
| 1007 | if (paint != nullptr) { |
Jim Graham | de9093d | 2023-02-24 17:42:20 -0800 | [diff] [blame] | 1008 | SetAttributesFromPaint(*paint, |
| 1009 | DisplayListOpFlags::kDrawImageNineWithPaintFlags); |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 1010 | drawImageNine(image, center, dst, filter, true); |
| 1011 | } else { |
| 1012 | drawImageNine(image, center, dst, filter, false); |
| 1013 | } |
| 1014 | } |
Chinmay Garde | 6dd43e6 | 2022-03-30 13:31:37 -0700 | [diff] [blame] | 1015 | void DisplayListBuilder::drawAtlas(const sk_sp<DlImage> atlas, |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 1016 | const SkRSXform xform[], |
| 1017 | const SkRect tex[], |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 1018 | const DlColor colors[], |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 1019 | int count, |
JsouLiang | 1aa5255 | 2022-03-20 05:10:07 +0800 | [diff] [blame] | 1020 | DlBlendMode mode, |
JsouLiang | e25d1ce | 2022-06-18 03:26:04 +0800 | [diff] [blame] | 1021 | DlImageSampling sampling, |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 1022 | const SkRect* cull_rect, |
| 1023 | bool render_with_attributes) { |
| 1024 | int bytes = count * (sizeof(SkRSXform) + sizeof(SkRect)); |
| 1025 | void* data_ptr; |
| 1026 | if (colors != nullptr) { |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 1027 | bytes += count * sizeof(DlColor); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 1028 | if (cull_rect != nullptr) { |
gaaclarke | 56841d4 | 2022-10-26 01:19:12 -0700 | [diff] [blame] | 1029 | data_ptr = |
| 1030 | Push<DrawAtlasCulledOp>(bytes, 1, atlas, count, mode, sampling, true, |
| 1031 | *cull_rect, render_with_attributes); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 1032 | } else { |
gaaclarke | 56841d4 | 2022-10-26 01:19:12 -0700 | [diff] [blame] | 1033 | data_ptr = Push<DrawAtlasOp>(bytes, 1, atlas, count, mode, sampling, true, |
| 1034 | render_with_attributes); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 1035 | } |
| 1036 | CopyV(data_ptr, xform, count, tex, count, colors, count); |
| 1037 | } else { |
| 1038 | if (cull_rect != nullptr) { |
gaaclarke | 56841d4 | 2022-10-26 01:19:12 -0700 | [diff] [blame] | 1039 | data_ptr = |
| 1040 | Push<DrawAtlasCulledOp>(bytes, 1, atlas, count, mode, sampling, false, |
| 1041 | *cull_rect, render_with_attributes); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 1042 | } else { |
gaaclarke | 56841d4 | 2022-10-26 01:19:12 -0700 | [diff] [blame] | 1043 | data_ptr = Push<DrawAtlasOp>(bytes, 1, atlas, count, mode, sampling, |
| 1044 | false, render_with_attributes); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 1045 | } |
| 1046 | CopyV(data_ptr, xform, count, tex, count); |
| 1047 | } |
| 1048 | // drawAtlas treats each image as a separate operation so we cannot rely |
| 1049 | // on it to distribute the opacity without overlap without checking all |
| 1050 | // of the transforms and texture rectangles. |
| 1051 | UpdateLayerOpacityCompatibility(false); |
Jim Graham | 35833e7 | 2023-04-17 16:47:20 -0700 | [diff] [blame] | 1052 | is_ui_thread_safe_ = is_ui_thread_safe_ && atlas->isUIThreadSafe(); |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 1053 | |
| 1054 | SkPoint quad[4]; |
| 1055 | RectBoundsAccumulator atlasBounds; |
| 1056 | for (int i = 0; i < count; i++) { |
| 1057 | const SkRect& src = tex[i]; |
| 1058 | xform[i].toQuad(src.width(), src.height(), quad); |
| 1059 | for (int j = 0; j < 4; j++) { |
| 1060 | atlasBounds.accumulate(quad[j]); |
| 1061 | } |
| 1062 | } |
| 1063 | if (atlasBounds.is_not_empty()) { |
| 1064 | DisplayListAttributeFlags flags = render_with_attributes // |
| 1065 | ? kDrawAtlasWithPaintFlags |
| 1066 | : kDrawAtlasFlags; |
| 1067 | AccumulateOpBounds(atlasBounds.bounds(), flags); |
| 1068 | } |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 1069 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 1070 | void DisplayListBuilder::DrawAtlas(const sk_sp<DlImage>& atlas, |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 1071 | const SkRSXform xform[], |
| 1072 | const SkRect tex[], |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 1073 | const DlColor colors[], |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 1074 | int count, |
| 1075 | DlBlendMode mode, |
JsouLiang | e25d1ce | 2022-06-18 03:26:04 +0800 | [diff] [blame] | 1076 | DlImageSampling sampling, |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 1077 | const SkRect* cull_rect, |
| 1078 | const DlPaint* paint) { |
| 1079 | if (paint != nullptr) { |
Jim Graham | de9093d | 2023-02-24 17:42:20 -0800 | [diff] [blame] | 1080 | SetAttributesFromPaint(*paint, |
| 1081 | DisplayListOpFlags::kDrawAtlasWithPaintFlags); |
Jim Graham | e881225 | 2022-04-22 15:54:03 -0700 | [diff] [blame] | 1082 | drawAtlas(atlas, xform, tex, colors, count, mode, sampling, cull_rect, |
| 1083 | true); |
| 1084 | } else { |
| 1085 | drawAtlas(atlas, xform, tex, colors, count, mode, sampling, cull_rect, |
| 1086 | false); |
| 1087 | } |
| 1088 | } |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 1089 | |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 1090 | void DisplayListBuilder::DrawDisplayList(const sk_sp<DisplayList> display_list, |
| 1091 | SkScalar opacity) { |
| 1092 | DlPaint current_paint = current_; |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 1093 | Push<DrawDisplayListOp>(0, 1, display_list, opacity); |
Jim Graham | 35833e7 | 2023-04-17 16:47:20 -0700 | [diff] [blame] | 1094 | is_ui_thread_safe_ = is_ui_thread_safe_ && display_list->isUIThreadSafe(); |
Jim Graham | 25514ec | 2023-03-19 15:59:17 -0700 | [diff] [blame] | 1095 | // Not really necessary if the developer is interacting with us via |
| 1096 | // our attribute-state-less DlCanvas methods, but this avoids surprises |
| 1097 | // for those who may have been using the stateful Dispatcher methods. |
| 1098 | SetAttributesFromPaint(current_paint, |
| 1099 | DisplayListOpFlags::kSaveLayerWithPaintFlags); |
Jim Graham | 147ac7d | 2022-12-22 02:16:25 -0800 | [diff] [blame] | 1100 | |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 1101 | const SkRect bounds = display_list->bounds(); |
| 1102 | switch (accumulator()->type()) { |
| 1103 | case BoundsAccumulatorType::kRect: |
| 1104 | AccumulateOpBounds(bounds, kDrawDisplayListFlags); |
| 1105 | break; |
| 1106 | case BoundsAccumulatorType::kRTree: |
| 1107 | auto rtree = display_list->rtree(); |
| 1108 | if (rtree) { |
| 1109 | std::list<SkRect> rects = |
| 1110 | rtree->searchAndConsolidateRects(bounds, false); |
| 1111 | for (const SkRect& rect : rects) { |
| 1112 | // TODO (https://github.com/flutter/flutter/issues/114919): Attributes |
| 1113 | // are not necessarily `kDrawDisplayListFlags`. |
| 1114 | AccumulateOpBounds(rect, kDrawDisplayListFlags); |
| 1115 | } |
| 1116 | } else { |
| 1117 | AccumulateOpBounds(bounds, kDrawDisplayListFlags); |
| 1118 | } |
| 1119 | break; |
| 1120 | } |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 1121 | // The non-nested op count accumulated in the |Push| method will include |
| 1122 | // this call to |drawDisplayList| for non-nested op count metrics. |
| 1123 | // But, for nested op count metrics we want the |drawDisplayList| call itself |
| 1124 | // to be transparent. So we subtract 1 from our accumulated nested count to |
| 1125 | // balance out against the 1 that was accumulated into the regular count. |
Jim Graham | de9093d | 2023-02-24 17:42:20 -0800 | [diff] [blame] | 1126 | // This behavior is identical to the way SkPicture computed nested op counts. |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 1127 | nested_op_count_ += display_list->op_count(true) - 1; |
| 1128 | nested_bytes_ += display_list->bytes(true); |
| 1129 | UpdateLayerOpacityCompatibility(display_list->can_apply_group_opacity()); |
| 1130 | } |
| 1131 | void DisplayListBuilder::drawTextBlob(const sk_sp<SkTextBlob> blob, |
| 1132 | SkScalar x, |
| 1133 | SkScalar y) { |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 1134 | Push<DrawTextBlobOp>(0, 1, blob, x, y); |
| 1135 | AccumulateOpBounds(blob->bounds().makeOffset(x, y), kDrawTextBlobFlags); |
| 1136 | // There is no way to query if the glyphs of a text blob overlap and |
| 1137 | // there are no current guarantees from either Skia or Impeller that |
| 1138 | // they will protect overlapping glyphs from the effects of overdraw |
| 1139 | // so we must make the conservative assessment that this DL layer is |
| 1140 | // not compatible with group opacity inheritance. |
| 1141 | UpdateLayerOpacityCompatibility(false); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 1142 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 1143 | void DisplayListBuilder::DrawTextBlob(const sk_sp<SkTextBlob>& blob, |
Jason Simmons | 4cbfe42 | 2022-11-11 08:39:23 -0800 | [diff] [blame] | 1144 | SkScalar x, |
| 1145 | SkScalar y, |
| 1146 | const DlPaint& paint) { |
Jim Graham | de9093d | 2023-02-24 17:42:20 -0800 | [diff] [blame] | 1147 | SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawTextBlobFlags); |
Jason Simmons | 4cbfe42 | 2022-11-11 08:39:23 -0800 | [diff] [blame] | 1148 | drawTextBlob(blob, x, y); |
| 1149 | } |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 1150 | void DisplayListBuilder::DrawShadow(const SkPath& path, |
Jim Graham | d45b911 | 2022-04-29 13:59:06 -0700 | [diff] [blame] | 1151 | const DlColor color, |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 1152 | const SkScalar elevation, |
| 1153 | bool transparent_occluder, |
| 1154 | SkScalar dpr) { |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 1155 | transparent_occluder // |
| 1156 | ? Push<DrawShadowTransparentOccluderOp>(0, 1, path, color, elevation, dpr) |
| 1157 | : Push<DrawShadowOp>(0, 1, path, color, elevation, dpr); |
| 1158 | |
| 1159 | SkRect shadow_bounds = |
| 1160 | DlCanvas::ComputeShadowBounds(path, elevation, dpr, GetTransform()); |
| 1161 | AccumulateOpBounds(shadow_bounds, kDrawShadowFlags); |
| 1162 | UpdateLayerOpacityCompatibility(false); |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 1163 | } |
| 1164 | |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 1165 | bool DisplayListBuilder::ComputeFilteredBounds(SkRect& bounds, |
| 1166 | const DlImageFilter* filter) { |
| 1167 | if (filter) { |
| 1168 | if (!filter->map_local_bounds(bounds, bounds)) { |
| 1169 | return false; |
| 1170 | } |
| 1171 | } |
| 1172 | return true; |
| 1173 | } |
| 1174 | |
| 1175 | bool DisplayListBuilder::AdjustBoundsForPaint(SkRect& bounds, |
| 1176 | DisplayListAttributeFlags flags) { |
| 1177 | if (flags.ignores_paint()) { |
| 1178 | return true; |
| 1179 | } |
| 1180 | |
| 1181 | if (flags.is_geometric()) { |
Jim Graham | f73ac7d | 2023-03-01 19:49:18 -0800 | [diff] [blame] | 1182 | bool is_stroked = flags.is_stroked(current_.getDrawStyle()); |
| 1183 | |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 1184 | // Path effect occurs before stroking... |
| 1185 | DisplayListSpecialGeometryFlags special_flags = |
Jim Graham | f73ac7d | 2023-03-01 19:49:18 -0800 | [diff] [blame] | 1186 | flags.WithPathEffect(current_.getPathEffectPtr(), is_stroked); |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 1187 | if (current_.getPathEffect()) { |
| 1188 | auto effect_bounds = current_.getPathEffect()->effect_bounds(bounds); |
| 1189 | if (!effect_bounds.has_value()) { |
| 1190 | return false; |
| 1191 | } |
| 1192 | bounds = effect_bounds.value(); |
| 1193 | } |
| 1194 | |
Jim Graham | f73ac7d | 2023-03-01 19:49:18 -0800 | [diff] [blame] | 1195 | if (is_stroked) { |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 1196 | // Determine the max multiplier to the stroke width first. |
| 1197 | SkScalar pad = 1.0f; |
| 1198 | if (current_.getStrokeJoin() == DlStrokeJoin::kMiter && |
| 1199 | special_flags.may_have_acute_joins()) { |
| 1200 | pad = std::max(pad, current_.getStrokeMiter()); |
| 1201 | } |
| 1202 | if (current_.getStrokeCap() == DlStrokeCap::kSquare && |
| 1203 | special_flags.may_have_diagonal_caps()) { |
| 1204 | pad = std::max(pad, SK_ScalarSqrt2); |
| 1205 | } |
| 1206 | SkScalar min_stroke_width = 0.01; |
Jim Graham | 25514ec | 2023-03-19 15:59:17 -0700 | [diff] [blame] | 1207 | pad *= std::max(current_.getStrokeWidth() * 0.5f, min_stroke_width); |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 1208 | bounds.outset(pad, pad); |
| 1209 | } |
| 1210 | } |
| 1211 | |
| 1212 | if (flags.applies_mask_filter()) { |
Jim Graham | f73ac7d | 2023-03-01 19:49:18 -0800 | [diff] [blame] | 1213 | auto filter = current_.getMaskFilter(); |
| 1214 | if (filter) { |
| 1215 | switch (filter->type()) { |
| 1216 | case DlMaskFilterType::kBlur: { |
| 1217 | FML_DCHECK(filter->asBlur()); |
| 1218 | SkScalar mask_sigma_pad = filter->asBlur()->sigma() * 3.0; |
| 1219 | bounds.outset(mask_sigma_pad, mask_sigma_pad); |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 1220 | } |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 1221 | } |
| 1222 | } |
| 1223 | } |
| 1224 | |
| 1225 | if (flags.applies_image_filter()) { |
| 1226 | return ComputeFilteredBounds(bounds, current_.getImageFilter().get()); |
| 1227 | } |
| 1228 | |
| 1229 | return true; |
| 1230 | } |
| 1231 | |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 1232 | void DisplayListBuilder::AccumulateUnbounded() { |
| 1233 | accumulator()->accumulate(tracker_.device_cull_rect(), op_index_ - 1); |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 1234 | } |
| 1235 | |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 1236 | void DisplayListBuilder::AccumulateOpBounds(SkRect& bounds, |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 1237 | DisplayListAttributeFlags flags) { |
| 1238 | if (AdjustBoundsForPaint(bounds, flags)) { |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 1239 | AccumulateBounds(bounds); |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 1240 | } else { |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 1241 | AccumulateUnbounded(); |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 1242 | } |
| 1243 | } |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 1244 | void DisplayListBuilder::AccumulateBounds(SkRect& bounds) { |
| 1245 | tracker_.mapRect(&bounds); |
| 1246 | if (bounds.intersect(tracker_.device_cull_rect())) { |
| 1247 | accumulator()->accumulate(bounds, op_index_ - 1); |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 1248 | } |
| 1249 | } |
| 1250 | |
| 1251 | bool DisplayListBuilder::paint_nops_on_transparency() { |
| 1252 | // SkImageFilter::canComputeFastBounds tests for transparency behavior |
| 1253 | // This test assumes that the blend mode checked down below will |
| 1254 | // NOP on transparent black. |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 1255 | if (current_.getImageFilter() && |
| 1256 | current_.getImageFilter()->modifies_transparent_black()) { |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 1257 | return false; |
| 1258 | } |
| 1259 | |
| 1260 | // We filter the transparent black that is used for the background of a |
| 1261 | // saveLayer and make sure it returns transparent black. If it does, then |
| 1262 | // the color filter will leave all area surrounding the contents of the |
| 1263 | // save layer untouched out to the edge of the output surface. |
| 1264 | // This test assumes that the blend mode checked down below will |
| 1265 | // NOP on transparent black. |
Zachary Anderson | 886a14e | 2023-07-15 07:14:10 -0700 | [diff] [blame^] | 1266 | if (current_.getColorFilter() && |
| 1267 | current_.getColorFilter()->modifies_transparent_black()) { |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 1268 | return false; |
| 1269 | } |
| 1270 | |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 1271 | // Unusual blendmodes require us to process a saved layer |
Jim Graham | ee6969d | 2023-03-20 19:34:48 -0700 | [diff] [blame] | 1272 | // even with operations outside the clip. |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 1273 | // For example, DstIn is used by masking layers. |
| 1274 | // https://code.google.com/p/skia/issues/detail?id=1291 |
| 1275 | // https://crbug.com/401593 |
Jim Graham | 25514ec | 2023-03-19 15:59:17 -0700 | [diff] [blame] | 1276 | switch (current_.getBlendMode()) { |
ColdPaleLight | 948699b | 2022-12-15 19:52:52 +0800 | [diff] [blame] | 1277 | // For each of the following transfer modes, if the source |
| 1278 | // alpha is zero (our transparent black), the resulting |
| 1279 | // blended pixel is not necessarily equal to the original |
| 1280 | // destination pixel. |
| 1281 | // Mathematically, any time in the following equations where |
| 1282 | // the result is not d assuming source is 0 |
| 1283 | case DlBlendMode::kClear: // r = 0 |
| 1284 | case DlBlendMode::kSrc: // r = s |
| 1285 | case DlBlendMode::kSrcIn: // r = s * da |
| 1286 | case DlBlendMode::kDstIn: // r = d * sa |
| 1287 | case DlBlendMode::kSrcOut: // r = s * (1-da) |
| 1288 | case DlBlendMode::kDstATop: // r = d*sa + s*(1-da) |
| 1289 | case DlBlendMode::kModulate: // r = s*d |
| 1290 | return false; |
| 1291 | break; |
| 1292 | |
| 1293 | // And in these equations, the result must be d if the |
| 1294 | // source is 0 |
| 1295 | case DlBlendMode::kDst: // r = d |
| 1296 | case DlBlendMode::kSrcOver: // r = s + (1-sa)*d |
| 1297 | case DlBlendMode::kDstOver: // r = d + (1-da)*s |
| 1298 | case DlBlendMode::kDstOut: // r = d * (1-sa) |
| 1299 | case DlBlendMode::kSrcATop: // r = s*da + d*(1-sa) |
| 1300 | case DlBlendMode::kXor: // r = s*(1-da) + d*(1-sa) |
| 1301 | case DlBlendMode::kPlus: // r = min(s + d, 1) |
| 1302 | case DlBlendMode::kScreen: // r = s + d - s*d |
| 1303 | case DlBlendMode::kOverlay: // multiply or screen, depending on dest |
| 1304 | case DlBlendMode::kDarken: // rc = s + d - max(s*da, d*sa), |
| 1305 | // ra = kSrcOver |
| 1306 | case DlBlendMode::kLighten: // rc = s + d - min(s*da, d*sa), |
| 1307 | // ra = kSrcOver |
| 1308 | case DlBlendMode::kColorDodge: // brighten destination to reflect source |
| 1309 | case DlBlendMode::kColorBurn: // darken destination to reflect source |
| 1310 | case DlBlendMode::kHardLight: // multiply or screen, depending on source |
| 1311 | case DlBlendMode::kSoftLight: // lighten or darken, depending on source |
| 1312 | case DlBlendMode::kDifference: // rc = s + d - 2*(min(s*da, d*sa)), |
| 1313 | // ra = kSrcOver |
| 1314 | case DlBlendMode::kExclusion: // rc = s + d - two(s*d), ra = kSrcOver |
| 1315 | case DlBlendMode::kMultiply: // r = s*(1-da) + d*(1-sa) + s*d |
| 1316 | case DlBlendMode::kHue: // ra = kSrcOver |
| 1317 | case DlBlendMode::kSaturation: // ra = kSrcOver |
| 1318 | case DlBlendMode::kColor: // ra = kSrcOver |
| 1319 | case DlBlendMode::kLuminosity: // ra = kSrcOver |
| 1320 | return true; |
| 1321 | break; |
| 1322 | } |
| 1323 | } |
Chinmay Garde | 41869f6 | 2021-12-28 15:19:35 -0800 | [diff] [blame] | 1324 | } // namespace flutter |