Originally we would invalidate image containers synchronously when
SVGRootRenderingObserver::OnRenderingChange was called. However at this
point in time, the layout tree is in the middle of updating its own
state, and triggering a paint will be problematic. Animated vector
images did not suffer from this problem because they would defer to the
next refresh tick, but non-animated do not receive refresh tick events.
As such, we should just defer the invalidation to immediately after the
layout tree has finished updating itself.
Differential Revision: https://phabricator.services.mozilla.com/D15668
If a vector image has an image container, it is unlikely the caller will
call VectorImage::Draw (and thus Show indirectly) to display the image.
As such, WebRender was missing subsequent invalidations and not
regenerating the rasterized surface as expected. Thus we now resume
honoring the invalidations if we updated the image container.
Differential Revision: https://phabricator.services.mozilla.com/D15667
Given the crash resolved in part 1, it is possible for the blob
rasterizer in the compositor process to still be using surfaces after
the animation has advanced to the next frame. With recycling this can be
problematic as the recycled surface will be reused for a future frame.
In an ideal world, the blob recording would use the animation's image
key instead, but the rasterizer doesn't have easy access to the mapping
table. As such, for any frames used in a blob recording, we now
explicitly mark them as non-recyclable and we will be forced to allocate
a new frame instead.
Differential Revision: https://phabricator.services.mozilla.com/D16192
SchemeIs only throws exceptions on null arguments now. Assert
arguments, as they should never be null anyways, and create an
infallible C++ version.
Differential Revision: https://phabricator.services.mozilla.com/D16143
--HG--
extra : moz-landing-system : lando
Summary: Really sorry for the size of the patch. It's mostly automatic
s/nsIDocument/Document/ but I had to fix up in a bunch of places manually to
add the right namespacing and such.
Overall it's not a very interesting patch I think.
nsDocument.cpp turns into Document.cpp, nsIDocument.h into Document.h and
nsIDocumentInlines.h into DocumentInlines.h.
I also changed a bunch of nsCOMPtr usage to RefPtr, but not all of it.
While fixing up some of the bits I also removed some unneeded OwnerDoc() null
checks and such, but I didn't do anything riskier than that.
This needs to add a few of includes in other places which were relying on the
massive (now gone) list in nsDocument.h.
I also needed to move an AnimationTimeline destructor out of line because it
relied on dom::Animation being defined, yet Animation.h includes
AnimationTimeline.h, so include hell.
Differential Revision: https://phabricator.services.mozilla.com/D15366
This is a big step in order to merge both.
Also allows to remove some very silly casts, though it causes us to add some
ToSupports around to deal with ambiguity of casts from nsIDocument to
nsISupports, and add a dummy nsISupports implementation that will go away later
in the series.
Differential Revision: https://phabricator.services.mozilla.com/D15352
Both libjpeg and windows.h typedef `boolean` to different types (`int` and
`unsiched char` respectively) and nsJPEGEncoder's public definition includes a
function that returns a `boolean`. Exposing this header results in type
conflicts.
We now isolate the internals of nsJPEGEncoder into a friend class whose
internals are hidden from the publica, allowing the header to exported.
Differential Revision: https://phabricator.services.mozilla.com/D14638
--HG--
extra : moz-landing-system : lando
MozPromise most common use is to have an single or exclusive listener. By making the MozPromise generated by IPDL exclusive we can also use move semantics.
While at it, we also use move semantics for the ResponseRejectReason and via the callback's reject method so that the lambda used with the MozPromise::Then can be identical to the one used by the IPDL callback.
As it currently is, it provides no advantage over a copy as it's just an enum; however, this will facilitate future changes where it may not be.
Differential Revision: https://phabricator.services.mozilla.com/D13906
--HG--
extra : moz-landing-system : lando
When an animation is reset, we can actually avoid the reallocations by
keeping the frames in the mRecycle and mDiscard queues. There is no real
need to do this. We just need to make sure the recycle rect calculation
is done appropriately, particularly when we haven't reached the end yet
and thus don't know the first frame refresh area yet.
Differential Revision: https://phabricator.services.mozilla.com/D13465
The size was originally incremented in AnimationFrameBuffer::Insert
however if an animation was reset before we finished decoding, it would
count some frames twice in the counter. Now we increment it inside
InsertInternal, where AnimationFrameDiscardingQueue can make a more
informed decision on whether the frame is a duplicate or not.
Additionally we now fail explicitly when we insert more frames on
subsequent decodes than the original decoders. This will help avoid
getting out of sync with FrameAnimator.
Differential Revision: https://phabricator.services.mozilla.com/D13464
If an animated frame buffer was reset just before the necessary frame to
cross the discard threshold, followed by said frame being inserted by
the decoder, it would insert a null pointer into the display queue for
the first frame. This is because it assumed that we have always advanced
past the first frame -- which was true, but the reset placed us back at
the beginning.
This would initially manifest to the user as the animation stopping,
since it could not advance past the first frame. Once a memory report
was requested, it would crash because we assume every frame in the
display queue is valid.
This patch removes the assumption about what frame we have advanced to.
Differential Revision: https://phabricator.services.mozilla.com/D13407
- modify line wrap up to 80 chars; (tw=80)
- modify size of tab to 2 chars everywhere; (sts=2, sw=2)
--HG--
extra : rebase_source : 7eedce0311b340c9a5a1265dc42d3121cc0f32a0
extra : amend_source : 9cb4ffdd5005f5c4c14172390dd00b04b2066cd7
This is a best effort attempt at ensuring that the adverse impact of
reformatting the entire tree over the comments would be minimal. I've used a
combination of strategies including disabling of formatting, some manual
formatting and some changes to formatting to work around some clang-format
limitations.
Differential Revision: https://phabricator.services.mozilla.com/D13193
--HG--
extra : moz-landing-system : lando
When bug 1508393 landed, it not only enabled producing of full frames
on the decoder threads, it also enabled recycling of old animated image
frame buffers it would have otherwise discarded. It reuses the contents
of the buffer where possible given we know what pixels changed between
the old frame and the frame we want to produce. However where this
calculation was done was incorrect. We originally calculated it when we
advanced the frame, but at that point there is no guarantee that we have
all of the necessary information; we may have fallen behind on decoding.
As such, we move the calculation to where we actually perform the
recycling. At this point we are guaranteed to have all the necessary
frames between the recycling and display queues.
Differential Revision: https://phabricator.services.mozilla.com/D12903
WebRender takes longer than OMTP to release its hold on the current
frame. This is because it is in a separate process and holds onto the
surface in between rendering frames, rather than getting a reference for
each repaint. This patch makes us less aggressive about taking the most
recent surface placed in the recycling queue out to avoid blocking on
waiting for the surface to be released.
Differential Revision: https://phabricator.services.mozilla.com/D10903
Also, fix a minor bug where when we discard an animated image that is a
full frame animated image, we need to reset
AnimationState::mCompositedFrameInvalid to false, just like we do for
animated images blended by FrameAnimator. This is because it is used as
part of our state checking in FrameAnimator::GetCompositedFrame before
we are willing to yield frame data.
Differential Revision: https://phabricator.services.mozilla.com/D12362
Bug 1249474 suggested that we add image/webp to the front of the Accept
header for images, to indicate to servers that we actually support WebP.
Differential Revision: https://phabricator.services.mozilla.com/D8120
Redecode errors break the state machine of FrameAnimator, since the
decoder and the animation state are now out of sync. Going forward this
tight coupling should be eliminated, as the decoder will produce full
frames and the animator can just take the current frame without worrying
about its relative position. For the moment, we should just not reset an
animation if it hit a redecode error (likely due to OOM) just like how
we already stop advancing the animation before the reset.
Differential Revision: https://phabricator.services.mozilla.com/D11046
Behavior-wise this only removes the HasAttr(src) check, and adds the IsEmpty()
check to the alt attribute value, since this function is only called for <img>
and <input>.
But it also cleans up a bit.
Differential Revision: https://phabricator.services.mozilla.com/D11194
Behavior-wise this only removes the HasAttr(src) check, and adds the IsEmpty()
check to the alt attribute value, since this function is only called for <img>
and <input>.
But it also cleans up a bit.
Differential Revision: https://phabricator.services.mozilla.com/D11194
--HG--
extra : source : 803b224d52a0940b4fb4b3b9cffc6a1fa6e5d4ee
Behavior-wise this only removes the HasAttr(src) check, and adds the IsEmpty()
check to the alt attribute value, since this function is only called for <img>
and <input>.
But it also cleans up a bit.
Differential Revision: https://phabricator.services.mozilla.com/D11194
There were two unrelated buffering problems in nsWebPDecoder. The first
was with the decoder contract. We are expected to loop until the
iterator is unable to provide more data, and wait for the SourceBuffer
to reschedule us, where as nsWebPDecoder::DoDecode only did one pass.
Thus when something yielded wanting more data, we would just wait
forever.
The second was the integration with the libwebp API. We are expected to
retry when we receive SUSPENDED from the decoder, as it decided to yield
pixels instead of continuing to decode as many as possible.
The tests did not cover the first problem because multi chunk decoder
tests do not use SourceBuffer scheduling. This is an oversight. They now
will write a chunk of data, let the SourceBuffer reschedule the decoder,
and repeat until all of the data has been written.
The tests did not cover the second problem because all of the reference
WebP images are too small. This patch adds a new test with a large WebP
image (converted from a Mozilla all hands photo of lanyards). This
should actually trigger the SUSPEND behaviour of libwebp.
Differential Revision: https://phabricator.services.mozilla.com/D10817
For decoders which produce unpaletted partial frames (APNG, WebP), the
surface format should always be BGRA. These frames while partial, are
the same size as the output size of the animated image. When
FrameAnimator performs the blend with the compositing frame, it expects
all pixels we don't care about to be set to fully transparent. If it is
BGRX, they will be set to solid white instead.
Differential Revision: https://phabricator.services.mozilla.com/D10753
This patch makes ImageContainer create a SharedSurfacesAnimation object
when it detects that we are using shared surfaces and are producing full
frames.
Differential Revision: https://phabricator.services.mozilla.com/D7505
First we did not handle the SourceBufferIterator::WAITING state which
can happen when we get woken up but there is no data to read from the
SourceBufferIterator. StreamingLexer handled this properly by yielding
with NEED_MORE_DATA, and properly scheduling the decoder to resume. This
patch does the same in the WebP decoder.
Second nsWebPDecoder::GetType was not implemented. This meant it would
return DecoderType::UNKNOWN, and would fail to recreate the decoder if
we are discarding frames and need to restart from the beginning. In
addition to implementing that method, this patch also corrects an assert
in DecoderFactory::CloneAnimationDecoder which failed to check for WebP
as a supported animated decoder.
This patch also modestly improves the logging output and library method
checks.
Differential Revision: https://phabricator.services.mozilla.com/D10624
We should only assert that the caller is requesting the first frame or
we have advanced to or beyond the expected initial frame, when we
successfully return a frame. This is because FrameAnimator will request
on refresh ticks for the current frame again, until it observes it. If
decoding is still behind, then we likely still have frames to
auto-advance, and we will trip the assert.
Differential Revision: https://phabricator.services.mozilla.com/D9507
This is what we have been working towards in all of the previous parts
in the series. This subclasses AnimationFrameDiscardingQueue to save the
discarded frames for recycling by the decoder, if the frame is marked as
supporting recycling.
Differential Revision: https://phabricator.services.mozilla.com/D7516
AnimatedFrameDiscardingQueue subclasses AnimationFrameBuffer to allow a
cleaner abstraction over the behaviour change when we cross the
threshold of too high a memory footprint for an animated image. The next
patch will build on top of this to provide an abstraction to reuse the
discarded frames.
Differential Revision: https://phabricator.services.mozilla.com/D7515
This patch makes AnimationSurfaceProvider use the new abstractions
provided by AnimationFrameBuffer and AnimationFrameRetainedBuffer to
provide storage and lifetime management of decoders and the produced
frames. We initially start out with an implementation that will just
keep every frame forever, like our historical behaviour. The next patch
will add support for discarding.
Differential Revision: https://phabricator.services.mozilla.com/D7514
In the next few patches, AnimationFrameBuffer will be reworked to split
the discarding behaviour from the retaining behaviour. Once implemented
as separate classes, it will allow easier reuse of the discarding code
for recycling.
Differential Revision: https://phabricator.services.mozilla.com/D7513
The owner for the decoder may implement IDecoderFrameRecycler to allow
the decoder to request a recycled frame instead of allocating a new one.
If none are available, it will fallback to allocating a new frame.
Not only may the IDecoderFrameRecycler not have any frames available for
recycling, the recycled frame itself may still be in use by other
entities outside of imagelib. Additionally it may still be required by
BlendAnimationFilter to restore the previous frame's data. It may even
be the same frame as to restore. In the worst case, we will simply
choose to allocate an entirely new frame, just like before.
When we allocate a new frame, that means the old frame we tried to
recycle will be taken out of circulation and not reused again,
regardless of why it failed.
Differential Revision: https://phabricator.services.mozilla.com/D7512
Beyond the necessary reinitialization methods, we need to protect
ourselves from recycling a frame that some other entity in the browser
is still using. Generally speaking the animated surface will only be
used in imgFrame::Draw since we don't layerize animated images, which
will be safe. However with OMTP or blob recordings, we could retain a
reference to the surface outside the current stack context. Additional
if something calls RasterImage::GetImageContainer(AtSize) or
RasterImage::GetFrame(AtSize), it may also have a reference to the
surface for an indetermine period of time.
As such, if an imgFrame is a candidate for recycling, it will wrap
imgFrame::mLockedSurface in a RecyclingSourceSurface. Its job is to
track how many consumers there are still of the surface, so that after
we advance the animation, the decoder will know if there are still
outstanding consumers.
If the surface is still in use, it will block for a finite period of
time (the refresh interval) before giving up on reclaiming the surface,
and will allocate a new surface. The old surface can then remain in
circulation for as long as necessary without further blocking the
animation progression, since we stop recycling that surface/imgFrame.
Differential Revision: https://phabricator.services.mozilla.com/D7511
Since imgFrame::Draw will limit the drawing to only look at pixels that
we have written to and posted an invalidation for, there is no need to
hold the monitor while doing so. By taking the most expensive operation
outside the lock, we will minimize our chances of hitting contention
with the decoder thread.
A later part in this series will require that a surface be freed outside
the lock because it may end up reacquiring it. In addition to the
contention win, this change should facilitate that.
Differential Revision: https://phabricator.services.mozilla.com/D7510
If we discard a frame during decoding, e.g. due to an error, then we
don't want to take that frame into account for the first frame refresh
area. We should also be handling partial frames here (the dirty rect
needs to encompass the rows that did not get written with actual pixel
data). The only place that can have the necessary information is at the
end rather than at the beginning.
Differential Revision: https://phabricator.services.mozilla.com/D7509
The clear rect and the recycle rect can overlap, and depending on the
size of the clear rect, it could be a significant amount of data that
needs to be copied from the restore frame. This patch minimizes the
copying for a row which contains both the recycle rect and the clear
rect.
Differential Revision: https://phabricator.services.mozilla.com/D7508
Given an invalidation rect, called the recycle rect, which represents
the area which may have changed between the current frame and the frame
we are recycling, we can not only reuse the buffer itself to avoid an
allocation and free, we can also avoid copying pixel data from the
restore frame which is already set.
Differential Revision: https://phabricator.services.mozilla.com/D7507
When blending full frames off the main thread, FrameAnimator no longer
requires access to the raw data of the frame to advance the animation.
Now we only request a RawAccessFrameRef for the current/next frames when
we have discovered that we need to do blending on the main thread.
In addition to avoiding the mutex overhead of RawAccessFrameRef, this
will also facilitate potentially optimizing the surfaces for the
DrawTarget for individual animated image frames.
Differential Revision: https://phabricator.services.mozilla.com/D7506
We were marking them used even if only a decode was requested.
This can cause us to hold extra decoded copies of the image around because we have a tendency to request decode at the intrinsic size.
Calls to do_QueryInterface to a base class can be replaced by a static
cast, which is faster.
Differential Revision: https://phabricator.services.mozilla.com/D7224
--HG--
extra : moz-landing-system : lando
If class A is derived from class B, then an instance of class A can be
converted to B via a static cast, so a slower QI is not needed.
Differential Revision: https://phabricator.services.mozilla.com/D6861
--HG--
extra : moz-landing-system : lando