MingaEditor.Renderer.Server (Minga v0.1.0)

Copy Markdown View Source

Standalone renderer GenServer. Owns the render pipeline and font registry so a slow frame doesn't block input dispatch in the Editor process.

Lifecycle

Started by MingaEditor.Supervisor for all non-headless backends. The headless backend renders synchronously in-process for test determinism; this server is not in the supervision tree in that case.

Snapshot mechanics

The Editor pushes RenderPipeline.Input snapshots via cast_snapshot/3. The Renderer holds an in-flight snapshot, a pending one, and the latest frontend cache state it emitted. When a snapshot arrives while a render is in progress, the previous pending snapshot is dropped (most-recent-wins coalescing) and a [:minga, :render, :coalesced] telemetry event fires. Each snapshot is normalized against the renderer-owned cache state before it renders. After each render emit completes, the Renderer stores the emitted cache state and threads it into any pending snapshot before starting the next frame; otherwise it goes idle. If the Editor emits a direct bare frame boundary, that newer snapshot cache wins instead. That keeps delta frame bases aligned with what the frontend just received, even when the Editor has not yet processed the prior render writeback.

Click-region writeback

The render pipeline computes modeline_click_regions and tab_bar_click_regions as part of chrome rendering. These need to flow back to the Editor so subsequent mouse events can resolve click positions. The Renderer sends {:render_done, writeback} back to the Editor after every emit; the Editor merges renderer-owned fields from that payload via apply_renderer_writeback/2.

Telemetry

  • [:minga, :render, :pipeline] span around RenderPipeline.run/1.
  • [:minga, :render, :coalesced] event when a pending snapshot is dropped.
  • [:minga, :render, :frame_latency] measurement (push timestamp → emit complete).
  • [:minga, :render, :hop_latency] (hop: :cast_snapshot) measures the Editor → Renderer.Server scheduling delay; (hop: :render_done) measures the Renderer.Server → Editor writeback scheduling delay.

Determinism in tests

EditorCase tests use the headless backend, which renders synchronously in-process. This server is not started in the test supervision tree.

Summary

Types

Editor process reference used for renderer writebacks.

Injected render pipeline function.

Render pipeline output after a frame has run.

t()

Renderer server state.

Click-region writeback payload sent to the Editor after each frame.

Functions

Pushes a render snapshot. Returns immediately; the actual emit happens asynchronously. If a previous snapshot is still rendering, this snapshot replaces any prior pending one.

Returns a specification to start this module under a supervisor.

Returns true while a render pass is in progress.

Starts the Renderer server. The :editor_pid option names the Editor process to send {:render_done, ...} writebacks to; defaults to MingaEditor (the registered name of the Editor GenServer).

Types

editor_ref()

@type editor_ref() :: pid() | atom() | nil

Editor process reference used for renderer writebacks.

pipeline()

@type pipeline() :: (MingaEditor.RenderPipeline.Input.t() -> render_output())

Injected render pipeline function.

render_output()

@type render_output() :: MingaEditor.RenderPipeline.Input.t()

Render pipeline output after a frame has run.

t()

@type t() :: %MingaEditor.Renderer.Server{
  caches: MingaEditor.Renderer.Caches.t(),
  editor_pid: editor_ref(),
  font_registry: MingaEditor.UI.FontRegistry.t(),
  in_flight:
    {MingaEditor.RenderPipeline.Input.t(), non_neg_integer(), integer()} | nil,
  pending:
    {MingaEditor.RenderPipeline.Input.t(), non_neg_integer(), integer()} | nil,
  pipeline: pipeline(),
  rendering?: boolean()
}

Renderer server state.

writeback()

@type writeback() :: %{
  caches: MingaEditor.Renderer.Caches.t(),
  layout: MingaEditor.Layout.t() | nil,
  focus_tree: MingaEditor.FocusTree.t() | nil,
  shell_id: atom(),
  shell_identity: MingaEditor.Shell.Identity.t() | nil,
  shell_state: term(),
  windows: term(),
  frame_seq: non_neg_integer(),
  keyframe?: boolean(),
  render_sent_at: integer()
}

Click-region writeback payload sent to the Editor after each frame.

Functions

cast_snapshot(server \\ __MODULE__, snapshot, frame_seq)

Pushes a render snapshot. Returns immediately; the actual emit happens asynchronously. If a previous snapshot is still rendering, this snapshot replaces any prior pending one.

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

rendering?(server \\ __MODULE__)

@spec rendering?(GenServer.server()) :: boolean()

Returns true while a render pass is in progress.

start_link(opts \\ [])

@spec start_link(keyword()) :: GenServer.on_start()

Starts the Renderer server. The :editor_pid option names the Editor process to send {:render_done, ...} writebacks to; defaults to MingaEditor (the registered name of the Editor GenServer).