Skip to main content

Output

Trait Output 

Source
pub trait Output {
    type Error: BackendError;

    // Required methods
    fn draw_layers<'a, I>(&mut self, content: I) -> Result<(), Self::Error>
       where I: Iterator<Item = DrawCell<'a>>;
    fn flush(&mut self) -> Result<(), Self::Error>;
    fn size(&self) -> Size<u16>;
    fn clear(&mut self) -> Result<(), Self::Error>;

    // Provided methods
    fn draw<'a, I>(&mut self, content: I) -> Result<(), Self::Error>
       where I: Iterator<Item = DrawCell<'a>> { ... }
    fn compositing(&self) -> Compositing { ... }
    fn resize(&mut self, size: Size<u16>) { ... }
}
Expand description

Draws grid content to a display and reports its dimensions.

This is the only one of the three backend facets (Output, Input, Cursor) that’s fallible: writing to a real display can fail (a broken pipe, a closed terminal, a lost surface), so every mutating method here returns Result<(), Self::Error>.

§Examples

use retroglyph_core::backend::{DrawCell, Output};
use retroglyph_core::grid::Size;

struct NullOutput;

impl Output for NullOutput {
    type Error = core::convert::Infallible;

    fn draw_layers<'a, I>(&mut self, _content: I) -> Result<(), Self::Error>
    where
        I: Iterator<Item = DrawCell<'a>>,
    {
        Ok(())
    }

    fn flush(&mut self) -> Result<(), Self::Error> {
        Ok(())
    }

    fn size(&self) -> Size {
        Size::new(4, 2)
    }

    fn clear(&mut self) -> Result<(), Self::Error> {
        Ok(())
    }
}

Required Associated Types§

Source

type Error: BackendError

Error type returned by fallible operations.

Required Methods§

Source

fn draw_layers<'a, I>(&mut self, content: I) -> Result<(), Self::Error>
where I: Iterator<Item = DrawCell<'a>>,

Draw changed cells across all layers.

crate::terminal::Terminal::present always calls this method, never draw directly, for every backend. A backend that returns Compositing::CellFlattened (the default, from compositing) receives a stream present has already pre-flattened onto layer 0 (all allocated layers composited into one frame first, so layers 1+ still appear on every backend, not only pixel ones); implementing this is no different from what implementing single-layer draw used to mean. A pixel/GPU backend that returns Compositing::PixelLayered receives the real, multi-layer stream here and does its own compositing (per-pixel or per-quad, plus sub-cell offsets and transparency as needed).

When compositing returns PixelLayered { needs_full_frame: true }, this receives all cells from every allocated layer, and the backend should clear its output surface before drawing; PixelLayered { needs_full_frame: false } and CellFlattened both receive only the changed cells.

Items are the same DrawCell draw receives, read through DrawCell::layer rather than a separate element.

§Errors

Self::Error is implementation-defined (a broken pipe or closed terminal for a process-backed display, a lost surface for a windowed one); implementations do not roll back cells already written before the failure. Because crate::terminal::Terminal::present only swaps its diff buffers into previous after the call that reached this method succeeds, a failed draw leaves the same cells marked dirty, so they are resent on the next successful present rather than silently dropped.

Source

fn flush(&mut self) -> Result<(), Self::Error>

Flush buffered output to the display.

§Errors

Self::Error is implementation-defined (a broken pipe, a closed terminal, a lost surface). crate::terminal::Terminal::present calls this only after draw/draw_layers succeed, and swaps its diff buffers only after flush also succeeds; a failed flush therefore leaves the current frame’s cells buffered but unconfirmed, and they are resent on the next successful present.

Source

fn size(&self) -> Size<u16>

Return current display dimensions.

Source

fn clear(&mut self) -> Result<(), Self::Error>

Clear the entire display.

§Errors

Self::Error is implementation-defined (a broken pipe, a closed terminal, a lost surface). Unlike draw/flush, this is not part of crate::terminal::Terminal::present’s per-frame path; callers that invoke it directly (some backends also call it internally on resize) should treat a failure as leaving the display in an unknown, possibly partially cleared state and retry or tear down rather than assume the previous contents are still intact.

Provided Methods§

Source

fn draw<'a, I>(&mut self, content: I) -> Result<(), Self::Error>
where I: Iterator<Item = DrawCell<'a>>,

Draw changed cells to the output surface, layer 0 only.

Every cell arrives as a DrawCell, which carries the out-of-line state a Tile cannot: its full grapheme cluster and its tint. Both live in a side table on Grid rather than in the tile, so a backend that needs either must read it from here.

The default implementation forwards to draw_layers, which every backend implements. crate::terminal::Terminal::present never calls this method directly (it always goes through draw_layers, pre-flattened onto layer 0 for a backend that doesn’t composite; see compositing), so overriding this is only worthwhile if a backend has a cheaper direct path for the known-single-layer case than its own draw_layers would take.

§Errors

See draw_layers, which this forwards to by default and shares its error contract with.

Source

fn compositing(&self) -> Compositing

How this backend wants layers handed to draw_layers.

Backends that render one glyph per cell return Compositing::CellFlattened (the default) and receive a pre-flattened, single-layer stream: crate::terminal::Terminal::present composites all allocated layers into one frame first. This makes layers 1+ appear on every backend, not only pixel backends. Pixel/GPU backends return Compositing::PixelLayered and composite the layers themselves; its needs_full_frame field asks for all cells on every draw_layers call (all cells on all layers) rather than just the changed ones, because pixel-based backends (e.g. SoftwareRenderer) can spill glyph pixels from sub-cell offsets into adjacent cells: without a full redraw, orphaned pixels from the previous frame linger.

Source

fn resize(&mut self, size: Size<u16>)

Notify the backend of a resize to size, updating what size reports.

Called automatically by crate::terminal::Terminal::resize after both grids are resized. Backends that maintain internal state tied to terminal dimensions (such as Headless) should override this to update that state. The default implementation is a no-op.

A driver may also call this directly, ahead of and independent from crate::terminal::Terminal::resize, to keep size in sync with an underlying surface the moment it changes (a windowed backend reacting to an OS resize, for example) without waiting for the app to resize the terminal’s grid content in response. Doing so does not resize the grid; only crate::terminal::Terminal::resize does that.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementations on Foreign Types§

Source§

impl Output for GlRenderer

Source§

type Error = Infallible

Source§

fn draw_layers<'a, I>( &mut self, content: I, ) -> Result<(), <GlRenderer as Output>::Error>
where I: Iterator<Item = DrawCell<'a>>,

Source§

fn compositing(&self) -> Compositing

Source§

fn flush(&mut self) -> Result<(), <GlRenderer as Output>::Error>

Source§

fn size(&self) -> Size<u16>

Source§

fn clear(&mut self) -> Result<(), <GlRenderer as Output>::Error>

Source§

fn resize(&mut self, size: Size<u16>)

§

impl Output for SoftwareRenderer

§

fn draw_layers<'a, I>( &mut self, content: I, ) -> Result<(), <SoftwareRenderer as Output>::Error>
where I: Iterator<Item = DrawCell<'a>>,

Composite the raw layer stream into the pixel buffer.

Layers arrive layer-major (0 first), so painting them in order gives the correct z-order. Layer 0 always fills its cell background; a higher layer’s occupied (non-empty) tile always fills a background too, and an empty tile never does: see the private resolve_bg_fill helper for the exact color each of those cases paints (it is not always the tile’s own background, to mirror Grid::flatten_into’s background-inheritance rule exactly). The is_empty guard matters because this receives the full frame (see Compositing::PixelLayered), including empty higher-layer cells that must not overwrite layer 0.

This matches cell backends (retroglyph#304): an occupied space with a Color::Default background on a higher layer erases the glyph beneath it when flattened, and this backend now does too, by repainting that cell’s background (see the private resolve_bg_fill helper) even though the occupied tile’s own background is the default one.

A TileFlags::SPAN_COVERED cell (retroglyph#412) paints its background but not its glyph: the span’s anchor already drew one sprite across the whole footprint, and the covered cell’s glyph is that sprite’s text fallback, for backends that cannot draw it. The sprite-transparency rule that decides whether a background is painted at all is resolved against the anchor (see resolve_cell_bg), so one span never sits on two different backdrops.

§

type Error = Infallible

§

fn flush(&mut self) -> Result<(), <SoftwareRenderer as Output>::Error>

§

fn size(&self) -> Size<u16>

§

fn resize(&mut self, size: Size<u16>)

§

fn clear(&mut self) -> Result<(), <SoftwareRenderer as Output>::Error>

§

fn compositing(&self) -> Compositing

Source§

impl Output for TerminalWasm

Source§

type Error = Error

Source§

fn draw_layers<'a, I>( &mut self, content: I, ) -> Result<(), <TerminalWasm as Output>::Error>
where I: Iterator<Item = DrawCell<'a>>,

Source§

fn flush(&mut self) -> Result<(), <TerminalWasm as Output>::Error>

Source§

fn size(&self) -> Size<u16>

Source§

fn resize(&mut self, size: Size<u16>)

Source§

fn clear(&mut self) -> Result<(), <TerminalWasm as Output>::Error>

§

impl Output for WgpuRenderer

§

type Error = Infallible

§

fn draw_layers<'a, I>( &mut self, content: I, ) -> Result<(), <WgpuRenderer as Output>::Error>
where I: Iterator<Item = DrawCell<'a>>,

§

fn compositing(&self) -> Compositing

§

fn flush(&mut self) -> Result<(), <WgpuRenderer as Output>::Error>

§

fn size(&self) -> Size<u16>

§

fn clear(&mut self) -> Result<(), <WgpuRenderer as Output>::Error>

§

fn resize(&mut self, size: Size<u16>)

Source§

impl<P> Output for WindowBackend<P>
where P: Presenter,

Source§

type Error = <P as Output>::Error

Source§

fn draw<'a, I>( &mut self, content: I, ) -> Result<(), <WindowBackend<P> as Output>::Error>
where I: Iterator<Item = DrawCell<'a>>,

Source§

fn draw_layers<'a, I>( &mut self, content: I, ) -> Result<(), <WindowBackend<P> as Output>::Error>
where I: Iterator<Item = DrawCell<'a>>,

Source§

fn flush(&mut self) -> Result<(), <WindowBackend<P> as Output>::Error>

Source§

fn size(&self) -> Size<u16>

Source§

fn clear(&mut self) -> Result<(), <WindowBackend<P> as Output>::Error>

Source§

fn resize(&mut self, size: Size<u16>)

Source§

fn compositing(&self) -> Compositing

Source§

impl<W> Output for Crossterm<W>
where W: Write,

Source§

type Error = Error

Source§

fn draw_layers<'a, I>( &mut self, content: I, ) -> Result<(), <Crossterm<W> as Output>::Error>
where I: Iterator<Item = DrawCell<'a>>,

Source§

fn flush(&mut self) -> Result<(), <Crossterm<W> as Output>::Error>

Source§

fn size(&self) -> Size<u16>

Source§

fn resize(&mut self, size: Size<u16>)

Source§

fn clear(&mut self) -> Result<(), <Crossterm<W> as Output>::Error>

Implementors§