1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
//! # Writing a frame pipeline
//!
//! A window does not know how to draw a frame. It hands each one to a
//! [`FramePipeline`](crate::FramePipeline), and the default —
//! [`StandardImmediatePipeline`](crate::StandardImmediatePipeline) — is the
//! immediate-mode loop described in the [authoring guide](crate::_authoring):
//! rebuild the view tree, lay it out, paint what it drew.
//!
//! Replacing that loop is how a frame is built some other way. A pipeline decides
//! two things: what a frame is made of, and whether the frame happens at all.
//!
//! ## What a frame is made of
//!
//! The passes are the phases a frame goes through, in order:
//! [`begin_frame`](crate::FramePipeline::begin_frame),
//! [`evaluate_roots`](crate::FramePipeline::evaluate_roots),
//! [`layout_roots`](crate::FramePipeline::layout_roots),
//! [`paint_roots`](crate::FramePipeline::paint_roots),
//! [`finish_frame`](crate::FramePipeline::finish_frame),
//! [`complete_frame`](crate::FramePipeline::complete_frame) and
//! [`end_frame`](crate::FramePipeline::end_frame).
//! [`draw`](crate::FramePipeline::draw) runs them in that order, and is what a
//! window calls when it draws.
//!
//! Every pass has a default body that calls the [`Window`](crate::Window) method
//! implementing it, so a pipeline starts by overriding the one pass it cares
//! about:
//!
//! - [`evaluate_roots`](crate::FramePipeline::evaluate_roots) to choose what the
//! frame draws, before any of it is measured. The
//! [`PreparedRoots`](crate::PreparedRoots) it returns carries the window's view
//! tree and, at most, one overlay: a prompt, a drag image or a tooltip.
//! - [`layout_roots`](crate::FramePipeline::layout_roots) to change how that is
//! measured, or to lay out something of your own beside it. When it returns,
//! the frame's geometry is settled and the pointer has been hit tested.
//! - [`paint_roots`](crate::FramePipeline::paint_roots) to draw differently, once
//! everything is placed and its hitboxes registered.
//! - [`begin_frame`](crate::FramePipeline::begin_frame) and the three passes that
//! close a frame, to bracket it.
//!
//! A pipeline that needs to drive the passes itself — in a different order, or
//! more than once — overrides [`draw`](crate::FramePipeline::draw). That means
//! reproducing what the default `draw` sets up around them: the per-app element
//! arena, and the input handler the previous frame left behind. Both are private
//! to this crate, so from outside it the passes are the seam.
//!
//! ## Whether a frame happens
//!
//! [`should_render`](crate::FramePipeline::should_render) is asked before a
//! frame's work starts. Answering `false` leaves the window as it was and leaves
//! the frame's work pending, so the next frame draws it: deferring a frame is not
//! dropping it. This is where pacing belongs — dropping the frames a display
//! cannot keep up with, or coalescing a burst of invalidations into one frame —
//! and it is the reason a pipeline instance is kept: the same one draws every
//! frame of the window it was built for, so it can remember a rate, a deadline,
//! or the timings behind it.
//!
//! Two frames are drawn whatever it answers: a window's first, and one forced
//! after the GPU device was lost, whose cached content may not be replayable.
//!
//! ## Where an implementation lives
//!
//! Anywhere above this crate. `gpui_runtime`'s `InstrumentedPipeline` is a worked
//! example: it times the root passes of the pipeline it wraps and forwards
//! everything else, using nothing but this crate's public surface.
//!
//! ## Composing pipelines
//!
//! [`FramePipeline`](crate::FramePipeline) is object-safe and every pass defaults
//! to the [`Window`](crate::Window) method implementing it, so independent concerns
//! compose as decorators: a pipeline wraps another, changes the one pass it cares
//! about, and forwards the rest. `gpui_runtime`'s `ThrottledPipeline` caps a frame
//! rate and its `InstrumentedPipeline` times the root passes this way, and the
//! `frame_pipeline_decorator` example in the `gpui` crate writes the same pattern
//! from an application, entirely outside the framework.
//!
//! ## Installing one
//!
//! `Application::with_frame_pipeline` takes a factory and builds a pipeline per
//! window, so a pipeline that holds per-window state gets its own for each. Test
//! harnesses install through the same factory the application method forwards to.
//!
//! ## Testing one
//!
//! Frames do not need a platform to be driven: the test harness renders windows
//! in-process, so a pipeline can be installed, drawn a frame or three, and its
//! effect asserted.