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
//! Row-parallel iteration over a pixel buffer.
//!
//! Single entry point [`par_rows`]: takes a contiguous `width × height` `u32` pixel buffer, a row range (clip-aware), and a closure invoked per row. With the `rayon` feature on, rows are dispatched across the rayon thread pool; off, the same iteration runs sequentially. The closure signature is identical either way — rasterizers and boundary passes don't branch on the feature gate, they just call this wrapper and the right thing happens.
//!
//! ## Why `Send + Sync` on the closure
//!
//! When rayon is on, rows run on different worker threads and the closure must be safe to call from multiple threads concurrently — that's `Send + Sync`. Rasterizer closures are tiny captures of small `f32` / `u32` / packed-pixel parameters with no interior mutability, so the bound is satisfied trivially. We require it unconditionally (even in sequential builds) so the call-site code is identical across feature combos — no `#[cfg]` per call.
/// Runtime override: when set, [`par_rows`] and [`par_chunks`] run sequentially even with the `rayon` feature enabled. Used by hosts that write into device-coherent memory (e.g. Android's `ANativeWindow_lock` buffer) where worker-thread writes need a single-thread ordering guarantee before `unlockAndPost` hands the buffer to the compositor.
pub static FORCE_SEQUENTIAL: AtomicBool =
new;
/// Iterate `pixels` row-by-row over `row_start..row_end`, calling `f(row_index, &mut row_slice)` for each row. Each `row_slice` is exactly `width` `u32`s. With `rayon` enabled and [`FORCE_SEQUENTIAL`] clear, rows are dispatched in parallel; otherwise sequentially.
///
/// Pre-conditions: `pixels.len() >= row_end * width` and `row_start <= row_end`. No internal clamping — the caller (a clipped rasterizer or a boundary pass) is responsible for shaping the range to fit the buffer.
/// Iterate a flat `pixels` slice in equal-sized chunks of `chunk_len` (handles trailing tail of any length). Closure receives `(chunk_offset_in_pixels, &mut chunk_slice)`. Same Rayon-vs- sequential dispatch as [`par_rows`] — used for whole-buffer passes (finalize, flatten, Op::Under) where row geometry doesn't matter and chunking by a multiple of cache-line size gives the best throughput.