Skip to main content

<alp/gpu2d.h> — 2D Graphics Acceleration

Portable 2D blit / fill / blend operations against framebuffer surfaces.

Zephyr has no portable 2D-accelerator driver class, and the Alif Ensemble parts carry a hardware 2D engine. Without a portable surface, a customer migrating from V2N to AEN would silently lose that acceleration. This header exists so customer code compiles — and runs — on every SoM, taking the hardware path where one exists and a CPU path everywhere else.

#include <alp/gpu2d.h>

Quick example

alp_gpu2d_t *g = alp_gpu2d_open();

const alp_gpu2d_surface_t fb = {
.base = framebuffer,
.width = 800,
.height = 480,
.stride_bytes = 800 * 4,
.format = ALP_GPU2D_FMT_ARGB8888,
};

alp_gpu2d_fill_rect(g, &fb, 10, 10, 100, 50, 0xFFFF0000); // red
alp_gpu2d_close(g);

Which SoMs have GPU2D silicon?

The 2D engine on the Alif Ensemble is the TES D/AVE 2D block (Alif markets it as "GPU2D"). Per the SoC metadata, it is present on exactly three Ensemble SKUs:

SoMSoC2D silicon?
E1M-AEN601Alif Ensemble E6✅ D/AVE 2D
E1M-AEN701Alif Ensemble E7✅ D/AVE 2D
E1M-AEN801Alif Ensemble E8✅ D/AVE 2D
E1M-AEN301 / AEN401 / AEN501Ensemble E3 / E4 / E5
E1M-V2N101/102, E1M-V2M101/102Renesas RZ/V2N
E1M-NX9101NXP i.MX 93❌ — the i.MX 93's 2D engine is PXP, which is not a GPU2D peer (see ADR 0008) and is not wired to this surface

ALP_HAS(GPU2D) / ALP_HAS(DAVE2D) from <alp/cap.h> are the portable way to ask.

:::caution The hardware backend is bench-unverified today The D/AVE 2D backend is structural. It is authored against the documented d2_* driver API and the D/AVE 2D programming model — no hardware register value or address is invented — but it has not been compiled against the real vendor pack and has not been run on AEN silicon. Call sequencing, format/blend-mode mappings, and the submit-and-wait flush model are a first cut to be confirmed at bench bring-up. Cache maintenance against the caller's framebuffer is a documented follow-up, not yet implemented.

It is also gated behind CONFIG_ALP_SDK_GPU2D_ALIF_DAVE2D, which the build sets only when Alif's proprietary D/AVE 2D driver pack (AlifSemiconductor::Dave2DDriver) is on the include path. That pack is pulled at build time and is not vendored into the SDK.

In practice: unless you have explicitly supplied that pack, the software fallback is what runs — on every SoM, including AEN. Treat hardware acceleration here as not yet available. :::

Backends

Backendsilicon_refPriorityStatus
dave2d_e6 / dave2d_e7 / dave2d_e8"alif:ensemble:e6" / "e7" / "e8"100Bench-unverified; requires the proprietary pack. Advertises ALP_INSTANCE_CAP_DMA.
sw_fallback"*"0The backend that actually runs and is tested (on native_sim). Portable CPU fill/blit/blend.

One D/AVE 2D row per SKU that actually carries the engine, at priority 100 so the registry prefers it over the wildcard fallback on those parts only — see the selection rules. With the pack absent, those rows are not compiled at all and the priority-0 wildcard wins everywhere.

The software fallback is what V2N, i.MX 93, and ALP_OS=yocto Linux builds use, and it implements all five pixel formats.

Plain-CMake bare-metal builds are the exception: there is no backend registry on that path yet, so they link a NOSUPPORT stub — alp_gpu2d_open() returns NULL with ALP_ERR_NOSUPPORT and every op returns ALP_ERR_NOSUPPORT.

Functions

CallReturns
alp_gpu2d_open(void)alp_gpu2d_t *, or NULL with alp_last_error() set. With the software fallback enabled (the default, CONFIG_ALP_SDK_GPU2D_SW_FALLBACK) open succeeds on every SoM — there is no NOSUPPORT case at open time. NULL means either no backend compiled in at all (ALP_ERR_NOT_PRESENT_ON_THIS_SOC) or the handle pool is exhausted (ALP_ERR_NOMEM).
alp_gpu2d_fill_rect(handle, dst, x, y, w, h, argb_color)ALP_OK / ALP_ERR_NOT_READY / ALP_ERR_INVAL / ALP_ERR_OUT_OF_RANGE / ALP_ERR_NOSUPPORT. Rect is clipped to dst's dimensions.
alp_gpu2d_blit(handle, src, sx, sy, dst, dx, dy, w, h)Same set. Copy with no blend; converts format when src->format != dst->format and both are in the backend's supported set, else ALP_ERR_NOSUPPORT.
alp_gpu2d_blend(handle, src, sx, sy, dst, dx, dy, w, h, mode)Same set. Alpha-blends per mode.
alp_gpu2d_close(handle)void. NULL is a no-op.
alp_gpu2d_capabilities(const alp_gpu2d_t *handle)const alp_capabilities_t *, valid for the handle's lifetime; NULL handle → NULL. See instance capabilities.

:::note The handle pool defaults to ONE The 2D engine is a system-wide singleton, so a second alp_gpu2d_open() before alp_gpu2d_close() fails with ALP_ERR_NOMEM rather than aliasing the live handle. The pool size is the CONFIG_ALP_SDK_MAX_GPU2D_HANDLES compile-time override — there is no Kconfig entry for it today; define it on the build. :::

The colour passed to fill_rect is always ARGB8888 and the backend converts: RGB565 ignores the high 16 bits, A8 takes only the high byte (alpha).

Concurrency

The singleton handle is reentrant under a shared driver mutex, but callers must serialise fill_rect / blit / blend issuance themselves — the software fallback writes caller memory directly, and the D/AVE 2D HAL's display-list builder is not itself thread-safe.

Blit overlap contract

Pixels are processed top-to-bottom, left-to-right. An overlapping same-buffer copy toward earlier memory (dy < sy, or dy == sy with dx <= sx) is safe. A copy toward later memory may read pixels the op already wrote — backends do not reverse-iterate. Callers needing overlap-safe moves in both directions must use distinct buffers.

Surface descriptor

alp_gpu2d_surface_t lives in caller memory and is copied internally per operation, so you can reuse or modify the struct between calls.

FieldTypeNotes
basevoid *Pointer to the top-left pixel (no header byte).
width / heightuint32_tDimensions in pixels.
stride_bytesuint32_tBytes from one row's start to the next (= width * bytes-per-pixel when tightly packed).
formatalp_gpu2d_format_tSee below.

Pixel formats

Backends honour the subset their hardware supports; unsupported formats return ALP_ERR_NOSUPPORT.

FormatLayout
ALP_GPU2D_FMT_ARGB888832-bit, A:R:G:B = 8:8:8:8 (the D/AVE 2D default)
ALP_GPU2D_FMT_RGB56516-bit, R:G:B = 5:6:5
ALP_GPU2D_FMT_A88-bit alpha only — useful for masks
ALP_GPU2D_FMT_RGB88824-bit packed; backend-defined byte order
ALP_GPU2D_FMT_RGBA888832-bit, R:G:B:A = 8:8:8:8 (alternate ordering)

Blend modes

Colours are straight (non-premultiplied) alpha.

ModeFormula
ALP_GPU2D_BLEND_REPLACEdst = src (no blend)
ALP_GPU2D_BLEND_SRC_OVERdst = src*src.a + dst*(1-src.a) — a transparent src leaves dst untouched; an opaque src replaces it
ALP_GPU2D_BLEND_ADDITIVEdst = src + dst (clamped)
ALP_GPU2D_BLEND_MULTIPLYdst = src * dst

ABI status

[ABI-EXPERIMENTAL] — new in v0.5 (AEN audit headline gap). A portable surface, but only one silicon family populates it today. Pin your SDK to a specific commit if you depend on it.

See also

Questions about this page? Discuss in Community Forum