Detect HW acceleration; default lava off on software renderer; release probe WebGL context
Probes UNMASKED_RENDERER_WEBGL once per page via a throwaway WebGL context; defaults the lava subsystem off on a positive software-renderer match or total WebGL failure; releases the throwaway context via WEBGL_lose_context after reading the renderer string to avoid exhausting the browser's per-page context limit.
This commit is contained in:
@@ -265,6 +265,24 @@ public partial class WaveformVisualizer : ComponentBase, IAsyncDisposable
|
||||
return;
|
||||
}
|
||||
|
||||
// Apply the hardware-capability default ONCE per session before seeding the controls: if the
|
||||
// browser has no WebGL hardware acceleration, the lava subsystem (which software-renders on
|
||||
// the main thread and starves audio decode) defaults off while the waveform stays on. The
|
||||
// probe lives in JS (it needs a real WebGL context); the scoped state guards the one-time
|
||||
// application, so a remounted visualizer never re-applies and a later explicit toggle is
|
||||
// never clobbered. Sequenced before PushControlsAsync so the seed already carries the
|
||||
// corrected enables; ApplyCapabilityDefault also raises Changed for the controls UI.
|
||||
try
|
||||
{
|
||||
var hardwareAccelerated = await _module.InvokeAsync<bool>("detectHardwareAcceleration");
|
||||
ControlState.ApplyCapabilityDefault(hardwareAccelerated);
|
||||
}
|
||||
catch (JSException ex)
|
||||
{
|
||||
// A probe failure must not regress the HW-accel majority: leave the defaults (lava on).
|
||||
Logger.LogWarning(ex, "WaveformVisualizer: hardware-acceleration probe failed; leaving lava at its default.");
|
||||
}
|
||||
|
||||
// Seed the module with the current state now that it exists. All control values (the eight
|
||||
// dials + the two Phase 15 subsystem enables) come from the shared (session-persisted) state,
|
||||
// so a mix opened mid-session seeds the module with the knob/toggle positions the listener
|
||||
|
||||
@@ -160,6 +160,47 @@ public sealed class WaveformVisualizerControlState
|
||||
/// </summary>
|
||||
public event Action? Changed;
|
||||
|
||||
// Whether the one-time, capability-driven default has been applied this session. The default-set
|
||||
// (lava off when the browser has no WebGL hardware acceleration) must run exactly once — on the
|
||||
// first interactive render, before the listener has touched a toggle — so it sets the *initial
|
||||
// default* and never clobbers a later explicit in-session toggle. Scoped with the rest of this
|
||||
// state, so it survives SPA navigation (a remounted visualizer does not re-apply) and resets on a
|
||||
// fresh page load (F5 re-probes).
|
||||
private bool _capabilityDefaultApplied;
|
||||
|
||||
/// <summary>
|
||||
/// Applies the hardware-capability default exactly once per session: when the browser reports no
|
||||
/// WebGL hardware acceleration, the lava subsystem (the expensive, main-thread software-rendered
|
||||
/// part that starves audio decode) defaults <c>off</c> while the waveform stays <c>on</c>. With
|
||||
/// acceleration present this is a no-op — lava keeps its <see cref="DefaultLavaEnabled"/> on-state.
|
||||
///
|
||||
/// <para>
|
||||
/// Idempotent and guarded: only the FIRST call this session has any effect, so it sets the initial
|
||||
/// default and never overrides a listener's explicit toggle (the control remains fully functional —
|
||||
/// a user on a software renderer may re-enable lava at their own risk). Mutates, coerces
|
||||
/// Theater Mode, then raises <see cref="Changed"/> once so the controls UI, the visualizer bridge,
|
||||
/// and the Theater observers all reflect the default in a single cycle. Called by the visualizer
|
||||
/// bridge on first interactive render, once JS interop (the probe) is available.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="hardwareAccelerated">
|
||||
/// The probe result — <c>true</c> when WebGL hardware acceleration is present (or the renderer is
|
||||
/// unknown/masked, favoring the common case), <c>false</c> only on a positive software-renderer
|
||||
/// match or total WebGL failure.
|
||||
/// </param>
|
||||
public void ApplyCapabilityDefault(bool hardwareAccelerated)
|
||||
{
|
||||
if (_capabilityDefaultApplied) return;
|
||||
_capabilityDefaultApplied = true;
|
||||
|
||||
// Accelerated (or unknown): keep the as-shipped defaults — no observer churn.
|
||||
if (hardwareAccelerated) return;
|
||||
|
||||
LavaEnabled = false; // the expensive subsystem off; WaveformEnabled stays at its default (true).
|
||||
CoerceTheaterMode();
|
||||
NotifyChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enforces the Theater-Mode invariant: Theater Mode cannot remain on when both visualizer
|
||||
/// subsystems are off (there is nothing to go to theater FOR). Call this after mutating
|
||||
|
||||
Reference in New Issue
Block a user