Emerge 0.4 unifies renderer selection, changes screenshot capture to retained renderer state, and moves video submission to viewport-local atom targets.
Use rendering_api
Replace macOS-specific selection:
# 0.3
EmergeSkia.start(otp_app: :my_app, backend: :macos, macos_backend: :metal)
# 0.4
EmergeSkia.start(otp_app: :my_app, backend: :macos, rendering_api: :metal)Replace the compatibility renderer name:
# Deprecated in 0.4
backend_renderer: :gl
# Current
rendering_api: :openglbackend_renderer and :gl still warn and work in 0.4, but should not be used
in new configuration. macos_backend and dispatch_mode have been removed and
raise during option validation.
See EmergeSkia.start/1 for supported backend/rendering API combinations and
fallback rules.
Capture a retained renderer
In 0.3, render_to_pixels/2 and render_to_png/2 accepted a tree, created a
one-shot raster surface, and returned a binary:
# 0.3
png =
EmergeSkia.render_to_png(tree,
otp_app: :my_app,
width: 800,
height: 600
)In 0.4, they capture the latest already-presented frame from a running renderer and return a result tuple:
# 0.4
{:ok, renderer} = EmergeSkia.start(otp_app: :my_app, backend: :wayland)
{_diff_state, _assigned_tree} = EmergeSkia.upload_tree(renderer, tree)
{:ok, png} = EmergeSkia.render_to_png(renderer, timeout: 5_000)Update both the first argument and return-value matching. macOS host and headless PRIME sessions currently return a not-supported error for capture.
See EmergeSkia.render_to_pixels/2 and EmergeSkia.render_to_png/2 for the
current capture options and backend support.
Submit video to an atom target
Renderer-owned target handles, direct viewport connections, and
submit_prime/2 were removed. Describe the destination with an atom:
video([width(fill()), height(fill()), image_fit(:contain)], :camera)Submit each owned binary or borrowed DMA-BUF frame to the viewport:
:ok = Emerge.submit_video_frame(viewport, :camera, frame)Every normal return consumes the frame. Hidden targets drop it immediately;
visible targets retain only the latest frame. Use VideoInterop.retain/2 first
when another branch also needs the borrowed storage.
For Emerge-to-Emerge transport, configure the headless viewport to send
%VideoInterop.Frame{} values into Membrane.VideoInterop.Source, then route
them to Membrane.VideoInterop.Sink with an MFA that calls
Emerge.submit_video_frame/3. Do not forward frames through an application
handle_info/2 bridge.
The native video ownership contract changed in 0.4. Stop producers and consumers and cold-restart the BEAM operating-system process before loading upgraded Emerge, VideoInterop, or producer native libraries.
Handle renderer stop errors
EmergeSkia.stop/1 can now return {:error, reason} when a headless PRIME
session cannot prove ownership-safe shutdown:
case EmergeSkia.stop(renderer) do
:ok -> :ok
{:error, reason} -> Logger.error("renderer did not stop cleanly: #{inspect(reason)}")
endDo not treat an error as successful cleanup. Cold-restart the operating-system process before loading replacement native code.
Check stats schema version
The renderer stats payload changed with renderer, video, Vulkan, and cache
diagnostics. The 0.4 schema version is 25.
with {:ok, %{version: 25} = snapshot} <- EmergeSkia.stats(renderer, :peek) do
inspect_snapshot(snapshot)
endConsumers that persist or transmit snapshots should branch on version rather
than assuming the 0.3 map shape.
Review new memory defaults
Decoded raster assets now default to a 256-entry, 256 MiB cache. Constrained devices should set smaller limits and enable target-sized decode:
assets: [
decode_at_size: true,
cache: [max_entries: 8, max_bytes: 2 * 1024 * 1024]
]See Use assets for configuration and memory examples.
Scope runtime font registration
Runtime font registration now requires the renderer that owns the font:
# 0.3
:ok = EmergeSkia.load_font_file("my-font", 400, false, path)
# 0.4
:ok = EmergeSkia.load_font_file(renderer, "my-font", 400, false, path)The registration and its text-metrics cache are isolated from every other
renderer. Fonts declared through assets.fonts are loaded into the renderer
created by that start/1 call.
Review Vulkan configuration
Vulkan is supported and opt-in at build time. Existing OpenGL configurations do not switch to Vulkan automatically.
config :emerge,
compiled_backends: [wayland: [:opengl, :vulkan]]compiled_backends is a backend/API matrix. Use :all for every GPU API on a
backend or list the exact APIs to include. For example,
[wayland: [:vulkan]] contains Vulkan but no OpenGL. Atom entries retain their
0.3 behavior and select OpenGL. 64-bit Linux has precompiled Vulkan-only
Wayland, DRM, and headless variants.
Explicit rendering_api: :vulkan does not fall back. DRM Vulkan also requires
an exact vulkan_drm_node path separate from drm_card.