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#ifndef FLOW_TESTING_LAYER_TEST_H_
6#define FLOW_TESTING_LAYER_TEST_H_
7
8#include "flutter/flow/layer_snapshot_store.h"
9#include "flutter/flow/layers/layer.h"
10
11#include <optional>
12#include <utility>
13#include <vector>
14
15#include "flutter/flow/testing/mock_raster_cache.h"
16#include "flutter/fml/macros.h"
17#include "flutter/testing/canvas_test.h"
18#include "flutter/testing/display_list_testing.h"
19#include "flutter/testing/mock_canvas.h"
20#include "third_party/skia/include/core/SkCanvas.h"
21#include "third_party/skia/include/core/SkImageInfo.h"
22#include "third_party/skia/include/utils/SkNWayCanvas.h"
23
24namespace flutter {
25namespace testing {
26
27// This fixture allows generating tests which can |Paint()| and |Preroll()|
28// |Layer|'s.
29// |LayerTest| is a default implementation based on |::testing::Test|.
30//
31// By default the preroll and paint contexts will not use a raster cache.
32// If a test needs to verify the proper operation of a layer in the presence
33// of a raster cache then a number of options can be enabled by using the
34// methods |LayerTestBase::use_null_raster_cache()|,
35// |LayerTestBase::use_mock_raster_cache()| or
36// |LayerTestBase::use_skia_raster_cache()|
37//
38// |BaseT| should be the base test type, such as |::testing::Test| below.
39template <typename BaseT>
40class LayerTestBase : public CanvasTestBase<BaseT> {
41 using TestT = CanvasTestBase<BaseT>;
42
43 const SkRect kDlBounds = SkRect::MakeWH(w: 500, h: 500);
44
45 public:
46 LayerTestBase()
47 : texture_registry_(std::make_shared<TextureRegistry>()),
48 preroll_context_{
49 // clang-format off
50 .raster_cache = nullptr,
51 .gr_context = nullptr,
52 .view_embedder = nullptr,
53 .state_stack = preroll_state_stack_,
54 .dst_color_space = TestT::mock_color_space(),
55 .surface_needs_readback = false,
56 .raster_time = raster_time_,
57 .ui_time = ui_time_,
58 .texture_registry = texture_registry_,
59 .has_platform_view = false,
60 .raster_cached_entries = &cacheable_items_,
61 // clang-format on
62 },
63 paint_context_{
64 // clang-format off
65 .state_stack = paint_state_stack_,
66 .canvas = &TestT::mock_canvas(),
67 .gr_context = nullptr,
68 .view_embedder = nullptr,
69 .raster_time = raster_time_,
70 .ui_time = ui_time_,
71 .texture_registry = texture_registry_,
72 .raster_cache = nullptr,
73 // clang-format on
74 },
75 display_list_builder_(kDlBounds),
76 display_list_paint_context_{
77 // clang-format off
78 .state_stack = display_list_state_stack_,
79 .canvas = &display_list_builder_,
80 .gr_context = nullptr,
81 .view_embedder = nullptr,
82 .raster_time = raster_time_,
83 .ui_time = ui_time_,
84 .texture_registry = texture_registry_,
85 .raster_cache = nullptr,
86 // clang-format on
87 },
88 checkerboard_context_{
89 // clang-format off
90 .state_stack = checkerboard_state_stack_,
91 .canvas = &display_list_builder_,
92 .gr_context = nullptr,
93 .view_embedder = nullptr,
94 .raster_time = raster_time_,
95 .ui_time = ui_time_,
96 .texture_registry = texture_registry_,
97 .raster_cache = nullptr,
98 // clang-format on
99 } {
100 use_null_raster_cache();
101 preroll_state_stack_.set_preroll_delegate(cull_rect: kGiantRect, matrix: SkMatrix::I());
102 paint_state_stack_.set_delegate(&TestT::mock_canvas());
103 display_list_state_stack_.set_delegate(&display_list_builder_);
104 checkerboard_state_stack_.set_delegate(&display_list_builder_);
105 checkerboard_state_stack_.set_checkerboard_func(draw_checkerboard);
106 checkerboard_paint_.setColor(checkerboard_color_);
107 }
108
109 /**
110 * @brief Use no raster cache in the preroll_context() and
111 * paint_context() structures.
112 *
113 * This method must be called before using the preroll_context() and
114 * paint_context() structures in calls to the Layer::Preroll() and
115 * Layer::Paint() methods. This is the default mode of operation.
116 *
117 * @see use_mock_raster_cache()
118 * @see use_skia_raster_cache()
119 */
120 void use_null_raster_cache() { set_raster_cache_(nullptr); }
121
122 /**
123 * @brief Use a mock raster cache in the preroll_context() and
124 * paint_context() structures.
125 *
126 * This method must be called before using the preroll_context() and
127 * paint_context() structures in calls to the Layer::Preroll() and
128 * Layer::Paint() methods. The mock raster cache behaves like a normal
129 * raster cache with respect to decisions about when layers and pictures
130 * should be cached, but it does not incur the overhead of rendering the
131 * layers or caching the resulting pixels.
132 *
133 * @see use_null_raster_cache()
134 * @see use_skia_raster_cache()
135 */
136 void use_mock_raster_cache() {
137 set_raster_cache_(std::make_unique<MockRasterCache>());
138 }
139
140 /**
141 * @brief Use a normal raster cache in the preroll_context() and
142 * paint_context() structures.
143 *
144 * This method must be called before using the preroll_context() and
145 * paint_context() structures in calls to the Layer::Preroll() and
146 * Layer::Paint() methods. The Skia raster cache will behave identically
147 * to the raster cache typically used when handling a frame on a device
148 * including rendering the contents of pictures and layers to an
149 * SkImage, but using a software rather than a hardware renderer.
150 *
151 * @see use_null_raster_cache()
152 * @see use_mock_raster_cache()
153 */
154 void use_skia_raster_cache() {
155 set_raster_cache_(std::make_unique<RasterCache>());
156 }
157
158 std::vector<RasterCacheItem*>& cacheable_items() { return cacheable_items_; }
159
160 std::shared_ptr<TextureRegistry> texture_registry() {
161 return texture_registry_;
162 }
163 RasterCache* raster_cache() { return raster_cache_.get(); }
164 PrerollContext* preroll_context() { return &preroll_context_; }
165 PaintContext& paint_context() { return paint_context_; }
166 PaintContext& display_list_paint_context() {
167 return display_list_paint_context_;
168 }
169 const DlPaint& checkerboard_paint() { return checkerboard_paint_; }
170 PaintContext& checkerboard_context() { return checkerboard_context_; }
171 LayerSnapshotStore& layer_snapshot_store() { return snapshot_store_; }
172
173 sk_sp<DisplayList> display_list() {
174 if (display_list_ == nullptr) {
175 display_list_ = display_list_builder_.Build();
176 }
177 return display_list_;
178 }
179
180 void reset_display_list() {
181 display_list_ = nullptr;
182 // Build() will leave the builder in a state to start recording a new DL
183 display_list_builder_.Build();
184 // Make sure we are starting from a fresh state stack
185 FML_DCHECK(display_list_state_stack_.is_empty());
186 }
187
188 void enable_leaf_layer_tracing() {
189 paint_context_.enable_leaf_layer_tracing = true;
190 paint_context_.layer_snapshot_store = &snapshot_store_;
191 }
192
193 void disable_leaf_layer_tracing() {
194 paint_context_.enable_leaf_layer_tracing = false;
195 paint_context_.layer_snapshot_store = nullptr;
196 }
197
198 void enable_impeller() {
199 preroll_context_.impeller_enabled = true;
200 paint_context_.impeller_enabled = true;
201 display_list_paint_context_.impeller_enabled = true;
202 }
203
204 private:
205 void set_raster_cache_(std::unique_ptr<RasterCache> raster_cache) {
206 raster_cache_ = std::move(raster_cache);
207 preroll_context_.raster_cache = raster_cache_.get();
208 paint_context_.raster_cache = raster_cache_.get();
209 display_list_paint_context_.raster_cache = raster_cache_.get();
210 }
211
212 static constexpr SkColor checkerboard_color_ = 0x42424242;
213
214 static void draw_checkerboard(DlCanvas* canvas, const SkRect& rect) {
215 if (canvas) {
216 DlPaint paint;
217 paint.setColor(checkerboard_color_);
218 canvas->DrawRect(rect, paint);
219 }
220 }
221
222 LayerStateStack preroll_state_stack_;
223 LayerStateStack paint_state_stack_;
224 LayerStateStack checkerboard_state_stack_;
225 FixedRefreshRateStopwatch raster_time_;
226 FixedRefreshRateStopwatch ui_time_;
227 std::shared_ptr<TextureRegistry> texture_registry_;
228
229 std::unique_ptr<RasterCache> raster_cache_;
230 PrerollContext preroll_context_;
231 PaintContext paint_context_;
232 DisplayListBuilder display_list_builder_;
233 LayerStateStack display_list_state_stack_;
234 sk_sp<DisplayList> display_list_;
235 PaintContext display_list_paint_context_;
236 DlPaint checkerboard_paint_;
237 PaintContext checkerboard_context_;
238 LayerSnapshotStore snapshot_store_;
239
240 std::vector<RasterCacheItem*> cacheable_items_;
241
242 FML_DISALLOW_COPY_AND_ASSIGN(LayerTestBase);
243};
244using LayerTest = LayerTestBase<::testing::Test>;
245
246} // namespace testing
247} // namespace flutter
248
249#endif // FLOW_TESTING_LAYER_TEST_H_
250

source code of flutter_engine/flutter/flow/testing/layer_test.h