Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions .github/workflows/esp32p4.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: ESP32-P4 backend

on:
pull_request:
paths:
- ".github/workflows/esp32p4.yml"
- "engine/core/**"
- "engine/backends/esp32p4-ppa/**"
- "hosts/esp32p4/**"
push:
branches: [main]
paths:
- ".github/workflows/esp32p4.yml"
- "engine/core/**"
- "engine/backends/esp32p4-ppa/**"
- "hosts/esp32p4/**"
workflow_dispatch: {}

permissions:
contents: read

jobs:
rust:
name: Rust renderer
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4

- uses: dtolnay/rust-toolchain@stable

- name: Test RGB565 core rasterizer
run: cargo test --locked --manifest-path engine/core/Cargo.toml

- name: Test ESP32-P4 DrawList backend
run: cargo test --locked --manifest-path engine/backends/esp32p4-ppa/Cargo.toml --features std

- name: Check ESP-IDF Rust adapter
run: cargo check --locked --manifest-path engine/backends/esp32p4-ppa/Cargo.toml --features esp-idf

esp-idf:
name: ESP-IDF release/v6.0
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4

- name: Build ESP32-P4 component smoke app
uses: espressif/esp-idf-ci-action@v1
with:
esp_idf_version: release-v6.0
target: esp32p4
path: hosts/esp32p4/examples/ppa-smoke
5 changes: 3 additions & 2 deletions contracts/spec/spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -496,10 +496,11 @@ export const ENUMS = {
// ---------------------------------------------------------------------------
// Values MUST equal rust-psp's TexturePixelFormat (sceGuTexMode arg), as used
// by the dreamcart runtime — verified against rust-psp/psp/src/sys/gu.rs
// (Psm4444 = 2, Psm8888 = 3) and runtime/src/gfx3d.rs psm_for(). v1 supports
// only these two (4444 for baked corner/shadow alpha sprites, 8888 for images).
// (Psm5650 = 0, Psm4444 = 2, Psm8888 = 3) and runtime/src/gfx3d.rs
// psm_for().

export const PSM = {
PSM_5650: 0, // RGB 565, 16-bit (B5:G6:R5 bit order)
PSM_4444: 2, // RGBA 4444, 16-bit
PSM_8888: 3, // RGBA 8888, 32-bit
PSM_T8: 5, // CLUT8: one palette index/px + a 256 x u32 ABGR palette
Expand Down
5 changes: 5 additions & 0 deletions docs/DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ artifacts: `$JOB_TMP/map-*.json`).
PSP bin wraps it with QuickJS + sceGu; `wasm32-unknown-unknown` build wraps
it with a deterministic software rasterizer used by BOTH the browser dev
host and headless Bun goldens. One layout engine everywhere.
- **ESP32-P4 stays 16-bit**: `engine/backends/esp32p4-ppa/` consumes the same
DrawList into an opaque RGB565 target. It maps flat fills, A8 coverage
blending, and compatible PSM 5650 texture transforms to the PPA, then
preserves ordering with the core RGB565 rasterizer for unsupported ops.
It never allocates a full-frame RGB888/ARGB8888 intermediate.
- **Native animation**: tweens/springs tick in Rust per vblank with **fixed
dt = 1/60 s** (frame content is a pure function of frame index — this is
what makes byte-exact goldens possible **[R]**). JS only declares motion.
Expand Down
8 changes: 5 additions & 3 deletions docs/STRUCTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ directory; nothing else gets a top-level name.
pocketjs/
├─ engine/ Cores: the Rust simulation cores
│ ├─ core/ pocketjs-core — retained UI tree, taffy layout, raster (standalone crate)
│ ├─ backends/ platform render backends (ESP32-P4 PPA is a standalone no_std crate)
│ ├─ wasm/ core compiled to wasm32 for web/sim hosts (standalone crate)
│ ├─ pocket3d/ the 3D core family (bsp, cook, gu, vita) + desktop examples
│ ├─ crates/ non-3D engine crates: pocket-mod, pocket-ui-wgpu, pocket-vrm, pocket-widget
Expand All @@ -18,6 +19,7 @@ pocketjs/
├─ hosts/ Surfaces: every embedding of the cores
│ ├─ psp/ QuickJS + rust-psp EBOOT host
│ ├─ vita/ Vita host
│ ├─ esp32p4/ reusable ESP-IDF PPA adapter + component smoke build
│ ├─ web/ browser dev host (wasm core)
│ └─ sim/ deterministic headless simulation host (docs/DETERMINISM.md)
├─ framework/ Guest: @pocketjs/framework
Expand Down Expand Up @@ -60,7 +62,7 @@ New things go where the axis says — never invent a top-level directory:
- **npm surface is frozen**: `@pocketjs/framework/*` export *keys* never
change; the `exports`/`files` maps in package.json absorb internal moves.
- **Cargo stays non-workspace where toolchains demand it**: `engine/core`,
`engine/wasm`, `hosts/psp`, `hosts/vita`, and the gu/vita 3D crates each
stand alone with their own lockfiles. `engine/Cargo.toml` is the one
desktop workspace.
`engine/wasm`, `engine/backends/esp32p4-ppa`, `hosts/psp`, `hosts/vita`,
and the gu/vita 3D crates each stand alone with their own lockfiles.
`engine/Cargo.toml` is the one desktop workspace.
- **Moves are `git mv`** — history stays traceable.
6 changes: 4 additions & 2 deletions engine/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
# (docs/RUNTIMES.md: these are the Cores plus their desktop surfaces).
#
# Deliberately EXCLUDED and standalone (each with its own Cargo.lock):
# core/, wasm/ — cargo-psp needs hosts/psp to consume core as a
# lone standalone crate (see core/Cargo.toml)
# core/, wasm/, backends/esp32p4-ppa/
# — cargo-psp and ESP-IDF need to consume these as
# lone standalone crates (see their Cargo.toml)
# pocket3d/crates/pocket3d-gu, gu-demo — PSP-only (cargo-psp toolchain)
# pocket3d/crates/pocket3d-vita — Vita-only (vitasdk toolchain)
[workspace]
Expand All @@ -21,6 +22,7 @@ members = [
"pocket3d/examples/uihost",
]
exclude = [
"backends/esp32p4-ppa",
"core",
"wasm",
"pocket3d/crates/pocket3d-gu",
Expand Down
121 changes: 121 additions & 0 deletions engine/backends/esp32p4-ppa/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions engine/backends/esp32p4-ppa/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "pocketjs-esp32p4-ppa"
version = "0.1.0"
edition = "2021"
license = "MIT"
publish = false

[dependencies]
pocketjs-core = { path = "../../core" }

[dev-dependencies]
pocketjs-core = { path = "../../core", features = ["std"] }

[features]
default = []
esp-idf = []
std = ["pocketjs-core/std"]

[workspace]
42 changes: 42 additions & 0 deletions engine/backends/esp32p4-ppa/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# PocketJS ESP32-P4 PPA backend

This `no_std` crate interprets PocketJS DrawLists directly into an RGB565
surface. It accelerates operations that map exactly to the ESP32-P4 Pixel
Processing Accelerator and preserves DrawList order with an RGB565 software
fallback for everything else.

The default crate deliberately does not depend on ESP-IDF or a board support
package. Hosts can implement `PpaOps` for another driver or test double.
Enabling the `esp-idf` feature exposes the concrete `EspIdfPpaOps`
implementation, backed by the reusable ESP-IDF component under
[`hosts/esp32p4`](../../../hosts/esp32p4/README.md). Board-specific display
presentation remains in the BSP.

Accelerated paths:

- opaque and translucent flat rectangles (`FILL` or A8 `BLEND`);
- antialiased font runs (`A8` coverage composed once, then `BLEND`);
- single-color alpha textures such as PocketJS rounded-corner masks (`A8`
`BLEND`);
- opaque PSM 5650 texture quads (`SRM`) when scaling semantics are compatible.

Gradients, arbitrary triangles, textured triangles, and unsupported texture
formats fall back to `pocketjs_core::raster::render_scaled_rgb565_over`.
No full-frame RGB888 or ARGB8888 surface is allocated.

## Test

Run the portable renderer and pixel-parity tests on the host:

```sh
cargo test --locked --manifest-path engine/backends/esp32p4-ppa/Cargo.toml \
--features std
```

Compile-check the Rust side of the ESP-IDF adapter without linking an IDF
application:

```sh
cargo check --locked --manifest-path engine/backends/esp32p4-ppa/Cargo.toml \
--features esp-idf
```
Loading
Loading