Skiasharp: Screen updates are not stable

Created on 20 Aug 2018  路  5Comments  路  Source: mono/SkiaSharp

Description

Screen updates are not stable

https://youtu.be/5rGbVSVFMZk

I am developing Android applications using SkiaSharp and SkiaSharp.Views.Forms (using Xamarin.Forms).
I am suffering because this application is not stable frame rate.

I am programming to update the screen at 60 FPS, but the update is not stable.

I wonder why
For some reason the screen update is done at 60 FPS only during the touch, and if there is no touch it will be a slow screen update.

There is no touch related setting in the code.

What kind of place do I have to check to update the screen at 60 FPS?

Code

Buildable solution:
https://www.dropbox.com/s/aquap1xwfxinz3j/SkiaSharpFrameratesProblem.zip?dl=0

<ContentPage x:Class="App5.MainPage"
             xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:forms="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms">
    <forms:SKCanvasView x:Name="Canvas"/>
</ContentPage>
public partial class MainPage
{
    public MainPage()
    {
        InitializeComponent();
    }

    protected override void OnAppearing()
    {
        base.OnAppearing();

        var stopwatch = Stopwatch.StartNew();
        var tp = new SKPaint
        {
            Style = SKPaintStyle.Fill,
            Color = SKColors.DarkBlue,
            IsAntialias = true,
            TextSize = 70.0f,
        };

        var timer = new Timer(1000.0 / 60.0);
        timer.Elapsed += (_, __) => Device.BeginInvokeOnMainThread(Canvas.InvalidateSurface);
        timer.Start();

        var x = 0;

        Canvas.PaintSurface += (_, e) =>
        {
            var interval = stopwatch.ElapsedMilliseconds;
            stopwatch.Restart();

            e.Surface.Canvas.Clear(SKColors.LightGray);

            e.Surface.Canvas.DrawText($"Interval:{interval}", new SKPoint(150, 150), tp);

            if ((++x) >= 120)
                x = 0;

            e.Surface.Canvas.DrawText("$", new SKPoint(150 + x * 4, 300), tp);
        };
    }
}

Basic Information

Android: OnePlus6(Oreo 8.1)
SkiaSharp: 1.60.3
Xamarin.Forms: 3.1.0.697

area-SkiaSharp.Views os-Android type-bug

Most helpful comment

This is very interesting... I had a look and as long as you don't touch the screen, you get about 45 fps just fine - this is less that 60 fps because maybe of something we are doing that can be improved. But that is not the issue here.

As soon as I touch the screen, the frames drop to about 30 fps and hover around there. Then, when I drag my finger across the screen, the fps go up to 45 again.

This happens with the plain Android view, so appears to have nothing to do with Xamarin.Forms or the Forms view directly.

I will investigate this and see what I find.

All 5 comments

Commenting to mention that fixing the issue here: https://github.com/mono/SkiaSharp/issues/552

Could possibly fixup this problem.

Thank you for the information.
I am looking forward to being fixup.

Please let me know if you know the reason.

This case is FPS 60 only while touching.
What is the reason why the frame rate is low if I do not touch it?

I feel wondering why the frame rate will be high during touch.

This is very interesting... I had a look and as long as you don't touch the screen, you get about 45 fps just fine - this is less that 60 fps because maybe of something we are doing that can be improved. But that is not the issue here.

As soon as I touch the screen, the frames drop to about 30 fps and hover around there. Then, when I drag my finger across the screen, the fps go up to 45 again.

This happens with the plain Android view, so appears to have nothing to do with Xamarin.Forms or the Forms view directly.

I will investigate this and see what I find.

Hey @mattleibow have you been able to find any solutions to this yet? I am running into the same problem with Xamarin.Forms when deployed on a real android device. The issue doesn't seem to be present when on an emulator.

I am using:
-Xamarin.Forms version 3.3.0.893527-pre3
-VS Pro 17
-SkiaSharp.Views.Forms 1.60.3
-Samsung Galaxy S4, 5.0 - API 21 (real device)
-Nexus 5X, Oreo 8.1 - API 27 (emulator)

Thanks!

You better use SKGLView if you want real time or independent updates on the view. Because Timer updates inaccurate and therefore View invalidations may happen with noticeable delays, and thus new visual updates hardly depend on how soon the last update happened. And in the end your 1000.0 / 60.0 interval will not give you expected results.
Also counting frame interval is a bit wrong though works in this case. It is usually done like this

time = stopwatch. ElapsedMilliseconds;
interval = time - lastTime;
lastTime = time;

Also animations should never be depended on frame delay. They have to be interpolated between known start time and end time. And here it helps to store current time to count start time and end time and interpolate in between them.
Edit: forgot to mention that not every screen on phones is 60 hrz (most of them are of course), so on some screens animations may look smooth, on the others - pretty jittering. So it's always better to interpolate and never depend on hardcoded frame update.

Was this page helpful?
0 / 5 - 0 ratings