Bug 1440177 - Part 6: Don't dereference display items during AddPaintedDisplayItem for the LAYER_NONE case. r=jnicol

The display items are almost certainly gone from the cache at this point, so dereferencing them can take a while.
This moves the DisplayItemData lookup, and the IsReused/HasMergedFrames checks into the ProcessDisplayItems pass (where we already use the items), and then just uses the AssignedDisplayItem entry for everything.

MozReview-Commit-ID: 3NibNGSVsax

--HG--
extra : rebase_source : b5b4d82798404ad4c8d84ca33bfb30d4afa55fb6
This commit is contained in:
Matt Woodrow 2018-03-01 11:42:27 +13:00
Родитель e7ccc78c95
Коммит 3eb2633a17
2 изменённых файлов: 90 добавлений и 88 удалений

Просмотреть файл

@ -196,6 +196,16 @@ DisplayItemData::EndUpdate(nsAutoPtr<nsDisplayItemGeometry> aGeometry)
void
DisplayItemData::BeginUpdate(Layer* aLayer, LayerState aState,
nsDisplayItem* aItem /* = nullptr */)
{
BeginUpdate(aLayer, aState, aItem,
aItem ? aItem->IsReused() : false,
aItem ? aItem->HasMergedFrames() : false);
}
void
DisplayItemData::BeginUpdate(Layer* aLayer, LayerState aState,
nsDisplayItem* aItem, bool aIsReused,
bool aIsMerged)
{
MOZ_RELEASE_ASSERT(mLayer);
MOZ_RELEASE_ASSERT(aLayer);
@ -207,13 +217,18 @@ DisplayItemData::BeginUpdate(Layer* aLayer, LayerState aState,
if (aLayer->AsPaintedLayer()) {
mItem = aItem;
mReusedItem = aItem->IsReused();
mReusedItem = aIsReused;
}
if (!aItem) {
return;
}
if (!aIsMerged && mFrameList.Length() == 1) {
MOZ_ASSERT(mFrameList[0] == aItem->Frame());
return;
}
// We avoid adding or removing element unnecessarily
// since we have to modify userdata each time
AutoTArray<nsIFrame*, 4> copy(mFrameList);
@ -3208,15 +3223,10 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB
MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_LAYER_EVENT_REGIONS);
MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO);
DisplayItemData* oldData =
mLayerBuilder->GetOldLayerForFrame(item.mItem->Frame(),
item.mItem->GetPerFrameKey(),
item.mItem->HasMergedFrames() ? nullptr : item.mItem->GetDisplayItemData());
InvalidateForLayerChange(item.mItem, data->mLayer, oldData);
mLayerBuilder->AddPaintedDisplayItem(data, item.mItem, item.mClip,
*this, item.mLayerState,
data->mAnimatedGeometryRootOffset,
oldData, item);
InvalidateForLayerChange(item.mItem, data->mLayer, item.mDisplayItemData);
mLayerBuilder->AddPaintedDisplayItem(data, item, *this,
data->mAnimatedGeometryRootOffset);
item.mDisplayItemData = nullptr;
}
PaintedDisplayItemLayerUserData* userData = GetPaintedDisplayItemLayerUserData(data->mLayer);
@ -3516,7 +3526,11 @@ PaintedLayerData::Accumulate(ContainerState* aState,
bool clipMatches = mItemClip == aClip;
mItemClip = aClip;
mAssignedDisplayItems.AppendElement(AssignedDisplayItem(aItem, aClip, aLayerState));
DisplayItemData* oldData =
aState->mLayerBuilder->GetOldLayerForFrame(aItem->Frame(),
aItem->GetPerFrameKey(),
aItem->HasMergedFrames() ? nullptr : aItem->GetDisplayItemData());
mAssignedDisplayItems.AppendElement(AssignedDisplayItem(aItem, aClip, aLayerState, oldData));
if (aItem->MustPaintOnContentSide()) {
mShouldPaintOnContentSide = true;
@ -4624,9 +4638,11 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
* No need to allocate geometry for items that aren't
* part of a PaintedLayer.
*/
oldData =
mLayerBuilder->GetOldLayerForFrame(item->Frame(), item->GetPerFrameKey());
mLayerBuilder->AddLayerDisplayItem(ownLayer, item, layerState, nullptr, oldData);
if (ownLayer->Manager() == mLayerBuilder->GetRetainingLayerManager()) {
oldData =
mLayerBuilder->GetOldLayerForFrame(item->Frame(), item->GetPerFrameKey());
mLayerBuilder->StoreDataForFrame(item, ownLayer, layerState, oldData);
}
} else {
const bool backfaceHidden = item->In3DContextAndBackfaceIsHidden();
const nsIFrame* referenceFrame = item->ReferenceFrame();
@ -4817,13 +4833,9 @@ FrameLayerBuilder::ComputeGeometryChangeForItem(DisplayItemData* aData)
void
FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData,
nsDisplayItem* aItem,
const DisplayItemClip& aClip,
ContainerState& aContainerState,
LayerState aLayerState,
const nsPoint& aTopLeft,
DisplayItemData* aData,
AssignedDisplayItem& aAssignedDisplayItem)
AssignedDisplayItem& aItem,
ContainerState& aContainerState,
const nsPoint& aTopLeft)
{
PaintedLayer* layer = aLayerData->mLayer;
PaintedDisplayItemLayerUserData* paintedData =
@ -4832,13 +4844,13 @@ FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData,
RefPtr<BasicLayerManager> tempManager;
nsIntRect intClip;
bool hasClip = false;
if (aLayerState != LAYER_NONE) {
if (aData) {
tempManager = aData->mInactiveManager;
if (aItem.mLayerState != LAYER_NONE) {
if (aItem.mDisplayItemData) {
tempManager = aItem.mDisplayItemData->mInactiveManager;
// We need to grab these before calling AddLayerDisplayItem because it will overwrite them.
// We need to grab these before updating the DisplayItemData because it will overwrite them.
nsRegion clip;
if (aClip.ComputeRegionInClips(&aData->GetClip(),
if (aItem.mClip.ComputeRegionInClips(&aItem.mDisplayItemData->GetClip(),
aTopLeft - paintedData->mLastAnimatedGeometryRootOrigin,
&clip)) {
intClip = clip.GetBounds().ScaleToOutsidePixels(paintedData->mXScale,
@ -4851,13 +4863,23 @@ FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData,
}
}
AddLayerDisplayItem(layer, aItem, aLayerState, tempManager, aData);
if (layer->Manager() == mRetainingManager) {
DisplayItemData *data = aItem.mDisplayItemData;
if (data) {
if (!data->mUsed) {
data->BeginUpdate(layer, aItem.mLayerState, aItem.mItem, aItem.mReused, aItem.mMerged);
}
} else {
data = StoreDataForFrame(aItem.mItem, layer, aItem.mLayerState, nullptr);
}
data->mInactiveManager = tempManager;
}
if (tempManager) {
FLB_LOG_PAINTED_LAYER_DECISION(aLayerData, "Creating nested FLB for item %p\n", aItem);
FLB_LOG_PAINTED_LAYER_DECISION(aLayerData, "Creating nested FLB for item %p\n", aItem.mItem);
FrameLayerBuilder* layerBuilder = new FrameLayerBuilder();
layerBuilder->Init(mDisplayListBuilder, tempManager, aLayerData, true,
&aClip);
&aItem.mClip);
tempManager->BeginTransaction();
if (mRetainingManager) {
@ -4866,24 +4888,24 @@ FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData,
UniquePtr<LayerProperties> props(LayerProperties::CloneFrom(tempManager->GetRoot()));
RefPtr<Layer> tmpLayer =
aItem->BuildLayer(mDisplayListBuilder, tempManager, ContainerLayerParameters());
aItem.mItem->BuildLayer(mDisplayListBuilder, tempManager, ContainerLayerParameters());
// We have no easy way of detecting if this transaction will ever actually get finished.
// For now, I've just silenced the warning with nested transactions in BasicLayers.cpp
if (!tmpLayer) {
tempManager->EndTransaction(nullptr, nullptr);
tempManager->SetUserData(&gLayerManagerLayerBuilder, nullptr);
aAssignedDisplayItem.mItem = nullptr;
aItem.mItem = nullptr;
return;
}
bool snap;
nsRect visibleRect =
aItem->GetVisibleRect().Intersect(aItem->GetBounds(mDisplayListBuilder, &snap));
aItem.mItem->GetVisibleRect().Intersect(aItem.mItem->GetBounds(mDisplayListBuilder, &snap));
nsIntRegion rgn = visibleRect.ToOutsidePixels(paintedData->mAppUnitsPerDevPixel);
// Convert the visible rect to a region and give the item
// a chance to try restrict it further.
nsRegion tightBounds = aItem->GetTightBounds(mDisplayListBuilder, &snap);
nsRegion tightBounds = aItem.mItem->GetTightBounds(mDisplayListBuilder, &snap);
if (!tightBounds.IsEmpty()) {
rgn.AndWith(tightBounds.ToOutsidePixels(paintedData->mAppUnitsPerDevPixel));
}
@ -4899,8 +4921,8 @@ FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData,
(tempManager->GetUserData(&gLayerManagerUserData));
lmd->mParent = parentLmd;
#endif
DisplayItemData* data = layerBuilder->GetDisplayItemDataForManager(aItem, tempManager);
layerBuilder->StoreDataForFrame(aItem, tmpLayer, LAYER_ACTIVE, data);
DisplayItemData* data = layerBuilder->GetDisplayItemDataForManager(aItem.mItem, tempManager);
layerBuilder->StoreDataForFrame(aItem.mItem, tmpLayer, LAYER_ACTIVE, data);
}
tempManager->SetRoot(tmpLayer);
@ -4909,7 +4931,7 @@ FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData,
#ifdef MOZ_DUMP_PAINTING
if (gfxUtils::DumpDisplayList() || gfxEnv::DumpPaint()) {
fprintf_stderr(gfxUtils::sDumpPaintFile, "Basic layer tree for painting contents of display item %s(%p):\n", aItem->Name(), aItem->Frame());
fprintf_stderr(gfxUtils::sDumpPaintFile, "Basic layer tree for painting contents of display item %s(%p):\n", aItem.mItem->Name(), aItem.mItem->Frame());
std::stringstream stream;
tempManager->Dump(stream, "", gfxEnv::DumpPaintToFile());
fprint_stderr(gfxUtils::sDumpPaintFile, stream); // not a typo, fprint_stderr declared in LayersLogging.h
@ -4922,18 +4944,18 @@ FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData,
tmpLayer->ComputeEffectiveTransforms(Matrix4x4());
nsIntRegion invalid;
if (!props->ComputeDifferences(tmpLayer, invalid, nullptr)) {
nsRect visible = aItem->Frame()->GetVisualOverflowRect();
nsRect visible = aItem.mItem->Frame()->GetVisualOverflowRect();
invalid = visible.ToOutsidePixels(paintedData->mAppUnitsPerDevPixel);
}
if (aLayerState == LAYER_SVG_EFFECTS) {
invalid = nsSVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(aItem->Frame(),
aItem->ToReferenceFrame(),
if (aItem.mLayerState == LAYER_SVG_EFFECTS) {
invalid = nsSVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(aItem.mItem->Frame(),
aItem.mItem->ToReferenceFrame(),
invalid);
}
if (!invalid.IsEmpty()) {
#ifdef MOZ_DUMP_PAINTING
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
printf_stderr("Inactive LayerManager(%p) for display item %s(%p) has an invalid region - invalidating layer %p\n", tempManager.get(), aItem->Name(), aItem->Frame(), layer);
printf_stderr("Inactive LayerManager(%p) for display item %s(%p) has an invalid region - invalidating layer %p\n", tempManager.get(), aItem.mItem->Name(), aItem.mItem->Frame(), layer);
}
#endif
invalid.ScaleRoundOut(paintedData->mXScale, paintedData->mYScale);
@ -4946,7 +4968,7 @@ FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData,
GetTranslationForPaintedLayer(layer));
}
}
aAssignedDisplayItem.mInactiveLayerManager = tempManager;
aItem.mInactiveLayerManager = tempManager;
}
DisplayItemData*
@ -4999,6 +5021,18 @@ FrameLayerBuilder::StoreDataForFrame(nsIFrame* aFrame,
lmd->mDisplayItems.PutEntry(data);
}
AssignedDisplayItem::AssignedDisplayItem(nsDisplayItem* aItem,
const DisplayItemClip& aClip,
LayerState aLayerState,
DisplayItemData* aData)
: mItem(aItem)
, mClip(aClip)
, mLayerState(aLayerState)
, mDisplayItemData(aData)
, mReused(aItem->IsReused())
, mMerged(aItem->HasMergedFrames())
{}
AssignedDisplayItem::~AssignedDisplayItem()
{
if (mInactiveLayerManager) {
@ -5006,20 +5040,6 @@ AssignedDisplayItem::~AssignedDisplayItem()
}
}
void
FrameLayerBuilder::AddLayerDisplayItem(Layer* aLayer,
nsDisplayItem* aItem,
LayerState aLayerState,
BasicLayerManager* aManager,
DisplayItemData* aData)
{
if (aLayer->Manager() != mRetainingManager)
return;
DisplayItemData *data = StoreDataForFrame(aItem, aLayer, aLayerState, aData);
data->mInactiveManager = aManager;
}
nsIntPoint
FrameLayerBuilder::GetLastPaintOffset(PaintedLayer* aLayer)
{

Просмотреть файл

@ -156,6 +156,8 @@ private:
*/
void BeginUpdate(layers::Layer* aLayer, LayerState aState,
nsDisplayItem* aItem = nullptr);
void BeginUpdate(layers::Layer* aLayer, LayerState aState,
nsDisplayItem* aItem, bool aIsReused, bool aIsMerged);
/**
* Completes the update of this, and removes any references to data that won't live
@ -212,17 +214,14 @@ struct AssignedDisplayItem
{
AssignedDisplayItem(nsDisplayItem* aItem,
const DisplayItemClip& aClip,
LayerState aLayerState)
: mItem(aItem)
, mClip(aClip)
, mLayerState(aLayerState)
{}
LayerState aLayerState,
DisplayItemData* aData);
~AssignedDisplayItem();
nsDisplayItem* mItem;
DisplayItemClip mClip;
LayerState mLayerState;
DisplayItemData* mDisplayItemData;
/**
* If the display item is being rendered as an inactive
@ -230,6 +229,9 @@ struct AssignedDisplayItem
* used for the inactive transaction.
*/
RefPtr<layers::LayerManager> mInactiveLayerManager;
bool mReused;
bool mMerged;
};
@ -501,21 +503,6 @@ public:
* to be called by file-scope helper functions in FrameLayerBuilder.cpp.
*/
/**
* Record aItem as a display item that is rendered by aLayer.
*
* @param aLayer Layer that the display item will be rendered into
* @param aItem Display item to be drawn.
* @param aLayerState What LayerState the item is using.
* @param aManager If the layer is in the LAYER_INACTIVE state,
* then this is the temporary layer manager to draw with.
*/
void AddLayerDisplayItem(Layer* aLayer,
nsDisplayItem* aItem,
LayerState aLayerState,
BasicLayerManager* aManager,
DisplayItemData* aData);
/**
* Record aItem as a display item that is rendered by the PaintedLayer
* aLayer, with aClipRect, where aContainerLayerFrame is the frame
@ -524,13 +511,9 @@ public:
* @param aTopLeft offset from active scrolled root to reference frame
*/
void AddPaintedDisplayItem(PaintedLayerData* aLayer,
nsDisplayItem* aItem,
const DisplayItemClip& aClip,
ContainerState& aContainerState,
LayerState aLayerState,
const nsPoint& aTopLeft,
DisplayItemData* aData,
AssignedDisplayItem& aAssignedDisplayItem);
AssignedDisplayItem& aAssignedDisplayItem,
ContainerState& aContainerState,
const nsPoint& aTopLeft);
/**
* Calls GetOldLayerForFrame on the underlying frame of the display item,
@ -627,10 +610,6 @@ public:
*/
DisplayItemData* GetOldLayerForFrame(nsIFrame* aFrame, uint32_t aDisplayItemKey, DisplayItemData* aOldData = nullptr);
protected:
friend class LayerManagerData;
/**
* Stores DisplayItemData associated with aFrame, stores the data in
* mNewDisplayItemData.
@ -642,6 +621,9 @@ protected:
Layer* aLayer,
LayerState aState);
protected:
friend class LayerManagerData;
// Flash the area within the context clip if paint flashing is enabled.
static void FlashPaint(gfxContext *aContext);