Open Bug 1665726 Opened 1 year ago Updated 1 year ago

CompositorWidget::GetClientSize is racy - deliver widget size with main thread paint transaction, and figure out what the compositor/renderer should do while the resize is in-flight


(Core :: Graphics, defect)





(Reporter: mstange, Unassigned)


When a window is resized, the resize is processed on the main thread of the parent process. While processing the resize, the main thread paints the browser chrome at the new size and submits a transaction to the compositor.

What happens if the compositor decides to composite before it has processed that transaction?
At the moment, the compositor obtains the new widget size in a racy way via CompositorWidget::GetClientSize. That means that it will draw old content into a buffer of the new size. This drawing will have gaps or cropped areas, since it's not using the new browser chrome paint yet.
Now this drawing is submitted to the OS in a platform-specific way. What happens at this point really depends on the OS and on the configuration. For example:

  • On macOS, while the resize is in-flight, doing any kind of CoreAnimation commit off the main thread results in artifacts. Our Mac code goes through some pain to "suspend" commits during the resize danger zone. Only commits on the main thread result in artifact-free drawing. The window chrome updates in sync with the main thread commit, once the main thread has finished processing the resize. (So yes, on macOS, a window resize is processed synchronously, on the main thread, and the OS waits for us to finish before updating the screen.)
  • On other platforms / configurations: What happens if the "present" / "swap" is done with the old window size? What happens if it is done with the new window size before the main thread has finished processing the resize notification? Is the resize notification on the main thread synchronous or asynchronous? How is the window chrome drawn? Is there a way to synchronize our drawing with the window chrome resize drawing? Does the OS have an API to say whether to squish/scale layers which still have the old size, or which window corner to anchor those layers at?

It would be great if we could just eliminate CompositorWidget::GetClientSize and always composite at the window size that came with the most recent parent process paint. This would eliminate the race, and would mean that the buffer that we draw to does not contain incomplete or cropped content.
But we need to make sure that this doesn't cause artifacts, in case there are OS configurations where compositing at the new size is required.

See also bug 1656266 and bug 1533550.

Blocks: gfx-triage
No longer blocks: gfx-triage
Severity: -- → S3
You need to log in before you can comment on or make changes to this bug.