LavaUI docs

protocol FrameSink

Swift

protocol FrameSink : AnyObject

Where a DrawList writes its frame, and who it hands the frame to.

Those are one question rather than two, and that is the whole point: the property worth keeping is that a draw command is written once, into the memory its consumer will read it from. A sink that only received a finished list would have to copy it, and a 1 MB copy is 0.3 ms — 2% of a frame, for something that should cost nothing. So a sink hands out the buffers first and is told what was filled in afterwards.

Two of them, and the shapes match closely enough that DrawList needed no new concepts to support the second:

  • In-process. The buffers are the engine's own per-window vectors, and commit is a submission the renderer picks up on its next repaint.
  • Shared memory. The buffers are a slot in a DrawArena another process reads, and commit publishes it. See ArenaFrameSink.

The mid-frame growth is not an optimization either, in either case: how many commands a frame needs is not known when it starts, because DrawList grows during emit as the tree turns out to be bigger than last time.

Sources/LavaUI/FrameSink.swift:74

Properties

var framesInFlight: Int { get }

Frames handed over that the consumer has not taken yet.

Back-pressure, and the producer's half of a frame-callback contract: a non-zero answer means the last frame has not been picked up, so building another one is work nobody asked for. Zero for a sink whose consumer is in this process and takes every frame synchronously.

Advisory, never a lock. The signal that clears it can be lost, so a caller that waits on this has to give up after a deadline — see DrawArena::framesInFlight.

Sources/LavaUI/FrameSink.swift:106

var framesInFlight: Int { get }

Nothing is in flight for a sink that has no other process in the loop.

Sources/LavaUI/FrameSink.swift:111

Methods

func beginFrame(minimum: FrameCapacity) -> FrameBuffers?

Claims buffers for a new frame with at least minimum room.

Returns nil if none could be claimed, which DrawList treats as a frame that draws nothing rather than as an error — the next one will try again, and refusing to emit is better than emitting into memory somebody else is reading.

Sources/LavaUI/FrameSink.swift:81

func commit(_ written: FrameCapacity)

Publishes what was written.

Sources/LavaUI/FrameSink.swift:94

func grow(to wanted: FrameCapacity, written: FrameCapacity) -> FrameBuffers?

Enlarges mid-frame, preserving the written prefix and returning where it now lives.

Takes written rather than reading it from anywhere because a growth may move the storage, and the part already filled in has to come with it. Returns nil if the sink could not grow, leaving the caller with the buffers it already had — a frame that has to finish smaller than it wanted, not a frame that is abandoned halfway.

Sources/LavaUI/FrameSink.swift:91