@@ -43,27 +43,41 @@ size_t EntityPass::GetSubpassesDepth() const {
4343 return max_subpass_depth + 1u ;
4444}
4545
46- Rect EntityPass::GetCoverageRect () const {
47- std::optional<Point> min, max ;
46+ std::optional< Rect> EntityPass::GetEntitiesCoverage () const {
47+ std::optional<Rect> result ;
4848 for (const auto & entity : entities_) {
49- auto coverage = entity.GetPath ().GetMinMaxCoveragePoints ();
50- if (!coverage.has_value ()) {
49+ auto coverage = entity.GetCoverage ();
50+ if (!result.has_value () && coverage.has_value ()) {
51+ result = coverage;
5152 continue ;
5253 }
53- if (!min.has_value ()) {
54- min = coverage->first ;
55- }
56- if (!max.has_value ()) {
57- max = coverage->second ;
54+ if (!coverage.has_value ()) {
55+ continue ;
5856 }
59- min = min->Min (coverage->first );
60- max = max->Max (coverage->second );
57+ result = result->Union (coverage.value ());
58+ }
59+ return result;
60+ }
61+
62+ std::optional<Rect> EntityPass::GetSubpassCoverage (
63+ const EntityPass& subpass) const {
64+ auto entities_coverage = subpass.GetEntitiesCoverage ();
65+ // The entities don't cover anything. There is nothing to do.
66+ if (!entities_coverage.has_value ()) {
67+ return std::nullopt ;
6168 }
62- if (!min.has_value () || !max.has_value ()) {
63- return {};
69+
70+ // The delegates don't have an opinion on what the entity coverage has to be.
71+ // Just use that as-is.
72+ auto delegate_coverage = delegate_->GetCoverageRect ();
73+ if (!delegate_coverage.has_value ()) {
74+ return entities_coverage;
6475 }
65- const auto diff = *max - *min;
66- return {min->x , min->y , diff.x , diff.y };
76+
77+ // If the delete tells us the coverage is smaller than it needs to be, then
78+ // great. OTOH, if the delegate is being wasteful, limit coverage to what is
79+ // actually needed.
80+ return entities_coverage->Intersection (delegate_coverage.value ());
6781}
6882
6983EntityPass* EntityPass::GetSuperpass () const {
@@ -74,18 +88,6 @@ const EntityPass::Subpasses& EntityPass::GetSubpasses() const {
7488 return subpasses_;
7589}
7690
77- Rect EntityPass::GetSubpassCoverage (const EntityPass& subpass) const {
78- auto subpass_coverage = subpass.GetCoverageRect ();
79- auto delegate_coverage =
80- delegate_->GetCoverageRect ().value_or (subpass_coverage);
81- Rect coverage;
82- coverage.origin = subpass_coverage.origin ;
83- // TODO(csg): This must still be restricted to the max texture size. Or,
84- // decide if this must be done by the allocator.
85- coverage.size = subpass_coverage.size .Min (delegate_coverage.size );
86- return coverage;
87- }
88-
8991EntityPass* EntityPass::AddSubpass (std::unique_ptr<EntityPass> pass) {
9092 if (!pass) {
9193 return nullptr ;
@@ -117,7 +119,11 @@ bool EntityPass::Render(ContentRenderer& renderer,
117119
118120 const auto subpass_coverage = GetSubpassCoverage (*subpass);
119121
120- if (subpass_coverage.IsEmpty ()) {
122+ if (!subpass_coverage.has_value ()) {
123+ continue ;
124+ }
125+
126+ if (subpass_coverage->size .IsEmpty ()) {
121127 // It is not an error to have an empty subpass. But subpasses that can't
122128 // create their intermediates must trip errors.
123129 continue ;
@@ -126,7 +132,7 @@ bool EntityPass::Render(ContentRenderer& renderer,
126132 auto context = renderer.GetContext ();
127133
128134 auto subpass_target = RenderTarget::CreateOffscreen (
129- *context, ISize::Ceil (subpass_coverage. size ));
135+ *context, ISize::Ceil (subpass_coverage-> size ));
130136
131137 auto subpass_texture = subpass_target.GetRenderTargetTexture ();
132138
@@ -178,7 +184,8 @@ bool EntityPass::Render(ContentRenderer& renderer,
178184 }
179185
180186 Entity entity;
181- entity.SetPath (PathBuilder{}.AddRect (subpass_coverage).CreatePath ());
187+ entity.SetPath (
188+ PathBuilder{}.AddRect (subpass_coverage.value ()).CreatePath ());
182189 entity.SetContents (std::move (offscreen_texture_contents));
183190 entity.SetStencilDepth (stencil_depth_);
184191 entity.SetTransformation (xformation_);
0 commit comments