csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
3.6 KiB
105 lines
3.6 KiB
using System;
|
|
using Avalonia.Skia.Helpers;
|
|
using Avalonia.Vulkan;
|
|
using SkiaSharp;
|
|
|
|
namespace Avalonia.Skia.Vulkan;
|
|
|
|
class VulkanSkiaRenderTarget : ISkiaGpuRenderTarget
|
|
{
|
|
private readonly VulkanSkiaGpu _gpu;
|
|
private readonly IVulkanRenderTarget _target;
|
|
|
|
public VulkanSkiaRenderTarget(VulkanSkiaGpu gpu, IVulkanRenderTarget target)
|
|
{
|
|
_gpu = gpu;
|
|
_target = target;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_target.Dispose();
|
|
}
|
|
|
|
public ISkiaGpuRenderSession BeginRenderingSession()
|
|
{
|
|
var session = _target.BeginDraw();
|
|
bool success = false;
|
|
try
|
|
{
|
|
var size = session.Size;
|
|
var scaling = session.Scaling;
|
|
if (size.Width <= 0 || size.Height <= 0 || scaling < 0)
|
|
{
|
|
session.Dispose();
|
|
throw new InvalidOperationException(
|
|
$"Can't create drawing context for surface with {size} size and {scaling} scaling");
|
|
}
|
|
_gpu.GrContext.ResetContext();
|
|
var sessionImageInfo = session.ImageInfo;
|
|
var imageInfo = new GRVkImageInfo
|
|
{
|
|
CurrentQueueFamily = _gpu.Vulkan.Device.GraphicsQueueFamilyIndex,
|
|
Format = sessionImageInfo.Format,
|
|
Image = (ulong)sessionImageInfo.Handle,
|
|
ImageLayout = sessionImageInfo.Layout,
|
|
ImageTiling = sessionImageInfo.Tiling,
|
|
ImageUsageFlags = sessionImageInfo.UsageFlags,
|
|
LevelCount = sessionImageInfo.LevelCount,
|
|
SampleCount = sessionImageInfo.SampleCount,
|
|
Protected = sessionImageInfo.IsProtected,
|
|
Alloc = new GRVkAlloc
|
|
{
|
|
Memory = (ulong)sessionImageInfo.MemoryHandle,
|
|
Size = sessionImageInfo.MemorySize
|
|
}
|
|
};
|
|
using var renderTarget = new GRBackendRenderTarget(size.Width, size.Height, 1, imageInfo);
|
|
var surface = SKSurface.Create(_gpu.GrContext, renderTarget,
|
|
session.IsYFlipped ? GRSurfaceOrigin.TopLeft : GRSurfaceOrigin.BottomLeft,
|
|
session.IsRgba ? SKColorType.Rgba8888 : SKColorType.Bgra8888, SKColorSpace.CreateSrgb());
|
|
|
|
if (surface == null)
|
|
throw new InvalidOperationException(
|
|
$"Surface can't be created with the provided render target");
|
|
success = true;
|
|
return new VulkanSkiaRenderSession(_gpu.GrContext, surface, session);
|
|
}
|
|
finally
|
|
{
|
|
if(!success)
|
|
session.Dispose();
|
|
}
|
|
}
|
|
|
|
public bool IsCorrupted => false;
|
|
|
|
|
|
internal class VulkanSkiaRenderSession : ISkiaGpuRenderSession
|
|
{
|
|
private readonly IVulkanRenderSession _vulkanSession;
|
|
|
|
public VulkanSkiaRenderSession(GRContext grContext,
|
|
SKSurface surface,
|
|
IVulkanRenderSession vulkanSession)
|
|
{
|
|
GrContext = grContext;
|
|
SkSurface = surface;
|
|
_vulkanSession = vulkanSession;
|
|
SurfaceOrigin = vulkanSession.IsYFlipped ? GRSurfaceOrigin.TopLeft : GRSurfaceOrigin.BottomLeft;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
SkSurface.Canvas.Flush();
|
|
SkSurface.Dispose();
|
|
GrContext.Flush();
|
|
_vulkanSession.Dispose();
|
|
}
|
|
|
|
public GRContext GrContext { get; }
|
|
public SKSurface SkSurface { get; }
|
|
public double ScaleFactor => _vulkanSession.Scaling;
|
|
public GRSurfaceOrigin SurfaceOrigin { get; }
|
|
}
|
|
}
|
|
|