Before
Code
Let us firstly review the scenario before modification. Looking at animator.cc
, we see the following (simplified) code:
Animator::Animator()
: layer_tree_pipeline_(std::make_shared<LayerTreePipeline>(2)) {}
void Animator::BeginFrame() {
if (!producer_continuation_) {
// We may already have a valid pipeline continuation in case a previous
// begin frame did not result in an Animation::Render. Simply reuse that
// instead of asking the pipeline for a fresh continuation.
producer_continuation_ = layer_tree_pipeline_->Produce();
if (!producer_continuation_) {
// If we still don't have valid continuation, the pipeline is currently
// full because the consumer is being too slow. Try again at the next
// frame interval.
TRACE_EVENT0("flutter", "PipelineFull");
RequestFrame();
return;
}
}
// We have acquired a valid continuation from the pipeline and are ready
// to service potential frame.
FML_DCHECK(producer_continuation_);
delegate_.OnAnimatorBeginFrame();
}
void Animator::Render(std::shared_ptr<flutter::LayerTree> layer_tree) {
// Commit the pending continuation.
PipelineProduceResult result = producer_continuation_.Complete(layer_tree);
if (!result.success) {
FML_DLOG(INFO) << "No pending continuation to commit";
return;
}
... notify rasterizer ...
}
Summary
Briefly recall the Flutter internal implementation:
Animator::BeginFrame
is called in each frame, and finally callsOnAnimatorBeginFrame
which will really call Dart sidehandleBeginFrame
andhandleDrawFrame
etc.Animator::Render
is called by Dartwindow.render
. It is normally called after paint/composite/etc phase, and flutter_smooth needs to call it extra times whenever we want to submit an extra frame.- The
layer_tree_pipeline_
is aLayerTreePipeline
with pipeline depth2
(seen in constructor). TheAnimator
is the producer of the pipeline, and theRasterizer
is the consumer.
Briefly speaking, the code about pipeline works as follows:
- During
BeginFrame
, we either reuse or create a "continuation" in pipeline (i.e. occupy a seat). If we cannot, it means pipeline is full, and we skip the current frame. - During
Render
, we put Layer tree into the occupied seat. But if there is not any occupied seat, we indeed do nothing.