5

An extension of this question. I'm using SkiaSharp to draw shapes with OpenGL. Most of code samples for WPF suggest using SKElement control and get reference to the drawing surface inside PaintSurface event. I need reference to drawing surface al the time, not only inside of this event, so I'm using SKBitmap and SKCanvas and send the output to Image control in WPF.

XAML

<Canvas x:Name="ScreenControl" />

CS

var bmp = new SKBitmap((int)ScreenControl.ActualWidth, (int)ScreenControl.ActualHeight);
var canvas = new SKCanvas(bmp);
var image = new Image
{
  Stretch = Stretch.Fill
};

canvas.DrawText("Demo", new SKPoint(20, 20), new SKPaint { TextSize = 20 });

var index = 0;
var clock = new Timer();
var wrt = bmp.ToWriteableBitmap();

image.Source = wrt;

clock.Interval = 100;
clock.Elapsed += (object sender, ElapsedEventArgs e) =>
{
  Application.Current.Dispatcher.BeginInvoke(new Action(() =>
  {
    var wrt = bmp.ToWriteableBitmap(); // Potentially slow line #1

    canvas.Clear();
    canvas.DrawText((index++).ToString(), new SKPoint(20, 20), new SKPaint { TextSize = 20 });
    image.Source = wrt;                // Potentially slow line #2
    image.InvalidateVisual();
  }));
};
clock.Start();

ScreenControl.Children.Clear();
ScreenControl.Children.Add(image);

Project

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net5.0-windows</TargetFramework>
    <UseWPF>true</UseWPF>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="SkiaSharp.Views.WPF" Version="2.80.3-preview.18" />
  </ItemGroup>

</Project>

Question

Is there a way to draw faster, specifically, without recreating bitmap bmp.ToWriteableBitmap() and without changing image source every time image.Source = wrt? Back buffer or something related?

1 Answers1

0

You have to use Skia's SKElement:

<Grid>
    <skia:SKElement PaintSurface="OnPaintSurface" IgnorePixelScaling="True" />
</Grid>

And draw in OnPaintSurface:

    private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e)
    {
        // the the canvas and properties
        var canvas = e.Surface.Canvas;

        // make sure the canvas is blank
        canvas.Clear(SKColors.White);

        // draw some text
        var paint = new SKPaint
        {
            Color = SKColors.Black,
            IsAntialias = true,
            Style = SKPaintStyle.Fill,
            TextAlign = SKTextAlign.Center,
            TextSize = 24
        };
        var coord = new SKPoint(e.Info.Width / 2, (e.Info.Height + paint.TextSize) / 2);
        canvas.DrawText("SkiaSharp", coord, paint);
    }