WebGL canvas flickering when resizing the window if the web page adjusts the canvas dimensions

RESOLVED WORKSFORME

Status

()

Core
Canvas: WebGL
RESOLVED WORKSFORME
6 years ago
4 years ago

People

(Reporter: Away for a while, Unassigned)

Tracking

Trunk
Points:
---

Firefox Tracking Flags

(Not tracked)

Details

Attachments

(1 attachment)

(Reporter)

Description

6 years ago
see these two apps (both built on top of CubicVR.js):

http://cjcliffe.github.com/CubicVR.js/cubicvr/samples/pdf/pdf_gallery.html
http://rescuefox.mozillalabs.com/src/index.html

If you resize the window you'll see part of the web page (or all of it in case of the second example) painting in white.  In case of the second web page, if I resize for a short while, the entire canvas goes white and nothing gets drawn to it any more until I reload the page.
Does rescuefox stay white after resizing while you still have air? It refreshes fine for me until I run out of air, at which point, because the app stops rendering, resize on both mac and windows machines I tested it on stayed white.

I also cannot replicate on the first page.

Tested on Win7 Fx7, OSX Fx7,10.

Does it still reproduce for you?
After re-reading, I should note that it does flicker white on both examples, while resizing, but does not stay white except for the 2nd demo, once air runs out.
Is the expected behavior that the last drawn frame persists during resize until it is rendered to again?
(In reply to Jeff Gilbert [:jgilbert] from comment #3)
> Is the expected behavior that the last drawn frame persists during resize
> until it is rendered to again?

Yes, this is the desired behavior. This is outside of the scope of the spec, as for example the whole window manager could not show the inside of windows at all during resizing, it's just desired behavior.

Note that this is unrelated to the preserveDrawingBuffer context attribute. That controls only the drawingbuffer i.e. the backbuffer, not the buffer actually used for compositing i.e. the frontbuffer.
The problem really seems specific to these pages: other WebGL pages like
    http://webglsamples.googlecode.com/hg/aquarium/aquarium.html
do not flicker during resizing.
I can reproduce on Linux with GL Layers, so this isn't Mac-specific.
OS: Mac OS X → All
Hardware: x86 → All
I can reproduce without GL Layers, so this isn't specific to accelerated compositing.
When the page resizes the canvas, this calls WebGLContext::SetDimensions which does gl->ResizeOffscreenFBO which recreates a fresh new FBO, losing the current rendered frame.

Currently we're single-buffered, right? This FBO is both our drawing-buffer and the buffer used for compositing, in my understanding. This works even with preserveDrawingBuffer=false because we delay the clearing of the drawingbuffer until the next WebGL drawing commands, but it's a bit fragile in the present case... to be consistent with our current approach we would have to also delay the resizing of the FBO until the next WebGL drawing... does that sound reasonable? Or should we switch to double buffering now?

CCing Vlad for help.
It's possible to persist the contents of the buffer across resizes, and I'm playing with a patch which does this now for ResizeOffscreenFBO.

Aquarium might be working properly because of requestAnimationFrame, which doesn't seem to be used in CubicVR in at least the PDF reader demo. If this is the case, this is even less necessary, though would still be nice to have.
Created attachment 566449 [details] [diff] [review]
Demo patch for a readback-based buffer persistance across resize events for FBOs

If you force native GL on win7, or, iirc, use linux, this patch will use read/drawpixels to persist the contents of the FBO across resizes.

This should be done later by framebuffer blits to keep it on the GPU, but I didn't want to add that yet. (will be landing from 615976 soon)
Attachment #566449 - Attachment description: Demo patch for a readback-based buffer persistance across resize events for WGL+Force FBOs → Demo patch for a readback-based buffer persistance across resize events for FBOs
Depends on: 716859
(In reply to Benoit Jacob [:bjacob] from comment #8)
> When the page resizes the canvas, this calls WebGLContext::SetDimensions
> which does gl->ResizeOffscreenFBO which recreates a fresh new FBO, losing
> the current rendered frame.
> 
> Currently we're single-buffered, right? This FBO is both our drawing-buffer
> and the buffer used for compositing, in my understanding. This works even
> with preserveDrawingBuffer=false because we delay the clearing of the
> drawingbuffer until the next WebGL drawing commands, but it's a bit fragile
> in the present case... to be consistent with our current approach we would
> have to also delay the resizing of the FBO until the next WebGL drawing...
> does that sound reasonable? Or should we switch to double buffering now?
> 
> CCing Vlad for help.

Actually, I like this in view of that we probably want to move to lazy SetDimensions. We can set it up to keep the old FBO until we draw the next time.
Bug 716859 gave us a proper backbuffer/frontbuffer split.
Status: NEW → RESOLVED
Last Resolved: 4 years ago
Resolution: --- → WORKSFORME
You need to log in before you can comment on or make changes to this bug.