From 57f9d82f0dfb79b623ceccf40afbd1517540acfd Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Fri, 22 Sep 2023 16:56:03 -0400 Subject: [PATCH] [Impeller] Incorporate backdrop filters in subpass coverage. (flutter/engine#46130) Resolves https://github.com/flutter/flutter/issues/134775. Before: ![image](https://github.com/flutter/engine/assets/919017/0e709d09-38bc-458b-850f-ca13f82c269d) After: ![image](https://github.com/flutter/engine/assets/919017/a30fff08-e6bb-421a-9ed2-39f2cfa53d72) --- .../flutter/impeller/entity/entity_pass.cc | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/engine/src/flutter/impeller/entity/entity_pass.cc b/engine/src/flutter/impeller/entity/entity_pass.cc index 7390c14df9d..1d8b0a4f373 100644 --- a/engine/src/flutter/impeller/entity/entity_pass.cc +++ b/engine/src/flutter/impeller/entity/entity_pass.cc @@ -124,10 +124,43 @@ std::optional EntityPass::GetElementsCoverage( std::optional unfiltered_coverage = GetSubpassCoverage(subpass, std::nullopt); + + // If the current pass elements have any coverage so far and there's a + // backdrop filter, then incorporate the backdrop filter in the + // pre-filtered coverage of the subpass. + if (result.has_value() && subpass.backdrop_filter_proc_) { + std::shared_ptr backdrop_filter = + subpass.backdrop_filter_proc_(FilterInput::Make(result.value()), + subpass.xformation_, + Entity::RenderingMode::kSubpass); + if (backdrop_filter) { + auto backdrop_coverage = backdrop_filter->GetCoverage({}); + backdrop_coverage->origin += result->origin; + if (backdrop_coverage.has_value()) { + if (unfiltered_coverage.has_value()) { + unfiltered_coverage = coverage->Union(*backdrop_coverage); + } else { + unfiltered_coverage = backdrop_coverage; + } + } + } else { + VALIDATION_LOG << "The EntityPass backdrop filter proc didn't return " + "a valid filter."; + } + } + if (!unfiltered_coverage.has_value()) { continue; } + // Additionally, subpass textures may be passed through filters, which may + // modify the coverage. + // + // Note that we currently only assume that ImageFilters (such as blurs and + // matrix transforms) may modify coverage, although it's technically + // possible ColorFilters to affect coverage as well. For example: A + // ColorMatrixFilter could output a completely transparent result, and + // we could potentially detect this case as zero coverage in the future. std::shared_ptr image_filter = subpass.delegate_->WithImageFilter(*unfiltered_coverage, subpass.xformation_);