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