ForeignTextureLayer class Core
A grid cell showing a texture SOMEBODY ELSE rendered: "bring your own renderer". The producer implements IGpuTextureSource and keeps its own rendering code; this layer puts the result in the cell, with Skia's text, clipping and scrolling over it like any other cell.
public sealed class ForeignTextureLayer : IGpuLayer, IGpuResource, IDisposable
- Namespace
- ArionUI.Rendering.Skia
- Package
- ArionUI.Rendering.Skia ·
dotnet add package ArionUI.Rendering.Skia --prerelease - Implements
- IGpuLayer, IGpuResource, IDisposable
Remarks
No copy in the picture path. A Direct3D texture is bound to a GL texture of this context (EGL_ANGLE_d3d_texture_client_buffer), and a GL texture from a shared context is used as it is. Either way the pixels stay where the producer wrote them; what this layer draws is one textured quad over them. The binding is kept across frames while the producer hands over the SAME texture, so a producer that keeps drawing into its texture needs no further handover - and writes that happen after the binding are simply there in the next frame, which is what ForeignTextureIdentityTests measures.
Aspect ratio. The texture is fitted into the cell, centred, without stretching: a producer that renders 1:1 while the cell is wide gets bars rather than a distorted picture, and the bars are the cell's cleared background.
Failure is a hint line, never a crash. A source that says no, a texture on the wrong device, a host whose context is not ANGLE: the layer draws nothing, reports the reason in ForeignTextureLayer.Failure, and the cell falls back to the text its template carries for "no GPU".
Constructors
ForeignTextureLayer
public ForeignTextureLayer(IGpuTextureSource source);Shows what source renders, in one grid cell.
Properties
Binds
public int Binds { get; }How many times a texture was bound - 1 per producer texture in a healthy run. A number that grows with the frame count means the producer hands over a different texture every frame, and each of those costs a bind.
Failure
public string? Failure { get; }Why the last frame showed nothing, or null after a frame that showed the foreign texture.
IsLive
public bool IsLive { get; }True while the layer changes from frame to frame (animation, streaming).
The scroll blit keeps a persistent buffer and only repaints uncovered bands, so a cell that changes on its own must say so: the template then invalidates its row every frame tick through the ordinary redraw path. Without that, scrolling shifts a FROZEN picture of the cell along.
RendererName
public string? RendererName { get; }GL_RENDERER of the context this layer last drew on, or null before its first frame (and for a layer that does not care to report it).
On the contract rather than on the concrete layer, because the overlay text of a chart cell wants the GPU name and must not have to know WHICH layer it is holding: a type test there would have to grow a case per layer type.
Samples
public int Samples { get; }Multisample count for this layer's offscreen target: 0 = off, 4 = the usual choice. A default member, so a layer that does not care says nothing.
Remarks
The foreign picture is already rendered; multisampling our quad would only blur its edge pixels.
Methods
Dispose
public void Dispose();Releases the binding and this layer's own GL objects. On the render thread.
Invalidate
public void Invalidate();Forget every handle WITHOUT calling GL: after device loss the objects are already gone, and deleting them would talk to a dead context.
Rebuild
public void Rebuild();Recreate everything from the resource's own description. Must be safe to call when nothing was invalidated (then it is a no-op) and after IGpuResource.Invalidate.
Render
public void Render(GlApi gl, in GpuLayerFrame frame);Draws into the bound offscreen target. Called on the RENDER thread, inside a GlScope.
