forked from flutter/engine
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathpaint_pass_delegate.cc
More file actions
161 lines (139 loc) · 5.4 KB
/
paint_pass_delegate.cc
File metadata and controls
161 lines (139 loc) · 5.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/aiks/paint_pass_delegate.h"
#include "impeller/core/formats.h"
#include "impeller/core/sampler_descriptor.h"
#include "impeller/entity/contents/contents.h"
#include "impeller/entity/contents/texture_contents.h"
#include "impeller/entity/entity_pass.h"
#include "impeller/geometry/color.h"
namespace impeller {
/// PaintPassDelegate
/// ----------------------------------------------
PaintPassDelegate::PaintPassDelegate(Paint paint) : paint_(std::move(paint)) {}
// |EntityPassDelgate|
PaintPassDelegate::~PaintPassDelegate() = default;
// |EntityPassDelgate|
bool PaintPassDelegate::CanElide() {
return paint_.blend_mode == BlendMode::kDestination;
}
// |EntityPassDelgate|
bool PaintPassDelegate::CanCollapseIntoParentPass(EntityPass* entity_pass) {
return false;
}
// |EntityPassDelgate|
std::shared_ptr<Contents> PaintPassDelegate::CreateContentsForSubpassTarget(
std::shared_ptr<Texture> target,
const Matrix& effect_transform) {
auto contents = TextureContents::MakeRect(Rect::MakeSize(target->GetSize()));
contents->SetTexture(target);
contents->SetLabel("Subpass");
contents->SetSourceRect(Rect::MakeSize(target->GetSize()));
contents->SetOpacity(paint_.color.alpha);
contents->SetDeferApplyingOpacity(true);
return paint_.WithFiltersForSubpassTarget(std::move(contents),
effect_transform);
}
// |EntityPassDelgate|
std::shared_ptr<FilterContents> PaintPassDelegate::WithImageFilter(
const FilterInput::Variant& input,
const Matrix& effect_transform) const {
return paint_.WithImageFilter(
input, effect_transform,
Entity::RenderingMode::kSubpassPrependSnapshotTransform);
}
/// OpacityPeepholePassDelegate
/// ----------------------------------------------
OpacityPeepholePassDelegate::OpacityPeepholePassDelegate(Paint paint)
: paint_(std::move(paint)) {}
// |EntityPassDelgate|
OpacityPeepholePassDelegate::~OpacityPeepholePassDelegate() = default;
// |EntityPassDelgate|
bool OpacityPeepholePassDelegate::CanElide() {
return paint_.blend_mode == BlendMode::kDestination;
}
// |EntityPassDelgate|
bool OpacityPeepholePassDelegate::CanCollapseIntoParentPass(
EntityPass* entity_pass) {
// Passes with enforced bounds that clip the contents can not be safely
// collapsed.
if (entity_pass->GetBoundsLimitMightClipContent()) {
return false;
}
// OpacityPeepholePassDelegate will only get used if the pass's blend mode is
// SourceOver, so no need to check here.
if (paint_.color.alpha <= 0.0 || paint_.color.alpha >= 1.0 ||
paint_.image_filter || paint_.color_filter) {
return false;
}
// Note: determing whether any coverage intersects has quadradic complexity in
// the number of rectangles, and depending on whether or not we cache at
// different levels of the entity tree may end up cubic. In the interest of
// proving whether or not this optimization is valuable, we only consider very
// simple peephole optimizations here - where there is a single drawing
// command wrapped in save layer. This would indicate something like an
// Opacity or FadeTransition wrapping a very simple widget, like in the
// CupertinoPicker.
if (entity_pass->GetElementCount() > 3) {
// Single paint command with a save layer would be:
// 1. clip
// 2. draw command
// 3. restore.
return false;
}
bool all_can_accept = true;
std::vector<Rect> all_coverages;
auto had_subpass = entity_pass->IterateUntilSubpass(
[&all_coverages, &all_can_accept](Entity& entity) {
const auto& contents = entity.GetContents();
if (!entity.CanInheritOpacity()) {
all_can_accept = false;
return false;
}
auto maybe_coverage = contents->GetCoverage(entity);
if (maybe_coverage.has_value()) {
auto coverage = maybe_coverage.value();
for (const auto& cv : all_coverages) {
if (cv.IntersectsWithRect(coverage)) {
all_can_accept = false;
return false;
}
}
all_coverages.push_back(coverage);
}
return true;
});
if (had_subpass || !all_can_accept) {
return false;
}
auto alpha = paint_.color.alpha;
entity_pass->IterateUntilSubpass([&alpha](Entity& entity) {
entity.SetInheritedOpacity(alpha);
return true;
});
return true;
}
// |EntityPassDelgate|
std::shared_ptr<Contents>
OpacityPeepholePassDelegate::CreateContentsForSubpassTarget(
std::shared_ptr<Texture> target,
const Matrix& effect_transform) {
auto contents = TextureContents::MakeRect(Rect::MakeSize(target->GetSize()));
contents->SetLabel("Subpass");
contents->SetTexture(target);
contents->SetSourceRect(Rect::MakeSize(target->GetSize()));
contents->SetOpacity(paint_.color.alpha);
contents->SetDeferApplyingOpacity(true);
return paint_.WithFiltersForSubpassTarget(std::move(contents),
effect_transform);
}
// |EntityPassDelgate|
std::shared_ptr<FilterContents> OpacityPeepholePassDelegate::WithImageFilter(
const FilterInput::Variant& input,
const Matrix& effect_transform) const {
return paint_.WithImageFilter(
input, effect_transform,
Entity::RenderingMode::kSubpassPrependSnapshotTransform);
}
} // namespace impeller