Implement iris-canvas Phase 2: viewport, compositor, and blend pass#7
Merged
Conversation
- Exclude crates/appthere-canvas from workspace members (external path dep) - Fix workspace appthere-canvas path (was ../appthere-canvas, now crates/appthere-canvas) - Add features = ["gpu", "font-cache"] to appthere-canvas workspace dep - Uncomment appthere-canvas (+ dioxus feature), vello, wgpu in iris-canvas/Cargo.toml - Replace iris-canvas/src/lib.rs TODO stub: re-export CacheKey, CacheTier, ScrollPhase, ScrollState, GpuTexture, PageSource, RenderError from appthere_canvas; compile-time assertion that TileCoord satisfies CacheKey - ADR/006: status Proposed → Accepted; add Implementation notes section - CLAUDE.md: iris-canvas gate updated to GATE OPEN (ADR 006) cargo check --workspace: zero errors cargo test --workspace: 55 tests, 0 failures https://claude.ai/code/session_01X8kb2QAMhu3VtT8C2CkdYa
…ompositor, IrisCanvas - TileKey: (LayerId, TileCoord) composite key satisfying appthere_canvas::CacheKey - CanvasViewport: screen-center-anchored pan, zoom/rotation math, screen↔doc round-trip transforms, visible_doc_rect AABB for culling, zoom_to anchor-stable - Compositor: lazy BlendPass pipeline (Normal blend via PREMULTIPLIED_ALPHA_BLENDING render pipeline), DFS bottom-to-top layer iteration, tile upload to Rgba16Float, tile_params NDC quad corners per viewport transform - IrisCanvas Dioxus component (placeholder div, BLOCKED on appthere-canvas paint hook) with complete IrisPageSource / PageSource<Key = ()> implementation - Integration tests: viewport round-trips, TileKey hash, LayerTree structure - Upgrade wgpu workspace dep 22→26 to match appthere-canvas; add bytemuck, dioxus deps - Split compositor/mod.rs under 100-line ceiling into mod.rs + composite.rs - All 11 iris-canvas tests pass; clippy -D warnings clean; cargo test --workspace green https://claude.ai/code/session_01X8kb2QAMhu3VtT8C2CkdYa
…urce
- Add anyrender_vello = "0.6.2" dep to iris-canvas (Option B: bridge in iris-canvas)
- New paint_bridge.rs: IrisCanvasPaintSource implements anyrender_vello::CustomPaintSource
- resume(): clones DeviceHandle (wgpu::Device + Queue are Clone in wgpu 26)
- suspend(): drops device handle and last registered TextureHandle
- render(): reads viewport/tree from Arc<Mutex<>>, calls compositor.composite(),
unregisters old TextureHandle, calls ctx.register_texture(gpu_texture.inner),
returns Some(TextureHandle) — None skips the frame (Blitz reuses last texture)
- Update canvas_widget.rs: replace placeholder div with working use_wgpu integration
- shared_viewport and shared_tree are Arc<Mutex<>> updated on each Dioxus re-render
- use_wgpu captures cloned Arcs via FnOnce; auto-unregisters on component drop
- RSX: <canvas "src"="{canvas_id}"> (quoted attr bypasses Dioxus schema;
blitz-dom reads "src" on <canvas> elements to load custom paint sources)
- Add #[derive(Clone)] to LayerTree in iris-pixel (all fields already Clone)
- All 11 iris-canvas tests pass; clippy -D warnings clean; cargo test --workspace green
API discoveries vs audit assumptions:
- DeviceHandle.device / .queue are public fields (not getters) — direct field access
- TextureHandle: Clone — can clone for storage while returning from render()
- anyrender_vello uses wgpu = "26" — same as iris-canvas, types compatible
- use_wgpu is at dioxus::native::use_wgpu (not dioxus::prelude)
- canvas src attribute must be quoted "src" in RSX (not in Dioxus element schema)
https://claude.ai/code/session_01X8kb2QAMhu3VtT8C2CkdYa
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the core Iris infinite-canvas rendering pipeline (Phase 2 per SPEC.md §6.2):
use_wgpuhook andCustomPaintSourcebridgeThis unblocks Phase 2 delivery and establishes the foundation for Phase 3+ (vector/text layers, additional blend modes).
Key Changes
New modules
viewport.rs(221 lines):CanvasViewportstruct with screen↔document coordinate transforms, zoom anchoring, and visible-rect culling. Includes 8 unit tests covering round-trip transforms, rotation, and zoom clamping.compositor/mod.rs(66 lines):Compositorwrapper managing lazyBlendPassinitialization and the maincomposite()entry point.compositor/pass.rs(193 lines):BlendPasswgpu render pipeline (vertex/fragment shaders, bind groups, sampler) for Normal blend viaPREMULTIPLIED_ALPHA_BLENDING.compositor/composite.rs(133 lines): Core composite logic—layer iteration (DFS bottom-to-top), tile selection via visible rect, NDC quad computation, and blend pass invocation.compositor/upload.rs(95 lines): CPU→GPU tile upload helpers (upload_tile,transparent_tile) forRgba16Floattextures.canvas_widget.rs(136 lines):IrisCanvasDioxus component with reactive signals for viewport/tree,use_wgpuhook integration, andIrisPageSourcefor headless rendering.paint_bridge.rs(93 lines):IrisCanvasPaintSourceimplementingCustomPaintSourceto bridgeCompositorinto Blitz's paint loop.key.rs(41 lines):TileKeycache key type (layer ID + tile coordinate) for future page-cache integration.shaders/normal_blend.wgsl(65 lines): Vertex/fragment shaders with bilinear corner interpolation for rotated tiles and premultiplied-alpha blending.Modified files
lib.rs: Expose public API (CanvasViewport,IrisCanvas,CompositorError, re-exports fromappthere-canvas).Cargo.toml: Uncommentappthere-canvas,anyrender-vello,wgpu,kurbo,bytemuck,thiserrordependencies (gate now open per ADR 006).tests/integration.rs: Add 5 integration tests covering viewport transforms, tile selection, andTileKeyhashing.ADR/006-shared-canvas-extraction.md: Update status to "Accepted" and document implementation completion.SPEC.md: Update §6.2 to reflect screen-center pan convention (Q1 decision).CLAUDE.md: Update gating table—iris-canvasgate is now open.Cargo.toml: Excludeappthere-canvasfrom workspace (external dependency).Implementation Details
Pan convention (Q1 decision)
Document-space coordinate visible at the screen center, not top-left. Rotation is always around screen center. This avoids undefined behavior when rotation is non-zero.
Blend mode phasing
Phase 2 supports Normal blend only via hardware
PREMULTIPLIED_ALPHA_BLENDING. Non-Normal modes log a warning and skip the layer. Phase 4 will add compute shaders for additional blend modes (SPEC.md §4.8).Tile rendering
Rgba16Floattextures (f16 RGBA, straight alphahttps://claude.ai/code/session_01X8kb2QAMhu3VtT8C2CkdYa