blob: 0a39ba254a2d88913d6e537be0e66006257e92c3 [file] [view]
# Fuchsia UI examples
This directory contains sample applications demonstrating how to build graphical
components on Fuchsia using Scenic's Flatland composition APIs, `sysmem2`
buffer allocation, Vulkan / Escher rendering, screen capture, and pointer /
keyboard input handling.
## Quick comparison
| Example | Language | Composition API | Rendering Backend | Scene Attachment | Input & Extra APIs |
| :--- | :--- | :--- | :--- | :--- | :--- |
| [`snake-flatland`](snake-flatland/) | Rust (2024) | `Flatland2` (`FlatlandFactory`) | Solid-color `Layer`s (no buffers) | `GraphicalPresenter` | Touch (swipes + taps), Mouse, Keyboard (`input3`), `Focuser` |
| [`simplest-app-flatland`](simplest-app-flatland/) | Rust (2024) | Classic `Flatland` | Single `CreateFilledRect` | `GraphicalPresenter` or `ViewProvider` | Touch, Mouse, Keyboard (`input3`), `Focuser`, Tracing |
| [`flatland-rainbow`](flatland-rainbow/) | Rust (2024) | Classic `Flatland` | CPU (`sysmem2`) or Vulkan (`ash`) | `ViewProvider` or `GraphicalPresenter` | Touch, Mouse (logged), `ViewRefFocused`, `ThroughputScheduler`, Tracing |
| [`simplest_sysmem`](simplest_sysmem/) | C++ (HLCPP) | Classic `Flatland` | CPU (`sysmem2` VMO / `libpng`) or `CreateFilledRect` | `ViewProvider` | Packaged PNG decoding (`libpng`) |
| [`screen_recording`](screen_recording/) | C++ (Natural / Wire) | Classic `Flatland` | Zero-copy `ScreenCapture` `sysmem2` + `CreateFilledRect` | `ViewProvider` | `fuchsia.ui.composition.internal.ScreenCapture` |
| [`escher-flatland`](escher-flatland/) | C++ (Natural) | Classic `Flatland` (`escher_flatland`) | Escher (Vulkan) | `GraphicalPresenter` | Minimal `escher_flatland` integration |
| [`escher`](escher/) (`rainfall`) | C++ (Natural) | `VkImagePipeSurfaceFUCHSIA` (swapchain layer) | Escher `RectangleCompositor` | `GraphicalPresenter` (via layer) or raw display | Escher built-in flatland shaders, `DemoHarness` (`_on_scenic` / `_on_fb`) |
## Which example should I try?
| Use case | Recommended example | Rendering strategy | Input capabilities |
| :--- | :--- | :--- | :--- |
| I want to exercise `Flatland2` (layers and layer stacks) or write a modern Rust UI app | [`snake-flatland`](snake-flatland/) | Solid-color `Flatland2` `Layer`s & `LayerStack`s (`CompositionMode::SolidColor`, no buffers) | Touch (taps transformed via `ViewParameters`; swipes via viewport-space deltas), Mouse (`ViewParameters` transform), Keyboard (`input3`), `Focuser` |
| I want to compare `GraphicalPresenter` vs. `ViewProvider` in a minimal Rust skeleton | [`simplest-app-flatland`](simplest-app-flatland/) | Single classic `Flatland` solid rectangle (`CreateFilledRect` / `SetSolidFill`) | Touch, Mouse, Keyboard (`input3`), `Focuser` |
| I want to exercise CPU software rendering or raw Vulkan (`ash`) with `sysmem2` in Rust | [`flatland-rainbow`](flatland-rainbow/) | Dual backends: CPU software rendering into `sysmem2` VMOs or raw Vulkan (`ash`) with `VK_FUCHSIA_buffer_collection` | Touch, Mouse (logged to syslog); `ViewRefFocused` (adjusts color saturation) |
| I want to allocate host-visible `sysmem2` buffers or decode PNGs in C++ | [`simplest_sysmem`](simplest_sysmem/) | CPU-writable `sysmem2` VMO uploads (`--png` via `libpng`, `--block` BGRA32) or `CreateFilledRect` (`--rect`) | None (output-only) |
| I want to capture screen frames in C++ (Natural / Wire bindings) | [`screen_recording`](screen_recording/) | Zero-copy `sysmem2` buffer collection populated by Scenic (`ScreenCapture::GetNextFrame`, `kNoneUsage`) composited via `Flatland::CreateImage` alongside a `CreateFilledRect` bouncing square | None (output-only) |
| I want to exercise GPU rendering with Escher in C++ (minimal Flatland setup) | [`escher-flatland`](escher-flatland/) | Vulkan GPU rendering via `escher::Escher` presented through `//src/ui/lib/escher/escher_flatland` | None (output-only) |
| I want to exercise Escher `RectangleCompositor` with built-in flatland shaders via Vulkan swapchain layers (Scenic or direct display FB) | [`escher`](escher/) (`rainfall`) | Vulkan GPU rendering via `escher::RectangleCompositor` + Escher built-in flatland shaders over `VkImagePipeSurfaceFUCHSIA` (`VK_LAYER_FUCHSIA_imagepipe_swapchain` or `_fb`) | None on Fuchsia (`/dev/class/input-report` stubbed in `DemoHarness`) |
## Example catalog
### snake-flatland
* **Path:** [`//src/ui/examples/snake-flatland`](snake-flatland/)
* **Components:**
* `fuchsia-pkg://fuchsia.com/flatland-examples#meta/snake-flatland.cm`
* **Description:** A complete, playable Snake game built purely from
`Flatland2` `CompositionMode::SolidColor` layers—no `sysmem` buffer
allocations or texture uploads required. Demonstrates `FlatlandFactory`
session creation with `use_flatland2: true`, 7-segment score rendering with
solid layers, responsive viewport layout via `ParentViewportWatcher`,
on-screen D-pad hit testing, tap and mouse click handling with
`ViewParameters.viewport_to_view_transform` coordinate conversion (plus
swipe detection using viewport-space deltas against `SWIPE_THRESHOLD_PX`),
and keyboard/focus integration.
### simplest-app-flatland
* **Path:** [`//src/ui/examples/simplest-app-flatland`](simplest-app-flatland/)
* **Components:**
* `fuchsia-pkg://fuchsia.com/flatland-examples#meta/simplest-app-flatland.cm`
(passes `graphical_presenter`)
* `fuchsia-pkg://fuchsia.com/flatland-examples#meta/simplest-app-flatland-session.cm`
(passes `view_provider`)
* **Description:** The smallest interactive classic `Flatland` application in
Rust. Renders a single solid-colored rectangle (`CreateFilledRect` /
`SetSolidFill`) that changes color on each touch, mouse, or keyboard event,
while cleanly isolating `TouchSource`, `MouseSource`, and `KeyboardListener`
event loops and showing both `GraphicalPresenter` and `ViewProvider` startup
paths.
### flatland-rainbow
* **Path:** [`//src/ui/examples/flatland-rainbow`](flatland-rainbow/)
* **Components:**
* `fuchsia-pkg://fuchsia.com/flatland-examples#meta/flatland-rainbow.cm`
(CPU software renderer)
* `fuchsia-pkg://fuchsia.com/flatland-examples#meta/flatland-rainbow-vulkan.cm`
(passes `--use-vulkan` and `--use-graphical-presenter`)
* **Description:** Side-by-side CPU (`render_cpu.rs`) and Vulkan
(`render_vk.rs` via `ash`) rendering backends sharing a single Flatland
presentation loop. Shows how to negotiate `fuchsia.sysmem2` buffer
collections, define a custom `ash` extension loader for
`VK_FUCHSIA_buffer_collection` (importing memory via
`VK_FUCHSIA_external_memory`; `VK_FUCHSIA_external_semaphore` is currently
commented out in `render_vk.rs` where `VulkanRenderer::render_rgba` submits
with a `vk::Fence` and waits on the CPU via `wait_for_fences` rather than
importing external semaphores or passing fences to `Flatland::Present`),
pace frames with `flatland_frame_scheduling_lib::ThroughputScheduler`
(`OnNextFrameBegin` / `OnFramePresented`), adjust color saturation based on
focus state via `fuchsia.ui.views.ViewRefFocused`, and log touch/mouse
events to syslog rather than mutating the scene. *(Note: Vulkan mode
currently renders a single solid color rather than four quadrants; see
`b/42055867`.)*
### simplest_sysmem
* **Path:** [`//src/ui/examples/simplest_sysmem`](simplest_sysmem/)
* **Components:**
* `fuchsia-pkg://fuchsia.com/simplest_sysmem#meta/simplest_sysmem.cm`
* `fuchsia-pkg://fuchsia.com/flatland-examples#meta/simplest_sysmem.cm`
* **Description:** A focused C++ reference for host-visible `sysmem2` VMO
allocation and CPU pixel writes without Vulkan. Supports three modes via
component program `args`: `--png` (decodes a packaged PNG with `libpng` into
RGBA pixels), `--block` (generates four BGRA32 color blocks), and `--rect`
(displays a solid `CreateFilledRect`).
### screen_recording
* **Path:** [`//src/ui/examples/screen_recording`](screen_recording/)
* **Components:**
* `fuchsia-pkg://fuchsia.com/screen_recording#meta/screen_recording.cm`
* `fuchsia-pkg://fuchsia.com/flatland-examples#meta/screen_recording.cm`
* **Description:** Demonstrates live screen capture via
`fuchsia.ui.composition.internal.ScreenCapture` (`view_provider.cc` uses
C++ Natural bindings, while `screen_capture_helper.cc` also uses
`fidl::WireClient<fuchsia_sysmem2::Allocator>`). Rather than mapping or
writing to `sysmem2` buffers on the CPU, Scenic
(`ScreenCapture::GetNextFrame`) writes directly into the shared `sysmem2`
buffer collection (`kNoneUsage`,
`RegisterBufferCollectionUsages::kDefault | kScreenshot`), and the app
composites those buffers zero-copy via `Flatland::CreateImage` alongside a
`CreateFilledRect` bouncing square.
### escher-flatland
* **Path:** [`//src/ui/examples/escher-flatland`](escher-flatland/)
* **Components:**
* `fuchsia-pkg://fuchsia.com/escher-flatland#meta/escher-flatland.cm`
* **Description:** A minimal C++ entry point showing how to bootstrap
`escher::Escher`, clear the swapchain image, and blit a bouncing digital
clock string via `escher::DebugFont::Blit` into a child swapchain viewport
managed by `//src/ui/lib/escher/escher_flatland` (`escher::EscherFlatland`).
### escher (rainfall)
* **Path:** [`//src/ui/examples/escher`](escher/)
* **Components:**
* `fuchsia-pkg://fuchsia.com/escher_rainfall_on_scenic#meta/escher_rainfall_on_scenic.cm`
* `fuchsia-pkg://fuchsia.com/escher_rainfall_on_fb#meta/escher_rainfall_on_fb.cm`
* **Description:** An Escher demo (`DemoHarness` supporting Scenic and
direct display framebuffer access) rendering animated falling rectangles
with `escher::RectangleCompositor` and Escher's built-in flatland shaders
packaged from `//src/ui/lib/escher/shaders/flatland/` (rather than custom
GLSL shaders). Rather than calling Flatland FIDL APIs directly in the app,
`DemoHarnessFuchsia` creates a `VkImagePipeSurfaceFUCHSIA` and relies on
`VK_LAYER_FUCHSIA_imagepipe_swapchain` (Scenic mode) or
`VK_LAYER_FUCHSIA_imagepipe_swapchain_fb` (direct display framebuffer
mode). Accompanied by an automated Vulkan smoke test
(`//src/ui/examples/escher/test:escher_examples_test`).
## Building and running
Add the examples and their test targets to your `fx set` configuration (for example, on `workbench_eng.x64`):
```sh
fx set workbench_eng.x64 --with //src/ui/examples --with-test //src/ui/examples:tests
fx build
```
Launch any session-compatible example on a running device or emulator with `ffx session add`:
```sh
ffx session add --name snake-flatland fuchsia-pkg://fuchsia.com/flatland-examples#meta/snake-flatland.cm
```
To run the unit tests for the examples (`//src/ui/examples:tests` currently includes `flatland-rainbow-tests` and `snake-flatland-tests`; `//src/ui/examples/escher/test:escher_examples_test` can be built and run separately):
```sh
fx test //src/ui/examples:tests
```