Bug 166057 - [GTK] RequestAnimationFrame ticks at 66 FPS instead of 60 FPS
Summary: [GTK] RequestAnimationFrame ticks at 66 FPS instead of 60 FPS
Status: NEW
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebKitGTK (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL: https://people.igalia.com/clopez/wkbu...
Keywords:
Depends on:
Blocks:
 
Reported: 2016-12-20 05:42 PST by Carlos Alberto Lopez Perez
Modified: 2017-01-04 09:59 PST (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Carlos Alberto Lopez Perez 2016-12-20 05:42:37 PST
WebKitGTK+ is reporting 66 FPS in this test, meanwhile all the other browsers report 60FPS.

https://people.igalia.com/clopez/wkbug/fps-counter/raf.html
Comment 1 Carlos Alberto Lopez Perez 2016-12-20 06:24:40 PST
It seems the rAF timer in WebCore defaults to ~66FPS (15 ms) after r94908. See rationale: https://bugs.webkit.org/show_bug.cgi?id=67171#c12

But the Mac/iOS port implements REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR ( see bug 68911 ) which allows to sync and throttle the rAF timer according to the display refresh rate.
Comment 2 Zan Dobersek 2016-12-28 08:50:28 PST
I looked into using DisplayRefreshMonitor for the GTK port, specifically in the ThreadedCompositor. The problem is that when using GLX, there's no facility available that could send a notification about the vsync event from the UIProcess down to the WebProcess. With Wayland there's frame callbacks.
Comment 3 Carlos Alberto Lopez Perez 2017-01-04 07:23:45 PST
(In reply to comment #2)
> I looked into using DisplayRefreshMonitor for the GTK port, specifically in
> the ThreadedCompositor. The problem is that when using GLX, there's no
> facility available that could send a notification about the vsync event from
> the UIProcess down to the WebProcess. With Wayland there's frame callbacks.

Some people suggest to use a separate thread doing glXSwapBuffers(); glFinish(); all the time after setting glXSwapIntervalEXT(1) (which should cause the glXSwapBuffers call to be synced with vsync) and then notify the main thread about the vsync events.

But I doubt this will be a good idea from a performance-related point of view.
Comment 4 Zan Dobersek 2017-01-04 07:55:09 PST
(In reply to comment #3)
> (In reply to comment #2)
> > I looked into using DisplayRefreshMonitor for the GTK port, specifically in
> > the ThreadedCompositor. The problem is that when using GLX, there's no
> > facility available that could send a notification about the vsync event from
> > the UIProcess down to the WebProcess. With Wayland there's frame callbacks.
> 
> Some people suggest to use a separate thread doing glXSwapBuffers();
> glFinish(); all the time after setting glXSwapIntervalEXT(1) (which should
> cause the glXSwapBuffers call to be synced with vsync) and then notify the
> main thread about the vsync events.
> 
> But I doubt this will be a good idea from a performance-related point of
> view.

I don't know the specifics of those suggestions, but it's maybe similar to what we do with the threaded compositor? GL operations are done on a separate thread, and this DisplayRefreshMonitor would be dispatching the event on the main thread so that it can be signalled to the Web content as well.
Comment 5 Carlos Alberto Lopez Perez 2017-01-04 09:13:29 PST
(In reply to comment #4)
> (In reply to comment #3)
> > (In reply to comment #2)
> > > I looked into using DisplayRefreshMonitor for the GTK port, specifically in
> > > the ThreadedCompositor. The problem is that when using GLX, there's no
> > > facility available that could send a notification about the vsync event from
> > > the UIProcess down to the WebProcess. With Wayland there's frame callbacks.
> > 
> > Some people suggest to use a separate thread doing glXSwapBuffers();
> > glFinish(); all the time after setting glXSwapIntervalEXT(1) (which should
> > cause the glXSwapBuffers call to be synced with vsync) and then notify the
> > main thread about the vsync events.
> > 
> > But I doubt this will be a good idea from a performance-related point of
> > view.
> 
> I don't know the specifics of those suggestions, but it's maybe similar to
> what we do with the threaded compositor? GL operations are done on a
> separate thread, and this DisplayRefreshMonitor would be dispatching the
> event on the main thread so that it can be signalled to the Web content as
> well.

I got that info from this thread: http://stackoverflow.com/q/36888288

In our use case (with the threaded compositor) I think that we don't call glXSwapBuffers() all the time, but only when we have new content to show.

But a DisplayRefreshMonitor should send an event notification every time a vsync happens on the monitor (even if we don't have nothing new to show on the screen).

So, perhaps a way to achieve that in X11 is a dummy thread doing all the time dummy glXSwapBuffers();glFinish(); calls, with the hope that this calls will be throttled to the display refresh rate.
Comment 6 Zan Dobersek 2017-01-04 09:29:39 PST
(In reply to comment #5)
> (In reply to comment #4)
> > (In reply to comment #3)
> > > (In reply to comment #2)
> > > > I looked into using DisplayRefreshMonitor for the GTK port, specifically in
> > > > the ThreadedCompositor. The problem is that when using GLX, there's no
> > > > facility available that could send a notification about the vsync event from
> > > > the UIProcess down to the WebProcess. With Wayland there's frame callbacks.
> > > 
> > > Some people suggest to use a separate thread doing glXSwapBuffers();
> > > glFinish(); all the time after setting glXSwapIntervalEXT(1) (which should
> > > cause the glXSwapBuffers call to be synced with vsync) and then notify the
> > > main thread about the vsync events.
> > > 
> > > But I doubt this will be a good idea from a performance-related point of
> > > view.
> > 
> > I don't know the specifics of those suggestions, but it's maybe similar to
> > what we do with the threaded compositor? GL operations are done on a
> > separate thread, and this DisplayRefreshMonitor would be dispatching the
> > event on the main thread so that it can be signalled to the Web content as
> > well.
> 
> I got that info from this thread: http://stackoverflow.com/q/36888288
> 
> In our use case (with the threaded compositor) I think that we don't call
> glXSwapBuffers() all the time, but only when we have new content to show.
> 

When there's nothing to update, we don't.

> But a DisplayRefreshMonitor should send an event notification every time a
> vsync happens on the monitor (even if we don't have nothing new to show on
> the screen).
> 

Why? I see no reason for that.

> So, perhaps a way to achieve that in X11 is a dummy thread doing all the
> time dummy glXSwapBuffers();glFinish(); calls, with the hope that this calls
> will be throttled to the display refresh rate.

Then you need a whole additional context just for that thread.
Comment 7 Carlos Alberto Lopez Perez 2017-01-04 09:59:58 PST
(In reply to comment #6)
> (In reply to comment #5)
> > (In reply to comment #4)
> > > (In reply to comment #3)
> > > > (In reply to comment #2)
> > > > > I looked into using DisplayRefreshMonitor for the GTK port, specifically in
> > > > > the ThreadedCompositor. The problem is that when using GLX, there's no
> > > > > facility available that could send a notification about the vsync event from
> > > > > the UIProcess down to the WebProcess. With Wayland there's frame callbacks.
> > > > 
> > > > Some people suggest to use a separate thread doing glXSwapBuffers();
> > > > glFinish(); all the time after setting glXSwapIntervalEXT(1) (which should
> > > > cause the glXSwapBuffers call to be synced with vsync) and then notify the
> > > > main thread about the vsync events.
> > > > 
> > > > But I doubt this will be a good idea from a performance-related point of
> > > > view.
> > > 
> > > I don't know the specifics of those suggestions, but it's maybe similar to
> > > what we do with the threaded compositor? GL operations are done on a
> > > separate thread, and this DisplayRefreshMonitor would be dispatching the
> > > event on the main thread so that it can be signalled to the Web content as
> > > well.
> > 
> > I got that info from this thread: http://stackoverflow.com/q/36888288
> > 
> > In our use case (with the threaded compositor) I think that we don't call
> > glXSwapBuffers() all the time, but only when we have new content to show.
> > 
> 
> When there's nothing to update, we don't.
> 
> > But a DisplayRefreshMonitor should send an event notification every time a
> > vsync happens on the monitor (even if we don't have nothing new to show on
> > the screen).
> > 
> 
> Why? I see no reason for that.


I was not taking into account that what the page schedules during a rAF callback should trigger new content to be shown, hence a new call to glxswapbuffers().

So, maybe it works.

However, I'm a bit wary that this may break some webpage that (incorrectly) expects rAF to trigger at 60FPS always, and uses this callback to schedule calculations that don't necessarily trigger an update of the webview (like the fps-counter example i posted at the top.. it only updates the page every second and not on every rAF callback... with this idea i would be measuring 1-2FPS)

Chrome seems to tick always at 60FPS (and also firefox). They throttle the rAF timer when the webview is not focused.

> 
> > So, perhaps a way to achieve that in X11 is a dummy thread doing all the
> > time dummy glXSwapBuffers();glFinish(); calls, with the hope that this calls
> > will be throttled to the display refresh rate.
> 
> Then you need a whole additional context just for that thread.

Yes.