From 8a24fe264607d9e1f683493049a87650c050d206 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Fri, 3 Feb 2023 00:47:36 -0800 Subject: [PATCH] [Impeller] Use minimal coverage for stencil restores after overdraw prevention (#39358) --- impeller/entity/contents/clip_contents.cc | 22 ++++++++++++------- impeller/entity/contents/clip_contents.h | 8 +++++++ .../contents/linear_gradient_contents.cc | 8 +++++-- .../contents/radial_gradient_contents.cc | 8 +++++-- .../contents/runtime_effect_contents.cc | 4 +++- .../entity/contents/solid_color_contents.cc | 4 +++- .../contents/sweep_gradient_contents.cc | 8 +++++-- .../entity/contents/tiled_texture_contents.cc | 4 +++- 8 files changed, 49 insertions(+), 17 deletions(-) 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 f19d9077abf3c..54d63578e68f7 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 ab94c3bde9221..82de84b2b2129 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 68c95acefe8d5..3e1033590cdff 100644 --- a/impeller/entity/contents/runtime_effect_contents.cc +++ b/impeller/entity/contents/runtime_effect_contents.cc @@ -213,7 +213,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 395acc543c0d3..0e39175eccafb 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 31f245801bcf8..bc0b17fcbe3f0 100644 --- a/impeller/entity/contents/tiled_texture_contents.cc +++ b/impeller/entity/contents/tiled_texture_contents.cc @@ -89,7 +89,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; }