Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom Avalonia controll to render from other thread performance problem

I have a background thread, which renders some image to WriteableBitmap. I'm making a custom control, which will use this writeablebitmap and update every frame to make animation. Unfortunately, now forcing this control to InvalidateVisual(). That worked, but the performance is pretty bad. On the main window I subscribed to Renderer.SceneInvalidated to log some framerates.

this.Renderer.SceneInvalidated += (s, e) =>
{
    _logs.Add((DateTime.Now - _prev).Ticks);

    _prev = DateTime.Now;
};

And found that about 7%-10% frames are rendered in 30ms, and others 90% in 16ms. So I'm looking for a better performance solution with this problem.

like image 549
Kamiky Avatar asked Feb 17 '26 00:02

Kamiky


1 Answers

You can utilize custom drawing operation API with direct access to SKCanvas on the render thread.

public class CustomSkiaPage : Control
{   
  public CustomSkiaPage()
  { 
    ClipToBounds = true;
  } 
        
  class CustomDrawOp : ICustomDrawOperation
  { 
    public CustomDrawOp(Rect bounds)
    {   
      Bounds = bounds;
    }   
            
    public void Dispose()
    {   
      // No-op in this example
    }   

    public Rect Bounds { get; }
    public bool HitTest(Point p) => false;
    public bool Equals(ICustomDrawOperation other) => false;
    public void Render(IDrawingContextImpl context)
    {   
      var canvas = (context as ISkiaDrawingContextImpl)?.SkCanvas;
      // draw stuff 
    }   
  } 

  public override void Render(DrawingContext context)
  { 
    context.Custom(new CustomDrawOp(new Rect(0, 0, Bounds.Width, Bounds.Height)));
    Dispatcher.UIThread.InvokeAsync(InvalidateVisual, DispatcherPriority.Background);
  } 
}
like image 73
kekekeks Avatar answered Feb 18 '26 12:02

kekekeks



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!