5
5
#include " impeller/entity/entity_pass.h"
6
6
7
7
#include " flutter/fml/trace_event.h"
8
+ #include " impeller/base/validation.h"
8
9
#include " impeller/entity/contents/content_context.h"
9
10
#include " impeller/geometry/path_builder.h"
10
11
#include " impeller/renderer/command_buffer.h"
11
12
#include " impeller/renderer/render_pass.h"
13
+ #include " impeller/renderer/texture.h"
12
14
13
15
namespace impeller {
14
16
@@ -78,6 +80,9 @@ std::optional<Rect> EntityPass::GetSubpassCoverage(
78
80
if (!delegate_coverage.has_value ()) {
79
81
return entities_coverage;
80
82
}
83
+ // The delegate coverage hint is in given in local space, so apply the subpass
84
+ // transformation.
85
+ delegate_coverage = delegate_coverage->TransformBounds (subpass.xformation_ );
81
86
82
87
// If the delegate tells us the coverage is smaller than it needs to be, then
83
88
// great. OTOH, if the delegate is being wasteful, limit coverage to what is
@@ -103,22 +108,31 @@ EntityPass* EntityPass::AddSubpass(std::unique_ptr<EntityPass> pass) {
103
108
}
104
109
105
110
bool EntityPass::Render (ContentContext& renderer,
106
- RenderPass& parent_pass) const {
111
+ RenderPass& parent_pass,
112
+ Point position) const {
107
113
TRACE_EVENT0 (" impeller" , " EntityPass::Render" );
108
114
109
- for (const auto & entity : entities_) {
115
+ for (Entity entity : entities_) {
116
+ if (!position.IsZero ()) {
117
+ // If the pass image is going to be rendered with a non-zero position,
118
+ // apply the negative translation to entity copies before rendering them
119
+ // so that they'll end up rendering to the correct on-screen position.
120
+ entity.SetTransformation (Matrix::MakeTranslation (Vector3 (-position)) *
121
+ entity.GetTransformation ());
122
+ }
110
123
if (!entity.Render (renderer, parent_pass)) {
111
124
return false ;
112
125
}
113
126
}
127
+
114
128
for (const auto & subpass : subpasses_) {
115
129
if (delegate_->CanElide ()) {
116
130
continue ;
117
131
}
118
132
119
133
if (delegate_->CanCollapseIntoParentPass ()) {
120
134
// Directly render into the parent pass and move on.
121
- if (!subpass->Render (renderer, parent_pass)) {
135
+ if (!subpass->Render (renderer, parent_pass, position )) {
122
136
return false ;
123
137
}
124
138
continue ;
@@ -178,7 +192,7 @@ bool EntityPass::Render(ContentContext& renderer,
178
192
179
193
sub_renderpass->SetLabel (" OffscreenPass" );
180
194
181
- if (!subpass->Render (renderer, *sub_renderpass)) {
195
+ if (!subpass->Render (renderer, *sub_renderpass, subpass_coverage-> origin )) {
182
196
return false ;
183
197
}
184
198
@@ -191,10 +205,17 @@ bool EntityPass::Render(ContentContext& renderer,
191
205
}
192
206
193
207
Entity entity;
194
- entity.SetPath (PathBuilder{}.AddRect (subpass_coverage.value ()).TakePath ());
208
+ entity.SetPath (PathBuilder{}
209
+ .AddRect (Rect::MakeSize (subpass_coverage->size ))
210
+ .TakePath ());
195
211
entity.SetContents (std::move (offscreen_texture_contents));
196
212
entity.SetStencilDepth (stencil_depth_);
197
- entity.SetTransformation (xformation_);
213
+ // Once we have filters being applied for SaveLayer, some special sauce
214
+ // may be needed here (or in PaintPassDelegate) to ensure the filter
215
+ // parameters are transformed by the `xformation_` matrix, while continuing
216
+ // to apply only the subpass offset to the offscreen texture.
217
+ entity.SetTransformation (
218
+ Matrix::MakeTranslation (Vector3 (subpass_coverage->origin - position)));
198
219
if (!entity.Render (renderer, parent_pass)) {
199
220
return false ;
200
221
}
0 commit comments