forked from mirrors/gecko-dev
Bug 1510139 - Part 2. Do not invalidate vector image containers synchronously. r=tnikkel
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
This commit is contained in:
parent
2d6036e804
commit
ddb99ba9af
1 changed files with 34 additions and 7 deletions
|
|
@ -542,7 +542,6 @@ VectorImage::RequestRefresh(const TimeStamp& aTime) {
|
||||||
mSVGDocumentWrapper->TickRefreshDriver();
|
mSVGDocumentWrapper->TickRefreshDriver();
|
||||||
|
|
||||||
if (mHasPendingInvalidation) {
|
if (mHasPendingInvalidation) {
|
||||||
mHasPendingInvalidation = false;
|
|
||||||
SendInvalidationNotifications();
|
SendInvalidationNotifications();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -555,14 +554,16 @@ void VectorImage::SendInvalidationNotifications() {
|
||||||
// notifications there to ensure that there is actually a document observing
|
// notifications there to ensure that there is actually a document observing
|
||||||
// us. Otherwise, the notifications are just wasted effort.
|
// us. Otherwise, the notifications are just wasted effort.
|
||||||
//
|
//
|
||||||
// Non-animated images call this method directly from
|
// Non-animated images post an event to call this method from
|
||||||
// InvalidateObserversOnNextRefreshDriverTick, because RequestRefresh is never
|
// InvalidateObserversOnNextRefreshDriverTick, because RequestRefresh is never
|
||||||
// called for them. Ordinarily this isn't needed, since we send out
|
// called for them. Ordinarily this isn't needed, since we send out
|
||||||
// invalidation notifications in OnSVGDocumentLoaded, but in rare cases the
|
// invalidation notifications in OnSVGDocumentLoaded, but in rare cases the
|
||||||
// SVG document may not be 100% ready to render at that time. In those cases
|
// SVG document may not be 100% ready to render at that time. In those cases
|
||||||
// we would miss the subsequent invalidations if we didn't send out the
|
// we would miss the subsequent invalidations if we didn't send out the
|
||||||
// notifications directly in |InvalidateObservers...|.
|
// notifications indirectly in |InvalidateObservers...|.
|
||||||
|
|
||||||
|
MOZ_ASSERT(mHasPendingInvalidation);
|
||||||
|
mHasPendingInvalidation = false;
|
||||||
SurfaceCache::RemoveImage(ImageKey(this));
|
SurfaceCache::RemoveImage(ImageKey(this));
|
||||||
|
|
||||||
if (UpdateImageContainer(Nothing())) {
|
if (UpdateImageContainer(Nothing())) {
|
||||||
|
|
@ -1472,11 +1473,37 @@ VectorImage::OnDataAvailable(nsIRequest* aRequest, nsISupports* aCtxt,
|
||||||
// Invalidation helper method
|
// Invalidation helper method
|
||||||
|
|
||||||
void VectorImage::InvalidateObserversOnNextRefreshDriverTick() {
|
void VectorImage::InvalidateObserversOnNextRefreshDriverTick() {
|
||||||
if (mHaveAnimations) {
|
if (mHasPendingInvalidation) {
|
||||||
mHasPendingInvalidation = true;
|
return;
|
||||||
} else {
|
|
||||||
SendInvalidationNotifications();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mHasPendingInvalidation = true;
|
||||||
|
|
||||||
|
// Animated images can wait for the refresh tick.
|
||||||
|
if (mHaveAnimations) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non-animated images won't get the refresh tick, so we should just send an
|
||||||
|
// invalidation outside the current execution context. We need to defer
|
||||||
|
// because the layout tree is in the middle of invalidation, and the tree
|
||||||
|
// state needs to be consistent. Specifically only some of the frames have
|
||||||
|
// had the NS_FRAME_DESCENDANT_NEEDS_PAINT and/or NS_FRAME_NEEDS_PAINT bits
|
||||||
|
// set by InvalidateFrameInternal in layout/generic/nsFrame.cpp. These bits
|
||||||
|
// get cleared when we repaint the SVG into a surface by
|
||||||
|
// nsIFrame::ClearInvalidationStateBits in nsDisplayList::PaintRoot.
|
||||||
|
nsCOMPtr<nsIEventTarget> eventTarget;
|
||||||
|
if (mProgressTracker) {
|
||||||
|
eventTarget = mProgressTracker->GetEventTarget();
|
||||||
|
} else {
|
||||||
|
eventTarget = do_GetMainThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<VectorImage> self(this);
|
||||||
|
nsCOMPtr<nsIRunnable> ev(NS_NewRunnableFunction(
|
||||||
|
"VectorImage::SendInvalidationNotifications",
|
||||||
|
[=]() -> void { self->SendInvalidationNotifications(); }));
|
||||||
|
eventTarget->Dispatch(ev.forget(), NS_DISPATCH_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VectorImage::PropagateUseCounters(Document* aParentDocument) {
|
void VectorImage::PropagateUseCounters(Document* aParentDocument) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue