Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 184 lines 6.4 kB view raw view rendered
1# Glaze Resize/Reframe Synchronization Plan 2 3## Problem Statement 4During window resize on `prompt.mjs` (dark mode), users occasionally see **both** the glaze canvas and the underlying main canvas, causing a visual "double vision" or layering artifact. 5 6## Root Cause Analysis 7 8### Canvas Stack Architecture (z-index order) 91. **3D canvas** (z-index: 0) - Three.js 102. **WebGPU canvas** (z-index: 1) 113. **Glaze canvas** (z-index: 2) - WebGL2 post-processing 124. **Freeze frame canvas** (z-index: 3, position: fixed) 135. **UI canvas** (z-index: 6) 146. **Main 2D canvas** (z-index: 7) 157. **Debug canvas** (z-index: 8) 16 17### Current Resize Flow (bios.mjs) 18 191. **Window resize event** → debounced (80ms `REFRAME_DELAY`) 202. **`needsReframe = true`** triggers `frame()` call 213. **Freeze frame creation** (lines 1016-1071): 22 - Copy current canvas to `freezeFrameCan` 23 - If glaze is on: `Glaze.freeze(ffCtx)` - draws glaze canvas to freeze frame 24 - Set `canvas.style.opacity = 0` (hide main canvas) 25 - Append freeze frame to wrapper 264. **Canvas resize** (lines 1156-1158): 27 - `canvas.width = width; canvas.height = height` 28 - This clears the canvas! 295. **Glaze reload** (lines 1538-1557): 30 - `Glaze.on()` checks if dimensions changed 31 - If changed: creates new Glaze instance, reloads shaders 32 - Glaze canvas starts with `opacity: 0` (glaze.mjs line 40) 336. **Frame completion** (lines 15938-15951): 34 - Remove freeze frame: `freezeFrameCan.remove()` 35 - Call `Glaze.unfreeze()` - removes opacity property 36 - If glaze off: `canvas.style.removeProperty("opacity")` 37 38### Identified Race Conditions 39 40#### Issue 1: Glaze shader reload timing 41In `glaze.mjs` `on()` function (line 340): 42```javascript 43await glaze.load(() => { 44 offed = false; 45 frame(w, h, rect, nativeWidth, nativeHeight, wrapper); 46 loaded(); 47}); 48``` 49The glaze shaders load **asynchronously**, but `frame()` is called inside the callback. If a resize happens during shader compilation, the canvas dimensions and glaze dimensions can get out of sync. 50 51#### Issue 2: Opacity transition timing (CSS) 52```css 53canvas[data-type="glaze"].first-glaze { 54 transition: 0.5s opacity; 55} 56``` 57The `first-glaze` class adds a 500ms opacity transition. During rapid resizes, this transition may not complete before another resize triggers, leaving both canvases partially visible. 58 59#### Issue 3: Freeze frame removal timing 60In `bios.mjs` lines 15938-15951: 61```javascript 62if (freezeFrame && freezeFrameFrozen) { 63 if (glaze.on === false) { 64 canvas.style.removeProperty("opacity"); 65 } 66 freezeFrameCan.remove(); 67 freezeFrame = false; 68 // ... 69} 70 71if (glaze.on) { 72 Glaze.unfreeze(); // This just removes opacity property 73} else { 74 canvas.style.removeProperty("opacity"); 75} 76``` 77The freeze frame is removed **before** we can guarantee that: 781. The glaze canvas has finished its shader reload 792. The glaze canvas has been properly positioned/sized 803. The main canvas has been hidden (opacity: 0) 81 82#### Issue 4: Missing synchronization between canvas opacity states 83When glaze is on: 84- Main canvas should have `opacity: 0` 85- Glaze canvas should have `opacity: 1` (no opacity set) 86 87But there's no atomic transition between these states. 88 89## Proposed Solutions 90 91### Solution A: Deferred Freeze Frame Removal (Low Risk) 92Wait for glaze to be fully ready before removing freeze frame. 93 94**Changes in bios.mjs:** 95```javascript 96// Add a flag for glaze readiness 97let glazeReady = false; 98 99// In Glaze.on() callback: 100currentGlaze = Glaze.on( 101 canvas.width, 102 canvas.height, 103 canvasRect, 104 projectedWidth, 105 projectedHeight, 106 wrapper, 107 glaze.type, 108 () => { 109 glazeReady = true; // Mark glaze as ready 110 send({ type: "needs-paint" }); 111 }, 112); 113 114// In paint loop, before removing freeze frame: 115if (freezeFrame && freezeFrameFrozen && (!glaze.on || glazeReady)) { 116 // ... remove freeze frame 117 glazeReady = false; // Reset for next resize 118} 119``` 120 121### Solution B: Eliminate CSS Transition During Resize (Medium Risk) 122Remove the `first-glaze` class during resize operations. 123 124**Changes:** 1251. In glaze.mjs `frame()`: Don't add `first-glaze` class if dimensions are changing 1262. Or: Add `transition: none` inline style during resize, restore after 127 128### Solution C: Atomic Opacity Swap (Higher Risk, Most Robust) 129Ensure main canvas opacity and glaze canvas opacity change atomically. 130 131**Changes in bios.mjs:** 132```javascript 133// Before showing glaze canvas 134requestAnimationFrame(() => { 135 canvas.style.opacity = 0; // Hide main canvas 136 Glaze.unfreeze(); // Show glaze canvas 137 freezeFrameCan.remove(); // Remove freeze frame 138}); 139``` 140 141### Solution D: Use Visibility Instead of Opacity 142Replace opacity manipulation with visibility for instant switching. 143 144**Changes:** 145- Replace `canvas.style.opacity = 0` with `canvas.style.visibility = "hidden"` 146- Replace `removeProperty("opacity")` with `style.visibility = "visible"` 147 148## Recommended Implementation Order 149 1501. **Phase 1** (Quick Win): Implement Solution A - deferred freeze frame removal 1512. **Phase 2** (If still issues): Add Solution B - disable transition during resize 1523. **Phase 3** (If needed): Implement Solution C - atomic opacity swap 153 154## Testing Checklist 155 156- [ ] Resize window slowly in dark mode (prompt.mjs) 157- [ ] Resize window rapidly in dark mode 158- [ ] Resize while content is actively animating 159- [ ] Test with different screen densities (devicePixelRatio) 160- [ ] Test switching between light/dark mode during resize 161- [ ] Test on macOS, Windows, Linux 162- [ ] Test in VS Code webview (ac-electron) 163 164## Files to Modify 165 1661. [bios.mjs](../system/public/aesthetic.computer/bios.mjs) - Main resize/glaze coordination 1672. [glaze.mjs](../system/public/aesthetic.computer/lib/glaze.mjs) - Shader loading and canvas management 1683. [style.css](../system/public/aesthetic.computer/style.css) - CSS transitions (if Solution B) 169 170## Performance Considerations 171 172- Avoid adding more async operations in the paint loop 173- The current 80ms `REFRAME_DELAY` is already a debounce - don't reduce it 174- Consider using `will-change: opacity` CSS hint on glaze canvas 175- Monitor for memory leaks from repeated shader program creation 176 177## References 178 179- bios.mjs freeze frame logic: lines 1016-1071 180- bios.mjs glaze.on() call: lines 1538-1557 181- bios.mjs freeze frame removal: lines 15938-15951 182- glaze.mjs on() function: lines 326-361 183- glaze.mjs frame() function: lines 120-200 184- glaze.mjs freeze/unfreeze: lines 392-405