Make finer-grained decisions about whether to update hit testing trees. (bug 1352918, r=kats)

Updating hit testing trees is very expensive for many layers, and often
layer properties that change don't necessitate hit testing tree updates.
While layer tree structure changes do, we can be smarter about
individual layer attributes.
This commit is contained in:
David Anderson 2017-04-13 21:25:16 -07:00
Родитель 16e78d9ec4
Коммит bc9324f621
4 изменённых файлов: 83 добавлений и 27 удалений

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

@ -170,6 +170,27 @@ public:
return true;
}
// This returns true if scrolling info is equivalent for the purposes of
// APZ hit testing.
bool HitTestingInfoIsEqual(const SimpleLayerAttributes& aOther) const {
if (mIsScrollbarContainer != aOther.mIsScrollbarContainer) {
return false;
}
if (mScrollbarTargetContainerId != aOther.mScrollbarTargetContainerId) {
return false;
}
if (mScrollbarDirection != aOther.mScrollbarDirection) {
return false;
}
if (FixedPositionScrollContainerId() != aOther.FixedPositionScrollContainerId()) {
return false;
}
if (mTransform != aOther.mTransform) {
return false;
}
return true;
}
//
// Getters.
//

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

@ -480,6 +480,9 @@ APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer,
RefPtr<HitTestingTreeNode> node = nullptr;
if (!needsApzc) {
// Note: if layer properties must be propagated to nodes, RecvUpdate in
// LayerTransactionParent.cpp must ensure that APZ will be notified
// when those properties change.
node = RecycleOrCreateNode(aState, nullptr, aLayersId);
AttachNodeToTree(node, aParent, aNextSibling);
node->SetHitTestData(
@ -674,6 +677,9 @@ APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer,
GetEventRegionsOverride(aParent, aLayer));
}
// Note: if layer properties must be propagated to nodes, RecvUpdate in
// LayerTransactionParent.cpp must ensure that APZ will be notified
// when those properties change.
node->SetScrollbarData(aLayer.GetScrollbarTargetContainerId(),
aLayer.GetScrollbarDirection(),
aLayer.GetScrollThumbLength(),

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

@ -172,8 +172,8 @@ LayerTransactionParent::RecvUpdate(const TransactionInfo& aInfo)
layer_manager()->BeginTransaction();
}
// not all edits require an update to the hit testing tree
bool updateHitTestingTree = false;
// Not all edits require an update to the hit testing tree.
mUpdateHitTestingTree = false;
for (EditArray::index_type i = 0; i < aInfo.cset().Length(); ++i) {
const Edit& edit = const_cast<Edit&>(aInfo.cset()[i]);
@ -188,7 +188,7 @@ LayerTransactionParent::RecvUpdate(const TransactionInfo& aInfo)
return IPC_FAIL_NO_REASON(this);
}
updateHitTestingTree = true;
UpdateHitTestingTree(layer, "CreatePaintedLayer");
break;
}
case Edit::TOpCreateContainerLayer: {
@ -199,7 +199,7 @@ LayerTransactionParent::RecvUpdate(const TransactionInfo& aInfo)
return IPC_FAIL_NO_REASON(this);
}
updateHitTestingTree = true;
UpdateHitTestingTree(layer, "CreateContainerLayer");
break;
}
case Edit::TOpCreateImageLayer: {
@ -210,7 +210,7 @@ LayerTransactionParent::RecvUpdate(const TransactionInfo& aInfo)
return IPC_FAIL_NO_REASON(this);
}
updateHitTestingTree = true;
UpdateHitTestingTree(layer, "CreateImageLayer");
break;
}
case Edit::TOpCreateColorLayer: {
@ -221,7 +221,7 @@ LayerTransactionParent::RecvUpdate(const TransactionInfo& aInfo)
return IPC_FAIL_NO_REASON(this);
}
updateHitTestingTree = true;
UpdateHitTestingTree(layer, "CreateColorLayer");
break;
}
case Edit::TOpCreateTextLayer: {
@ -232,18 +232,18 @@ LayerTransactionParent::RecvUpdate(const TransactionInfo& aInfo)
return IPC_FAIL_NO_REASON(this);
}
updateHitTestingTree = true;
UpdateHitTestingTree(layer, "CreateTextLayer");
break;
}
case Edit::TOpCreateBorderLayer: {
MOZ_LAYERS_LOG(("[ParentSide] CreateTextLayer"));
MOZ_LAYERS_LOG(("[ParentSide] CreateBorderLayer"));
RefPtr<BorderLayer> layer = layer_manager()->CreateBorderLayer();
if (!BindLayer(layer, edit.get_OpCreateBorderLayer())) {
return IPC_FAIL_NO_REASON(this);
}
updateHitTestingTree = true;
UpdateHitTestingTree(layer, "CreateBorderLayer");
break;
}
case Edit::TOpCreateCanvasLayer: {
@ -254,7 +254,7 @@ LayerTransactionParent::RecvUpdate(const TransactionInfo& aInfo)
return IPC_FAIL_NO_REASON(this);
}
updateHitTestingTree = true;
UpdateHitTestingTree(layer, "CreateCanvasLayer");
break;
}
case Edit::TOpCreateRefLayer: {
@ -265,7 +265,7 @@ LayerTransactionParent::RecvUpdate(const TransactionInfo& aInfo)
return IPC_FAIL_NO_REASON(this);
}
updateHitTestingTree = true;
UpdateHitTestingTree(layer, "CreateRefLayer");
break;
}
case Edit::TOpSetDiagnosticTypes: {
@ -291,7 +291,7 @@ LayerTransactionParent::RecvUpdate(const TransactionInfo& aInfo)
}
mRoot = newRoot;
updateHitTestingTree = true;
UpdateHitTestingTree(mRoot, "SetRoot");
break;
}
case Edit::TOpInsertAfter: {
@ -309,7 +309,7 @@ LayerTransactionParent::RecvUpdate(const TransactionInfo& aInfo)
return IPC_FAIL_NO_REASON(this);
}
updateHitTestingTree = true;
UpdateHitTestingTree(layer, "InsertAfter");
break;
}
case Edit::TOpPrependChild: {
@ -326,7 +326,7 @@ LayerTransactionParent::RecvUpdate(const TransactionInfo& aInfo)
return IPC_FAIL_NO_REASON(this);
}
updateHitTestingTree = true;
UpdateHitTestingTree(layer, "PrependChild");
break;
}
case Edit::TOpRemoveChild: {
@ -343,7 +343,7 @@ LayerTransactionParent::RecvUpdate(const TransactionInfo& aInfo)
return IPC_FAIL_NO_REASON(this);
}
updateHitTestingTree = true;
UpdateHitTestingTree(layer, "RemoveChild");
break;
}
case Edit::TOpRepositionChild: {
@ -361,7 +361,7 @@ LayerTransactionParent::RecvUpdate(const TransactionInfo& aInfo)
return IPC_FAIL_NO_REASON(this);
}
updateHitTestingTree = true;
UpdateHitTestingTree(layer, "RepositionChild");
break;
}
case Edit::TOpRaiseToTopChild: {
@ -381,7 +381,7 @@ LayerTransactionParent::RecvUpdate(const TransactionInfo& aInfo)
return IPC_FAIL_NO_REASON(this);
}
updateHitTestingTree = true;
UpdateHitTestingTree(layer, "RaiseToTopChild");
break;
}
case Edit::TCompositableOperation: {
@ -446,8 +446,12 @@ LayerTransactionParent::RecvUpdate(const TransactionInfo& aInfo)
if (!layer) {
return IPC_FAIL_NO_REASON(this);
}
const SimpleLayerAttributes& attrs = op.attrs();
const SimpleLayerAttributes& orig = layer->GetSimpleAttributes();
if (!attrs.HitTestingInfoIsEqual(orig)) {
UpdateHitTestingTree(layer, "scrolling info changed");
}
layer->SetSimpleAttributes(op.attrs());
updateHitTestingTree = true;
}
// Process attribute updates.
@ -456,7 +460,6 @@ LayerTransactionParent::RecvUpdate(const TransactionInfo& aInfo)
if (!SetLayerAttributes(op)) {
return IPC_FAIL_NO_REASON(this);
}
updateHitTestingTree = true;
}
// Process paints separately, after all normal edits.
@ -466,7 +469,7 @@ LayerTransactionParent::RecvUpdate(const TransactionInfo& aInfo)
}
}
mCompositorBridge->ShadowLayersUpdated(this, aInfo, updateHitTestingTree);
mCompositorBridge->ShadowLayersUpdated(this, aInfo, mUpdateHitTestingTree);
{
AutoResolveRefLayers resolve(mCompositorBridge->GetCompositionManager(this));
@ -521,16 +524,29 @@ LayerTransactionParent::SetLayerAttributes(const OpSetLayerAttributes& aOp)
const LayerAttributes& attrs = aOp.attrs();
const CommonLayerAttributes& common = attrs.common();
layer->SetVisibleRegion(common.visibleRegion());
layer->SetEventRegions(common.eventRegions());
layer->SetClipRect(common.useClipRect() ? Some(common.clipRect()) : Nothing());
if (common.visibleRegion() != layer->GetVisibleRegion()) {
UpdateHitTestingTree(layer, "visible region changed");
layer->SetVisibleRegion(common.visibleRegion());
}
if (common.eventRegions() != layer->GetEventRegions()) {
UpdateHitTestingTree(layer, "event regions changed");
layer->SetEventRegions(common.eventRegions());
}
Maybe<ParentLayerIntRect> clipRect = common.useClipRect() ? Some(common.clipRect()) : Nothing();
if (clipRect != layer->GetClipRect()) {
UpdateHitTestingTree(layer, "clip rect changed");
layer->SetClipRect(clipRect);
}
if (LayerHandle maskLayer = common.maskLayer()) {
layer->SetMaskLayer(AsLayer(maskLayer));
} else {
layer->SetMaskLayer(nullptr);
}
layer->SetCompositorAnimations(common.compositorAnimations());
layer->SetScrollMetadata(common.scrollMetadata());
if (common.scrollMetadata() != layer->GetAllScrollMetadata()) {
UpdateHitTestingTree(layer, "scroll metadata changed");
layer->SetScrollMetadata(common.scrollMetadata());
}
layer->SetDisplayListLog(common.displayListLog().get());
// The updated invalid region is added to the existing one, since we can
@ -579,8 +595,10 @@ LayerTransactionParent::SetLayerAttributes(const OpSetLayerAttributes& aOp)
containerLayer->SetInheritedScale(attrs.inheritedXScale(), attrs.inheritedYScale());
containerLayer->SetScaleToResolution(attrs.scaleToResolution(),
attrs.presShellResolution());
containerLayer->SetEventRegionsOverride(attrs.eventRegionsOverride());
if (attrs.eventRegionsOverride() != containerLayer->GetEventRegionsOverride()) {
UpdateHitTestingTree(layer, "event regions override changed");
containerLayer->SetEventRegionsOverride(attrs.eventRegionsOverride());
}
break;
}
case Specific::TColorLayerAttributes: {
@ -640,6 +658,7 @@ LayerTransactionParent::SetLayerAttributes(const OpSetLayerAttributes& aOp)
}
refLayer->SetReferentId(specific.get_RefLayerAttributes().id());
refLayer->SetEventRegionsOverride(specific.get_RefLayerAttributes().eventRegionsOverride());
UpdateHitTestingTree(layer, "event regions override changed");
break;
}
case Specific::TImageLayerAttributes: {

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

@ -171,6 +171,13 @@ protected:
friend class CrossProcessCompositorBridgeParent;
friend class layout::RenderFrameParent;
private:
// This is a function so we can log or breakpoint on why hit
// testing tree changes are made.
void UpdateHitTestingTree(Layer* aLayer, const char* aWhy) {
mUpdateHitTestingTree = true;
}
private:
RefPtr<HostLayerManager> mLayerManager;
CompositorBridgeParentBase* mCompositorBridge;
@ -216,8 +223,11 @@ private:
// transactions posted by the child.
bool mDestroyed;
bool mIPCOpen;
// This is set during RecvUpdate to track whether we'll need to update
// APZ's hit test regions.
bool mUpdateHitTestingTree;
};
} // namespace layers