mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
merge mozilla-central to mozilla-inbound
This commit is contained in:
commit
fad4d039ef
@ -3631,7 +3631,6 @@ nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext, nsIFrame* aFrame,
|
||||
PaintFrameFlags aFlags)
|
||||
{
|
||||
AUTO_PROFILER_LABEL("nsLayoutUtils::PaintFrame", GRAPHICS);
|
||||
typedef RetainedDisplayListBuilder::PartialUpdateResult PartialUpdateResult;
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
if (!gPaintCountStack) {
|
||||
@ -3789,7 +3788,6 @@ nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext, nsIFrame* aFrame,
|
||||
}
|
||||
|
||||
nsRect visibleRect = visibleRegion.GetBounds();
|
||||
PartialUpdateResult updateState = PartialUpdateResult::Failed;
|
||||
|
||||
{
|
||||
AUTO_PROFILER_LABEL("nsLayoutUtils::PaintFrame:BuildDisplayList",
|
||||
@ -3839,20 +3837,22 @@ nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext, nsIFrame* aFrame,
|
||||
// Attempt to do a partial build and merge into the existing list.
|
||||
// This calls BuildDisplayListForStacking context on a subset of the
|
||||
// viewport.
|
||||
bool merged = false;
|
||||
|
||||
if (useRetainedBuilder) {
|
||||
if (gfxPrefs::LayoutVerifyRetainDisplayList()) {
|
||||
beforeMergeChecker.Set(&list, "BM");
|
||||
}
|
||||
updateState = retainedBuilder->AttemptPartialUpdate(
|
||||
merged = retainedBuilder->AttemptPartialUpdate(
|
||||
aBackstop, beforeMergeChecker ? &toBeMergedChecker : nullptr);
|
||||
if ((updateState != PartialUpdateResult::Failed) && beforeMergeChecker) {
|
||||
if (merged && beforeMergeChecker) {
|
||||
afterMergeChecker.Set(&list, "AM");
|
||||
}
|
||||
}
|
||||
|
||||
if ((updateState != PartialUpdateResult::Failed) &&
|
||||
if (merged &&
|
||||
(gfxPrefs::LayoutDisplayListBuildTwice() || afterMergeChecker)) {
|
||||
updateState = PartialUpdateResult::Failed;
|
||||
merged = false;
|
||||
if (gfxPrefs::LayersDrawFPS()) {
|
||||
if (RefPtr<LayerManager> lm = builder.GetWidgetLayerManager()) {
|
||||
if (PaintTiming* pt = ClientLayerManager::MaybeGetPaintTiming(lm)) {
|
||||
@ -3863,7 +3863,7 @@ nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext, nsIFrame* aFrame,
|
||||
dlStart = TimeStamp::Now();
|
||||
}
|
||||
|
||||
if (updateState == PartialUpdateResult::Failed) {
|
||||
if (!merged) {
|
||||
list.DeleteAll(&builder);
|
||||
builder.EnterPresShell(aFrame);
|
||||
builder.SetDirtyRect(visibleRect);
|
||||
@ -3872,7 +3872,6 @@ nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext, nsIFrame* aFrame,
|
||||
AddExtraBackgroundItems(builder, list, aFrame, canvasArea, visibleRegion, aBackstop);
|
||||
|
||||
builder.LeavePresShell(aFrame, &list);
|
||||
updateState = PartialUpdateResult::Updated;
|
||||
|
||||
if (afterMergeChecker) {
|
||||
DisplayListChecker nonRetainedChecker(&list, "NR");
|
||||
@ -3910,7 +3909,6 @@ nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext, nsIFrame* aFrame,
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(updateState != PartialUpdateResult::Failed);
|
||||
builder.Check();
|
||||
|
||||
Telemetry::AccumulateTimeDelta(Telemetry::PAINT_BUILD_DISPLAYLIST_TIME,
|
||||
@ -3985,9 +3983,6 @@ nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext, nsIFrame* aFrame,
|
||||
if (aFlags & PaintFrameFlags::PAINT_COMPRESSED) {
|
||||
flags |= nsDisplayList::PAINT_COMPRESSED;
|
||||
}
|
||||
if (updateState == PartialUpdateResult::NoChange) {
|
||||
flags |= nsDisplayList::PAINT_IDENTICAL_DISPLAY_LIST;
|
||||
}
|
||||
|
||||
TimeStamp paintStart = TimeStamp::Now();
|
||||
RefPtr<LayerManager> layerManager
|
||||
|
@ -194,7 +194,7 @@ nsPresContext::MakeColorPref(const nsString& aColor)
|
||||
bool
|
||||
nsPresContext::IsDOMPaintEventPending()
|
||||
{
|
||||
if (!mTransactions.IsEmpty()) {
|
||||
if (mFireAfterPaintEvents) {
|
||||
return true;
|
||||
}
|
||||
nsRootPresContext* drpc = GetRootPresContext();
|
||||
@ -203,6 +203,7 @@ nsPresContext::IsDOMPaintEventPending()
|
||||
// fired, we record an empty invalidation in case display list
|
||||
// invalidation doesn't invalidate anything further.
|
||||
NotifyInvalidation(drpc->mRefreshDriver->LastTransactionId() + 1, nsRect(0, 0, 0, 0));
|
||||
NS_ASSERTION(mFireAfterPaintEvents, "Why aren't we planning to fire the event?");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -314,6 +315,7 @@ nsPresContext::nsPresContext(nsIDocument* aDocument, nsPresContextType aType)
|
||||
mFontFeatureValuesDirty(true),
|
||||
mSuppressResizeReflow(false),
|
||||
mIsVisual(false),
|
||||
mFireAfterPaintEvents(false),
|
||||
mIsChrome(false),
|
||||
mIsChromeOriginImage(false),
|
||||
mPaintFlashing(false),
|
||||
@ -2594,17 +2596,6 @@ nsPresContext::NotifyInvalidation(uint64_t aTransactionId, const nsIntRect& aRec
|
||||
NotifyInvalidation(aTransactionId, rect);
|
||||
}
|
||||
|
||||
nsPresContext::TransactionInvalidations*
|
||||
nsPresContext::GetInvalidations(uint64_t aTransactionId)
|
||||
{
|
||||
for (TransactionInvalidations& t : mTransactions) {
|
||||
if (t.mTransactionId == aTransactionId) {
|
||||
return &t;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
nsPresContext::NotifyInvalidation(uint64_t aTransactionId, const nsRect& aRect)
|
||||
{
|
||||
@ -2618,13 +2609,9 @@ nsPresContext::NotifyInvalidation(uint64_t aTransactionId, const nsRect& aRect)
|
||||
|
||||
nsPresContext* pc;
|
||||
for (pc = this; pc; pc = pc->GetParentPresContext()) {
|
||||
TransactionInvalidations* transaction = pc->GetInvalidations(aTransactionId);
|
||||
if (transaction) {
|
||||
if (pc->mFireAfterPaintEvents)
|
||||
break;
|
||||
} else {
|
||||
transaction = pc->mTransactions.AppendElement();
|
||||
transaction->mTransactionId = aTransactionId;
|
||||
}
|
||||
pc->mFireAfterPaintEvents = true;
|
||||
}
|
||||
if (!pc) {
|
||||
nsRootPresContext* rpc = GetRootPresContext();
|
||||
@ -2633,8 +2620,18 @@ nsPresContext::NotifyInvalidation(uint64_t aTransactionId, const nsRect& aRect)
|
||||
}
|
||||
}
|
||||
|
||||
TransactionInvalidations* transaction = GetInvalidations(aTransactionId);
|
||||
MOZ_ASSERT(transaction);
|
||||
TransactionInvalidations* transaction = nullptr;
|
||||
for (TransactionInvalidations& t : mTransactions) {
|
||||
if (t.mTransactionId == aTransactionId) {
|
||||
transaction = &t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!transaction) {
|
||||
transaction = mTransactions.AppendElement();
|
||||
transaction->mTransactionId = aTransactionId;
|
||||
}
|
||||
|
||||
transaction->mInvalidations.AppendElement(aRect);
|
||||
}
|
||||
|
||||
@ -2686,6 +2683,7 @@ nsPresContext::ClearNotifySubDocInvalidationData(ContainerLayer* aContainer)
|
||||
struct NotifyDidPaintSubdocumentCallbackClosure {
|
||||
uint64_t mTransactionId;
|
||||
const mozilla::TimeStamp& mTimeStamp;
|
||||
bool mNeedsAnotherDidPaintNotification;
|
||||
};
|
||||
/* static */ bool
|
||||
nsPresContext::NotifyDidPaintSubdocumentCallback(nsIDocument* aDocument, void* aData)
|
||||
@ -2698,6 +2696,9 @@ nsPresContext::NotifyDidPaintSubdocumentCallback(nsIDocument* aDocument, void* a
|
||||
if (pc) {
|
||||
pc->NotifyDidPaintForSubtree(closure->mTransactionId,
|
||||
closure->mTimeStamp);
|
||||
if (pc->mFireAfterPaintEvents) {
|
||||
closure->mNeedsAnotherDidPaintNotification = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -2742,12 +2743,12 @@ nsPresContext::NotifyDidPaintForSubtree(uint64_t aTransactionId,
|
||||
if (IsRoot()) {
|
||||
static_cast<nsRootPresContext*>(this)->CancelDidPaintTimers(aTransactionId);
|
||||
|
||||
if (mTransactions.IsEmpty()) {
|
||||
if (!mFireAfterPaintEvents) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PresShell()->IsVisible() && mTransactions.IsEmpty()) {
|
||||
if (!PresShell()->IsVisible() && !mFireAfterPaintEvents) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2761,13 +2762,11 @@ nsPresContext::NotifyDidPaintForSubtree(uint64_t aTransactionId,
|
||||
uint32_t i = 0;
|
||||
while (i < mTransactions.Length()) {
|
||||
if (mTransactions[i].mTransactionId <= aTransactionId) {
|
||||
if (!mTransactions[i].mInvalidations.IsEmpty()) {
|
||||
nsCOMPtr<nsIRunnable> ev =
|
||||
new DelayedFireDOMPaintEvent(this, &mTransactions[i].mInvalidations,
|
||||
mTransactions[i].mTransactionId, aTimeStamp);
|
||||
nsContentUtils::AddScriptRunner(ev);
|
||||
sent = true;
|
||||
}
|
||||
nsCOMPtr<nsIRunnable> ev =
|
||||
new DelayedFireDOMPaintEvent(this, &mTransactions[i].mInvalidations,
|
||||
mTransactions[i].mTransactionId, aTimeStamp);
|
||||
nsContentUtils::AddScriptRunner(ev);
|
||||
sent = true;
|
||||
mTransactions.RemoveElementAt(i);
|
||||
} else {
|
||||
i++;
|
||||
@ -2782,8 +2781,14 @@ nsPresContext::NotifyDidPaintForSubtree(uint64_t aTransactionId,
|
||||
nsContentUtils::AddScriptRunner(ev);
|
||||
}
|
||||
|
||||
NotifyDidPaintSubdocumentCallbackClosure closure = { aTransactionId, aTimeStamp };
|
||||
NotifyDidPaintSubdocumentCallbackClosure closure = { aTransactionId, aTimeStamp, false };
|
||||
mDocument->EnumerateSubDocuments(nsPresContext::NotifyDidPaintSubdocumentCallback, &closure);
|
||||
|
||||
if (!closure.mNeedsAnotherDidPaintNotification &&
|
||||
mTransactions.IsEmpty()) {
|
||||
// Nothing more to do for the moment.
|
||||
mFireAfterPaintEvents = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1291,12 +1291,6 @@ protected:
|
||||
const char* aName,
|
||||
uint32_t aDelay);
|
||||
|
||||
struct TransactionInvalidations {
|
||||
uint64_t mTransactionId;
|
||||
nsTArray<nsRect> mInvalidations;
|
||||
};
|
||||
TransactionInvalidations* GetInvalidations(uint64_t aTransactionId);
|
||||
|
||||
// IMPORTANT: The ownership implicit in the following member variables
|
||||
// has been explicitly checked. If you add any members to this class,
|
||||
// please make the ownership explicit (pinkerton, scc).
|
||||
@ -1365,6 +1359,10 @@ protected:
|
||||
|
||||
mozilla::UniquePtr<nsBidi> mBidiEngine;
|
||||
|
||||
struct TransactionInvalidations {
|
||||
uint64_t mTransactionId;
|
||||
nsTArray<nsRect> mInvalidations;
|
||||
};
|
||||
AutoTArray<TransactionInvalidations, 4> mTransactions;
|
||||
|
||||
// text performance metrics
|
||||
@ -1491,6 +1489,8 @@ protected:
|
||||
|
||||
unsigned mIsVisual : 1;
|
||||
|
||||
unsigned mFireAfterPaintEvents : 1;
|
||||
|
||||
unsigned mIsChrome : 1;
|
||||
unsigned mIsChromeOriginImage : 1;
|
||||
|
||||
|
@ -104,25 +104,21 @@ SelectAGRForFrame(nsIFrame* aFrame, AnimatedGeometryRoot* aParentAGR)
|
||||
// TODO: We currently descend into all children even if we don't have an AGR
|
||||
// to mark, as child stacking contexts might. It would be nice if we could
|
||||
// jump into those immediately rather than walking the entire thing.
|
||||
bool
|
||||
void
|
||||
RetainedDisplayListBuilder::PreProcessDisplayList(nsDisplayList* aList,
|
||||
AnimatedGeometryRoot* aAGR)
|
||||
{
|
||||
bool modified = false;
|
||||
nsDisplayList saved;
|
||||
while (nsDisplayItem* i = aList->RemoveBottom()) {
|
||||
if (i->HasDeletedFrame() || !i->CanBeReused()) {
|
||||
i->Destroy(&mBuilder);
|
||||
modified = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
nsIFrame* f = i->Frame();
|
||||
|
||||
if (i->GetChildren()) {
|
||||
if (PreProcessDisplayList(i->GetChildren(), SelectAGRForFrame(f, aAGR))) {
|
||||
modified = true;
|
||||
}
|
||||
PreProcessDisplayList(i->GetChildren(), SelectAGRForFrame(f, aAGR));
|
||||
}
|
||||
|
||||
// TODO: We should be able to check the clipped bounds relative
|
||||
@ -130,7 +126,6 @@ RetainedDisplayListBuilder::PreProcessDisplayList(nsDisplayList* aList,
|
||||
// frame) and determine if they can ever intersect.
|
||||
if (aAGR && i->GetAnimatedGeometryRoot()->GetAsyncAGR() != aAGR) {
|
||||
mBuilder.MarkFrameForDisplayIfVisible(f, mBuilder.RootReferenceFrame());
|
||||
modified = true;
|
||||
}
|
||||
|
||||
// TODO: This is here because we sometimes reuse the previous display list
|
||||
@ -142,7 +137,6 @@ RetainedDisplayListBuilder::PreProcessDisplayList(nsDisplayList* aList,
|
||||
}
|
||||
aList->AppendToTop(&saved);
|
||||
aList->RestoreState();
|
||||
return modified;
|
||||
}
|
||||
|
||||
bool IsSameItem(nsDisplayItem* aFirst, nsDisplayItem* aSecond)
|
||||
@ -205,13 +199,12 @@ void SwapAndRemove(nsTArray<T>& aArray, uint32_t aIndex)
|
||||
aArray.RemoveElementAt(aArray.Length() - 1);
|
||||
}
|
||||
|
||||
static bool
|
||||
static void
|
||||
MergeFrameRects(nsDisplayLayerEventRegions* aOldItem,
|
||||
nsDisplayLayerEventRegions* aNewItem,
|
||||
nsDisplayLayerEventRegions::FrameRects nsDisplayLayerEventRegions::*aRectList,
|
||||
nsTArray<nsIFrame*>& aAddedFrames)
|
||||
{
|
||||
bool modified = false;
|
||||
// Go through the old item's rect list and remove any rectangles
|
||||
// belonging to invalidated frames (deleted frames should
|
||||
// already be gone at this point)
|
||||
@ -226,13 +219,12 @@ MergeFrameRects(nsDisplayLayerEventRegions* aOldItem,
|
||||
f->RemoveDisplayItem(aOldItem);
|
||||
SwapAndRemove(oldRects.mFrames, i);
|
||||
SwapAndRemove(oldRects.mBoxes, i);
|
||||
modified = true;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (!aNewItem) {
|
||||
return modified;
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy items from the source list to the dest list, but
|
||||
@ -253,15 +245,12 @@ MergeFrameRects(nsDisplayLayerEventRegions* aOldItem,
|
||||
// FrameRects lists, so defer that until the end.
|
||||
aAddedFrames.AppendElement(f);
|
||||
MOZ_ASSERT(f != aOldItem->Frame());
|
||||
|
||||
modified = true;
|
||||
}
|
||||
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
bool MergeLayerEventRegions(nsDisplayItem* aOldItem,
|
||||
void MergeLayerEventRegions(nsDisplayItem* aOldItem,
|
||||
nsDisplayItem* aNewItem)
|
||||
{
|
||||
nsDisplayLayerEventRegions* oldItem =
|
||||
@ -271,13 +260,12 @@ bool MergeLayerEventRegions(nsDisplayItem* aOldItem,
|
||||
|
||||
nsTArray<nsIFrame*> addedFrames;
|
||||
|
||||
bool modified = false;
|
||||
modified |= MergeFrameRects(oldItem, newItem, &nsDisplayLayerEventRegions::mHitRegion, addedFrames);
|
||||
modified |= MergeFrameRects(oldItem, newItem, &nsDisplayLayerEventRegions::mMaybeHitRegion, addedFrames);
|
||||
modified |= MergeFrameRects(oldItem, newItem, &nsDisplayLayerEventRegions::mDispatchToContentHitRegion, addedFrames);
|
||||
modified |= MergeFrameRects(oldItem, newItem, &nsDisplayLayerEventRegions::mNoActionRegion, addedFrames);
|
||||
modified |= MergeFrameRects(oldItem, newItem, &nsDisplayLayerEventRegions::mHorizontalPanRegion, addedFrames);
|
||||
modified |= MergeFrameRects(oldItem, newItem, &nsDisplayLayerEventRegions::mVerticalPanRegion, addedFrames);
|
||||
MergeFrameRects(oldItem, newItem, &nsDisplayLayerEventRegions::mHitRegion, addedFrames);
|
||||
MergeFrameRects(oldItem, newItem, &nsDisplayLayerEventRegions::mMaybeHitRegion, addedFrames);
|
||||
MergeFrameRects(oldItem, newItem, &nsDisplayLayerEventRegions::mDispatchToContentHitRegion, addedFrames);
|
||||
MergeFrameRects(oldItem, newItem, &nsDisplayLayerEventRegions::mNoActionRegion, addedFrames);
|
||||
MergeFrameRects(oldItem, newItem, &nsDisplayLayerEventRegions::mHorizontalPanRegion, addedFrames);
|
||||
MergeFrameRects(oldItem, newItem, &nsDisplayLayerEventRegions::mVerticalPanRegion, addedFrames);
|
||||
|
||||
// MergeFrameRects deferred updating the display item data list during
|
||||
// processing so that earlier calls didn't change the result of later
|
||||
@ -287,7 +275,6 @@ bool MergeLayerEventRegions(nsDisplayItem* aOldItem,
|
||||
f->AddDisplayItem(aOldItem);
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
void
|
||||
@ -401,14 +388,12 @@ void UpdateASR(nsDisplayItem* aItem,
|
||||
*
|
||||
* Merged List: C, A, B
|
||||
*/
|
||||
bool
|
||||
void
|
||||
RetainedDisplayListBuilder::MergeDisplayLists(nsDisplayList* aNewList,
|
||||
nsDisplayList* aOldList,
|
||||
nsDisplayList* aOutList,
|
||||
Maybe<const ActiveScrolledRoot*>& aOutContainerASR)
|
||||
{
|
||||
bool modified = false;
|
||||
|
||||
nsDisplayList merged;
|
||||
const auto UseItem = [&](nsDisplayItem* aItem) {
|
||||
const ActiveScrolledRoot* itemClipASR =
|
||||
@ -472,11 +457,9 @@ RetainedDisplayListBuilder::MergeDisplayLists(nsDisplayList* aNewList,
|
||||
oldListLookup.Remove({ old->Frame(), old->GetPerFrameKey() });
|
||||
aOldList->RemoveBottom();
|
||||
old->Destroy(&mBuilder);
|
||||
modified = true;
|
||||
} else if (newListLookup.Get({ old->Frame(), old->GetPerFrameKey() })) {
|
||||
// This old item is also in the new list, but we haven't got to it yet.
|
||||
// Stop now, and we'll deal with it when we get to the new entry.
|
||||
modified = true;
|
||||
break;
|
||||
} else {
|
||||
// Recurse into the child list (without a matching new list) to
|
||||
@ -484,10 +467,8 @@ RetainedDisplayListBuilder::MergeDisplayLists(nsDisplayList* aNewList,
|
||||
if (old->GetChildren()) {
|
||||
nsDisplayList empty;
|
||||
Maybe<const ActiveScrolledRoot*> containerASRForChildren;
|
||||
if (MergeDisplayLists(&empty, old->GetChildren(),
|
||||
old->GetChildren(), containerASRForChildren)) {
|
||||
modified = true;
|
||||
}
|
||||
MergeDisplayLists(&empty, old->GetChildren(),
|
||||
old->GetChildren(), containerASRForChildren);
|
||||
UpdateASR(old, containerASRForChildren);
|
||||
old->UpdateBounds(&mBuilder);
|
||||
}
|
||||
@ -517,21 +498,16 @@ RetainedDisplayListBuilder::MergeDisplayLists(nsDisplayList* aNewList,
|
||||
// the lists of regions and frames, so we have no need to use the
|
||||
// newer item. Always use the old item instead since we assume it's
|
||||
// likely to have the bigger lists and merging will be quicker.
|
||||
if (MergeLayerEventRegions(oldItem, newItem)) {
|
||||
modified = true;
|
||||
}
|
||||
MergeLayerEventRegions(oldItem, newItem);
|
||||
ReuseItem(oldItem);
|
||||
newItem->Destroy(&mBuilder);
|
||||
} else {
|
||||
if (IsAnyAncestorModified(oldItem->FrameForInvalidation())) {
|
||||
modified = true;
|
||||
} else if (oldItem->GetChildren()) {
|
||||
if (!IsAnyAncestorModified(oldItem->FrameForInvalidation()) &&
|
||||
oldItem->GetChildren()) {
|
||||
MOZ_ASSERT(newItem->GetChildren());
|
||||
Maybe<const ActiveScrolledRoot*> containerASRForChildren;
|
||||
if (MergeDisplayLists(newItem->GetChildren(), oldItem->GetChildren(),
|
||||
newItem->GetChildren(), containerASRForChildren)) {
|
||||
modified = true;
|
||||
}
|
||||
MergeDisplayLists(newItem->GetChildren(), oldItem->GetChildren(),
|
||||
newItem->GetChildren(), containerASRForChildren);
|
||||
UpdateASR(newItem, containerASRForChildren);
|
||||
newItem->UpdateBounds(&mBuilder);
|
||||
}
|
||||
@ -544,7 +520,6 @@ RetainedDisplayListBuilder::MergeDisplayLists(nsDisplayList* aNewList,
|
||||
} else {
|
||||
// If there was no matching item in the old list, then we only need to
|
||||
// add the new item to the merged list.
|
||||
modified = true;
|
||||
UseItem(newItem);
|
||||
}
|
||||
}
|
||||
@ -562,27 +537,21 @@ RetainedDisplayListBuilder::MergeDisplayLists(nsDisplayList* aNewList,
|
||||
nsDisplayList empty;
|
||||
Maybe<const ActiveScrolledRoot*> containerASRForChildren;
|
||||
|
||||
if (MergeDisplayLists(&empty, old->GetChildren(),
|
||||
old->GetChildren(), containerASRForChildren)) {
|
||||
modified = true;
|
||||
}
|
||||
MergeDisplayLists(&empty, old->GetChildren(),
|
||||
old->GetChildren(), containerASRForChildren);
|
||||
UpdateASR(old, containerASRForChildren);
|
||||
old->UpdateBounds(&mBuilder);
|
||||
}
|
||||
if (old->GetType() == DisplayItemType::TYPE_LAYER_EVENT_REGIONS) {
|
||||
if (MergeLayerEventRegions(old, nullptr)) {
|
||||
modified = true;
|
||||
}
|
||||
MergeLayerEventRegions(old, nullptr);
|
||||
}
|
||||
ReuseItem(old);
|
||||
} else {
|
||||
old->Destroy(&mBuilder);
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
|
||||
aOutList->AppendToTop(&merged);
|
||||
return modified;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -766,8 +735,6 @@ ProcessFrame(nsIFrame* aFrame, nsDisplayListBuilder& aBuilder,
|
||||
{
|
||||
nsIFrame* currentFrame = aFrame;
|
||||
|
||||
aBuilder.MarkFrameForDisplayIfVisible(aFrame, aBuilder.RootReferenceFrame());
|
||||
|
||||
while (currentFrame != aStopAtFrame) {
|
||||
CRR_LOG("currentFrame: %p (placeholder=%d), aOverflow: %d %d %d %d\n",
|
||||
currentFrame, !aStopAtStackingContext,
|
||||
@ -818,10 +785,6 @@ ProcessFrame(nsIFrame* aFrame, nsDisplayListBuilder& aBuilder,
|
||||
/* aStopAtStackingContextAndDisplayPortAndOOFFrame = */ true,
|
||||
¤tFrame);
|
||||
MOZ_ASSERT(currentFrame);
|
||||
aOverflow.IntersectRect(aOverflow, currentFrame->GetVisualOverflowRectRelativeToSelf());
|
||||
if (aOverflow.IsEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (nsLayoutUtils::FrameHasDisplayPort(currentFrame)) {
|
||||
CRR_LOG("Frame belongs to displayport frame %p\n", currentFrame);
|
||||
@ -994,20 +957,18 @@ RetainedDisplayListBuilder::ComputeRebuildRegion(nsTArray<nsIFrame*>& aModifiedF
|
||||
ProcessFrame(f, mBuilder, &agr, overflow, mBuilder.RootReferenceFrame(),
|
||||
aOutFramesWithProps, true);
|
||||
|
||||
if (!overflow.IsEmpty()) {
|
||||
aOutDirty->UnionRect(*aOutDirty, overflow);
|
||||
CRR_LOG("Adding area to root draw area: %d %d %d %d\n",
|
||||
overflow.x, overflow.y, overflow.width, overflow.height);
|
||||
aOutDirty->UnionRect(*aOutDirty, overflow);
|
||||
CRR_LOG("Adding area to root draw area: %d %d %d %d\n",
|
||||
overflow.x, overflow.y, overflow.width, overflow.height);
|
||||
|
||||
// If we get changed frames from multiple AGRS, then just give up as it gets really complex to
|
||||
// track which items would need to be marked in MarkFramesForDifferentAGR.
|
||||
if (!*aOutModifiedAGR) {
|
||||
CRR_LOG("Setting %p as root stacking context AGR\n", agr);
|
||||
*aOutModifiedAGR = agr;
|
||||
} else if (agr && *aOutModifiedAGR != agr) {
|
||||
CRR_LOG("Found multiple AGRs in root stacking context, giving up\n");
|
||||
return false;
|
||||
}
|
||||
// If we get changed frames from multiple AGRS, then just give up as it gets really complex to
|
||||
// track which items would need to be marked in MarkFramesForDifferentAGR.
|
||||
if (!*aOutModifiedAGR) {
|
||||
CRR_LOG("Setting %p as root stacking context AGR\n", agr);
|
||||
*aOutModifiedAGR = agr;
|
||||
} else if (agr && *aOutModifiedAGR != agr) {
|
||||
CRR_LOG("Found multiple AGRs in root stacking context, giving up\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1060,36 +1021,21 @@ ClearFrameProps(nsTArray<nsIFrame*>& aFrames)
|
||||
}
|
||||
}
|
||||
|
||||
class AutoClearFramePropsArray
|
||||
{
|
||||
public:
|
||||
AutoClearFramePropsArray() = default;
|
||||
|
||||
~AutoClearFramePropsArray()
|
||||
{
|
||||
ClearFrameProps(mFrames);
|
||||
}
|
||||
|
||||
nsTArray<nsIFrame*>& Frames() { return mFrames; }
|
||||
|
||||
bool IsEmpty() const { return mFrames.IsEmpty(); }
|
||||
|
||||
private:
|
||||
nsTArray<nsIFrame*> mFrames;
|
||||
};
|
||||
|
||||
void
|
||||
RetainedDisplayListBuilder::ClearFramesWithProps()
|
||||
{
|
||||
AutoClearFramePropsArray modifiedFrames;
|
||||
AutoClearFramePropsArray framesWithProps;
|
||||
GetModifiedAndFramesWithProps(&mBuilder, &modifiedFrames.Frames(), &framesWithProps.Frames());
|
||||
nsTArray<nsIFrame*> modifiedFrames;
|
||||
nsTArray<nsIFrame*> framesWithProps;
|
||||
GetModifiedAndFramesWithProps(&mBuilder, &modifiedFrames, &framesWithProps);
|
||||
|
||||
ClearFrameProps(modifiedFrames);
|
||||
ClearFrameProps(framesWithProps);
|
||||
}
|
||||
|
||||
auto
|
||||
bool
|
||||
RetainedDisplayListBuilder::AttemptPartialUpdate(
|
||||
nscolor aBackstop,
|
||||
mozilla::DisplayListChecker* aChecker) -> PartialUpdateResult
|
||||
mozilla::DisplayListChecker* aChecker)
|
||||
{
|
||||
mBuilder.RemoveModifiedWindowRegions();
|
||||
mBuilder.ClearWindowOpaqueRegion();
|
||||
@ -1100,27 +1046,24 @@ RetainedDisplayListBuilder::AttemptPartialUpdate(
|
||||
|
||||
mBuilder.EnterPresShell(mBuilder.RootReferenceFrame());
|
||||
|
||||
// We set the override dirty regions during ComputeRebuildRegion or in
|
||||
// nsLayoutUtils::InvalidateForDisplayPortChange. The display port change also
|
||||
// marks the frame modified, so those regions are cleared here as well.
|
||||
AutoClearFramePropsArray modifiedFrames;
|
||||
AutoClearFramePropsArray framesWithProps;
|
||||
GetModifiedAndFramesWithProps(&mBuilder, &modifiedFrames.Frames(), &framesWithProps.Frames());
|
||||
nsTArray<nsIFrame*> modifiedFrames;
|
||||
nsTArray<nsIFrame*> framesWithProps;
|
||||
GetModifiedAndFramesWithProps(&mBuilder, &modifiedFrames, &framesWithProps);
|
||||
|
||||
// Do not allow partial builds if the retained display list is empty, or if
|
||||
// ShouldBuildPartial heuristic fails.
|
||||
const bool shouldBuildPartial = !mList.IsEmpty() && ShouldBuildPartial(modifiedFrames.Frames());
|
||||
const bool shouldBuildPartial = !mList.IsEmpty() && ShouldBuildPartial(modifiedFrames);
|
||||
|
||||
if (mPreviousCaret != mBuilder.GetCaretFrame()) {
|
||||
if (mPreviousCaret) {
|
||||
if (mBuilder.MarkFrameModifiedDuringBuilding(mPreviousCaret)) {
|
||||
modifiedFrames.Frames().AppendElement(mPreviousCaret);
|
||||
modifiedFrames.AppendElement(mPreviousCaret);
|
||||
}
|
||||
}
|
||||
|
||||
if (mBuilder.GetCaretFrame()) {
|
||||
if (mBuilder.MarkFrameModifiedDuringBuilding(mBuilder.GetCaretFrame())) {
|
||||
modifiedFrames.Frames().AppendElement(mBuilder.GetCaretFrame());
|
||||
modifiedFrames.AppendElement(mBuilder.GetCaretFrame());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1129,60 +1072,61 @@ RetainedDisplayListBuilder::AttemptPartialUpdate(
|
||||
|
||||
nsRect modifiedDirty;
|
||||
AnimatedGeometryRoot* modifiedAGR = nullptr;
|
||||
if (!shouldBuildPartial ||
|
||||
!ComputeRebuildRegion(modifiedFrames.Frames(), &modifiedDirty,
|
||||
&modifiedAGR, framesWithProps.Frames())) {
|
||||
mBuilder.LeavePresShell(mBuilder.RootReferenceFrame(), &mList);
|
||||
return PartialUpdateResult::Failed;
|
||||
bool merged = false;
|
||||
if (shouldBuildPartial &&
|
||||
ComputeRebuildRegion(modifiedFrames, &modifiedDirty,
|
||||
&modifiedAGR, framesWithProps)) {
|
||||
modifiedDirty.IntersectRect(modifiedDirty, mBuilder.RootReferenceFrame()->GetVisualOverflowRectRelativeToSelf());
|
||||
|
||||
PreProcessDisplayList(&mList, modifiedAGR);
|
||||
|
||||
nsDisplayList modifiedDL;
|
||||
if (!modifiedDirty.IsEmpty() || !framesWithProps.IsEmpty()) {
|
||||
mBuilder.SetDirtyRect(modifiedDirty);
|
||||
mBuilder.SetPartialUpdate(true);
|
||||
mBuilder.RootReferenceFrame()->BuildDisplayListForStackingContext(&mBuilder, &modifiedDL);
|
||||
nsLayoutUtils::AddExtraBackgroundItems(mBuilder, modifiedDL, mBuilder.RootReferenceFrame(),
|
||||
nsRect(nsPoint(0, 0), mBuilder.RootReferenceFrame()->GetSize()),
|
||||
mBuilder.RootReferenceFrame()->GetVisualOverflowRectRelativeToSelf(),
|
||||
aBackstop);
|
||||
mBuilder.SetPartialUpdate(false);
|
||||
|
||||
//printf_stderr("Painting --- Modified list (dirty %d,%d,%d,%d):\n",
|
||||
// modifiedDirty.x, modifiedDirty.y, modifiedDirty.width, modifiedDirty.height);
|
||||
//nsFrame::PrintDisplayList(&mBuilder, modifiedDL);
|
||||
|
||||
} else {
|
||||
// TODO: We can also skip layer building and painting if
|
||||
// PreProcessDisplayList didn't end up changing anything
|
||||
// Invariant: display items should have their original state here.
|
||||
// printf_stderr("Skipping display list building since nothing needed to be done\n");
|
||||
}
|
||||
|
||||
if (aChecker) {
|
||||
aChecker->Set(&modifiedDL, "TM");
|
||||
}
|
||||
|
||||
// |modifiedDL| can sometimes be empty here. We still perform the
|
||||
// display list merging to prune unused items (for example, items that
|
||||
// are not visible anymore) from the old list.
|
||||
// TODO: Optimization opportunity. In this case, MergeDisplayLists()
|
||||
// unnecessarily creates a hashtable of the old items.
|
||||
Maybe<const ActiveScrolledRoot*> dummy;
|
||||
MergeDisplayLists(&modifiedDL, &mList, &mList, dummy);
|
||||
|
||||
//printf_stderr("Painting --- Merged list:\n");
|
||||
//nsFrame::PrintDisplayList(&mBuilder, mList);
|
||||
|
||||
merged = true;
|
||||
}
|
||||
|
||||
modifiedDirty.IntersectRect(modifiedDirty, mBuilder.RootReferenceFrame()->GetVisualOverflowRectRelativeToSelf());
|
||||
|
||||
PartialUpdateResult result = PartialUpdateResult::NoChange;
|
||||
if (PreProcessDisplayList(&mList, modifiedAGR) ||
|
||||
!modifiedDirty.IsEmpty() ||
|
||||
!framesWithProps.IsEmpty()) {
|
||||
result = PartialUpdateResult::Updated;
|
||||
}
|
||||
|
||||
mBuilder.SetDirtyRect(modifiedDirty);
|
||||
mBuilder.SetPartialUpdate(true);
|
||||
|
||||
nsDisplayList modifiedDL;
|
||||
mBuilder.RootReferenceFrame()->BuildDisplayListForStackingContext(&mBuilder, &modifiedDL);
|
||||
if (!modifiedDL.IsEmpty()) {
|
||||
nsLayoutUtils::AddExtraBackgroundItems(mBuilder, modifiedDL, mBuilder.RootReferenceFrame(),
|
||||
nsRect(nsPoint(0, 0), mBuilder.RootReferenceFrame()->GetSize()),
|
||||
mBuilder.RootReferenceFrame()->GetVisualOverflowRectRelativeToSelf(),
|
||||
aBackstop);
|
||||
}
|
||||
mBuilder.SetPartialUpdate(false);
|
||||
|
||||
if (aChecker) {
|
||||
aChecker->Set(&modifiedDL, "TM");
|
||||
}
|
||||
|
||||
//printf_stderr("Painting --- Modified list (dirty %d,%d,%d,%d):\n",
|
||||
// modifiedDirty.x, modifiedDirty.y, modifiedDirty.width, modifiedDirty.height);
|
||||
//nsFrame::PrintDisplayList(&mBuilder, modifiedDL);
|
||||
|
||||
// |modifiedDL| can sometimes be empty here. We still perform the
|
||||
// display list merging to prune unused items (for example, items that
|
||||
// are not visible anymore) from the old list.
|
||||
// TODO: Optimization opportunity. In this case, MergeDisplayLists()
|
||||
// unnecessarily creates a hashtable of the old items.
|
||||
// TODO: Ideally we could skip this if result is NoChange, but currently when
|
||||
// we call RestoreState on nsDisplayWrapList it resets the clip to the base
|
||||
// clip, and we need the UpdateBounds call (within MergeDisplayLists) to
|
||||
// move it to the correct inner clip.
|
||||
Maybe<const ActiveScrolledRoot*> dummy;
|
||||
if (MergeDisplayLists(&modifiedDL, &mList, &mList, dummy)) {
|
||||
result = PartialUpdateResult::Updated;
|
||||
}
|
||||
|
||||
//printf_stderr("Painting --- Merged list:\n");
|
||||
//nsFrame::PrintDisplayList(&mBuilder, mList);
|
||||
|
||||
mBuilder.LeavePresShell(mBuilder.RootReferenceFrame(), &mList);
|
||||
return result;
|
||||
|
||||
// We set the override dirty regions during ComputeRebuildRegion or in
|
||||
// nsLayoutUtils::InvalidateForDisplayPortChange. The display port change also
|
||||
// marks the frame modified, so those regions are cleared here as well.
|
||||
ClearFrameProps(modifiedFrames);
|
||||
ClearFrameProps(framesWithProps);
|
||||
|
||||
return merged;
|
||||
}
|
||||
|
@ -29,14 +29,8 @@ struct RetainedDisplayListBuilder {
|
||||
|
||||
nsDisplayList* List() { return &mList; }
|
||||
|
||||
enum class PartialUpdateResult {
|
||||
Failed,
|
||||
NoChange,
|
||||
Updated
|
||||
};
|
||||
|
||||
PartialUpdateResult AttemptPartialUpdate(nscolor aBackstop,
|
||||
mozilla::DisplayListChecker* aChecker);
|
||||
bool AttemptPartialUpdate(nscolor aBackstop,
|
||||
mozilla::DisplayListChecker* aChecker);
|
||||
|
||||
/**
|
||||
* Iterates through the display list builder reference frame document and
|
||||
@ -49,9 +43,9 @@ struct RetainedDisplayListBuilder {
|
||||
NS_DECLARE_FRAME_PROPERTY_DELETABLE(Cached, RetainedDisplayListBuilder)
|
||||
|
||||
private:
|
||||
bool PreProcessDisplayList(nsDisplayList* aList, AnimatedGeometryRoot* aAGR);
|
||||
void PreProcessDisplayList(nsDisplayList* aList, AnimatedGeometryRoot* aAGR);
|
||||
|
||||
bool MergeDisplayLists(nsDisplayList* aNewList,
|
||||
void MergeDisplayLists(nsDisplayList* aNewList,
|
||||
nsDisplayList* aOldList,
|
||||
nsDisplayList* aOutList,
|
||||
mozilla::Maybe<const mozilla::ActiveScrolledRoot*>& aOutContainerASR);
|
||||
|
@ -54,7 +54,7 @@ DECLARE_DISPLAY_ITEM_TYPE(SELECTION_OVERLAY, TYPE_RENDERS_NO_IMAGES)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(SOLID_COLOR, TYPE_RENDERS_NO_IMAGES)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(SOLID_COLOR_REGION, TYPE_RENDERS_NO_IMAGES)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(SUBDOCUMENT, TYPE_RENDERS_NO_IMAGES)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(MASK, 0)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(MASK, TYPE_RENDERS_NO_IMAGES)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(FILTER, TYPE_RENDERS_NO_IMAGES)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(SVG_OUTER_SVG, TYPE_RENDERS_NO_IMAGES)
|
||||
DECLARE_DISPLAY_ITEM_TYPE(SVG_GEOMETRY, 0)
|
||||
|
@ -2504,100 +2504,6 @@ nsDisplayListBuilder::GetWidgetLayerManager(nsView** aView)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FrameLayerBuilder*
|
||||
nsDisplayList::BuildLayers(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aLayerManager,
|
||||
uint32_t aFlags,
|
||||
bool aIsWidgetTransaction)
|
||||
{
|
||||
nsIFrame* frame = aBuilder->RootReferenceFrame();
|
||||
nsPresContext* presContext = frame->PresContext();
|
||||
nsIPresShell* presShell = presContext->PresShell();
|
||||
|
||||
FrameLayerBuilder *layerBuilder = new FrameLayerBuilder();
|
||||
layerBuilder->Init(aBuilder, aLayerManager);
|
||||
|
||||
if (aFlags & PAINT_COMPRESSED) {
|
||||
layerBuilder->SetLayerTreeCompressionMode();
|
||||
}
|
||||
|
||||
RefPtr<ContainerLayer> root;
|
||||
{
|
||||
AUTO_PROFILER_TRACING("Paint", "LayerBuilding");
|
||||
|
||||
if (XRE_IsContentProcess() && gfxPrefs::AlwaysPaint()) {
|
||||
FrameLayerBuilder::InvalidateAllLayers(aLayerManager);
|
||||
}
|
||||
|
||||
if (aIsWidgetTransaction) {
|
||||
layerBuilder->DidBeginRetainedLayerTransaction(aLayerManager);
|
||||
}
|
||||
|
||||
// Clear any ScrollMetadata that may have been set on the root layer on a
|
||||
// previous paint. This paint will set new metrics if necessary, and if we
|
||||
// don't clear the old one here, we may be left with extra metrics.
|
||||
if (Layer* rootLayer = aLayerManager->GetRoot()) {
|
||||
rootLayer->SetScrollMetadata(nsTArray<ScrollMetadata>());
|
||||
}
|
||||
|
||||
ContainerLayerParameters containerParameters
|
||||
(presShell->GetResolution(), presShell->GetResolution());
|
||||
|
||||
{
|
||||
PaintTelemetry::AutoRecord record(PaintTelemetry::Metric::Layerization);
|
||||
|
||||
root = layerBuilder->
|
||||
BuildContainerLayerFor(aBuilder, aLayerManager, frame, nullptr, this,
|
||||
containerParameters, nullptr);
|
||||
|
||||
if (!record.GetStart().IsNull() && gfxPrefs::LayersDrawFPS()) {
|
||||
if (PaintTiming* pt = ClientLayerManager::MaybeGetPaintTiming(aLayerManager)) {
|
||||
pt->flbMs() = (TimeStamp::Now() - record.GetStart()).ToMilliseconds();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!root) {
|
||||
return nullptr;
|
||||
}
|
||||
// Root is being scaled up by the X/Y resolution. Scale it back down.
|
||||
root->SetPostScale(1.0f/containerParameters.mXScale,
|
||||
1.0f/containerParameters.mYScale);
|
||||
root->SetScaleToResolution(presShell->ScaleToResolution(),
|
||||
containerParameters.mXScale);
|
||||
|
||||
auto callback = [root](FrameMetrics::ViewID aScrollId) -> bool {
|
||||
return nsLayoutUtils::ContainsMetricsWithId(root, aScrollId);
|
||||
};
|
||||
if (Maybe<ScrollMetadata> rootMetadata = nsLayoutUtils::GetRootMetadata(
|
||||
aBuilder, root->Manager(), containerParameters, callback)) {
|
||||
root->SetScrollMetadata(rootMetadata.value());
|
||||
}
|
||||
|
||||
// NS_WARNING is debug-only, so don't even bother checking the conditions in
|
||||
// a release build.
|
||||
#ifdef DEBUG
|
||||
bool usingDisplayport = false;
|
||||
if (nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame()) {
|
||||
nsIContent* content = rootScrollFrame->GetContent();
|
||||
if (content) {
|
||||
usingDisplayport = nsLayoutUtils::HasDisplayPort(content);
|
||||
}
|
||||
}
|
||||
if (usingDisplayport &&
|
||||
!(root->GetContentFlags() & Layer::CONTENT_OPAQUE) &&
|
||||
SpammyLayoutWarningsEnabled()) {
|
||||
// See bug 693938, attachment 567017
|
||||
NS_WARNING("Transparent content with displayports can be expensive.");
|
||||
}
|
||||
#endif
|
||||
|
||||
aLayerManager->SetRoot(root);
|
||||
layerBuilder->WillEndTransaction();
|
||||
}
|
||||
return layerBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* We paint by executing a layer manager transaction, constructing a
|
||||
* single layer representing the display list, and then making it the
|
||||
@ -2690,25 +2596,119 @@ already_AddRefed<LayerManager> nsDisplayList::PaintRoot(nsDisplayListBuilder* aB
|
||||
presContext->MayHavePaintEventListenerInSubDocument() ? nsPresContext::NotifySubDocInvalidation : 0;
|
||||
|
||||
UniquePtr<LayerProperties> props;
|
||||
RefPtr<ContainerLayer> root;
|
||||
|
||||
bool computeInvalidRect = (computeInvalidFunc ||
|
||||
(!layerManager->IsCompositingCheap() && layerManager->NeedsWidgetInvalidation())) &&
|
||||
widgetTransaction;
|
||||
// Store the existing layer builder to reinstate it on return.
|
||||
FrameLayerBuilder *oldBuilder = layerManager->GetLayerBuilder();
|
||||
|
||||
if (computeInvalidRect) {
|
||||
props = Move(LayerProperties::CloneFrom(layerManager->GetRoot()));
|
||||
FrameLayerBuilder *layerBuilder = new FrameLayerBuilder();
|
||||
layerBuilder->Init(aBuilder, layerManager);
|
||||
|
||||
if (aFlags & PAINT_COMPRESSED) {
|
||||
layerBuilder->SetLayerTreeCompressionMode();
|
||||
}
|
||||
|
||||
if (doBeginTransaction) {
|
||||
if (aCtx) {
|
||||
if (!layerManager->BeginTransactionWithTarget(aCtx)) {
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
if (!layerManager->BeginTransaction()) {
|
||||
return nullptr;
|
||||
{
|
||||
AUTO_PROFILER_TRACING("Paint", "LayerBuilding");
|
||||
|
||||
if (doBeginTransaction) {
|
||||
if (aCtx) {
|
||||
if (!layerManager->BeginTransactionWithTarget(aCtx)) {
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
if (!layerManager->BeginTransaction()) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (XRE_IsContentProcess() && gfxPrefs::AlwaysPaint()) {
|
||||
FrameLayerBuilder::InvalidateAllLayers(layerManager);
|
||||
}
|
||||
|
||||
if (widgetTransaction) {
|
||||
layerBuilder->DidBeginRetainedLayerTransaction(layerManager);
|
||||
}
|
||||
|
||||
bool computeInvalidRect = (computeInvalidFunc ||
|
||||
(!layerManager->IsCompositingCheap() && layerManager->NeedsWidgetInvalidation())) &&
|
||||
widgetTransaction;
|
||||
|
||||
if (computeInvalidRect) {
|
||||
props = Move(LayerProperties::CloneFrom(layerManager->GetRoot()));
|
||||
}
|
||||
|
||||
// Clear any ScrollMetadata that may have been set on the root layer on a
|
||||
// previous paint. This paint will set new metrics if necessary, and if we
|
||||
// don't clear the old one here, we may be left with extra metrics.
|
||||
if (Layer* rootLayer = layerManager->GetRoot()) {
|
||||
rootLayer->SetScrollMetadata(nsTArray<ScrollMetadata>());
|
||||
}
|
||||
|
||||
ContainerLayerParameters containerParameters
|
||||
(presShell->GetResolution(), presShell->GetResolution());
|
||||
|
||||
{
|
||||
PaintTelemetry::AutoRecord record(PaintTelemetry::Metric::Layerization);
|
||||
|
||||
root = layerBuilder->
|
||||
BuildContainerLayerFor(aBuilder, layerManager, frame, nullptr, this,
|
||||
containerParameters, nullptr);
|
||||
|
||||
if (!record.GetStart().IsNull() && gfxPrefs::LayersDrawFPS()) {
|
||||
if (PaintTiming* pt = ClientLayerManager::MaybeGetPaintTiming(layerManager)) {
|
||||
pt->flbMs() = (TimeStamp::Now() - record.GetStart()).ToMilliseconds();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!root) {
|
||||
layerManager->SetUserData(&gLayerManagerLayerBuilder, oldBuilder);
|
||||
return nullptr;
|
||||
}
|
||||
// Root is being scaled up by the X/Y resolution. Scale it back down.
|
||||
root->SetPostScale(1.0f/containerParameters.mXScale,
|
||||
1.0f/containerParameters.mYScale);
|
||||
root->SetScaleToResolution(presShell->ScaleToResolution(),
|
||||
containerParameters.mXScale);
|
||||
|
||||
auto callback = [root](FrameMetrics::ViewID aScrollId) -> bool {
|
||||
return nsLayoutUtils::ContainsMetricsWithId(root, aScrollId);
|
||||
};
|
||||
if (Maybe<ScrollMetadata> rootMetadata = nsLayoutUtils::GetRootMetadata(
|
||||
aBuilder, root->Manager(), containerParameters, callback)) {
|
||||
root->SetScrollMetadata(rootMetadata.value());
|
||||
}
|
||||
|
||||
// NS_WARNING is debug-only, so don't even bother checking the conditions in
|
||||
// a release build.
|
||||
#ifdef DEBUG
|
||||
bool usingDisplayport = false;
|
||||
if (nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame()) {
|
||||
nsIContent* content = rootScrollFrame->GetContent();
|
||||
if (content) {
|
||||
usingDisplayport = nsLayoutUtils::HasDisplayPort(content);
|
||||
}
|
||||
}
|
||||
if (usingDisplayport &&
|
||||
!(root->GetContentFlags() & Layer::CONTENT_OPAQUE) &&
|
||||
SpammyLayoutWarningsEnabled()) {
|
||||
// See bug 693938, attachment 567017
|
||||
NS_WARNING("Transparent content with displayports can be expensive.");
|
||||
}
|
||||
#endif
|
||||
|
||||
layerManager->SetRoot(root);
|
||||
layerBuilder->WillEndTransaction();
|
||||
}
|
||||
|
||||
if (widgetTransaction ||
|
||||
// SVG-as-an-image docs don't paint as part of the retained layer tree,
|
||||
// but they still need the invalidation state bits cleared in order for
|
||||
// invalidation for CSS/SMIL animation to work properly.
|
||||
(document && document->IsBeingUsedAsImage())) {
|
||||
frame->ClearInvalidationStateBits();
|
||||
}
|
||||
|
||||
bool temp = aBuilder->SetIsCompositingCheap(layerManager->IsCompositingCheap());
|
||||
@ -2725,53 +2725,25 @@ already_AddRefed<LayerManager> nsDisplayList::PaintRoot(nsDisplayListBuilder* aB
|
||||
}
|
||||
}
|
||||
|
||||
// If this is the content process, we ship plugin geometry updates over with layer
|
||||
// updates, so calculate that now before we call EndTransaction.
|
||||
nsRootPresContext* rootPresContext = presContext->GetRootPresContext();
|
||||
if (rootPresContext && XRE_IsContentProcess()) {
|
||||
if (aBuilder->WillComputePluginGeometry()) {
|
||||
rootPresContext->ComputePluginGeometryUpdates(aBuilder->RootReferenceFrame(), aBuilder, this);
|
||||
}
|
||||
// The layer system caches plugin configuration information for forwarding
|
||||
// with layer updates which needs to get set during reflow. This must be
|
||||
// called even if there are no windowed plugins in the page.
|
||||
rootPresContext->CollectPluginGeometryUpdates(layerManager);
|
||||
}
|
||||
|
||||
MaybeSetupTransactionIdAllocator(layerManager, presContext);
|
||||
|
||||
// Store the existing layer builder to reinstate it on return.
|
||||
FrameLayerBuilder *oldBuilder = layerManager->GetLayerBuilder();
|
||||
FrameLayerBuilder *layerBuilder = nullptr;
|
||||
|
||||
bool sent = false;
|
||||
if (aFlags & PAINT_IDENTICAL_DISPLAY_LIST) {
|
||||
sent = layerManager->EndEmptyTransaction(flags);
|
||||
}
|
||||
|
||||
if (!sent) {
|
||||
layerBuilder = BuildLayers(aBuilder, layerManager,
|
||||
aFlags, widgetTransaction);
|
||||
|
||||
if (!layerBuilder) {
|
||||
layerManager->SetUserData(&gLayerManagerLayerBuilder, oldBuilder);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// If this is the content process, we ship plugin geometry updates over with layer
|
||||
// updates, so calculate that now before we call EndTransaction.
|
||||
nsRootPresContext* rootPresContext = presContext->GetRootPresContext();
|
||||
if (rootPresContext && XRE_IsContentProcess()) {
|
||||
if (aBuilder->WillComputePluginGeometry()) {
|
||||
rootPresContext->ComputePluginGeometryUpdates(aBuilder->RootReferenceFrame(), aBuilder, this);
|
||||
}
|
||||
// The layer system caches plugin configuration information for forwarding
|
||||
// with layer updates which needs to get set during reflow. This must be
|
||||
// called even if there are no windowed plugins in the page.
|
||||
rootPresContext->CollectPluginGeometryUpdates(layerManager);
|
||||
}
|
||||
|
||||
layerManager->EndTransaction(FrameLayerBuilder::DrawPaintedLayer,
|
||||
aBuilder, flags);
|
||||
layerBuilder->DidEndTransaction();
|
||||
}
|
||||
|
||||
if (widgetTransaction ||
|
||||
// SVG-as-an-image docs don't paint as part of the retained layer tree,
|
||||
// but they still need the invalidation state bits cleared in order for
|
||||
// invalidation for CSS/SMIL animation to work properly.
|
||||
(document && document->IsBeingUsedAsImage())) {
|
||||
frame->ClearInvalidationStateBits();
|
||||
}
|
||||
|
||||
layerManager->EndTransaction(FrameLayerBuilder::DrawPaintedLayer,
|
||||
aBuilder, flags);
|
||||
aBuilder->SetIsCompositingCheap(temp);
|
||||
layerBuilder->DidEndTransaction();
|
||||
|
||||
if (document && widgetTransaction) {
|
||||
TriggerPendingAnimations(document, layerManager->GetAnimationReadyTime());
|
||||
@ -2780,11 +2752,11 @@ already_AddRefed<LayerManager> nsDisplayList::PaintRoot(nsDisplayListBuilder* aB
|
||||
nsIntRegion invalid;
|
||||
bool areaOverflowed = false;
|
||||
if (props) {
|
||||
if (!props->ComputeDifferences(layerManager->GetRoot(), invalid, computeInvalidFunc)) {
|
||||
if (!props->ComputeDifferences(root, invalid, computeInvalidFunc)) {
|
||||
areaOverflowed = true;
|
||||
}
|
||||
} else if (widgetTransaction) {
|
||||
LayerProperties::ClearInvalidations(layerManager->GetRoot());
|
||||
LayerProperties::ClearInvalidations(root);
|
||||
}
|
||||
|
||||
bool shouldInvalidate = layerManager->NeedsWidgetInvalidation();
|
||||
|
@ -3090,17 +3090,11 @@ public:
|
||||
PAINT_USE_WIDGET_LAYERS = 0x01,
|
||||
PAINT_EXISTING_TRANSACTION = 0x04,
|
||||
PAINT_NO_COMPOSITE = 0x08,
|
||||
PAINT_COMPRESSED = 0x10,
|
||||
PAINT_IDENTICAL_DISPLAY_LIST = 0x20
|
||||
PAINT_COMPRESSED = 0x10
|
||||
};
|
||||
already_AddRefed<LayerManager> PaintRoot(nsDisplayListBuilder* aBuilder,
|
||||
gfxContext* aCtx,
|
||||
uint32_t aFlags);
|
||||
|
||||
mozilla::FrameLayerBuilder* BuildLayers(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aLayerManager,
|
||||
uint32_t aFlags,
|
||||
bool aIsWidgetTransaction);
|
||||
/**
|
||||
* Get the bounds. Takes the union of the bounds of all children.
|
||||
* The result is not cached.
|
||||
@ -4787,7 +4781,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
friend bool MergeLayerEventRegions(nsDisplayItem*, nsDisplayItem*);
|
||||
friend void MergeLayerEventRegions(nsDisplayItem*, nsDisplayItem*);
|
||||
|
||||
// Relative to aFrame's reference frame.
|
||||
// These are the points that are definitely in the hit region.
|
||||
|
@ -1,8 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<body>
|
||||
<div style="opacity:0.5" id="hi">
|
||||
<div style="position:fixed; width:200px; height:200px; background-color:blue"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,20 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="reftest-wait">
|
||||
<body>
|
||||
<div style="opacity:0.5" id="hi">
|
||||
<div style="position:fixed; width:200px; height:200px; background-color:blue"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
function doTest()
|
||||
{
|
||||
var opacityElement = document.getElementById("hi");
|
||||
opacityElement.style.left = '100px';
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
|
||||
document.addEventListener("MozReftestInvalidate", doTest);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -19,5 +19,5 @@ skip-if(Android) == 1428993-1.html 1428993-1-ref.html
|
||||
needs-focus == 1429027-1.html 1429027-1-ref.html
|
||||
== 1432553-1.html 1432553-1-ref.html
|
||||
== 1432553-2.html 1432553-2-ref.html
|
||||
== 1436189-1.html 1436189-1-ref.html
|
||||
== 1420480-1.html 1420480-1-ref.html
|
||||
|
||||
|
@ -2292,8 +2292,8 @@ HttpChannelParent::UpdateAndSerializeSecurityInfo(nsACString& aSerializedSecurit
|
||||
bool
|
||||
HttpChannelParent::DoSendDeleteSelf()
|
||||
{
|
||||
mIPCClosed = true;
|
||||
bool rv = SendDeleteSelf();
|
||||
mIPCClosed = true;
|
||||
|
||||
CleanupBackgroundChannel();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user