[Impeller] Use minimal coverage for stencil restores after overdraw prevention (flutter/engine#39358)

This commit is contained in:
Brandon DeRosier 2023-02-03 00:47:36 -08:00 committed by GitHub
parent b139a05b64
commit 21710ccc6b
8 changed files with 49 additions and 17 deletions

View File

@ -136,6 +136,11 @@ ClipRestoreContents::ClipRestoreContents() = default;
ClipRestoreContents::~ClipRestoreContents() = default;
void ClipRestoreContents::SetRestoreCoverage(
std::optional<Rect> restore_coverage) {
restore_coverage_ = restore_coverage;
}
std::optional<Rect> 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<VS::PerVertexData> 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()));

View File

@ -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<Rect> coverage);
// |Contents|
std::optional<Rect> GetCoverage(const Entity& entity) const override;
@ -73,6 +79,8 @@ class ClipRestoreContents final : public Contents {
RenderPass& pass) const override;
private:
std::optional<Rect> restore_coverage_;
FML_DISALLOW_COPY_AND_ASSIGN(ClipRestoreContents);
};

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}