Skip to content

Commit 07c74ad

Browse files
Make NativeSurface abstract, simplify, and add WebGPU surface
1 parent b5c6458 commit 07c74ad

5 files changed

Lines changed: 52 additions & 39 deletions

File tree

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright (c) Six Labors.
2+
// Licensed under the Six Labors Split License.
3+
4+
using System.Diagnostics.CodeAnalysis;
5+
6+
namespace SixLabors.ImageSharp.Drawing.Processing.Backends;
7+
8+
/// <summary>
9+
/// WebGPU native drawing target exposed through the backend-agnostic <see cref="NativeSurface"/> contract.
10+
/// </summary>
11+
internal sealed class WebGPUNativeSurface : NativeSurface
12+
{
13+
private readonly WebGPUSurfaceCapability capability;
14+
15+
/// <summary>
16+
/// Initializes a new instance of the <see cref="WebGPUNativeSurface"/> class.
17+
/// </summary>
18+
/// <param name="capability">The WebGPU capability exposed by this surface.</param>
19+
internal WebGPUNativeSurface(WebGPUSurfaceCapability capability)
20+
=> this.capability = capability;
21+
22+
/// <inheritdoc />
23+
public override bool TryGetCapability<TCapability>([NotNullWhen(true)] out TCapability? capability)
24+
where TCapability : class
25+
{
26+
if (this.capability is TCapability typed)
27+
{
28+
capability = typed;
29+
return true;
30+
}
31+
32+
capability = null;
33+
return false;
34+
}
35+
}

src/ImageSharp.Drawing.WebGPU/WebGPUNativeSurfaceFactory.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,14 @@ internal static NativeSurface Create<TPixel>(
6969
Guard.MustBeGreaterThan(height, 0, nameof(height));
7070
ValidatePixelCompatibility<TPixel>(targetFormat);
7171

72-
NativeSurface nativeSurface = new(TPixel.GetPixelTypeInfo());
73-
nativeSurface.SetCapability(new WebGPUSurfaceCapability(
72+
return new WebGPUNativeSurface(new WebGPUSurfaceCapability(
7473
deviceHandle,
7574
queueHandle,
7675
targetTextureHandle,
7776
targetTextureViewHandle,
7877
targetFormat,
7978
width,
8079
height));
81-
return nativeSurface;
8280
}
8381

8482
/// <summary>

src/ImageSharp.Drawing.WebGPU/WebGPUSurfaceCapability.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
namespace SixLabors.ImageSharp.Drawing.Processing.Backends;
55

66
/// <summary>
7-
/// Native WebGPU surface capability attached to <see cref="NativeSurface"/>.
7+
/// Native WebGPU surface capability exposed by a <see cref="NativeSurface"/>.
88
/// </summary>
99
/// <remarks>
1010
/// The backing WebGPU device, queue, texture, and texture view must remain valid while canvases target this surface.
Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,20 @@
11
// Copyright (c) Six Labors.
22
// Licensed under the Six Labors Split License.
33

4-
using System.Collections.Concurrent;
54
using System.Diagnostics.CodeAnalysis;
65

76
namespace SixLabors.ImageSharp.Drawing.Processing.Backends;
87

98
/// <summary>
109
/// Represents a backend-specific native drawing target.
1110
/// </summary>
12-
public sealed class NativeSurface
11+
public abstract class NativeSurface
1312
{
14-
private readonly ConcurrentDictionary<Type, object> capabilities = new();
15-
1613
/// <summary>
1714
/// Initializes a new instance of the <see cref="NativeSurface"/> class.
1815
/// </summary>
19-
/// <param name="pixelType">Pixel format information for the destination surface.</param>
20-
public NativeSurface(PixelTypeInfo pixelType)
21-
=> this.PixelType = pixelType;
22-
23-
/// <summary>
24-
/// Gets pixel format information for this destination surface.
25-
/// </summary>
26-
public PixelTypeInfo PixelType { get; }
27-
28-
/// <summary>
29-
/// Associates a backend capability with this surface.
30-
/// </summary>
31-
/// <typeparam name="TCapability">Capability type.</typeparam>
32-
/// <param name="capability">Capability instance.</param>
33-
public void SetCapability<TCapability>(TCapability capability)
34-
where TCapability : class
16+
protected NativeSurface()
3517
{
36-
Guard.NotNull(capability, nameof(capability));
37-
this.capabilities[typeof(TCapability)] = capability;
3818
}
3919

4020
/// <summary>
@@ -43,16 +23,6 @@ public void SetCapability<TCapability>(TCapability capability)
4323
/// <typeparam name="TCapability">Capability type.</typeparam>
4424
/// <param name="capability">Capability instance when available.</param>
4525
/// <returns><see langword="true"/> when found.</returns>
46-
public bool TryGetCapability<TCapability>([NotNullWhen(true)] out TCapability? capability)
47-
where TCapability : class
48-
{
49-
if (this.capabilities.TryGetValue(typeof(TCapability), out object? value) && value is TCapability typed)
50-
{
51-
capability = typed;
52-
return true;
53-
}
54-
55-
capability = null;
56-
return false;
57-
}
26+
public abstract bool TryGetCapability<TCapability>([NotNullWhen(true)] out TCapability? capability)
27+
where TCapability : class;
5828
}

tests/ImageSharp.Drawing.Tests/Processing/DrawingCanvasTests.Process.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public void Process_NoCpuFrame_WithReadbackCapability_MatchesReference<TPixel>(T
7474
MemoryCanvasFrame<TPixel> proxyFrame = new(new Buffer2DRegion<TPixel>(target.Frames.RootFrame.PixelBuffer));
7575
MirroringCpuReadbackTestBackend<TPixel> mirroringBackend = new(proxyFrame, target);
7676

77-
NativeSurface nativeSurface = new(TPixel.GetPixelTypeInfo());
77+
NativeSurface nativeSurface = new NoCapabilityNativeSurface();
7878
Configuration configuration = provider.Configuration.Clone();
7979
configuration.SetDrawingBackend(mirroringBackend);
8080

@@ -158,6 +158,16 @@ private static IPath CreatePixelateTrianglePath()
158158
return pathBuilder.Build();
159159
}
160160

161+
private sealed class NoCapabilityNativeSurface : NativeSurface
162+
{
163+
public override bool TryGetCapability<TCapability>(out TCapability capability)
164+
where TCapability : class
165+
{
166+
capability = null!;
167+
return false;
168+
}
169+
}
170+
161171
/// <summary>
162172
/// Test backend that mirrors composition output into a CPU frame and optionally serves readback
163173
/// from a backing image for process-path tests.

0 commit comments

Comments
 (0)