Skip to main content

euv_engine/renderer/
enum.rs

1use crate::*;
2
3/// Defines how new pixels are composited with existing pixels on the canvas.
4///
5/// Maps directly to the CSS `globalCompositeOperation` property.
6#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
7pub enum BlendMode {
8    /// The source is drawn over the destination (default alpha blending).
9    #[default]
10    Normal,
11    /// The source color is multiplied with the destination, producing a darker result.
12    Multiply,
13    /// The source and destination are inverted, multiplied, then inverted again.
14    Screen,
15    /// The source and destination colors are added together, clamped to maximum brightness.
16    Lighter,
17    /// Combines `Multiply` and `Screen` based on the destination color.
18    Overlay,
19    /// Keeps the darker of the source and destination per channel.
20    Darken,
21    /// Keeps the lighter of the source and destination per channel.
22    Lighten,
23    /// Dodges the destination color brightening it based on the source.
24    ColorDodge,
25    /// Burns the destination color darkening it based on the source.
26    ColorBurn,
27    /// A harsher version of `Overlay` using the source color as the filter.
28    HardLight,
29    /// A softer version of `Overlay` using the source color as the filter.
30    SoftLight,
31    /// Subtracts the darker color from the lighter color per channel.
32    Difference,
33    /// Similar to `Difference` but with lower contrast.
34    Exclusion,
35    /// Uses the hue of the source with the saturation and luminosity of the destination.
36    Hue,
37    /// Uses the saturation of the source with the hue and luminosity of the destination.
38    Saturation,
39    /// Uses the hue and saturation of the source with the luminosity of the destination.
40    Color,
41    /// Uses the luminosity of the source with the hue and saturation of the destination.
42    Luminosity,
43}
44
45/// Rendering quality preset controlling anti-aliasing smoothing strategy.
46///
47/// Maps to the canvas `imageSmoothingQuality` value plus an explicit
48/// `imageSmoothingEnabled` toggle. Combined with a CSS `image-rendering:
49/// pixelated` rule on the consumer side, `Low` produces crisp pixel-art
50/// rendering while `High` produces smooth vector-style rendering.
51#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
52pub enum RenderQuality {
53    /// Fastest rendering, pixelated scaling.
54    ///
55    /// Disables `imageSmoothingEnabled` on the canvas context and sets
56    /// `imageSmoothingQuality = "low"`. Pair with CSS `image-rendering:
57    /// pixelated` for sharp nearest-neighbour scaling.
58    Low,
59    /// Balanced rendering with default smoothing quality.
60    ///
61    /// Sets `imageSmoothingQuality = "medium"`.
62    Medium,
63    /// Highest fidelity rendering with smooth edges and high-quality scaling.
64    ///
65    /// Sets `imageSmoothingQuality = "high"`. Best for vector-style content
66    /// on HiDPI displays. This is the default — when no explicit quality is
67    /// requested, the engine errs on the side of visual fidelity rather than
68    /// performance, since users typically notice aliasing artifacts before
69    /// they notice a few extra milliseconds of GPU time.
70    #[default]
71    High,
72}
73
74/// Errors that can occur while asynchronously initializing a `WebGpuRenderer`.
75///
76/// Each variant maps to one specific failure mode that the WebGPU init
77/// pipeline can encounter when calling into the browser's GPU API. The
78/// underlying JS error (when available) is carried as a `JsValue` so callers
79/// can surface the exact diagnostic string without losing fidelity.
80///
81/// Instead of logging diagnostics inside the engine, `WebGpuRenderer::init`
82/// returns `Result<WebGpuRenderer, WebGpuInitError>` and lets the caller
83/// decide how to react — typically via `Console::error` on the example side
84/// or by falling back to the Canvas 2D backend.
85#[derive(Clone, Debug)]
86pub enum WebGpuInitError {
87    /// `Reflect::get(navigator, "webgpu")` threw an exception.
88    ///
89    /// Surfaced when the JavaScript binding lookup itself fails rather than
90    /// simply returning `undefined`/`null`. Carries the original JS error.
91    NavigatorLookup(JsValue),
92    /// `navigator.gpu` is `undefined` or `null`.
93    ///
94    /// The browser does not expose WebGPU on the current origin. The most
95    /// common causes are serving over an insecure origin (must be HTTPS or
96    /// `localhost`) or running in a browser that lacks the WebGPU feature.
97    NavigatorGpuMissing,
98    /// `Reflect::get(gpu, "requestAdapter")` threw an exception.
99    ///
100    /// Carries the original JS error returned by the reflect call.
101    RequestAdapterLookup(JsValue),
102    /// `gpu.requestAdapter()` threw an exception synchronously.
103    ///
104    /// Carries the thrown JS error or value.
105    RequestAdapterCall(JsValue),
106    /// The adapter promise rejected, or the `INIT_PROMISE_TIMEOUT_MILLIS`
107    /// race timer fired before the adapter was produced.
108    ///
109    /// Carries the rejection value, which may be a string, an error object,
110    /// or `undefined` when the timeout won the race.
111    AdapterPromise(JsValue),
112    /// `requestAdapter()` resolved to `null` or `undefined`.
113    ///
114    /// No compatible GPU adapter exists for the requested `powerPreference`.
115    AdapterUnavailable,
116    /// `Reflect::get(adapter, "requestDevice")` threw an exception.
117    RequestDeviceLookup(JsValue),
118    /// `adapter.requestDevice()` threw an exception synchronously.
119    RequestDeviceCall(JsValue),
120    /// The device promise rejected, or the `INIT_PROMISE_TIMEOUT_MILLIS`
121    /// race timer fired before the device was produced.
122    DevicePromise(JsValue),
123    /// `requestDevice()` resolved to `null` or `undefined`.
124    ///
125    /// The adapter could not allocate a device, typically because the
126    /// adapter is in a `device-lost` state.
127    DeviceUnavailable,
128    /// `document.querySelector(canvas_selector)` returned `None`.
129    ///
130    /// The canvas element is not in the DOM yet (or its selector is wrong).
131    /// Carries the selector string that was queried.
132    CanvasNotFound(String),
133    /// `document.querySelector(canvas_selector)` threw an exception.
134    CanvasQuery(JsValue),
135    /// `canvas.get_context("webgpu")` returned `None`.
136    ///
137    /// The canvas is already using a different context type, or WebGPU is
138    /// disabled for this canvas.
139    CanvasContextUnavailable,
140    /// `Reflect::get(gpu, "getPreferredCanvasFormat")` threw an exception.
141    PreferredFormatLookup(JsValue),
142    /// `gpu.getPreferredCanvasFormat()` threw an exception synchronously.
143    PreferredFormatCall(JsValue),
144    /// `getPreferredCanvasFormat()` resolved to a value that is not a string.
145    ///
146    /// Carries the offending JS value so callers can log its type/name.
147    PreferredFormatType(JsValue),
148    /// `Reflect::get(context, "configure")` threw an exception.
149    ConfigureLookup(JsValue),
150    /// `Reflect::get(device, "queue")` threw an exception.
151    QueueLookup(JsValue),
152}