Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Conversation

@flar
Copy link
Contributor

@flar flar commented Aug 25, 2022

Fundamentally, this new object records all potential state changes that Layer objects might impose on their children.

This new object replaces a number of objects used to track state within the engine layers, some immediately and some remain to be replaced after further development:

  • PaintContext::internal_nodes_canvas
    • essentially just a multiplexer for state commands to all canvas objects used by embedder overlays
    • new object is more streamlined in how it manages the state for these overlay canvases
  • PaintContext::builder_multiplexer
    • performs the same role as internal_nodes_canvas for the builder
    • (and analogously, cheaper implementation here as well)
    • (and new object will manage state for both canvas and builder at the same time)
  • PrerollContext::mutators_stack
    • TBD: this new object records the same state changes as the MutatorsStack object and can eventually replace that object in the PrerollContext so that the same API is used in both Preroll and Paint to manage state mutations

More importantly, this state recording object replaces the multiplexing in the internal_nodes_canvas and builder_multiplexer with an object that doesn't need to broadcast the state. Instead it remembers the state itself so that if we ever switch leaf_nodes_canvas objects (now called just canvas) in a PlatformViewLayer, we can just update the new canvas from the internally stored state and that canvas will only see the state it needs for its current context, not all of the state from unrelated sub-trees that have already been exited. Additionally, the outgoing canvas that will no longer be the "current canvas" in the PaintContext will not see any future state changes that it has no intention of taking advantage of because it is done with its rendering.

Before: all canvas objects for all embedder underly/overlay layers would see every state change call (i.e. save/Layer, etc) even if it was not going to be used in the subtree that was currently being processed in the Paint cycle.
After: each embedder underlay/overlay layer only sees the state changes that apply to the rendering it will process in its own layer

Note that this is very WIP as I have only verified host_debug_unopt compilation and haven't run any tests or apps with the changes. I am submitting this early to get the concept out for evaluation by other engineers currently working on the state changes in the layer tree. Currently it very likely destroys our opacity inheritance peephole optimizations and some way of managing those optimizations (and other saveLayer attributes) will need to be incorporated into this state object before it is ready for final reviews.

@flar flar added the Work in progress (WIP) Not ready (yet) for review! label Aug 25, 2022
return;
}
}
auto save = context.state_stack.save();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this state_stack.save() will return an AutoRestore Object but if I don't know the save() implement only read this line code I will misunderstand we forget to restore.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would a better name help?

}
state_stack.setBuilderDelegate(builder);
} else {
state_stack.setCanvasDelegate(frame.canvas());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, don't we need to record the frame.view_embedder canvases?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The canvas here is a wrapper around the builder. If we set both then the builder would get double-state-notices.

context.state_stack.clipPath(path_, true);
auto saveLayer = context.state_stack.saveLayer(
&paint_bounds(), context.checkerboard_offscreen_layers);
context.canvas->drawColor(color_);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here don't we need to set the alias ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AA is in the clipPath with the "true" argument. The drawColor (was originally using a drawPaint which is silly for a solid color) doesn't process AA.

builder_restore_count_ = builder->getSaveCount();
builder_ = builder;
for (auto& state : state_stack_) {
if (!state->is_backdrop_filter()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where we apply the BF?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only when it is first pushed onto the state stack. If we update the canvas to a new overlay, we don't want to re-blur everything that is behind that overlay...(do we?)...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, but we do need to do a saveLayer so that the restores match up...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I swiched from an "is_bdf" conditional to calling a reapply method here in the delegate swap phase. That way, only BDFEntry has a different implementation that does a saveLayer without its backdrop filter.


PaintChildren(context);
}
auto save = context.state_stack.saveWithBackdropFilter(&paint_bounds(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the parent node is OpacityLayer, here we need set the alpha of paint.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the test case is TEST_F(BackdropFilterLayerTest, OpacityInheritance)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opacity inheritance is not really implemented yet - there is a skeleton of a concept for it, but it is not ready for review, just an inkling of where I'm headed. I'm still working out what is the best way to manage it with the new mechanism and what the API for layers will look like.

@flar flar force-pushed the layer-state-stack branch from 72beac3 to b8b1f52 Compare September 2, 2022 05:53
// Return a boolean indicating whether the color filtering operation can
// be applied either before or after modulating the pixels with an opacity
// value without changing the operation.
virtual bool can_commute_with_alpha() const { return false; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, if mostly CF can commute with alpha, but if the CF is a MtrixCF and has specific alpha in the matrix it should not commute with alpha?

@flutter-dashboard
Copy link

This pull request executed golden file tests, but it has not been updated in a while (20+ days). Test results from Gold expire after as many days, so this pull request will need to be updated with a fresh commit in order to get results from Gold.

@flar
Copy link
Contributor Author

flar commented Sep 27, 2022

The rebase got so complicated that I basically started over. The new version is at #36458

@flar flar closed this Sep 27, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Work in progress (WIP) Not ready (yet) for review!

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants