mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[Impeller] Keep track of a stencil depth floor for non-collapsed subpasses (flutter/engine#33473)
This commit is contained in:
parent
8af07c92c5
commit
1a8ff96a0d
@ -805,5 +805,29 @@ TEST_P(AiksTest, SiblingSaveLayerBoundsAreRespected) {
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, CanRenderClippedLayers) {
|
||||
Canvas canvas;
|
||||
|
||||
canvas.DrawPaint({.color = Color::White()});
|
||||
|
||||
// Draw a green circle on the screen.
|
||||
{
|
||||
// Increase the clip depth for the savelayer to contend with.
|
||||
canvas.ClipPath(PathBuilder{}.AddCircle({100, 100}, 50).TakePath());
|
||||
|
||||
canvas.SaveLayer({}, Rect::MakeXYWH(50, 50, 100, 100));
|
||||
|
||||
// Fill the layer with white.
|
||||
canvas.DrawRect(Rect::MakeSize({400, 400}), {.color = Color::White()});
|
||||
// Fill the layer with green, but do so with a color blend that can't be
|
||||
// collapsed into the parent pass.
|
||||
canvas.DrawRect(
|
||||
Rect::MakeSize({400, 400}),
|
||||
{.color = Color::Green(), .blend_mode = Entity::BlendMode::kColorBurn});
|
||||
}
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace impeller
|
||||
|
||||
@ -266,7 +266,8 @@ size_t Canvas::GetStencilDepth() const {
|
||||
void Canvas::SaveLayer(Paint paint, std::optional<Rect> bounds) {
|
||||
Save(true, paint.blend_mode);
|
||||
|
||||
GetCurrentPass().SetDelegate(
|
||||
auto& new_layer_pass = GetCurrentPass();
|
||||
new_layer_pass.SetDelegate(
|
||||
std::make_unique<PaintPassDelegate>(paint, bounds));
|
||||
|
||||
if (bounds.has_value()) {
|
||||
|
||||
@ -180,7 +180,8 @@ bool EntityPass::Render(ContentContext& renderer,
|
||||
bool EntityPass::RenderInternal(ContentContext& renderer,
|
||||
RenderTarget render_target,
|
||||
Point position,
|
||||
uint32_t depth) const {
|
||||
uint32_t pass_depth,
|
||||
size_t stencil_depth_floor) const {
|
||||
TRACE_EVENT0("impeller", "EntityPass::Render");
|
||||
|
||||
auto context = renderer.GetContext();
|
||||
@ -233,7 +234,7 @@ bool EntityPass::RenderInternal(ContentContext& renderer,
|
||||
if (subpass->delegate_->CanCollapseIntoParentPass()) {
|
||||
// Directly render into the parent target and move on.
|
||||
if (!subpass->RenderInternal(renderer, render_target, position,
|
||||
depth)) {
|
||||
pass_depth, stencil_depth_floor)) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
@ -286,13 +287,16 @@ bool EntityPass::RenderInternal(ContentContext& renderer,
|
||||
return false;
|
||||
}
|
||||
|
||||
// Stencil textures aren't shared between EntityPasses (as much of the
|
||||
// time they are transient).
|
||||
if (!subpass->RenderInternal(renderer, subpass_target,
|
||||
subpass_coverage->origin, ++depth)) {
|
||||
subpass_coverage->origin, ++pass_depth,
|
||||
subpass->stencil_depth_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
element_entity.SetContents(std::move(offscreen_texture_contents));
|
||||
element_entity.SetStencilDepth(stencil_depth_);
|
||||
element_entity.SetStencilDepth(subpass->stencil_depth_);
|
||||
element_entity.SetBlendMode(subpass->blend_mode_);
|
||||
// Once we have filters being applied for SaveLayer, some special sauce
|
||||
// may be needed here (or in PaintPassDelegate) to ensure the filter
|
||||
@ -305,7 +309,7 @@ bool EntityPass::RenderInternal(ContentContext& renderer,
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Render the element ======================================================
|
||||
// Configure the RenderPass ================================================
|
||||
// =========================================================================
|
||||
|
||||
if (pass && element_entity.GetBlendMode() >
|
||||
@ -350,7 +354,7 @@ bool EntityPass::RenderInternal(ContentContext& renderer,
|
||||
}
|
||||
|
||||
command_buffer->SetLabel(
|
||||
"EntityPass Command Buffer: Depth=" + std::to_string(depth) +
|
||||
"EntityPass Command Buffer: Depth=" + std::to_string(pass_depth) +
|
||||
" Count=" + std::to_string(pass_count));
|
||||
|
||||
// Never clear the texture for subsequent passes.
|
||||
@ -373,12 +377,20 @@ bool EntityPass::RenderInternal(ContentContext& renderer,
|
||||
return false;
|
||||
}
|
||||
|
||||
pass->SetLabel("EntityPass Render Pass: Depth=" + std::to_string(depth) +
|
||||
" Count=" + std::to_string(pass_count));
|
||||
pass->SetLabel(
|
||||
"EntityPass Render Pass: Depth=" + std::to_string(pass_depth) +
|
||||
" Count=" + std::to_string(pass_count));
|
||||
|
||||
++pass_count;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Render the element ======================================================
|
||||
// =========================================================================
|
||||
|
||||
element_entity.SetStencilDepth(element_entity.GetStencilDepth() -
|
||||
stencil_depth_floor);
|
||||
|
||||
if (!element_entity.Render(renderer, *pass)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -61,7 +61,8 @@ class EntityPass {
|
||||
bool RenderInternal(ContentContext& renderer,
|
||||
RenderTarget render_target,
|
||||
Point position,
|
||||
uint32_t depth) const;
|
||||
uint32_t pass_depth,
|
||||
size_t stencil_depth_floor = 0) const;
|
||||
|
||||
std::vector<Element> elements_;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user