1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//! The seam — the traits each GPU backend implements.
//!
//! [`BackdropBlur`] is the universal seam: **two-phase** (`prepare` then `record`) because the
//! backends demand it. wgpu uploads uniforms/textures through its **Queue** (not the encoder),
//! so the upload phase needs the queue and the record phase needs only the encoder; glow is
//! immediate-mode (`prepare` uploads via the context, `record` draws). Every backend implements
//! this trait, and it is **total** — it contains no method a given backend cannot perform.
//!
//! [`GrabPass`] is a **separate, additive** trait for the grab-pass family only. The own-loop
//! path (wgpu) hands the host's already-sampleable intermediate straight to `prepare` and never
//! grabs, so forcing a `grab_source` onto every backend would make wgpu stub an impossible
//! method (it cannot fabricate a source from nothing). Instead the grab-pass (glow) backend
//! *additionally* implements `GrabPass` to blit a sampleable source out of a live framebuffer.
//! This is the socket that keeps glow additive (DESIGN §4.4).
//!
//! The associated types are each backend's resource universe — distinct per backend, which is
//! exactly why these traits are **not object-safe** and backends are **separate crates** (the
//! `wgpu-types` → `wgpu-hal` model). Dispatch is static, monomorphized.
//!
//! # Gate verdict (IMPL §1d): the seam is kept — now proven by the real backend
//!
//! Before committing to this seam, the divergent backend was first sketched against it in a
//! compile-only `examples/glow-gate` crate (now retired). That gate has been **superseded by the
//! real implementation**: [`backdrop-blur-glow`] implements both `BackdropBlur` and `GrabPass`
//! with live, `unsafe` GL and a full Tier-1 readback suite, so the seam is proven by working code
//! rather than an `unimplemented!()` sketch. Each associated type binds to a real glow type
//! (`Device`/`Encoder` → `glow::Context`, `SourceTexture` → the grab source, `Target` →
//! `Option<glow::Framebuffer>` — the live draw FBO, `None` = the default framebuffer); the one `()`
//! (`Queue`) is honest because glow uploads through its context rather than a queue, and
//! `TargetFormat` is the **framebuffer size** (the composite viewport) — not a color format: the
//! composite needs the full draw-target size for its full-framebuffer `glViewport`, and the encode
//! bit is still derived at draw time from the live context's `GL_FRAMEBUFFER_SRGB` state, not from a
//! format token. v1 therefore ships **with** these traits, not a concrete one-backend pair.
//!
//! [`backdrop-blur-glow`]: https://github.com/abdu-benayad/backdrop-blur
use crate::;
/// Implemented once per GPU backend (`WgpuBlur` in v1; `GlowBlur` later). The implementor holds
/// the backend's cached resources — per-`(size, levels)` ping-pong chains and the pipelines —
/// across frames, so repeated frosted surfaces do not rebuild them.
///
/// # Lifecycle contract (v1)
///
/// - **Serial `prepare` → `record` per surface.** v1 scope is a single frosted surface over a
/// once-rendered backdrop; because the ping-pong scratch is shared, two surfaces are not
/// prepared-then-both-recorded — each is prepared and recorded before the next. The
/// [`Prepared`](Self::Prepared) handle is **owned** (it borrows nothing from the blurrer), so
/// the contract does not rely on "record immediately follows prepare"; genuine multi-surface
/// batching is deferred future work. Because `Prepared` is owned, the types permit (but the
/// contract forbids) preparing two surfaces against the shared scratch before recording
/// either — the backend should debug-assert against an outstanding handle (K1).
/// - **Single-threaded, frame-serial.** `prepare` takes `&mut self`, `record` takes `&self`.
/// The blurrer is **not** required to be `Send`/`Sync` in v1; a multi-threaded render loop
/// owns one per render thread.
/// The **grab-pass** socket, implemented *in addition to* [`BackdropBlur`] only by backends that
/// must extract a sampleable backdrop from a live framebuffer (glow; the deferred mainstream-egui
/// path). Own-loop backends (wgpu) do **not** implement this — they receive an already-sampleable
/// source — which is why it is a separate trait rather than a method every backend must stub.