Phase 12: Metal GPU Compositor (7/7)#
Goal: Abstract the renderer behind a trait so the browser can fall back to the existing software renderer when Metal is unavailable.
Depends on: Compositing layers for transforms, opacity, will-change
Requirements#
-
Define a renderer trait (or enum) that abstracts over Metal and software backends:
pub enum RenderBackend { Metal(MetalRenderer), Software(Renderer), }- Common interface: accept a display list + scroll state, produce rendered output
- Metal backend: translates to Metal draw calls and presents drawable
- Software backend: existing CPU rasterizer → BitmapContext → CGImage path
-
Detect Metal availability at startup:
- Call
MTLCreateSystemDefaultDevice()— returns null if Metal is unavailable - If Metal device is available, use Metal backend
- Otherwise, fall back to software renderer (existing CGImage path)
- Log which backend is active at startup
- Call
-
Ensure the software renderer path still works:
- Keep the existing
Rendererstruct and CGImage presentation path functional - When using software fallback, the view uses
drawRect:+ CGImage (current behavior) - When using Metal, the view uses CAMetalLayer (no drawRect:)
- Keep the existing
-
Handle Metal errors gracefully:
- If shader compilation fails, fall back to software
- If nextDrawable returns nil (e.g., app backgrounded), skip frame
Acceptance Criteria#
- Browser automatically selects Metal when available
- Browser falls back to software renderer when Metal is unavailable
- Both backends produce visually identical output
- Startup log message indicates active backend
- Metal errors (shader compilation, drawable unavailable) are handled gracefully
- No external crate dependencies
-
cargo clippy --workspace -- -D warningspasses -
cargo test --workspacepasses