diff --git a/impeller/entity/contents/clip_contents.cc b/impeller/entity/contents/clip_contents.cc index a00a423261ad4..d958822b45b7a 100644 --- a/impeller/entity/contents/clip_contents.cc +++ b/impeller/entity/contents/clip_contents.cc @@ -136,6 +136,11 @@ ClipRestoreContents::ClipRestoreContents() = default; ClipRestoreContents::~ClipRestoreContents() = default; +void ClipRestoreContents::SetRestoreCoverage( + std::optional restore_coverage) { + restore_coverage_ = restore_coverage; +} + std::optional ClipRestoreContents::GetCoverage( const Entity& entity) const { return std::nullopt; @@ -164,19 +169,20 @@ bool ClipRestoreContents::Render(const ContentContext& renderer, auto options = OptionsFromPassAndEntity(pass, entity); options.stencil_compare = CompareFunction::kLess; options.stencil_operation = StencilOperation::kSetToReferenceValue; + options.primitive_type = PrimitiveType::kTriangleStrip; cmd.pipeline = renderer.GetClipPipeline(options); cmd.stencil_reference = entity.GetStencilDepth(); - // Create a rect that covers the whole render target. - auto size = pass.GetRenderTargetSize(); + // Create a rect that covers either the given restore area, or the whole + // render target texture. + auto ltrb = restore_coverage_.value_or(Rect(Size(pass.GetRenderTargetSize()))) + .GetLTRB(); VertexBufferBuilder vtx_builder; vtx_builder.AddVertices({ - {Point(0.0, 0.0)}, - {Point(size.width, 0.0)}, - {Point(size.width, size.height)}, - {Point(0.0, 0.0)}, - {Point(size.width, size.height)}, - {Point(0.0, size.height)}, + {Point(ltrb[0], ltrb[1])}, + {Point(ltrb[2], ltrb[1])}, + {Point(ltrb[0], ltrb[3])}, + {Point(ltrb[2], ltrb[3])}, }); cmd.BindVertices(vtx_builder.CreateVertexBuffer(pass.GetTransientsBuffer())); diff --git a/impeller/entity/contents/clip_contents.h b/impeller/entity/contents/clip_contents.h index b70c8ba863c02..86606d2f59db7 100644 --- a/impeller/entity/contents/clip_contents.h +++ b/impeller/entity/contents/clip_contents.h @@ -55,6 +55,12 @@ class ClipRestoreContents final : public Contents { ~ClipRestoreContents(); + /// @brief The area on the pass texture where this clip restore will be + /// applied. If unset, the entire pass texture will be restored. + /// + /// @note This rectangle is not transformed by the entity's transformation. + void SetRestoreCoverage(std::optional coverage); + // |Contents| std::optional GetCoverage(const Entity& entity) const override; @@ -73,6 +79,8 @@ class ClipRestoreContents final : public Contents { RenderPass& pass) const override; private: + std::optional restore_coverage_; + FML_DISALLOW_COPY_AND_ASSIGN(ClipRestoreContents); }; diff --git a/impeller/entity/contents/linear_gradient_contents.cc b/impeller/entity/contents/linear_gradient_contents.cc index 9cccfd61e4101..323a71971a79a 100644 --- a/impeller/entity/contents/linear_gradient_contents.cc +++ b/impeller/entity/contents/linear_gradient_contents.cc @@ -111,7 +111,9 @@ bool LinearGradientContents::RenderTexture(const ContentContext& renderer, } if (geometry_result.prevent_overdraw) { - return ClipRestoreContents().Render(renderer, entity, pass); + auto restore = ClipRestoreContents(); + restore.SetRestoreCoverage(GetCoverage(entity)); + return restore.Render(renderer, entity, pass); } return true; } @@ -165,7 +167,9 @@ bool LinearGradientContents::RenderSSBO(const ContentContext& renderer, } if (geometry_result.prevent_overdraw) { - return ClipRestoreContents().Render(renderer, entity, pass); + auto restore = ClipRestoreContents(); + restore.SetRestoreCoverage(GetCoverage(entity)); + return restore.Render(renderer, entity, pass); } return true; } diff --git a/impeller/entity/contents/radial_gradient_contents.cc b/impeller/entity/contents/radial_gradient_contents.cc index 7a66f6c73e592..ee330fbdfa1a2 100644 --- a/impeller/entity/contents/radial_gradient_contents.cc +++ b/impeller/entity/contents/radial_gradient_contents.cc @@ -103,7 +103,9 @@ bool RadialGradientContents::RenderSSBO(const ContentContext& renderer, } if (geometry_result.prevent_overdraw) { - return ClipRestoreContents().Render(renderer, entity, pass); + auto restore = ClipRestoreContents(); + restore.SetRestoreCoverage(GetCoverage(entity)); + return restore.Render(renderer, entity, pass); } return true; } @@ -166,7 +168,9 @@ bool RadialGradientContents::RenderTexture(const ContentContext& renderer, } if (geometry_result.prevent_overdraw) { - return ClipRestoreContents().Render(renderer, entity, pass); + auto restore = ClipRestoreContents(); + restore.SetRestoreCoverage(GetCoverage(entity)); + return restore.Render(renderer, entity, pass); } return true; } diff --git a/impeller/entity/contents/runtime_effect_contents.cc b/impeller/entity/contents/runtime_effect_contents.cc index f36e0c9b21efa..8e2fefc29b100 100644 --- a/impeller/entity/contents/runtime_effect_contents.cc +++ b/impeller/entity/contents/runtime_effect_contents.cc @@ -238,7 +238,9 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer, pass.AddCommand(std::move(cmd)); if (geometry_result.prevent_overdraw) { - return ClipRestoreContents().Render(renderer, entity, pass); + auto restore = ClipRestoreContents(); + restore.SetRestoreCoverage(GetCoverage(entity)); + return restore.Render(renderer, entity, pass); } return true; } diff --git a/impeller/entity/contents/solid_color_contents.cc b/impeller/entity/contents/solid_color_contents.cc index 43cf7a913240c..032b06ed12488 100644 --- a/impeller/entity/contents/solid_color_contents.cc +++ b/impeller/entity/contents/solid_color_contents.cc @@ -83,7 +83,9 @@ bool SolidColorContents::Render(const ContentContext& renderer, } if (geometry_result.prevent_overdraw) { - return ClipRestoreContents().Render(renderer, entity, pass); + auto restore = ClipRestoreContents(); + restore.SetRestoreCoverage(GetCoverage(entity)); + return restore.Render(renderer, entity, pass); } return true; } diff --git a/impeller/entity/contents/sweep_gradient_contents.cc b/impeller/entity/contents/sweep_gradient_contents.cc index 506a33a2a4856..d6319392e76df 100644 --- a/impeller/entity/contents/sweep_gradient_contents.cc +++ b/impeller/entity/contents/sweep_gradient_contents.cc @@ -109,7 +109,9 @@ bool SweepGradientContents::RenderSSBO(const ContentContext& renderer, } if (geometry_result.prevent_overdraw) { - return ClipRestoreContents().Render(renderer, entity, pass); + auto restore = ClipRestoreContents(); + restore.SetRestoreCoverage(GetCoverage(entity)); + return restore.Render(renderer, entity, pass); } return true; } @@ -173,7 +175,9 @@ bool SweepGradientContents::RenderTexture(const ContentContext& renderer, } if (geometry_result.prevent_overdraw) { - return ClipRestoreContents().Render(renderer, entity, pass); + auto restore = ClipRestoreContents(); + restore.SetRestoreCoverage(GetCoverage(entity)); + return restore.Render(renderer, entity, pass); } return true; } diff --git a/impeller/entity/contents/tiled_texture_contents.cc b/impeller/entity/contents/tiled_texture_contents.cc index 90f1c15b22fbb..3324863613d68 100644 --- a/impeller/entity/contents/tiled_texture_contents.cc +++ b/impeller/entity/contents/tiled_texture_contents.cc @@ -96,7 +96,9 @@ bool TiledTextureContents::Render(const ContentContext& renderer, } if (geometry_result.prevent_overdraw) { - return ClipRestoreContents().Render(renderer, entity, pass); + auto restore = ClipRestoreContents(); + restore.SetRestoreCoverage(GetCoverage(entity)); + return restore.Render(renderer, entity, pass); } return true; }