Jim Graham | eab0cd4 | 2021-06-30 17:31:02 -0700 | [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 | |
| 5 | #include "flutter/flow/layers/display_list_layer.h" |
| 6 | |
JsouLiang | 557655b | 2022-06-30 11:59:06 +0800 | [diff] [blame] | 7 | #include <utility> |
| 8 | |
Jim Graham | ee6969d | 2023-03-20 19:34:48 -0700 | [diff] [blame] | 9 | #include "flutter/display_list/dl_builder.h" |
Kaushik Iska | 95e2b56 | 2022-05-25 14:43:04 -0400 | [diff] [blame] | 10 | #include "flutter/flow/layer_snapshot_store.h" |
JsouLiang | 557655b | 2022-06-30 11:59:06 +0800 | [diff] [blame] | 11 | #include "flutter/flow/layers/cacheable_layer.h" |
Kaushik Iska | 9164243 | 2022-04-11 21:24:04 -0400 | [diff] [blame] | 12 | #include "flutter/flow/layers/offscreen_surface.h" |
Kaushik Iska | 777c4ac | 2022-06-06 17:28:04 -0400 | [diff] [blame] | 13 | #include "flutter/flow/raster_cache.h" |
JsouLiang | 557655b | 2022-06-30 11:59:06 +0800 | [diff] [blame] | 14 | #include "flutter/flow/raster_cache_util.h" |
Jim Graham | eab0cd4 | 2021-06-30 17:31:02 -0700 | [diff] [blame] | 15 | |
| 16 | namespace flutter { |
| 17 | |
| 18 | DisplayListLayer::DisplayListLayer(const SkPoint& offset, |
Jim Graham | 35833e7 | 2023-04-17 16:47:20 -0700 | [diff] [blame] | 19 | sk_sp<DisplayList> display_list, |
Jim Graham | eab0cd4 | 2021-06-30 17:31:02 -0700 | [diff] [blame] | 20 | bool is_complex, |
| 21 | bool will_change) |
JsouLiang | 557655b | 2022-06-30 11:59:06 +0800 | [diff] [blame] | 22 | : offset_(offset), display_list_(std::move(display_list)) { |
Jim Graham | 35833e7 | 2023-04-17 16:47:20 -0700 | [diff] [blame] | 23 | if (display_list_) { |
| 24 | bounds_ = display_list_->bounds().makeOffset(offset_.x(), offset_.y()); |
JsouLiang | 557655b | 2022-06-30 11:59:06 +0800 | [diff] [blame] | 25 | display_list_raster_cache_item_ = DisplayListRasterCacheItem::Make( |
Jim Graham | 35833e7 | 2023-04-17 16:47:20 -0700 | [diff] [blame] | 26 | display_list_, offset_, is_complex, will_change); |
JsouLiang | 557655b | 2022-06-30 11:59:06 +0800 | [diff] [blame] | 27 | } |
| 28 | } |
Jim Graham | eab0cd4 | 2021-06-30 17:31:02 -0700 | [diff] [blame] | 29 | |
Jim Graham | eab0cd4 | 2021-06-30 17:31:02 -0700 | [diff] [blame] | 30 | bool DisplayListLayer::IsReplacing(DiffContext* context, |
| 31 | const Layer* layer) const { |
| 32 | // Only return true for identical display lists; This way |
| 33 | // ContainerLayer::DiffChildren can detect when a display list layer |
| 34 | // got inserted between other display list layers |
| 35 | auto old_layer = layer->as_display_list_layer(); |
| 36 | return old_layer != nullptr && offset_ == old_layer->offset_ && |
| 37 | Compare(context->statistics(), this, old_layer); |
| 38 | } |
| 39 | |
| 40 | void DisplayListLayer::Diff(DiffContext* context, const Layer* old_layer) { |
| 41 | DiffContext::AutoSubtreeRestore subtree(context); |
| 42 | if (!context->IsSubtreeDirty()) { |
| 43 | #ifndef NDEBUG |
| 44 | FML_DCHECK(old_layer); |
| 45 | auto prev = old_layer->as_display_list_layer(); |
| 46 | DiffContext::Statistics dummy_statistics; |
| 47 | // IsReplacing has already determined that the display list is same |
| 48 | FML_DCHECK(prev->offset_ == offset_ && |
| 49 | Compare(dummy_statistics, this, prev)); |
| 50 | #endif |
| 51 | } |
| 52 | context->PushTransform(SkMatrix::Translate(offset_.x(), offset_.y())); |
Jonah Williams | 07ebf3c | 2022-09-08 18:10:01 -0700 | [diff] [blame] | 53 | if (context->has_raster_cache()) { |
Matej Knopp | 6660300 | 2023-02-10 21:50:28 +0100 | [diff] [blame] | 54 | context->WillPaintWithIntegralTransform(); |
Jonah Williams | 07ebf3c | 2022-09-08 18:10:01 -0700 | [diff] [blame] | 55 | } |
Jim Graham | 5a4d88c | 2021-09-17 10:37:01 -0700 | [diff] [blame] | 56 | context->AddLayerBounds(display_list()->bounds()); |
Jim Graham | eab0cd4 | 2021-06-30 17:31:02 -0700 | [diff] [blame] | 57 | context->SetLayerPaintRegion(this, context->CurrentSubtreeRegion()); |
| 58 | } |
| 59 | |
| 60 | bool DisplayListLayer::Compare(DiffContext::Statistics& statistics, |
| 61 | const DisplayListLayer* l1, |
| 62 | const DisplayListLayer* l2) { |
Jim Graham | 35833e7 | 2023-04-17 16:47:20 -0700 | [diff] [blame] | 63 | const auto& dl1 = l1->display_list_; |
| 64 | const auto& dl2 = l2->display_list_; |
Jim Graham | eab0cd4 | 2021-06-30 17:31:02 -0700 | [diff] [blame] | 65 | if (dl1.get() == dl2.get()) { |
| 66 | statistics.AddSameInstancePicture(); |
| 67 | return true; |
| 68 | } |
| 69 | const auto op_cnt_1 = dl1->op_count(); |
| 70 | const auto op_cnt_2 = dl2->op_count(); |
| 71 | const auto op_bytes_1 = dl1->bytes(); |
| 72 | const auto op_bytes_2 = dl2->bytes(); |
| 73 | if (op_cnt_1 != op_cnt_2 || op_bytes_1 != op_bytes_2 || |
| 74 | dl1->bounds() != dl2->bounds()) { |
| 75 | statistics.AddNewPicture(); |
| 76 | return false; |
| 77 | } |
| 78 | |
| 79 | if (op_bytes_1 > kMaxBytesToCompare) { |
| 80 | statistics.AddPictureTooComplexToCompare(); |
| 81 | return false; |
| 82 | } |
| 83 | |
| 84 | statistics.AddDeepComparePicture(); |
| 85 | |
| 86 | auto res = dl1->Equals(*dl2); |
| 87 | if (res) { |
| 88 | statistics.AddDifferentInstanceButEqualPicture(); |
| 89 | } else { |
| 90 | statistics.AddNewPicture(); |
| 91 | } |
| 92 | return res; |
| 93 | } |
| 94 | |
Jim Graham | 5b31f4f | 2022-11-17 11:34:19 -0800 | [diff] [blame] | 95 | void DisplayListLayer::Preroll(PrerollContext* context) { |
Jim Graham | eab0cd4 | 2021-06-30 17:31:02 -0700 | [diff] [blame] | 96 | DisplayList* disp_list = display_list(); |
| 97 | |
Jim Graham | 5b31f4f | 2022-11-17 11:34:19 -0800 | [diff] [blame] | 98 | AutoCache cache = AutoCache(display_list_raster_cache_item_.get(), context, |
| 99 | context->state_stack.transform_3x3()); |
Jim Graham | 8ab4124 | 2022-04-22 16:19:04 -0700 | [diff] [blame] | 100 | if (disp_list->can_apply_group_opacity()) { |
Jim Graham | 5b31f4f | 2022-11-17 11:34:19 -0800 | [diff] [blame] | 101 | context->renderable_state_flags = LayerStateStack::kCallerCanApplyOpacity; |
Jim Graham | 8ab4124 | 2022-04-22 16:19:04 -0700 | [diff] [blame] | 102 | } |
JsouLiang | 557655b | 2022-06-30 11:59:06 +0800 | [diff] [blame] | 103 | set_paint_bounds(bounds_); |
Jim Graham | eab0cd4 | 2021-06-30 17:31:02 -0700 | [diff] [blame] | 104 | } |
| 105 | |
| 106 | void DisplayListLayer::Paint(PaintContext& context) const { |
Jim Graham | 35833e7 | 2023-04-17 16:47:20 -0700 | [diff] [blame] | 107 | FML_DCHECK(display_list_); |
Jim Graham | eab0cd4 | 2021-06-30 17:31:02 -0700 | [diff] [blame] | 108 | FML_DCHECK(needs_painting(context)); |
| 109 | |
Jim Graham | 5b31f4f | 2022-11-17 11:34:19 -0800 | [diff] [blame] | 110 | auto mutator = context.state_stack.save(); |
| 111 | mutator.translate(offset_.x(), offset_.y()); |
Jim Graham | 74969a2 | 2022-10-30 11:30:22 -0700 | [diff] [blame] | 112 | |
Jim Graham | 5b31f4f | 2022-11-17 11:34:19 -0800 | [diff] [blame] | 113 | if (context.raster_cache) { |
| 114 | // Always apply the integral transform in the presence of a raster cache |
| 115 | // whether or not we successfully draw from the cache |
| 116 | mutator.integralTransform(); |
| 117 | |
| 118 | if (display_list_raster_cache_item_) { |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 119 | DlPaint paint; |
Jim Graham | 5b31f4f | 2022-11-17 11:34:19 -0800 | [diff] [blame] | 120 | if (display_list_raster_cache_item_->Draw( |
| 121 | context, context.state_stack.fill(paint))) { |
| 122 | TRACE_EVENT_INSTANT0("flutter", "raster cache hit"); |
| 123 | return; |
| 124 | } |
Jim Graham | e444009 | 2021-12-14 16:19:09 -0800 | [diff] [blame] | 125 | } |
Jim Graham | eab0cd4 | 2021-06-30 17:31:02 -0700 | [diff] [blame] | 126 | } |
| 127 | |
Jim Graham | 5b31f4f | 2022-11-17 11:34:19 -0800 | [diff] [blame] | 128 | SkScalar opacity = context.state_stack.outstanding_opacity(); |
| 129 | |
Kaushik Iska | 9164243 | 2022-04-11 21:24:04 -0400 | [diff] [blame] | 130 | if (context.enable_leaf_layer_tracing) { |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 131 | const auto canvas_size = context.canvas->GetBaseLayerSize(); |
Kaushik Iska | 9164243 | 2022-04-11 21:24:04 -0400 | [diff] [blame] | 132 | auto offscreen_surface = |
| 133 | std::make_unique<OffscreenSurface>(context.gr_context, canvas_size); |
| 134 | |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 135 | const auto& ctm = context.canvas->GetTransform(); |
Kaushik Iska | 777c4ac | 2022-06-06 17:28:04 -0400 | [diff] [blame] | 136 | |
Kaushik Iska | 9164243 | 2022-04-11 21:24:04 -0400 | [diff] [blame] | 137 | const auto start_time = fml::TimePoint::Now(); |
| 138 | { |
| 139 | // render display list to offscreen surface. |
| 140 | auto* canvas = offscreen_surface->GetCanvas(); |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 141 | { |
| 142 | DlAutoCanvasRestore save(canvas, true); |
| 143 | canvas->Clear(DlColor::kTransparent()); |
| 144 | canvas->SetTransform(ctm); |
Jim Graham | 35833e7 | 2023-04-17 16:47:20 -0700 | [diff] [blame] | 145 | canvas->DrawDisplayList(display_list_, opacity); |
Jim Graham | 0d5b780 | 2023-02-23 22:09:35 -0800 | [diff] [blame] | 146 | } |
| 147 | canvas->Flush(); |
Kaushik Iska | 9164243 | 2022-04-11 21:24:04 -0400 | [diff] [blame] | 148 | } |
| 149 | const fml::TimeDelta offscreen_render_time = |
| 150 | fml::TimePoint::Now() - start_time; |
| 151 | |
Jonah Williams | edc2aa4 | 2022-06-13 16:43:05 -0700 | [diff] [blame] | 152 | const SkRect device_bounds = |
JsouLiang | 557655b | 2022-06-30 11:59:06 +0800 | [diff] [blame] | 153 | RasterCacheUtil::GetDeviceBounds(paint_bounds(), ctm); |
Kaushik Iska | 9164243 | 2022-04-11 21:24:04 -0400 | [diff] [blame] | 154 | sk_sp<SkData> raster_data = offscreen_surface->GetRasterData(true); |
Kaushik Iska | 95e2b56 | 2022-05-25 14:43:04 -0400 | [diff] [blame] | 155 | LayerSnapshotData snapshot_data(unique_id(), offscreen_render_time, |
Kaushik Iska | 777c4ac | 2022-06-06 17:28:04 -0400 | [diff] [blame] | 156 | raster_data, device_bounds); |
Kaushik Iska | 95e2b56 | 2022-05-25 14:43:04 -0400 | [diff] [blame] | 157 | context.layer_snapshot_store->Add(snapshot_data); |
Kaushik Iska | 9164243 | 2022-04-11 21:24:04 -0400 | [diff] [blame] | 158 | } |
| 159 | |
Jim Graham | 35833e7 | 2023-04-17 16:47:20 -0700 | [diff] [blame] | 160 | context.canvas->DrawDisplayList(display_list_, opacity); |
Jim Graham | eab0cd4 | 2021-06-30 17:31:02 -0700 | [diff] [blame] | 161 | } |
| 162 | |
| 163 | } // namespace flutter |