Closed Bug 1446309 Opened 6 years ago Closed 6 years ago

Some images are periodically flickering white in WebRender

Categories

(Core :: Graphics: WebRender, defect, P2)

63 Branch
defect

Tracking

()

RESOLVED FIXED
mozilla64
Tracking Status
firefox-esr52 --- unaffected
firefox59 --- unaffected
firefox60 --- unaffected
firefox61 --- unaffected
firefox62 --- disabled
firefox64 --- fixed

People

(Reporter: alice0775, Assigned: aosmond)

References

(Blocks 1 open bug, )

Details

Attachments

(3 files, 13 obsolete files)

47.85 KB, patch
aosmond
: review+
Details | Diff | Splinter Review
3.06 KB, patch
aosmond
: review+
Details | Diff | Splinter Review
40.06 KB, patch
tnikkel
: review+
Details | Diff | Splinter Review
Steps To Reproduce:
1. Open http://www.insecam.org/en/byrating/
2. Some IP cameras images periodically flicker if WebRender is enabled.
http://www.insecam.org/en/view/511950/
http://www.insecam.org/en/view/522101/
http://www.insecam.org/en/view/439726/

etc...
It looks like the src is changing. This may be related to:

https://searchfox.org/mozilla-central/rev/6e96a3f1e44e286ddae5fdafab737709741d237a/layout/generic/nsImageFrame.cpp#1551

On the non-WebRender path we would paint the previous image if the new image isn't ready. We probably want to do something similar for the WebRender path.
Assignee: nobody → aosmond
These have gotten ugly as I've learned about and covered the corner cases. It is starting to feel like I should just expose the actual draw result and modify the GetImageContainerAtSize API (or add another API to get the latest draw result).

try: https://treeherder.mozilla.org/#/jobs?repo=try&revision=e006d83783cd696d91771f386a9dcee8e2fd8c1f

It does however solve the flickering at the given links.
Attachment #8960718 - Attachment is obsolete: true
Attachment #8960954 - Flags: review?(tnikkel)
Comment on attachment 8960954 [details] [diff] [review]
0001-Bug-1446309-Part-1.-Add-imgIContainer-GetImageContai.patch, v2

Can we return the draw result from the getImageContainer(AtSize) call somehow? An out param? Return a tuple? This seems a little hacky.
(In reply to Timothy Nikkel (:tnikkel) from comment #7)
> Comment on attachment 8960954 [details] [diff] [review]
> 0001-Bug-1446309-Part-1.-Add-imgIContainer-GetImageContai.patch, v2
> 
> Can we return the draw result from the getImageContainer(AtSize) call
> somehow? An out param? Return a tuple? This seems a little hacky.

Okay. In parallel, I've been looking at stopping OrientedImage and ClippedImage from using fallback with WebRender. It looks like I need something a little more like CreateWebRenderCommands (to receive the stacking context and builder, to make appropriate adjustments...) for each image type anyways, so I'll try to incorporate that into the updated patches.
Attachment #8960954 - Flags: review?(tnikkel)
Attachment #8960955 - Flags: review?(tnikkel)
See Also: → 1479784
Status: NEW → ASSIGNED
Hardware: x86_64 → All
Version: 61 Branch → 63 Branch
Incorporate review feedback. The CreateWebRenderCommands path is proving tricky given there is state inside nsDisplayFrame (mPrevImage) that needs to be managed by imagelib now, and it may perform several passes of CreateWebRenderCommands to get there. For now I'm just going to return the draw result with GetImageContainerAtSize as originally suggested. This will get this working. OrientedImage and ClippedImage not using fallback isn't as important because they appear fine with blob images -- if perhaps not as efficient as we could be.
Attachment #8960954 - Attachment is obsolete: true
The image crashes don't really make any sense from the try run. It might be related to strict IDL ordering requirements and the fact I had to convert GetImageContainerAtSize to a {%C++ .. %} entry because of some macro expansion weirdness with the Tuple datatype. I moved it to the end with the rest of the native C++ declarations, hopefully that solves it.
Attachment #8998862 - Attachment is obsolete: true
Pushed by aosmond@gmail.com:
https://hg.mozilla.org/integration/mozilla-inbound/rev/3f41992ab77e
Store a shared surface's dirty rect update if we cannot process it immediately. r=nical
(In reply to Pulsebot from comment #14)
> Pushed by aosmond@gmail.com:
> https://hg.mozilla.org/integration/mozilla-inbound/rev/3f41992ab77e
> Store a shared surface's dirty rect update if we cannot process it
> immediately. r=nical

Ugh I checked this in with the wrong bug in the description.
Backout by aosmond@gmail.com:
https://hg.mozilla.org/integration/mozilla-inbound/rev/b44b01a42d8c
Backed out changeset 3f41992ab77e because wrong bug number. r=backout
Comment on attachment 8998863 [details] [diff] [review]
0002-Bug-1446309-Part-2.-Make-nsDisplayImage-fallback-to-.patch, v3

Should incorporate your feedback.
Attachment #8998863 - Flags: review?(tnikkel)
Attachment #8998939 - Flags: review?(tnikkel)
Comment on attachment 8998939 [details] [diff] [review]
0001-Bug-1446309-Part-1.-Return-draw-result-from-imgICont.patch, v4

So the thing I don't like about this approach is that generally we want to &= draw results and combine them instead of assign to them. Using a tuple for the return type makes this take an extra step/line.

We could return just a draw result and make the imgcontainer and outparam? Or pass the draw result as an in/out param? Although that seems kinda bad since GetImageContainerAtSize seems more like the origin of a draw result rather than a place that updates one.

What do you think we should do?
(In reply to Timothy Nikkel (:tnikkel) from comment #18)
> Comment on attachment 8998939 [details] [diff] [review]
> 0001-Bug-1446309-Part-1.-Return-draw-result-from-imgICont.patch, v4
> 
> So the thing I don't like about this approach is that generally we want to
> &= draw results and combine them instead of assign to them. Using a tuple
> for the return type makes this take an extra step/line.
> 
> We could return just a draw result and make the imgcontainer and outparam?
> Or pass the draw result as an in/out param? Although that seems kinda bad
> since GetImageContainerAtSize seems more like the origin of a draw result
> rather than a place that updates one.
> 
> What do you think we should do?

I will make it return the draw result and yield the ImageContainer as an outparam. That seems the most natural.
Attachment #8998939 - Attachment is obsolete: true
Attachment #8998939 - Flags: review?(tnikkel)
Attachment #8999599 - Flags: review?(tnikkel)
Attachment #8998863 - Attachment is obsolete: true
Attachment #8998863 - Flags: review?(tnikkel)
Attachment #8999600 - Flags: review?(tnikkel)
Comment on attachment 8999599 [details] [diff] [review]
0001-Bug-1446309-Part-1.-Return-draw-result-from-imgICont.patch, v5

Review of attachment 8999599 [details] [diff] [review]:
-----------------------------------------------------------------

::: image/Image.cpp
@@ +121,5 @@
>               "Unsupported flag passed to GetImageContainer");
>  
>    IntSize size = GetImageContainerSize(aManager, aSize, aFlags);
>    if (size.IsEmpty()) {
> +    return ImgDrawResult::NOT_READY;

Looking at the reasons GetImageContainerSize returns an empty size not all of them seem like they are NOT_READY. A lot of them seem like BAD_ARGS or NOT_SUPPORTED.

::: image/ImgDrawResult.h
@@ +57,5 @@
>    NOT_READY,
>    TEMPORARY_ERROR,
>    BAD_IMAGE,
> +  BAD_ARGS,
> +  NOT_SUPPORTED

Seems like we should handle NOT_SUPPORTED in the same way as BAD_ARGS here:

https://searchfox.org/mozilla-central/rev/2466b82b729765fb0a3ab62f812c1a96a7362478/widget/nsBaseDragService.cpp#792

::: image/imgIContainer.idl
@@ +321,5 @@
> +  [noscript, notxpcom] ImgDrawResult getImageContainerAtSize(in LayerManager aManager,
> +                                                             [const] in nsIntSize aSize,
> +                                                             [const] in MaybeSVGImageContext aSVGContext,
> +                                                             in uint32_t aFlags,
> +                                                             out ImageContainer aContainer);

aOutContainer might be more clear.
Attachment #8999599 - Flags: review?(tnikkel) → review+
Comment on attachment 8999600 [details] [diff] [review]
0002-Bug-1446309-Part-2.-Make-nsDisplayImage-fallback-to-.patch, v4

Review of attachment 8999600 [details] [diff] [review]:
-----------------------------------------------------------------

::: layout/generic/nsImageFrame.cpp
@@ +1816,5 @@
>    ImgDrawResult drawResult =
>      mImage->GetImageContainerAtSize(aManager, decodeSize, svgContext,
>                                      flags, getter_AddRefs(container));
> +
> +  // While we got a container, it may contain a fully decoded surface. If that

may *not*
Attachment #8999600 - Flags: review?(tnikkel) → review+
I made GetImageContainerSize return a draw result so that we can return that instead of NOT_READY. Renamed aContainer to aOutContainer.
Attachment #8999599 - Attachment is obsolete: true
Attachment #8999932 - Flags: review+
The changes to GetImageContainerSize returning a draw code are a good correction, and now I need run the tests to make sure I didn't break anything as a result...

try: https://treeherder.mozilla.org/#/jobs?repo=try&revision=56c97b6ee68c8746c87da7b424b844c5346aca25
Attachment #8999600 - Attachment is obsolete: true
Attachment #8999934 - Flags: review+
I say it might break something, and then realize that if we check that the image has a size *after* checking if the given size is valid, we will return BAD_ARGS when the caller just used the image's own (but unknown) size for GetImageContainerImpl.

Swap the order of those:

https://treeherder.mozilla.org/#/jobs?repo=try&revision=193c18a87d87d75342cb770bd8ddece974e0491f
Attachment #8999932 - Attachment is obsolete: true
Attachment #8999937 - Flags: review+
Pushed by aosmond@gmail.com:
https://hg.mozilla.org/integration/mozilla-inbound/rev/69a4c2a0aac6
Part 1. Return draw result from imgIContainer::GetImageContainerAtSize. r=tnikkel
https://hg.mozilla.org/integration/mozilla-inbound/rev/45e3f5d8e294
Part 2. Make nsDisplayImage fallback to the previous image to avoid flickering. r=tnikkel
Looking into the backout, the draw result really ought to be propagated up to the display item so that it can cache the value via UpdateDrawResult. This might explain some intermittent reftest failures wrt to images, as this is used to force sync decoding in that case. I also wonder if we are triggering fallback when we needed as an intermediate state in some cases, so it looks like this bug will have a part 3...
Flags: needinfo?(aosmond)
Attachment #9001250 - Flags: review?(tnikkel)
Comment on attachment 9001250 [details] [diff] [review]
0003-Bug-1446309-Part-3.-Properly-handle-ImgDrawResult-fo.patch, v1

Review of attachment 9001250 [details] [diff] [review]:
-----------------------------------------------------------------

::: layout/xul/nsImageBoxFrame.cpp
@@ +571,2 @@
>      CreateWebRenderCommands(aBuilder, aResources, aSc, aManager, this, ToReferenceFrame(), flags);
> +  if (result == ImgDrawResult::NOT_SUPPORTED) {

Based on this it seems that NOT_SUPPORTED needs to take precedence over all others in the DrawResult combining rules.

It feels like we are bundling up a lot of meaning into ImgDrawResults now, it gives me a vague uneasy feeling.
Attachment #9001250 - Flags: review?(tnikkel)
We can't release this to the field, but we can let this ride to beta.  Someone changing the src value on an image isn't that common. 

I know Andrew is close to landing this.  I'd certainly like to have it for Beta, and in the interest of not letting these patches bitrot, Andrew should probably push forward after his pto and finish this off.
Priority: P1 → P2
As discussed offline, I added an assert to nsImageGeometryMixin::UpdateDrawResult to ensure NOT_SUPPORTED is never received (as it should have been handled by fallback, always). I also updated the ImgDrawResult operator& method to always prefer NOT_SUPPORTED if either aLeft or aRight is set to it.

try: https://treeherder.mozilla.org/#/jobs?repo=try&revision=d1fd31402c496a949db504e39dbb417eac80c99d
Attachment #9001250 - Attachment is obsolete: true
Attachment #9008913 - Flags: review?(tnikkel)
Attachment #9008913 - Flags: review?(tnikkel) → review+
Pushed by aosmond@gmail.com:
https://hg.mozilla.org/integration/mozilla-inbound/rev/d10ab3f7b4ea
Part 1. Return draw result from imgIContainer::GetImageContainerAtSize. r=tnikkel
https://hg.mozilla.org/integration/mozilla-inbound/rev/2ca405997ed5
Part 2. Make nsDisplayImage fallback to the previous image to avoid flickering. r=tnikkel
https://hg.mozilla.org/integration/mozilla-inbound/rev/86b053d52632
Part 3. Properly handle ImgDrawResult for WebRender display list generation. r=tnikkel
https://hg.mozilla.org/mozilla-central/rev/d10ab3f7b4ea
https://hg.mozilla.org/mozilla-central/rev/2ca405997ed5
https://hg.mozilla.org/mozilla-central/rev/86b053d52632
Status: ASSIGNED → RESOLVED
Closed: 6 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla64
Regressions: 1677518
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: