Browse Source
To enable the raster backend set CustomGpuFactory to null in the existing SkiaOptions, by default Avalonia will use the GPU/GL Skia backend.pull/8417/head
6 changed files with 149 additions and 18 deletions
@ -0,0 +1,91 @@ |
|||||
|
using System.Runtime.InteropServices; |
||||
|
using Avalonia.Controls.Platform.Surfaces; |
||||
|
using Avalonia.Platform; |
||||
|
using Avalonia.Skia; |
||||
|
using SkiaSharp; |
||||
|
|
||||
|
namespace Avalonia.Web.Blazor |
||||
|
{ |
||||
|
internal class BlazorSkiaRasterSurface : IBlazorSkiaSurface, IFramebufferPlatformSurface, IDisposable |
||||
|
{ |
||||
|
public SKColorType ColorType { get; set; } |
||||
|
|
||||
|
public PixelSize Size { get; set; } |
||||
|
|
||||
|
public double Scaling { get; set; } |
||||
|
|
||||
|
private FramebufferData? _fbData; |
||||
|
private readonly Action<IntPtr, SKSizeI> _blitCallback; |
||||
|
private readonly Action _onDisposeAction; |
||||
|
|
||||
|
public BlazorSkiaRasterSurface( |
||||
|
SKColorType colorType, PixelSize size, double scaling, Action<IntPtr, SKSizeI> blitCallback) |
||||
|
{ |
||||
|
ColorType = colorType; |
||||
|
Size = size; |
||||
|
Scaling = scaling; |
||||
|
_blitCallback = blitCallback; |
||||
|
_onDisposeAction = Blit; |
||||
|
} |
||||
|
|
||||
|
public void Dispose() |
||||
|
{ |
||||
|
_fbData?.Dispose(); |
||||
|
_fbData = null; |
||||
|
} |
||||
|
|
||||
|
public ILockedFramebuffer Lock() |
||||
|
{ |
||||
|
var bytesPerPixel = 4; // TODO: derive from ColorType
|
||||
|
var dpi = Scaling * 96.0; |
||||
|
var width = (int)(Size.Width * Scaling); |
||||
|
var height = (int)(Size.Height * Scaling); |
||||
|
|
||||
|
if (_fbData is null || _fbData?.Size.Width != width || _fbData?.Size.Height != height) |
||||
|
{ |
||||
|
_fbData?.Dispose(); |
||||
|
_fbData = new FramebufferData(width, height, bytesPerPixel); |
||||
|
} |
||||
|
|
||||
|
var pixelFormat = ColorType.ToPixelFormat(); |
||||
|
var data = _fbData.Value; |
||||
|
return new LockedFramebuffer( |
||||
|
data.Address, data.Size, data.RowBytes, |
||||
|
new Vector(dpi, dpi), pixelFormat, _onDisposeAction); |
||||
|
} |
||||
|
|
||||
|
private void Blit() |
||||
|
{ |
||||
|
if (_fbData != null) |
||||
|
{ |
||||
|
var data = _fbData.Value; |
||||
|
_blitCallback(data.Address, new SKSizeI(data.Size.Width, data.Size.Height)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private readonly struct FramebufferData |
||||
|
{ |
||||
|
private readonly byte[]? _data; |
||||
|
private readonly GCHandle _dataHandle; |
||||
|
|
||||
|
public PixelSize Size { get; } |
||||
|
|
||||
|
public int RowBytes { get; } |
||||
|
|
||||
|
public IntPtr Address => _dataHandle.AddrOfPinnedObject(); |
||||
|
|
||||
|
public FramebufferData(int width, int height, int bytesPerPixel) |
||||
|
{ |
||||
|
Size = new PixelSize(width, height); |
||||
|
RowBytes = width * bytesPerPixel; |
||||
|
_data = new byte[width * height * bytesPerPixel]; |
||||
|
_dataHandle = GCHandle.Alloc(_data, GCHandleType.Pinned); |
||||
|
} |
||||
|
|
||||
|
public void Dispose() |
||||
|
{ |
||||
|
_dataHandle.Free(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
namespace Avalonia.Web.Blazor |
||||
|
{ |
||||
|
internal interface IBlazorSkiaSurface |
||||
|
{ |
||||
|
public PixelSize Size { get; set; } |
||||
|
|
||||
|
public double Scaling { get; set; } |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue