- override
Pump the rendering pipeline to generate a frame.
This method is called by handleBeginFrame
, which itself is called
automatically by the engine when when it is time to lay out and paint a
frame.
Each frame consists of the following phases:
- The animation phase: The
handleBeginFrame
method, which is registeredwithui.window.onBeginFrame
, invokes all the transient frame callbacksregistered withscheduleFrameCallback
andaddFrameCallback
, inregistration order. This includes all theTicker
instances that aredrivingAnimationController
objects, which means all of the activeAnimation
objects tick at this point.
handleBeginFrame
then invokes all the persistent frame callbacks, of which
the most notable is this method, beginFrame
, which proceeds as follows:
-
The layout phase: All the dirty
RenderObject
s in the system are laidout (seeRenderObject.performLayout
). SeeRenderObject.markNeedsLayout
for further details on marking an object dirty for layout. -
The compositing bits phase: The compositing bits on any dirty
RenderObject
objects are updated. SeeRenderObject.markNeedsCompositingBitsUpdate
. -
The paint phase: All the dirty
RenderObject
s in the system arerepainted (seeRenderObject.paint
). This generates theLayer
tree. SeeRenderObject.markNeedsPaint
for further details on marking an objectdirty for paint. -
The compositing phase: The layer tree is turned into a
ui.Scene
andsent to the GPU. -
The semantics phase: All the dirty
RenderObject
s in the system havetheir semantics updated (seeRenderObject.SemanticsAnnotator
). Thisgenerates theSemanticsNode
tree. SeeRenderObject.markNeedsSemanticsUpdate
for further details on marking anobject dirty for semantics.
For more details on steps 2-6, see PipelineOwner
.
- The finalization phase: After
beginFrame
returns,handleBeginFrame
then invokes post-frame callbacks (registered withaddPostFrameCallback
.
Some bindings (for example, the WidgetsBinding
) add extra steps to this
list (for example, see WidgetsBinding.beginFrame
).
Source
@override void beginFrame() { assert(inTest); try { debugBuildingDirtyElements = true; buildOwner.buildScope(renderViewElement); if (_phase == EnginePhase.build) return; assert(renderView != null); pipelineOwner.flushLayout(); if (_phase == EnginePhase.layout) return; pipelineOwner.flushCompositingBits(); if (_phase == EnginePhase.compositingBits) return; pipelineOwner.flushPaint(); if (_phase == EnginePhase.paint) return; renderView.compositeFrame(); // this sends the bits to the GPU if (_phase == EnginePhase.composite) return; pipelineOwner.flushSemantics(); if (_phase == EnginePhase.flushSemantics) return; } finally { buildOwner.finalizeTree(); debugBuildingDirtyElements = false; } }