55#include " impeller/entity/entity_pass.h"
66
77#include " flutter/fml/trace_event.h"
8+ #include " impeller/base/validation.h"
89#include " impeller/entity/contents/content_context.h"
910#include " impeller/geometry/path_builder.h"
1011#include " impeller/renderer/command_buffer.h"
1112#include " impeller/renderer/render_pass.h"
13+ #include " impeller/renderer/texture.h"
1214
1315namespace impeller {
1416
@@ -78,6 +80,9 @@ std::optional<Rect> EntityPass::GetSubpassCoverage(
7880 if (!delegate_coverage.has_value ()) {
7981 return entities_coverage;
8082 }
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_ );
8186
8287 // If the delegate tells us the coverage is smaller than it needs to be, then
8388 // 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) {
103108}
104109
105110bool EntityPass::Render (ContentContext& renderer,
106- RenderPass& parent_pass) const {
111+ RenderPass& parent_pass,
112+ Point position) const {
107113 TRACE_EVENT0 (" impeller" , " EntityPass::Render" );
108114
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+ }
110123 if (!entity.Render (renderer, parent_pass)) {
111124 return false ;
112125 }
113126 }
127+
114128 for (const auto & subpass : subpasses_) {
115129 if (delegate_->CanElide ()) {
116130 continue ;
117131 }
118132
119133 if (delegate_->CanCollapseIntoParentPass ()) {
120134 // Directly render into the parent pass and move on.
121- if (!subpass->Render (renderer, parent_pass)) {
135+ if (!subpass->Render (renderer, parent_pass, position )) {
122136 return false ;
123137 }
124138 continue ;
@@ -178,7 +192,7 @@ bool EntityPass::Render(ContentContext& renderer,
178192
179193 sub_renderpass->SetLabel (" OffscreenPass" );
180194
181- if (!subpass->Render (renderer, *sub_renderpass)) {
195+ if (!subpass->Render (renderer, *sub_renderpass, subpass_coverage-> origin )) {
182196 return false ;
183197 }
184198
@@ -191,10 +205,17 @@ bool EntityPass::Render(ContentContext& renderer,
191205 }
192206
193207 Entity entity;
194- entity.SetPath (PathBuilder{}.AddRect (subpass_coverage.value ()).TakePath ());
208+ entity.SetPath (PathBuilder{}
209+ .AddRect (Rect::MakeSize (subpass_coverage->size ))
210+ .TakePath ());
195211 entity.SetContents (std::move (offscreen_texture_contents));
196212 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)));
198219 if (!entity.Render (renderer, parent_pass)) {
199220 return false ;
200221 }
0 commit comments