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/transform_layer.h" |
6 | |
7 | #include <optional> |
8 | |
9 | namespace flutter { |
10 | |
11 | TransformLayer::TransformLayer(const SkMatrix& transform) |
12 | : transform_(transform) { |
13 | // Checks (in some degree) that SkMatrix transform_ is valid and initialized. |
14 | // |
15 | // If transform_ is uninitialized, this assert may look flaky as it doesn't |
16 | // fail all the time, and some rerun may make it pass. But don't ignore it and |
17 | // just rerun the test if this is triggered, since even a flaky failure here |
18 | // may signify a potentially big problem in the code. |
19 | // |
20 | // We have to write this flaky test because there is no reliable way to test |
21 | // whether a variable is initialized or not in C++. |
22 | FML_DCHECK(transform_.isFinite()); |
23 | if (!transform_.isFinite()) { |
24 | FML_LOG(ERROR) << "TransformLayer is constructed with an invalid matrix." ; |
25 | transform_.setIdentity(); |
26 | } |
27 | } |
28 | |
29 | void TransformLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { |
30 | TRACE_EVENT0("flutter" , "TransformLayer::Preroll" ); |
31 | |
32 | SkMatrix child_matrix; |
33 | child_matrix.setConcat(matrix, transform_); |
34 | context->mutators_stack.PushTransform(transform_); |
35 | SkRect previous_cull_rect = context->cull_rect; |
36 | SkMatrix inverse_transform_; |
37 | // Perspective projections don't produce rectangles that are useful for |
38 | // culling for some reason. |
39 | if (!transform_.hasPerspective() && transform_.invert(&inverse_transform_)) { |
40 | inverse_transform_.mapRect(&context->cull_rect); |
41 | } else { |
42 | context->cull_rect = kGiantRect; |
43 | } |
44 | |
45 | SkRect child_paint_bounds = SkRect::MakeEmpty(); |
46 | PrerollChildren(context, child_matrix, &child_paint_bounds); |
47 | |
48 | transform_.mapRect(&child_paint_bounds); |
49 | set_paint_bounds(child_paint_bounds); |
50 | |
51 | context->cull_rect = previous_cull_rect; |
52 | context->mutators_stack.Pop(); |
53 | } |
54 | |
55 | #if defined(LEGACY_FUCHSIA_EMBEDDER) |
56 | |
57 | void TransformLayer::UpdateScene(SceneUpdateContext& context) { |
58 | TRACE_EVENT0("flutter" , "TransformLayer::UpdateScene" ); |
59 | FML_DCHECK(needs_system_composite()); |
60 | |
61 | std::optional<SceneUpdateContext::Transform> transform; |
62 | if (!transform_.isIdentity()) { |
63 | transform.emplace(context, transform_); |
64 | } |
65 | |
66 | UpdateSceneChildren(context); |
67 | } |
68 | |
69 | #endif |
70 | |
71 | void TransformLayer::Paint(PaintContext& context) const { |
72 | TRACE_EVENT0("flutter" , "TransformLayer::Paint" ); |
73 | FML_DCHECK(needs_painting()); |
74 | |
75 | SkAutoCanvasRestore save(context.internal_nodes_canvas, true); |
76 | context.internal_nodes_canvas->concat(transform_); |
77 | |
78 | PaintChildren(context); |
79 | } |
80 | |
81 | } // namespace flutter |
82 | |