[Wayland][WebRender] Browser unresponsive when not all windows are displayed (minimized/different workspace)
Categories
(Core :: Graphics, defect, P3)
Tracking
()
People
(Reporter: yorickvanpelt, Unassigned)
References
(Blocks 2 open bugs)
Details
Attachments
(1 file)
Comment 1•7 years ago
|
||
| Reporter | ||
Comment 2•7 years ago
|
||
When using EGL on Wayland, clients need to set eglSwapInterval(0), otherwise they'll block when hidden. More info:
Comment 4•7 years ago
|
||
For egl to work with FF mobile still, set only set if MOZ_WAYLAND is enabled. I think https://paste.pound-python.org/show/T2j6FhtHY2HzXDM18LAb/ is right, we'll see if it even builds.
Comment 5•7 years ago
|
||
So it seems like (from the link in Comment 3) that Wayland does a crazy thing, and repurposes SwapInterval(1) as RAF?
From 1, it sounds like SwapInterval(0) won't tear, but just also won't block, but will allow us to no longer block if we SwapBuffers on a hidden window.
:stransky/:sotaro, am I reading this right and we should SwapInterval(0) on Wayland, because we render multiple windows from one thread?
Updated•7 years ago
|
Comment 6•7 years ago
|
||
https://paste.pound-python.org/show/uxrjeAHgEUjAqHArrerA/ is my updated patch (building now)
Just calling eglSwapInterval(0) won't be enough, you'll also need to register frame callbacks and redraw when you receive one.
Comment 8•7 years ago
|
||
Also, #if defined(MOZ_WAYLAND) is not enough, there should be a dynamic check I think
Comment 9•7 years ago
|
||
(In reply to Jeff Gilbert [:jgilbert] from comment #5)
:stransky/:sotaro, am I reading this right and we should SwapInterval(0) on Wayland, because we render multiple windows from one thread?
Yea, we should avoid blocking on eglSwapBuffers(). But when I just added calling SwapInterval(0), the block still happened.
Comment 10•7 years ago
|
||
(In reply to Sotaro Ikeda [:sotaro] from comment #9)
:stransky/:sotaro, am I reading this right and we should SwapInterval(0) on Wayland, because we render multiple windows from one thread?
Yea, we should avoid blocking on eglSwapBuffers(). But when I just added calling SwapInterval(0), the block still happened.
I called the SwapInterval(0) in GLContextEGLFactory::Create() like comment 6. It did not work. In this case, GLContextEGLFactory::Create() did not create EGLSurface, since widget was not fully mapped yet.
But when the SwapInterval(0) was called just after EGLSurface creation, it works as expected. From it, SwapInterval(0) seems to need valid current EGLSurface.
Updated•7 years ago
|
Comment 11•7 years ago
|
||
Comment 12•7 years ago
|
||
Sotaro Ikeda: just to make sure you've seen this:
Just calling eglSwapInterval(0) won't be enough, you'll also need to register frame callbacks and redraw when you receive one.
(This isn't addressed in the patch you sent)
Updated•7 years ago
|
Comment 13•7 years ago
|
||
(In reply to Jeff Gilbert [:jgilbert] from comment #5)
So it seems like (from the link in Comment 3) that Wayland does a crazy
thing, and repurposes SwapInterval(1) as RAF?
From 1, it sounds like SwapInterval(0) won't tear, but just also won't
block, but will allow us to no longer block if we SwapBuffers on a hidden
window.
:stransky/:sotaro, am I reading this right and we should SwapInterval(0) on
Wayland, because we render multiple windows from one thread?
Can you please run Firefox as:
WAYLAND_DEBUG=1 MOZ_ENABLE_WAYLAND=1 ./firefox
and attach the log here? Please mark the point at the log where Firefox hangs. That will be a starting point to find out why we have a hang here. I suspect this is a variant of:
https://bugs.freedesktop.org/show_bug.cgi?id=106753
We already do the VSync on wayland:
and that's derived from our SW compositor. When HW syc is missing we use 60fps approximation.
It may be possible to use the frame callback with eglSwapBuffers() as but I'd like to discuss it a bit with Jonas Ahdal first.
Also that may be Sway specific issue, I don't see that on mutter. Would be great to test it on Weston which is a reference Wayland compositor.
Comment 14•7 years ago
|
||
We already do the VSync on wayland
That's not a good way of doing vsync. The framerate information from wl_output must not be used for synchronization purposes. Instead, use frame callbacks!
Comment 15•7 years ago
|
||
BTW if we set eglSwapInterval(0) without the frame callback it may hide the actual problem and cause performance issues. eglSwapInterval(0) + frame callback may produce the same results as eglSwapInterval(1) as we don't use egl from main thread.
Comment 16•7 years ago
|
||
(In reply to emersion from comment #14)
We already do the VSync on wayland
That's not a good way of doing vsync. The framerate information from
wl_outputmust not be used for synchronization purposes. Instead, use
frame callbacks!
Yes, we use the frame callback, see https://dxr.mozilla.org/mozilla-central/rev/c2593a3058afdfeaac5c990e18794ee8257afe99/widget/gtk/WindowSurfaceWayland.cpp#556
Sorry for the confusion.
Comment 17•7 years ago
|
||
we use the frame callback
But you still rely on GetWaylandFrameDelay. Is there a reason why you use it instead of frame callbacks?
When you receive a frame callback, it doesn't mean "your content has been presented". It means "now is a good time for Firefox to draw and submit a new frame".
Comment 18•7 years ago
|
||
Related: https://patchwork.freedesktop.org/patch/258648/
Feel free to ask questions on the Wayland mailing list, or to join the IRC channel (#wayland on Freenode).
Updated•7 years ago
|
Comment 19•7 years ago
|
||
I can reproduce this on Gnome and Sway. Dropping [sway] from the title.
Comment 20•7 years ago
|
||
Hm. The steps to reproduce aren't obvious in GNOME; I only see the bug if I move windows / workspaces using keyboard shortcuts. Going through the Activities overview seems to work normally.
Steps to reproduce:
- Launch Firefox
- Ctrl-N -- create a new window
- Super-Shift-PgDown -- move window to next workspace
- Super-PgUp -- return to previous workspace
As long as you switch between workspaces using Super-PgUp/PgDown, the Firefox windows will be unresponsive.
Triggering the overview (Super) revives the windows.
Comment 21•7 years ago
|
||
For me in sway once I move firefox to a desktop/monitor that does not have the scale=1.5 it remains small, no matter how many other windows I open and try and force it to resize. https://imgur.com/a/nSR84ew
Comment 22•7 years ago
|
||
(In reply to Vladi from comment #21)
For me in sway once I move firefox to a desktop/monitor that does not have the scale=1.5 it remains small, no matter how many other windows I open and try and force it to resize. https://imgur.com/a/nSR84ew
This seems completely unrelated. Please check Sway's bugtracker if there's any opened issue (I think there is one). If not, please create one.
Updated•7 years ago
|
Comment 23•7 years ago
|
||
On Ubuntu 18.10 I also see this when a window is minimized with WebRender/OpenGL enabled. It also causes problems with videos playing minimized/hidden, there's a memory spike and after a short while the video stops playing until it becomes visible again.
Comment 24•7 years ago
|
||
I'm toying around with an attempt to use frame callbacks as VSyncSource (as my first attempt to poke at mozilla sources—wish me luck). I have a simple implementation, but I am debugging some hangs.
Unless it's okay to let WebRenders "wrench" event loop pause, we also need some integration there.
Comment 25•7 years ago
|
||
I think I can reproduce it with WebRender/OpenGL. But it takes some time to reproduce, it's not immediate.
Updated•7 years ago
|
Comment 26•7 years ago
|
||
It reproduces easily with sway:
- Launch sway
- Launch Firefox
- Start additional window
- Move additional window to a different workspace
- Observe that the windows appear frozen.
Another reproduction:
- Launch sway
- Launch Firefox
- Copy text from Firefox
- Attempt to paste text on a different workspace.
- Observe that paste hangs until Firefox is made visible again.
However, after testing only the eglSwapInterval(0) fix (without the much needed update to a more wayland-specific vsync logic), I see no immediate issue with :sotaro's patch. It seems to solve all the hangs.
Making a proper VSyncSource based on frame-callbacks (or refactoring so that things happen per-surface rather than globally) can be handled separately from this issue.
:stransky, anything holding back :sotaro's patch?
Comment 27•7 years ago
|
||
(In reply to Kenny Levinsen from comment #26)
:stransky, anything holding back :sotaro's patch?
eglSwapInterval(0) may cause performance overheads at least (I'm not sure about tearing). I'm going to investigate that as I can reproduce it now and understand what's going on before we eventually enable the eglSwapInterval(0).
Comment 28•7 years ago
|
||
I'm unable to reproduce that in debug build - looks like a kind of race condition to me.
Comment 29•7 years ago
|
||
Managed to reproduce in debug build:
#0 0x00007fa2b6a84847 in poll () at /lib64/libc.so.6
#1 0x00007fa2b567bb7c in poll (__timeout=-1, __nfds=1, __fds=0x7fa28fb95420) at /usr/include/bits/poll2.h:46
#2 0x00007fa2b567bb7c in wl_display_poll (display=display@entry=0x7fa2b67901c0, events=events@entry=1) at src/wayland-client.c:1713
#3 0x00007fa2b567d63c in wl_display_dispatch_queue (queue=<optimized out>, display=<optimized out>) at src/wayland-client.c:1786
#4 0x00007fa2b567d63c in wl_display_dispatch_queue (display=0x7fa2b67901c0, queue=0x7fa28a148140) at src/wayland-client.c:1759
#5 0x00007fa28b9ee09c in dri2_wl_swap_buffers_with_damage (drv=<optimized out>, disp=0x7fa28de69800, draw=0x7fa28ac74400, rects=0x0, n_rects=0)
at ../src/egl/drivers/dri2/platform_wayland.c:985
#6 0x00007fa28b9dc4b3 in eglSwapBuffers (dpy=0x7fa28de69800, surface=<optimized out>) at ../src/egl/main/eglapi.c:1278
#7 0x00007fa2aaab0ae9 in mozilla::gl::GLLibraryEGL::fSwapBuffers(void*, void*) const (this=0x7fa28de4a3e0, dpy=0x7fa28de69800, surface=0x7fa28ac74400)
at /home/komat/tmp676-trunk-gtk3/src-wayland/gfx/gl/GLLibraryEGL.h:226
#8 0x00007fa2aaa9e2ab in mozilla::gl::GLContextEGL::SwapBuffers() (this=0x7fa28aca9000) at /home/komat/tmp676-trunk-gtk3/src-wayland/gfx/gl/GLContextProviderEGL.cpp:494
#9 0x00007fa2aafec095 in mozilla::wr::RenderCompositorEGL::EndFrame() (this=0x7fa28de5cd00) at /home/komat/tmp676-trunk-gtk3/src-wayland/gfx/webrender_bindings/RenderCompositorEGL.cpp:120
....
As expected the freeze happens at eglSwapBuffers(). I suspect that the wl_surface passed to eglSwapBuffers() does not get the frame callbacks so we freeze here. Needs further debugging with WAYLAND_DEBUG=1 to see actual sequences.
Comment 30•7 years ago
|
||
Would be great to test it on Weston which is a reference Wayland compositor.
Weston sends frame callbacks if your surface is on at least one output - you get no frame callbacks if you're not on any output. You will get frame callbacks if your surface is on an output but completely hidden/occluded. However, this shouldn't be considered canonical, and we plan to follow the wlroots/Sway behaviour in future.
Frame callbacks aren't guaranteed to happen at every vblank interval (if the display is idle, you won't get them), nor are they guaranteed to happen at vblank either (Weston delivers them half an interval out of phase by default). They're just a callback for when the compositor thinks would be a good time for you to draw, which leaves a huge amount of discretion to the compositor developer.
| Comment hidden (obsolete) |
Comment 32•7 years ago
|
||
Okay let's go with the eglSwapInterval(0) for now.
Updated•7 years ago
|
Comment 33•7 years ago
|
||
Pushed by csabou@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/7a2b3a8fab9c
Set eglSwapInterval to 0 on wayland r=stransky
Comment 34•7 years ago
|
||
| bugherder | ||
Updated•7 years ago
|
Comment 35•7 years ago
|
||
please re-open
the root cause is still there. This fix is partial. This fix causes high CPU usage (I imagine setting the interval to 0 could be the cause...).
Updated•7 years ago
|
Updated•7 years ago
|
Comment 36•7 years ago
|
||
Looks like https://bugzilla.mozilla.org/show_bug.cgi?id=1542808 is the issue that handles 'the right fix' going forward, so this is closable. Sorry for the confusion.
Comment 37•7 years ago
|
||
The eglSwapInterval(0) is a generally a good thing here, because when the surface is not visible, eglSwapBuffers() may be blocked, according to the wayland specs and as Daniel mentioned here. And when eglSwapBuffers() blocks at Rendering thread also main thread is blocked at expose/paint event so whole Firefox freezes.
So we need to either:
- set eglSwapInterval(1) and make eglSwapBuffers() non-blocking at Firefox side which may not be possible (I use that for SW wayland rendering)
- set eglSwapInterval(0) and throttle the eglSwapBuffers() cadence.
while the second choice is more realistic.
Updated•7 years ago
|
Updated•7 years ago
|
Description
•