For animated images with finite animations we can finish running their animation. At which point we won't call RequestRefresh, and so we will never mark the composited frame as valid (since that is the only place we do that).
To fix this we mark the composited frame as valid when we finish decoding.
But we can do better than that, we can mark the composited frame as valid immediately when we create a new decoded since we are just drawing the final frame from now on.
The SurfaceCache can hold the first frame of a "static" decode as well as the animated frames in two seperate entries. We only care about what happens to the animated frames, so ignore OnSurfaceDiscarded for anything else.
To accomplish this we must pass the SurfaceKey to OnSurfaceDiscarded.
The SurfaceCache can hold the first frame of a "static" decode as well as the animated frames in two seperate entries. We only care about what happens to the animated frames, so ignore OnSurfaceDiscarded for anything else.
To accomplish this we must pass the SurfaceKey to OnSurfaceDiscarded.
When we allow animated images to be discarded we still want to track if the image has been fully decoded before, but it would be confusing to say that it is "done decoding" because that sounds like the image is currently decoded, even though it could be discarded at the time.
Each concrete class of imgIContainer is able to handle opacity already. All we
need to do is pass opacity value to them.
MozReview-Commit-ID: EMkLnG3YXA1
--HG--
extra : rebase_source : b0a0aad1fec0c2765e96d23ed9b627345c793795
Each concrete class of imgIContainer is able to handle opacity already. All we
need to do is pass opacity value to them.
MozReview-Commit-ID: EMkLnG3YXA1
--HG--
extra : rebase_source : 080a843b34cc1ca27831310d474243b4066f59f2
During painting we do some image decoding, but we want to send the image progress notifications from that decoding async. The CSS image renderer checks if the image is complete before painting it. So if the decoding we did during painting resulted in the images becoming complete there is no way to tell that during the same paint. Thus making that decoding a waste of time.
So we add a limited way of telling if the result of a StartDecoding call has resulting in an image that is ready to paint so we can get that result during the same paint.
I would have prefered to change StartDecoding to just return a bool but that would have made the bool an outparam, which would make every StartDecoding call uglier with extra code. Changing it to a notxpcom function would have fixed that, but I'm not sure if that is safe.
The Decode call may result in synchronously creating the surface, but we only check again if the surface is there for FLAG_SYNC_DECODE, not FLAG_SYNC_DECODE_IF_FAST.
All of the decoding we do during painting is of the type FLAG_SYNC_DECODE_IF_FAST, which means it would be useless to do that decoding synchronously during painting because the paint doesn't benefit from the result of that decoding.
Looking at the history of this code it looks like https://hg.mozilla.org/mozilla-central/rev/435df926eb10 (part 6 of bug 1119774) was where this bug was introduced. Before that changeset we always did another LookupFrameInternal call after the Decode (called WantDecodedFrames back then). But that changeset changed it to only be done for standard sync decodes, not "sync decode if fast".
FrameAnimator::GetCompositedFrame is only ever called with the current animation frame index. This is good because it can return invalid results if it is called for some other frame number.
Layout has been using imgIContainer::IsOpaque to determine if the image will draw opaquely to all pixels it covers, and doing culling based on this.
However imgIContainer::IsOpaque doesn't guarantee anything. It only describes if the image, when in a decoded state, has all opaque pixels. So if the image doesn't have fully decoded frames around (because they got discarded) it may not draw opaquely to all of its pixels.
So we create a new function that first checks if there is a fully decoded frame.
Layout has been using imgIContainer::IsOpaque to determine if the image will draw opaquely to all pixels it covers, and doing culling based on this.
However imgIContainer::IsOpaque doesn't guarantee anything. It only describes if the image, when in a decoded state, has all opaque pixels. So if the image doesn't have fully decoded frames around (because they got discarded) it may not draw opaquely to all of its pixels.
So we create a new function that first checks if there is a fully decoded frame.
If the sync decoding the LookupFrame does encounters an error it will set mError on the RasterImage, which LookupFrame callers check before calling LookupFrame. But they've called LookupFrame before the error was encountered, so we check if the frame has had Abort called on it to determine if we should return it at all.
We only does this if one of the sync decode flags was passed in because IsAborted needs to get the imgFrame's monitor, so we don't want to block consumers that haven't asked for decoding.
This means that in RasterImage::LookupFrame when we are asked to do a sync decode (if needed) we use WaitUntilComplete to wait until the frame is finished decoding. But we would actually return after the next progressive pass notified the monitor to wake up. Thus, we would draw a not-fully-decoded image even though the sync decode flag was passed.
The change in FrameAnimator means that we won't draw the next frame in an animated image until all progressive passes of that image are complete. This seems like what we want anyways.
There is one real use of IsImageComplete left, in imgFrame::Draw, where we need to know if the decoded image data covers the whole image frame. (There are a couple of uses of IsImageComplete in asserts.)
The bulk of this commit was generated with a script, executed at the top
level of a typical source code checkout. The only non-machine-generated
part was modifying MFBT's moz.build to reflect the new naming.
CLOSED TREE makes big refactorings like this a piece of cake.
# The main substitution.
find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \
xargs perl -p -i -e '
s/nsRefPtr\.h/RefPtr\.h/g; # handle includes
s/nsRefPtr ?</RefPtr</g; # handle declarations and variables
'
# Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h.
perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h
# Handle nsRefPtr.h itself, a couple places that define constructors
# from nsRefPtr, and code generators specially. We do this here, rather
# than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename
# things like nsRefPtrHashtable.
perl -p -i -e 's/nsRefPtr/RefPtr/g' \
mfbt/nsRefPtr.h \
xpcom/glue/nsCOMPtr.h \
xpcom/base/OwningNonNull.h \
ipc/ipdl/ipdl/lower.py \
ipc/ipdl/ipdl/builtin.py \
dom/bindings/Codegen.py \
python/lldbutils/lldbutils/utils.py
# In our indiscriminate substitution above, we renamed
# nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up.
find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \
xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g'
if [ -d .git ]; then
git mv mfbt/nsRefPtr.h mfbt/RefPtr.h
else
hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h
fi
--HG--
rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h