зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1504233 - Clip hit test info items properly r=mattwoodrow
Differential Revision: https://phabricator.services.mozilla.com/D11038 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
ca3f27dd60
Коммит
e2e8b3d221
|
@ -614,6 +614,7 @@ public:
|
|||
*/
|
||||
void AccumulateHitTestItem(ContainerState* aState,
|
||||
nsDisplayItem* aItem,
|
||||
const DisplayItemClip& aClip,
|
||||
TransformClipNode* aTransform);
|
||||
|
||||
/**
|
||||
|
@ -4254,6 +4255,7 @@ PaintedLayerData::CombinedTouchActionRegion()
|
|||
void
|
||||
PaintedLayerData::AccumulateHitTestItem(ContainerState* aState,
|
||||
nsDisplayItem* aItem,
|
||||
const DisplayItemClip& aClip,
|
||||
TransformClipNode* aTransform)
|
||||
{
|
||||
MOZ_ASSERT(aItem->HasHitTestInfo());
|
||||
|
@ -4269,11 +4271,7 @@ PaintedLayerData::AccumulateHitTestItem(ContainerState* aState,
|
|||
"area: [%d, %d, %d, %d], flags: 0x%x]\n",
|
||||
item, this, area.x, area.y, area.width, area.height, flags.serialize());
|
||||
|
||||
const DisplayItemClip& clip = info.mClip
|
||||
? *info.mClip
|
||||
: DisplayItemClip::NoClip();
|
||||
|
||||
area = clip.ApplyNonRoundedIntersection(area);
|
||||
area = aClip.ApplyNonRoundedIntersection(area);
|
||||
|
||||
if (aTransform) {
|
||||
area = aTransform->TransformRect(area, aState->mAppUnitsPerDevPixel);
|
||||
|
@ -4285,7 +4283,7 @@ PaintedLayerData::AccumulateHitTestItem(ContainerState* aState,
|
|||
return;
|
||||
}
|
||||
|
||||
bool hasRoundedCorners = clip.GetRoundedRectCount() > 0;
|
||||
bool hasRoundedCorners = aClip.GetRoundedRectCount() > 0;
|
||||
|
||||
// use the NS_FRAME_SIMPLE_EVENT_REGIONS to avoid calling the slightly
|
||||
// expensive HasNonZeroCorner function if we know from a previous run that
|
||||
|
@ -4803,13 +4801,6 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
|
|||
|
||||
const bool inEffect = InTransform() || InOpacity();
|
||||
|
||||
if (marker == DisplayItemEntryType::HIT_TEST_INFO && inEffect) {
|
||||
// Fast-path for hit test items inside flattened inactive layers.
|
||||
MOZ_ASSERT(selectedLayer);
|
||||
selectedLayer->AccumulateHitTestItem(this, item, transformNode);
|
||||
continue;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mAppUnitsPerDevPixel == AppUnitsPerDevPixel(item),
|
||||
"items in a container layer should all have the same app "
|
||||
"units per dev pixel");
|
||||
|
@ -4834,38 +4825,6 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
|
|||
}
|
||||
}
|
||||
|
||||
auto FuseItemClipChainIfNeeded = [&](const ActiveScrolledRoot* aASR) {
|
||||
if (marker == DisplayItemEntryType::ITEM || IsEffectStartMarker(marker)) {
|
||||
// No need to fuse clip chain for effect end markers, since it was
|
||||
// already done for effect start markers.
|
||||
item->FuseClipChainUpTo(mBuilder, aASR);
|
||||
}
|
||||
};
|
||||
|
||||
if (inEffect && marker == DisplayItemEntryType::ITEM) {
|
||||
// Fast-path for items inside flattened inactive layers. This works
|
||||
// because the layer state of the item cannot be active, otherwise the
|
||||
// parent item would not have been flattened.
|
||||
MOZ_ASSERT(selectedLayer);
|
||||
|
||||
FuseItemClipChainIfNeeded(containerASR);
|
||||
selectedLayer->Accumulate(this,
|
||||
item,
|
||||
nsIntRect(),
|
||||
nsRect(),
|
||||
item->GetClip(),
|
||||
layerState,
|
||||
aList,
|
||||
marker,
|
||||
opacityIndices,
|
||||
transformNode);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Items outside of flattened effects and non-item markers inside flattened
|
||||
// effects are processed here.
|
||||
MOZ_ASSERT(!inEffect || (marker != DisplayItemEntryType::ITEM));
|
||||
|
||||
AnimatedGeometryRoot* itemAGR = nullptr;
|
||||
const ActiveScrolledRoot* itemASR = nullptr;
|
||||
const DisplayItemClipChain* layerClipChain = nullptr;
|
||||
|
@ -4907,17 +4866,55 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
|
|||
itemAGR = inEffect ? containerAGR : mContainerAnimatedGeometryRoot;
|
||||
itemASR = inEffect ? containerASR : mContainerASR;
|
||||
|
||||
FuseItemClipChainIfNeeded(itemASR);
|
||||
if (marker != DisplayItemEntryType::HIT_TEST_INFO) {
|
||||
// Because of the clip chain fusing, |itemClipPtr| needs to be updated.
|
||||
itemClipPtr = &item->GetClip();
|
||||
if (marker == DisplayItemEntryType::HIT_TEST_INFO) {
|
||||
// Items with hit test info are processed twice, once with HIT_TEST_INFO
|
||||
// marker and then with ITEM marker.
|
||||
// With HIT_TEST_INFO markers, fuse the clip chain of hit test struct,
|
||||
// and with ITEM markers, fuse the clip chain of the actual item.
|
||||
itemClipChain = mBuilder->FuseClipChainUpTo(itemClipChain, itemASR);
|
||||
} else if (!IsEffectEndMarker(marker)) {
|
||||
// No need to fuse clip chain for effect end markers, since it was
|
||||
// already done for effect start markers.
|
||||
item->FuseClipChainUpTo(mBuilder, itemASR);
|
||||
itemClipChain = item->GetClipChain();
|
||||
}
|
||||
|
||||
itemClipPtr = itemClipChain ? &itemClipChain->mClip : nullptr;
|
||||
}
|
||||
|
||||
const DisplayItemClip& itemClip = itemClipPtr
|
||||
? *itemClipPtr
|
||||
: DisplayItemClip::NoClip();
|
||||
|
||||
if (inEffect && marker == DisplayItemEntryType::HIT_TEST_INFO) {
|
||||
// Fast-path for hit test items inside flattened inactive layers.
|
||||
MOZ_ASSERT(selectedLayer);
|
||||
selectedLayer->AccumulateHitTestItem(this, item, itemClip, transformNode);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (inEffect && marker == DisplayItemEntryType::ITEM) {
|
||||
// Fast-path for items inside flattened inactive layers. This works
|
||||
// because the layer state of the item cannot be active, otherwise the
|
||||
// parent item would not have been flattened.
|
||||
MOZ_ASSERT(selectedLayer);
|
||||
selectedLayer->Accumulate(this,
|
||||
item,
|
||||
nsIntRect(),
|
||||
nsRect(),
|
||||
itemClip,
|
||||
layerState,
|
||||
aList,
|
||||
marker,
|
||||
opacityIndices,
|
||||
transformNode);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Items outside of flattened effects and non-item markers inside flattened
|
||||
// effects are processed here.
|
||||
MOZ_ASSERT(!inEffect || (marker != DisplayItemEntryType::ITEM));
|
||||
|
||||
if (itemAGR == lastAnimatedGeometryRoot) {
|
||||
topLeft = lastTopLeft;
|
||||
} else {
|
||||
|
@ -5421,7 +5418,7 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
|
|||
|
||||
if (marker == DisplayItemEntryType::HIT_TEST_INFO) {
|
||||
MOZ_ASSERT(!transformNode);
|
||||
paintedLayerData->AccumulateHitTestItem(this, item, nullptr);
|
||||
paintedLayerData->AccumulateHitTestItem(this, item, itemClip, nullptr);
|
||||
} else {
|
||||
paintedLayerData->Accumulate(this,
|
||||
item,
|
||||
|
|
|
@ -1753,6 +1753,28 @@ nsDisplayListBuilder::CopyWholeChain(const DisplayItemClipChain* aClipChain)
|
|||
return CreateClipChainIntersection(nullptr, aClipChain, nullptr);
|
||||
}
|
||||
|
||||
const DisplayItemClipChain*
|
||||
nsDisplayListBuilder::FuseClipChainUpTo(const DisplayItemClipChain* aClipChain,
|
||||
const ActiveScrolledRoot* aASR)
|
||||
{
|
||||
if (!aClipChain) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const DisplayItemClipChain* sc = aClipChain;
|
||||
DisplayItemClip mergedClip;
|
||||
while (sc && ActiveScrolledRoot::PickDescendant(aASR, sc->mASR) == sc->mASR) {
|
||||
mergedClip.IntersectWith(sc->mClip);
|
||||
sc = sc->mParent;
|
||||
}
|
||||
|
||||
if (!mergedClip.HasClip()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return AllocateDisplayItemClipChain(mergedClip, aASR, sc);
|
||||
}
|
||||
|
||||
const nsIFrame*
|
||||
nsDisplayListBuilder::FindReferenceFrameFor(const nsIFrame* aFrame,
|
||||
nsPoint* aOffset) const
|
||||
|
@ -3321,17 +3343,11 @@ void
|
|||
nsDisplayItem::FuseClipChainUpTo(nsDisplayListBuilder* aBuilder,
|
||||
const ActiveScrolledRoot* aASR)
|
||||
{
|
||||
const DisplayItemClipChain* sc = mClipChain;
|
||||
DisplayItemClip mergedClip;
|
||||
while (sc && ActiveScrolledRoot::PickDescendant(aASR, sc->mASR) == sc->mASR) {
|
||||
mergedClip.IntersectWith(sc->mClip);
|
||||
sc = sc->mParent;
|
||||
}
|
||||
if (mergedClip.HasClip()) {
|
||||
mClipChain = aBuilder->AllocateDisplayItemClipChain(mergedClip, aASR, sc);
|
||||
mClipChain = aBuilder->FuseClipChainUpTo(mClipChain, aASR);
|
||||
|
||||
if (mClipChain) {
|
||||
mClip = &mClipChain->mClip;
|
||||
} else {
|
||||
mClipChain = nullptr;
|
||||
mClip = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1126,6 +1126,15 @@ public:
|
|||
const DisplayItemClipChain* CopyWholeChain(
|
||||
const DisplayItemClipChain* aClipChain);
|
||||
|
||||
/**
|
||||
* Returns a new clip chain containing an intersection of all clips of
|
||||
* |aClipChain| up to and including |aASR|.
|
||||
* If there is no clip, returns nullptr.
|
||||
*/
|
||||
const DisplayItemClipChain* FuseClipChainUpTo(
|
||||
const DisplayItemClipChain* aClipChain,
|
||||
const ActiveScrolledRoot* aASR);
|
||||
|
||||
/**
|
||||
* Only used for containerful root scrolling. This is a workaround.
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче