There is one main difference between raster images and vector images
with respect to factor of 2 scaling. Vector images may be scaled
infinitely and so we need to extend factor of 2 scaling to permit
growing instead of just shrinking. Also, we don't want to scale
infinitely, so we should configure a maximum size limit. This size limit
will apply even outside of factor of 2 scaling, and so the caller
(VectorImage) will need to be careful to take this into account.
If FLAG_HIGH_QUALITY_SCALING is used, we should use
SurfaceCache::LookupBestMatch just like how it is done in RasterImage.
This may provide an alternative size at which we should rasterize the
SVG instead of the requested size. Since SurfaceCache imposes a maximum
size for which it will permit rasterized SVGs, we should also bypass the
cache entirely if we are well above that and simply draw directly to the
draw target in such cases.
With WebRender, it is somewhat more complicated. We will now return
NOT_SUPPORTED if the size is too big, and this should trigger fallback
to blob images. This should only produce drawing commands for the
relevant region and save us the high cost of rasterized a very large
surface on the main thread, which at the same time, looking as crisp as
a user would expect.
There is one main difference between raster images and vector images
with respect to factor of 2 scaling. Vector images may be scaled
infinitely and so we need to extend factor of 2 scaling to permit
growing instead of just shrinking. Also, we don't want to scale
infinitely, so we should configure a maximum size limit. This size limit
will apply even outside of factor of 2 scaling, and so the caller
(VectorImage) will need to be careful to take this into account.
DecoderFlags::BLEND_ANIMATION will cause the decoder to inject the
BlendAnimationFilter from the previous patch into the SurfacePipe filter
chain. All frames produced by this decoder will be complete, and
should be equivalent to the result outputted by FrameAnimator.
This new SurfaceFilter can be added to a SurfacePipe to perform the
blending of a previous frame with the current partial frame, for an
animated image. This functionality is currently provided by
FrameAnimator and must be performed each time we want to advance the
displayed frame, all on the main thread. Moving this to SurfacePipe
allows us to do the same operation once per frame decode, and on a
decoder thread.
This should reduce the cost of a refresh tick since advancing animated
images is reduced to merely checking if the frame is available. Also, if
the image is below the discard frames threshold (to save memory), then
we will also save CPU due to only blending once at decode.
DecoderFlags::BLEND_ANIMATION will cause the decoder to inject the
BlendAnimationFilter from the previous patch into the SurfacePipe filter
chain. All frames produced by this decoder will be complete, and
should be equivalent to the result outputted by FrameAnimator.
This new SurfaceFilter can be added to a SurfacePipe to perform the
blending of a previous frame with the current partial frame, for an
animated image. This functionality is currently provided by
FrameAnimator and must be performed each time we want to advance the
displayed frame, all on the main thread. Moving this to SurfacePipe
allows us to do the same operation once per frame decode, and on a
decoder thread.
This should reduce the cost of a refresh tick since advancing animated
images is reduced to merely checking if the frame is available. Also, if
the image is below the discard frames threshold (to save memory), then
we will also save CPU due to only blending once at decode.
When generating display lists for WebRender, we were not caching the
draw result via nsDisplayItemGenericImageGeometry::UpdateDrawResult (or
similar) after completing CreateWebRenderCommands. This is important
because reftests use this to force sync decoding for images; it may be a
reason for image-related intermittent failures on *-qr builds.
Additionally, we may have been requesting fallback in cases where fallback
could not do anything more than WebRender could. For example, if we can't
get an image container yet, there is no point in requesting fallback
because it might just be we haven't started decoding yet. We should just
return the actual draw result in such cases.
In addition to the image container, the draw result can also be useful
for callers to know whether or not the surface(s) in the container are
fully decoded or not. This is used in subsequent parts to avoid
flickering in some cases.
nsIAssociatedContentSecurity and nsISecurityInfoProvider are unused as of
bug 832834, so this patch removes them.
Differential Revision: https://phabricator.services.mozilla.com/D5693
--HG--
extra : moz-landing-system : lando
The 'x' prefix makes it clearer that these are infallible.
A couple of nsJSID methods are now also infallible.
--HG--
extra : rebase_source : fcce44a00212d6d341afbf3827b31bd4f7355ad5
There are surprisingly many of them.
(Plus a couple of unnecessary checks after `new` calls that were nearby.)
--HG--
extra : rebase_source : 47b6d5d7c5c99b1b50b396daf7a3b67abfd74fc1
In addition to the image container, the draw result can also be useful
for callers to know whether or not the surface(s) in the container are
fully decoded or not. This is used in subsequent parts to avoid
flickering in some cases.
This patch introduces a new cookie behavior policy called
BEHAVIOR_REJECT_TRACKER. It also makes it possible to override that
behavior with cookie permissions similar to other cookie behaviors.
This patch was written entirely by the following script:
#!/bin/bash
if [ ! -d "./.hg" ]
then
echo "Not in a source tree." 1>&2
exit 1
fi
find . -regex '.*\(ref\|crash\)test.*\.list' | while read FILENAME
do
echo "Processing ${FILENAME}."
# The following has four substitutions:
# * The first one replaces the *first* argument to fuzzy() when it doesn't
# have a - in it, by replacing it with an explicit 0-N range.
# * The second one does the same for the *second* argument to fuzzy().
# * The third does the same for the *second* argument to fuzzy-if().
# * The fourth does the same for the *third* argument to fuzzy-if().
#
# Note that this is using perl rather than sed because perl doesn't
# support non-greedy matching, which is needed for the first argument to
# fuzzy-if.
perl -pi -e 's/(fuzzy\()([^ ,()-]*)(,[^ ,()]*\))/${1}0-${2}${3}/g;s/(fuzzy\([^ ,()]*,)([^ ,()-]*)(\))/${1}0-${2}${3}/g;s/(fuzzy-if\([^ ]*?,)([^ ,()-]*)(,[^ ,()]*\))/${1}0-${2}${3}/g;s/(fuzzy-if\([^ ]*?,[^ ,()]*,)([^ ,()-]*)(\))/${1}0-${2}${3}/g' "${FILENAME}"
done
Differential Revision: https://phabricator.services.mozilla.com/D2974
--HG--
extra : moz-landing-system : lando
DocShells are associated with outer DOM Windows, rather than Documents, so
having the getter on the document is a bit odd to begin with. But it's also
considerably less convenient, since most of the times when we want a docShell
from JS, we're dealing most directly with a window, and have to detour through
the document to get it.
MozReview-Commit-ID: LUj1H9nG3QL
--HG--
extra : source : fcfb99baa0f0fb60a7c420a712c6ae7c72576871
extra : histedit_source : 5be9b7b29a52a4b8376ee0bdfc5c08b12e3c775a
DocShells are associated with outer DOM Windows, rather than Documents, so
having the getter on the document is a bit odd to begin with. But it's also
considerably less convenient, since most of the times when we want a docShell
from JS, we're dealing most directly with a window, and have to detour through
the document to get it.
MozReview-Commit-ID: LUj1H9nG3QL
--HG--
extra : rebase_source : a13c59d1a5ed000187c7fd8e7339408ad6e2dee6
Much like the component manager, many of the strings that we use for category
manager entries are statically allocated. There's no need to duplicate these
strings.
This patch changes the category manager APIs to take nsACStrings rather than
raw pointers, and to pass literal nsCStrings when we know we have a literal
string to begin with. When adding the category entry, it then skips making
copies of any strings with the LITERAL flag.
MozReview-Commit-ID: EJEcYSdNMWs
***
amend-catman
--HG--
extra : source : aa9a8f18e98f930a3d8359565eef02f3f6efc5f9
extra : absorb_source : 81a22ab26ee8017ac43321ff2c987d8096182d37
Much like the component manager, many of the strings that we use for category
manager entries are statically allocated. There's no need to duplicate these
strings.
This patch changes the category manager APIs to take nsACStrings rather than
raw pointers, and to pass literal nsCStrings when we know we have a literal
string to begin with. When adding the category entry, it then skips making
copies of any strings with the LITERAL flag.
MozReview-Commit-ID: EJEcYSdNMWs
***
amend-catman
--HG--
extra : rebase_source : 4f70e7b296ecf3b52a4892c92155c7c163d424d2
The patch introduces NS_GetURIWithNewRef and NS_GetURIWithNewRef which perform the same function.
Differential Revision: https://phabricator.services.mozilla.com/D2239
--HG--
extra : moz-landing-system : lando
The JPEG decoder will currently only post an invalidation when it has
processed all of the rows it is able to. If it is has all the data, that
means it must fully decode before invalidating. This causes very large
JPEGs to appear in large chunks which feels janky compared to slowly
appearing row by row with the refresh tick. With WebRender, it also
allows us to upload less data per frame update which can be another
source of jank.
It is possible for a decoder's iterator to be invalid in some error
conditions, all related to the ICO decoder seeking behaviour. Since we
assume that the iterator is always valid for the purposes of generating
the decoder's telemetry data, a malformed ICO image could cause a crash.
This patch removes the assumption that the iterator is valid, and
ensures we don't add the decoder's data to telemetry if it is invalid.
This patch adds three telemetry scalars to track how WebP is used. All
of these scalars are updated when we do the MIME type confirmation for
an imgRequest when the first data comes in. We know at this point we
decided to load the given content, so there should be minimal false
positives for data the browser loaded but never displayed.
The first two scalars are merely whether or not WebP was observed. One
is for probes, which are tiny WebP images suggested by the Google WebP
FAQ to probe for different aspects of WebP support (lossy, animated,
etc). We want to count this separately as actual WebP content that the
website wishes us to display. Probes will give a measure of how many
users visit websites that probe for WebP support, and content will give
a measure of how many websites don't care and just give us WebP images
regardless.
The third scalar is intended to give a relative measure of how many WebP
images we are being served relative to all other image types. We expect
the ratio to be small, but it would be good to confirm this from the
data.
This patch is an automatic replacement of s/NS_NOTREACHED/MOZ_ASSERT_UNREACHABLE/. Reindenting long lines and whitespace fixups follow in patch 6b.
MozReview-Commit-ID: 5UQVHElSpCr
--HG--
extra : rebase_source : 4c1b2fc32b269342f07639266b64941e2270e9c4
extra : source : 907543f6eae716f23a6de52b1ffb1c82908d158a
Crash reports indicate that SourceBuffer::mStatus is not set, and thus
SourceBuffer::AppendFromInputStream crashes due to dereferencing an
invalid Maybe<nsresult> object. Since SourceBuffer::Append cannot fail
without mStatus being set (or already set), it must mean that the input
stream failed to read all the data, and swallowed any internal errors.
While we used to assert in this situation, we also silently swallowed
the error historically. This patch will check mStatus, but if it is
unavailable, it will assert like before, and silently return otherwise.
This patch splits FontTableURI and BlobURL in 2 classes:
FontTableURIProtocolHandler and BlobURLProtocolHandler
both under mozilla::dom.
It also removes a memory reporter because that report is already covered by the
BlobURL one.
--HG--
rename : dom/file/nsHostObjectProtocolHandler.cpp => dom/file/BlobURLProtocolHandler.cpp
rename : dom/file/nsHostObjectProtocolHandler.h => dom/file/BlobURLProtocolHandler.h
Same approach as the other bug, mostly replacing automatically by removing
'using mozilla::Forward;' and then:
s/mozilla::Forward/std::forward/
s/Forward</std::forward</
The only file that required manual fixup was TestTreeTraversal.cpp, which had
a class called TestNodeForward with template parameters :)
MozReview-Commit-ID: A88qFG5AccP
This was done automatically replacing:
s/mozilla::Move/std::move/
s/ Move(/ std::move(/
s/(Move(/(std::move(/
Removing the 'using mozilla::Move;' lines.
And then with a few manual fixups, see the bug for the split series..
MozReview-Commit-ID: Jxze3adipUh
We can easily use Maybe<DataSourceSurface::ScopedMap> instead of
allocated the map on the heap. This does require some minor changes to
ScopedMap to properly support moves, but should be much more efficient.
In FrameAnimator::GetCompositedFrame, we call SurfaceCache::Lookup even
when we use the composited frame directly and leave the lookup result
unused. The only value in performing the lookup could be to mark the
surface as used to avoid expiring it too soon, but
FrameAnimator::RequestRefresh should already be doing enough to keep it
alive, if the image isn't locked in the first place.
In FrameAnimator::RequestRefresh and AdvanceFrame, we currently create
several RawAccessFrameRef objects to the same frames, either to get
timeouts or perform the blending. With some tweaking, we can avoid
requesting the same frame more than once. This will avoid mutex locks on
the surface provider and the frame itself.
DrawableSurface only exposes DrawableFrameRef to its users. This is
sufficient for the drawing related code in general, but FrameAnimator
really needs RawAccessFrameRef to the underlying pixel data (which may
be paletted). While one can get a RawAccessFrameRef from a
DrawableFrameRef, it requires yet another lock of the imgFrame's mutex.
We can avoid this extra lock if we just allow the callers to get the
right data type in the first place.
RawAccessFrameRef ensures there is a valid data pointer to the pixel
data for the frame. It is a common pattern for users of
RawAccessFrameRef to follow up with a request for the data pointer
shortly after creation. We can avoid an extra lock by exposing this data
pointer from RawAccessFrameRef, and populating it via
imgFrame::LockImageData.
We currently choose to set the animation parameters (blend method, blend
rect, disposal method, timeout) in imgFrame::Finish instead of
imgFrame::InitForDecoder. The decoders themselves already have access to
the necessary information at the time InitForDecoder is called, so there
is no reason to do this. Moving the configuration to initialization will
allow us to relax the mutex protection on these parameters.
This part simply reorganizes imgFrame, and subsequent parts will
introduce the necessary changes to SurfacePipe and decoders.
We should avoiding creating a DrawTarget to create a new
DataSourceSurface when the original surface produced by
RasterImage::GetFrameAtSize matches our requirements in
imgTools::EncodeScaledImage. We should also be using Skia instead of
Cairo.
This patch also fixes a few error conditions where we would not have
unmapped the surface properly.
nsGIFDecoder2::YieldPixel is sufficiently complex that the optimizer
does not appear to inline it with the rest of the templated methods. As
such there is a high cost to calling it. This patch modifies it to yield
a requested number of pixels before exiting, allowing us to amortize the
cost of calling across a row instead of a pixel. Based on profiling,
this will significantly reduce the time require to decode a frame.
It has been observed in profiling that the templated methods that write
pixels to an image buffer do not always inline methods properly, leading
to a high cost of writing a single pixel if it is less than trivial. As
such, there is a new SurfacePipe method, WritePixelBlocks, which
requests pixels in blocks. The provided lambda will write up to the
requested number of pixels into the given buffer. WritePixelBlocks
itself will request enough pixels to fill the row, advance the row if
complete and iterate until it is complete or we need more data.
Regardless of the size of an encoded image, SourceBuffer::Compact would
try to consolidate all of the chunks into a single chunk. If an image is
quite large, it can be actively harmful to do this, because we want a
very large contiguous chunk of memory for no real reason, and spend
extra time on the main thread doing the memcpy/consolidation.
Instead we now cap out the chunk size at 20MB. If we start allocating
chunks of this size, we will not perform compacting when we have
received all of the data. (Save for realloc'ing the last chunk since it
probably isn't full.)
On a related note, if we hit an out-of-memory condition in the middle of
appending data to the SourceBuffer, we would swallow the error. This is
because nsIInputStream::ReadSegments will succeed if any data was
written. This leaves the SourceBuffer out of sync. We now propogate this
error up properly to the higher levels.
fixup
All animated images on a page are currently registered with the refresh
driver and advance with the tick refresh. These animations may not even
be in view, and if they are large and thus cause redecoding, cause a
marked increase in CPU usage for no benefit to the user.
This patch adds an additional flag, mCompositedFrameRequested, to the
AnimationState used by FrameAnimator. It is set to true each time the
current animated image frame is requested via
FrameAnimator::GetCompositedFrame. It is set to false each time the
frame is advanced in FrameAnimator::AdvanceFrame (via
FrameAnimator::RequestRefresh). If it is true when
FrameAnimator::RequestRefresh is called, then it will advance the
animation according to the normal rules. If it is false, then it will
set the current animation time to the current time instead of advancing.
This should not cause the animation to fall behind anymore or skip
frames more than it does today. This is because if
FrameAnimator::GetCompositedFrame is not called, then the internal state
of the animation is advancing ahead of what the user sees. Once it is
called, the new frame is far ahead of the previously displayed frame.
The only difference now is that we will display the previous frame for
slightly longer until the next refresh tick.
Note that if an animated image is layerized (should not happen today) or
otherwise uses an ImageContainer, this optimization fails. While we know
whether or not we have an image container, we do not know if anything is
actively using it.
We can discard frames from an animated image if the memory footprint
exceeds the threshold. This will cause us to redecode frames on demand
instead. However decoders can fail to produce the same results on
subsequent runs due to differences in memory pressure, etc. If this
happens our state can get inconsistent. In particular, if we keep
failing on the first frame, we end up in an infinite loop on the decoder
thread.
Since we don't have the owning image to signal, as we had to release our
reference to it after the first pass, we can do little but stop decoding.
From the user's perspective, the animation will come to a stop.
If an imgCacheValidator object is destroyed without calling
imgCacheValidator::OnStartRequest, or imgRequest::Init fails in
OnStartRequest, we left the bound proxies hanging on an update. Now we
cancel the new request, and bind the validating proxies to said request
to ensure their listeners fail gracefully.
We can discard frames from an animated image if the memory footprint
exceeds the threshold. This will cause us to redecode frames on demand
instead. However decoders can fail to produce the same results on
subsequent runs due to differences in memory pressure, etc. If this
happens our state can get inconsistent. In particular, if we keep
failing on the first frame, we end up in an infinite loop on the decoder
thread.
Since we don't have the owning image to signal, as we had to release our
reference to it after the first pass, we can do little but stop decoding.
From the user's perspective, the animation will come to a stop.
Many of these could probably be fuzzed but in the interests of getting
the reftest suite turned on sooner I'm doing a blanket fails-if. This
covers all the reftests where there is more fuzz with webrender on
windows than any of existing annotations account for. In some cases the
fuzz is only a few pixels more than the equivalent Linux fuzz already
annotated, but I'll clean that up in a future bug.
MozReview-Commit-ID: IaKarbnL46d
--HG--
extra : rebase_source : 71889340305b0b12fa8eace722e42bb3faf14419
NullPrincipal::Create() (will null OA) may cause an OriginAttributes bypass.
We change Create() so OriginAttributes is no longer optional, and rename
Create() with no arguments to make it more explicit about what the caller is doing.
MozReview-Commit-ID: 7DQGlgh1tgJ
When we shutdown the decode pool threads, it does not do a simple join
with the main thread. It will actually process the main thread event
loop, which can cause a bad series of events. The refresh tick could
still be running and advancing our animated images, causing the animated
decoders to continue running, which in turn prevents the decoder threads
from finishing shutting down, and the main thread from joining them.
Now we check on each frame whether or not the decoder should just stop
decoding more frames because the decode pool has started shutdown. If it
has, it will stop immediately.
We should only attempt to discard animation image frames after passing
the frame threshold on the very first pass on the animation. Redecodes
are already in the correct state, as it will discard frames as it
advances the animation. This patch makes it clear what it should be
doing when, but there should be no functional change.
* Deserialization now only happens via a mutator
* The CID for URI implementations actually returns the nsIURIMutator for each class
* The QueryInterface of mutators implementing nsISerializable will now act as a finalizer if passed the IID of an interface implemented by the URI it holds
MozReview-Commit-ID: H5MUJOEkpia
--HG--
extra : rebase_source : 01c8d16f7d31977eda6ca061e7889cedbf6940c2
* Deserialization now only happens via a mutator
* The CID for URI implementations actually returns the nsIURIMutator for each class
* The QueryInterface of mutators implementing nsISerializable will now act as a finalizer if passed the IID of an interface implemented by the URI it holds
MozReview-Commit-ID: H5MUJOEkpia
--HG--
extra : rebase_source : 8ebb459445cab23288a6c4c86e4e00c6ee611e34