1using System.Runtime.Versioning;
4using Microsoft.JSInterop;
6using SkiaSharp.Views.Blazor;
33[SupportedOSPlatform(
"browser")]
36 private readonly
string _generatedCanvasId = $
"gondwana-webgl-{Guid.NewGuid():N}";
38 private IJSObjectReference? _module;
39 private GRContext? _grContext;
40 private IReadOnlyDictionary<string, object>? _gpuCanvasAttributes;
41 private string _canvasId =
string.Empty;
42 private bool _backbufferNeedsRender =
true;
43 private bool _disposed;
49 public RenderSurfaceHost<GpuBackbuffer>
Host {
get;
private set; } =
null!;
52 private IReadOnlyDictionary<string, object>? GpuCanvasAttributes => _gpuCanvasAttributes;
54 internal override ValueTask<CanvasOffset> GetCanvasOffsetAsync()
55 => _module is
null ? ValueTask.FromResult(
default(CanvasOffset))
56 : _module.InvokeAsync<CanvasOffset>(
"getCanvasOffset", _canvasId);
64 Host =
new RenderSurfaceHost<GpuBackbuffer>(
Adapter);
71 base.OnParametersSet();
73 var attributes =
new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
77 attributes[attribute.Key] = attribute.Value;
80 if (attributes.TryGetValue(
"id", out var
id) &&
id is not
null)
81 _canvasId =
id.ToString() ?? _generatedCanvasId;
83 attributes[
"id"] = _canvasId = _generatedCanvasId;
85 attributes[nameof(SKGLView.OnPaintSurface)] =
86 (Action<SKPaintGLSurfaceEventArgs>)HandlePaintSurface;
88 _gpuCanvasAttributes = attributes;
97 _module = await JS.InvokeAsync<IJSObjectReference>(
99 "./_content/Gondwana.Blazor/gondwana-blazor.js");
103 await _module.InvokeVoidAsync(
"focusElementById", _canvasId);
104 await _module.InvokeVoidAsync(
"suppressBrowserInputDefaultsById", _canvasId);
112 private void HandlePaintSurface(SKPaintGLSurfaceEventArgs e)
114 long telemetryGeneration =
Host?.
Telemetry?.BeginSample() ?? 0;
118 var width = e.Info.Width;
119 var height = e.Info.Height;
120 Adapter.BeginPaint(width, height);
122 if (width <= 0 || height <= 0 || e.Surface.Context is not GRContext grContext)
124 e.Surface.Canvas.Clear(SKColors.Black);
129 _grContext = grContext;
130 if (backbuffer.EnsureInitialized(grContext))
131 _backbufferNeedsRender =
true;
134 if (!engine.IsRunning)
136 e.Surface.Canvas.Clear(backbuffer.ClearColor);
144 bool engineFrameRequested =
Adapter.ConsumeFrameRequest();
145 bool renderScene = _backbufferNeedsRender || engineFrameRequested;
147 bool presented = renderScene
153 e.Surface.Canvas.Clear(backbuffer.ClearColor);
158 _backbufferNeedsRender =
false;
162 backbuffer.RecordFrame();
163 if (telemetryGeneration != 0)
Host!.
Telemetry!.Record(telemetryGeneration,
"presentation.count", 1);
180 if (_module is not
null)
182 _ = _module.DisposeAsync();
Coordinates Gondwana foreground-frame requests with a Blazor WebGL render surface.
A Blazor WebGL render surface that draws Gondwana scenes through an GpuBackbuffer without transferrin...
override void OnInitialized()
override async Task OnAfterRenderAsync(bool firstRender)
RenderSurfaceHost< GpuBackbuffer > Host
Gets the GPU render-surface host bound to this component.
BlazorGpuRenderSurfaceAdapter Adapter
Gets the adapter that coordinates engine frame requests with this component.
override void OnParametersSet()
Provides the shared DOM input surface used by Gondwana's Blazor bitmap and GPU render components.
IReadOnlyDictionary< string, object >? CanvasAttributes
Gets the canvas attributes with the component-owned style attribute removed.
Gives Razor a local component name for SkiaSharp's WebGL view. This avoids Razor resolving SkiaSharp ...
Represents the core game engine singleton responsible for managing the main update loop,...
void Tick()
Advances the timer-driven engine by one externally presented frame.
static Engine Instance
Gets the singleton instance of the Engine.
Provides a fully GPU-rendered backbuffer implementation using SkiaSharp and OpenGL.
Represents the abstract base class for render surface adapters that present backbuffer output to a de...
override BackbufferBase Backbuffer
Gets the backbuffer used for off-screen rendering before presentation to the adapter.
Diagnostics.? TelemetrySource Telemetry
Neutral session-local measurements for this host; null when source capacity is exhausted or the share...
bool GlDrawCurrentFrameToCanvas(SKCanvas destinationCanvas)
Draws the existing GPU backbuffer surface directly to another GPU canvas without rendering a new scen...
bool GlRenderToCanvas(SKCanvas destinationCanvas)
Renders the current scene frame and draws the GPU backbuffer surface directly to another GPU canvas....