# `Emerge.Config.Headless`
[🔗](https://github.com/emerge-elixir/emerge/blob/v0.5.1/lib/emerge/config/headless.ex#L1)

Draw offscreen and send frames to an Elixir process. Set this record as
`Emerge.Config.output`.

```elixir
%Emerge.Config{
  output: %Emerge.Config.Headless{target: self(), size: {400, 300}},
  renderer: %Emerge.Config.Renderer{api: :raster},
  assets: %Emerge.Config.Assets{otp_app: :my_app}
}
```

## Fields

- `size` — output `{width, height}` in positive integer pixels;
  defaults to `{800, 600}`.
- `target` — the live local PID receiving frames. You must supply it;
  the default `nil` is not valid when starting a headless renderer.
- `frame_message` — message tag, an atom or string;
  defaults to `:emerge_skia_frame`.
- `frames` — `%Emerge.Config.BinaryFrames{}` (default) for owned pixel data,
  or `%Emerge.Config.PrimeFrames{}` for Linux DMA-BUF output. Use an explicit
  struct to choose the format.

The target receives `{frame_message, %VideoInterop.Frame{}}`. Binary frames
need no release; PRIME frames have a lease the recipient must release.
Headless output has no physical keyboard or pointer input.

## Changing settings

These fields require a new viewport. The frame-rate limit lives in
`Emerge.Config.Renderer.target_fps` and can change through `config`.

# `normalized_t`

```elixir
@type normalized_t() :: %Emerge.Config.Headless{
  frame_message: atom() | String.t(),
  frames:
    Emerge.Config.BinaryFrames.normalized_t()
    | Emerge.Config.PrimeFrames.normalized_t(),
  size: {pos_integer(), pos_integer()},
  target: pid() | nil
}
```

Canonical form after nested keyword records have been expanded.

# `t`

```elixir
@type t() :: %Emerge.Config.Headless{
  frame_message: atom() | String.t(),
  frames: Emerge.Config.BinaryFrames.t() | Emerge.Config.PrimeFrames.t(),
  size: {pos_integer(), pos_integer()},
  target: pid() | nil
}
```

---

*Consult [api-reference.md](api-reference.md) for complete listing*
