Bug 1534549 - Part 2: Allow all display items to carry hit testing information r=mstange

Differential Revision: https://phabricator.services.mozilla.com/D102515
This commit is contained in:
Miko Mynttinen 2021-02-04 22:19:56 +00:00
Родитель a32145a4c8
Коммит 63a9dd596a
19 изменённых файлов: 515 добавлений и 313 удалений

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

@ -266,6 +266,7 @@ EXPORTS.mozilla.layers += [
"wr/AsyncImagePipelineManager.h",
"wr/ClipManager.h",
"wr/DisplayItemCache.h",
"wr/HitTestInfoManager.h",
"wr/IpcResourceUpdateQueue.h",
"wr/OMTAController.h",
"wr/OMTASampler.h",
@ -545,6 +546,7 @@ UNIFIED_SOURCES += [
"wr/AsyncImagePipelineManager.cpp",
"wr/ClipManager.cpp",
"wr/DisplayItemCache.cpp",
"wr/HitTestInfoManager.cpp",
"wr/IpcResourceUpdateQueue.cpp",
"wr/OMTAController.cpp",
"wr/OMTASampler.cpp",

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

@ -0,0 +1,95 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "HitTestInfoManager.h"
#include "HitTestInfo.h"
#include "nsDisplayList.h"
namespace mozilla::layers {
using ViewID = ScrollableLayerGuid::ViewID;
/**
* TODO(miko): This used to be a performance bottle-neck, but it does not show
* up in profiles anymore, see bugs 1424637 and 1424968.
* A better way of doing this would be to store current app units per dev pixel
* in wr::DisplayListBuilder, and update it whenever display items that separate
* presshell boundaries are encountered.
*/
static int32_t GetAppUnitsFromDisplayItem(nsDisplayItem* aItem) {
nsIFrame* frame = aItem->Frame();
MOZ_ASSERT(frame);
return frame->PresContext()->AppUnitsPerDevPixel();
}
static void CreateWebRenderCommands(wr::DisplayListBuilder& aBuilder,
nsPaintedDisplayItem* aItem,
const nsRect& aArea,
const gfx::CompositorHitTestInfo& aFlags,
const ViewID& aViewId) {
const Maybe<SideBits> sideBits =
aBuilder.GetContainingFixedPosSideBits(aItem->GetActiveScrolledRoot());
const LayoutDeviceRect devRect =
LayoutDeviceRect::FromAppUnits(aArea, GetAppUnitsFromDisplayItem(aItem));
const wr::LayoutRect rect = wr::ToLayoutRect(devRect);
aBuilder.PushHitTest(rect, rect, !aItem->BackfaceIsHidden(), aViewId, aFlags,
sideBits.valueOr(SideBits::eNone));
}
void HitTestInfoManager::Reset() {
mArea = nsRect();
mFlags = gfx::CompositorHitTestInvisibleToHit;
}
void HitTestInfoManager::SwitchItem(nsPaintedDisplayItem* aItem,
wr::DisplayListBuilder& aBuilder,
nsDisplayListBuilder* aDisplayListBuilder) {
if (!aItem || aItem->HasChildren()) {
// Either the item is not a painted display item, or it is a container item.
return;
}
const HitTestInfo& hitTestInfo = aItem->GetHitTestInfo();
const nsRect& area = hitTestInfo.Area();
const gfx::CompositorHitTestInfo& flags = hitTestInfo.Info();
if (area.IsEmpty() || flags == gfx::CompositorHitTestInvisibleToHit) {
return;
}
const auto viewId =
hitTestInfo.GetViewId(aBuilder, aItem->GetActiveScrolledRoot());
const auto spaceAndClipChain = aBuilder.CurrentSpaceAndClipChain();
if (!Update(area, flags, viewId, spaceAndClipChain)) {
// The previous hit test information is still valid.
return;
}
CreateWebRenderCommands(aBuilder, aItem, area, flags, viewId);
}
bool HitTestInfoManager::Update(const nsRect& aArea,
const gfx::CompositorHitTestInfo& aFlags,
const ViewID& aViewId,
const wr::WrSpaceAndClipChain& aSpaceAndClip) {
if (mViewId == aViewId && mFlags == aFlags && mArea.Contains(aArea) &&
mSpaceAndClipChain == aSpaceAndClip) {
// The previous hit testing information can be reused.
return false;
}
mArea = aArea;
mFlags = aFlags;
mViewId = aViewId;
mSpaceAndClipChain = aSpaceAndClip;
return true;
}
} // namespace mozilla::layers

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

@ -0,0 +1,63 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GFX_HITTESTINFOMANAGER_H
#define GFX_HITTESTINFOMANAGER_H
#include "mozilla/gfx/CompositorHitTestInfo.h"
#include "mozilla/layers/ScrollableLayerGuid.h"
#include "mozilla/webrender/WebRenderAPI.h"
#include "nsRect.h"
#include "nsTArray.h"
class nsPaintedDisplayItem;
class nsDisplayListBuilder;
namespace mozilla {
namespace wr {
class DisplayListBuilder;
}
namespace layers {
/**
* This class extracts the hit testing information (area, flags, ViewId) from
* Gecko display items and pushes them into WebRender display list.
*
* The hit testing information is deduplicated: a new hit test item is only
* added if the new area is not contained in the previous area, or if the flags,
* ViewId, or current spatial id is different.
*/
class HitTestInfoManager {
public:
/**
* Resets the previous hit testing information.
*/
void Reset();
/**
* Extracts the hit testing information from |aItem|, and if necessary, adds
* a new WebRender hit test item using |aBuilder|.
*/
void SwitchItem(nsPaintedDisplayItem* aItem, wr::DisplayListBuilder& aBuilder,
nsDisplayListBuilder* aDisplayListBuilder);
private:
bool Update(const nsRect& aArea, const gfx::CompositorHitTestInfo& aFlags,
const ScrollableLayerGuid::ViewID& aViewId,
const wr::WrSpaceAndClipChain& aSpaceAndClip);
nsRect mArea;
gfx::CompositorHitTestInfo mFlags;
ScrollableLayerGuid::ViewID mViewId;
wr::WrSpaceAndClipChain mSpaceAndClipChain;
};
} // namespace layers
} // namespace mozilla
#endif

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

@ -207,6 +207,7 @@ struct Grouper {
int32_t mAppUnitsPerDevPixel;
nsDisplayListBuilder* mDisplayListBuilder;
ClipManager& mClipManager;
HitTestInfoManager mHitTestInfoManager;
Matrix mTransform;
// Paint the list of aChildren display items.
@ -1230,17 +1231,19 @@ void Grouper::ConstructGroups(nsDisplayListBuilder* aDisplayListBuilder,
{
auto spaceAndClipChain = mClipManager.SwitchItem(item);
wr::SpaceAndClipChainHelper saccHelper(aBuilder, spaceAndClipChain);
mHitTestInfoManager.SwitchItem(item->AsPaintedDisplayItem(), aBuilder,
aDisplayListBuilder);
sIndent++;
// Note: this call to CreateWebRenderCommands can recurse back into
// this function.
bool createdWRCommands = item->CreateWebRenderCommands(
aBuilder, aResources, aSc, manager, mDisplayListBuilder);
sIndent--;
MOZ_RELEASE_ASSERT(
createdWRCommands,
"active transforms should always succeed at creating "
"WebRender commands");
sIndent--;
}
currentGroup = &groupData->mFollowingGroup;
@ -1412,6 +1415,7 @@ void WebRenderCommandBuilder::DoGroupingForDisplayList(
GP("DoGroupingForDisplayList\n");
mClipManager.BeginList(aSc);
mHitTestInfoManager.Reset();
Grouper g(mClipManager);
int32_t appUnitsPerDevPixel =
@ -1566,6 +1570,8 @@ void WebRenderCommandBuilder::BuildWebRenderCommands(
aScrollData = WebRenderScrollData(mManager, aDisplayListBuilder);
MOZ_ASSERT(mLayerScrollData.empty());
mClipManager.BeginBuild(mManager, aBuilder);
mHitTestInfoManager.Reset();
mBuilderDumpIndex = 0;
mLastCanvasDatas.Clear();
mLastLocalCanvasDatas.Clear();
@ -1650,6 +1656,12 @@ void WebRenderCommandBuilder::CreateWebRenderCommands(
auto* item = aItem->AsPaintedDisplayItem();
MOZ_RELEASE_ASSERT(item, "Tried to paint item that cannot be painted");
mHitTestInfoManager.SwitchItem(item, aBuilder, aDisplayListBuilder);
if (item->GetType() == DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO) {
// The hit test information was processed above.
return;
}
if (aBuilder.ReuseItem(item)) {
// No further processing should be needed, since the item was reused.
return;

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

@ -9,6 +9,7 @@
#include "mozilla/webrender/WebRenderAPI.h"
#include "mozilla/layers/ClipManager.h"
#include "mozilla/layers/HitTestInfoManager.h"
#include "mozilla/layers/WebRenderMessages.h"
#include "mozilla/layers/WebRenderScrollData.h"
#include "mozilla/layers/WebRenderUserData.h"
@ -178,6 +179,7 @@ class WebRenderCommandBuilder final {
nsDisplayListBuilder* aDisplayListBuilder);
ClipManager mClipManager;
HitTestInfoManager mHitTestInfoManager;
// We use this as a temporary data structure while building the mScrollData
// inside a layers-free transaction.

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

@ -116,13 +116,11 @@ static void PrintDisplayItemTo(nsDisplayListBuilder* aBuilder,
aStream << ")";
}
if (aItem->GetType() == DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO) {
auto* hitTestInfoItem = static_cast<nsDisplayCompositorHitTestInfo*>(aItem);
if (auto* paintedItem = aItem->AsPaintedDisplayItem()) {
aStream << nsPrintfCString(" hitTestInfo(0x%x)",
hitTestInfoItem->HitTestFlags().serialize());
paintedItem->HitTestFlags().serialize());
nsRect area = hitTestInfoItem->HitTestArea();
nsRect area = paintedItem->HitTestArea();
aStream << nsPrintfCString(" hitTestArea(%d,%d,%d,%d)", area.x, area.y,
area.width, area.height);
}

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

@ -385,8 +385,12 @@ nsresult nsButtonFrameRenderer::DisplayButton(nsDisplayListBuilder* aBuilder,
nsRect buttonRect =
mFrame->GetRectRelativeToSelf() + aBuilder->ToReferenceFrame(mFrame);
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, mFrame,
buttonRect, aBackground);
const AppendedBackgroundType result =
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
aBuilder, mFrame, buttonRect, aBackground);
if (result == AppendedBackgroundType::None) {
aBuilder->BuildCompositorHitTestInfoIfNeeded(GetFrame(), aBackground);
}
aBackground->AppendNewToTop<nsDisplayButtonBorder>(aBuilder, GetFrame(),
this);

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

@ -3852,10 +3852,9 @@ void ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
if (info != CompositorHitTestInvisibleToHit) {
auto* hitInfo =
MakeDisplayItemWithIndex<nsDisplayCompositorHitTestInfo>(
aBuilder, mScrolledFrame, 1, info);
aBuilder, mScrolledFrame, 1);
if (hitInfo) {
aBuilder->SetCompositorHitTestInfo(hitInfo->HitTestArea(),
hitInfo->HitTestFlags());
aBuilder->SetCompositorHitTestInfo(info);
set.BorderBackground()->AppendToTop(hitInfo);
}
}
@ -4072,37 +4071,36 @@ void ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
// Make sure that APZ will dispatch events back to content so we can
// create a displayport for this frame. We'll add the item later on.
if (!mWillBuildScrollableLayer) {
if (aBuilder->BuildCompositorHitTestInfo()) {
int32_t zIndex = MaxZIndexInListOfItemsContainedInFrame(
scrolledContent.PositionedDescendants(), mOuter);
if (aBuilder->IsPartialUpdate()) {
if (auto* items =
mScrolledFrame->GetProperty(nsIFrame::DisplayItems())) {
for (nsDisplayItemBase* item : *items) {
if (item->GetType() ==
DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO) {
auto* hitTestItem =
static_cast<nsDisplayCompositorHitTestInfo*>(item);
if (hitTestItem->HitTestFlags().contains(
CompositorHitTestFlags::eInactiveScrollframe)) {
zIndex = std::max(zIndex, hitTestItem->ZIndex());
item->SetCantBeReused();
}
if (!mWillBuildScrollableLayer && aBuilder->BuildCompositorHitTestInfo()) {
int32_t zIndex = MaxZIndexInListOfItemsContainedInFrame(
scrolledContent.PositionedDescendants(), mOuter);
if (aBuilder->IsPartialUpdate()) {
if (auto* items =
mScrolledFrame->GetProperty(nsIFrame::DisplayItems())) {
for (nsDisplayItemBase* item : *items) {
if (item->GetType() ==
DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO) {
auto* hitTestItem =
static_cast<nsDisplayCompositorHitTestInfo*>(item);
if (hitTestItem->HitTestFlags().contains(
CompositorHitTestFlags::eInactiveScrollframe)) {
zIndex = std::max(zIndex, hitTestItem->ZIndex());
item->SetCantBeReused();
}
}
}
}
// Make sure the z-index of the inactive item is at least zero.
// Otherwise, it will end up behind non-positioned items in the scrolled
// content.
zIndex = std::max(zIndex, 0);
nsDisplayCompositorHitTestInfo* hitInfo =
MakeDisplayItemWithIndex<nsDisplayCompositorHitTestInfo>(
aBuilder, mScrolledFrame, 1, info, Some(area));
if (hitInfo) {
AppendInternalItemToTop(scrolledContent, hitInfo, Some(zIndex));
}
}
// Make sure the z-index of the inactive item is at least zero.
// Otherwise, it will end up behind non-positioned items in the scrolled
// content.
zIndex = std::max(zIndex, 0);
nsDisplayCompositorHitTestInfo* hitInfo =
MakeDisplayItemWithIndex<nsDisplayCompositorHitTestInfo>(
aBuilder, mScrolledFrame, 1, area, info);
if (hitInfo) {
AppendInternalItemToTop(scrolledContent, hitInfo, Some(zIndex));
aBuilder->SetCompositorHitTestInfo(info);
}
}

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

@ -2584,19 +2584,26 @@ bool nsIFrame::DisplayBackgroundUnconditional(nsDisplayListBuilder* aBuilder,
return false;
}
AppendedBackgroundType result = AppendedBackgroundType::None;
// Here we don't try to detect background propagation. Frames that might
// receive a propagated background should just set aForceBackground to
// true.
if (hitTesting || aForceBackground ||
!StyleBackground()->IsTransparent(this) ||
StyleDisplay()->HasAppearance()) {
return nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
result = nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
aBuilder, this,
GetRectRelativeToSelf() + aBuilder->ToReferenceFrame(this),
aLists.BorderBackground());
}
return false;
if (result == AppendedBackgroundType::None) {
aBuilder->BuildCompositorHitTestInfoIfNeeded(this,
aLists.BorderBackground());
}
return result == AppendedBackgroundType::ThemedBackground;
}
void nsIFrame::DisplayBorderBackgroundOutline(nsDisplayListBuilder* aBuilder,
@ -2875,6 +2882,19 @@ static void CheckForApzAwareEventHandlers(nsDisplayListBuilder* aBuilder,
}
}
static void UpdateCurrentHitTestInfo(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame) {
if (!aBuilder->BuildCompositorHitTestInfo()) {
// Compositor hit test info is not used.
return;
}
CheckForApzAwareEventHandlers(aBuilder, aFrame);
const CompositorHitTestInfo info = aFrame->GetCompositorHitTestInfo(aBuilder);
aBuilder->SetCompositorHitTestInfo(info);
}
/**
* True if aDescendant participates the context aAncestor participating.
*/
@ -3287,6 +3307,8 @@ void nsIFrame::BuildDisplayListForStackingContext(
nsDisplayListBuilder::AutoBuildingDisplayList buildingDisplayList(
aBuilder, this, visibleRect, dirtyRect, isTransformed);
UpdateCurrentHitTestInfo(aBuilder, this);
// Depending on the effects that are applied to this frame, we can create
// multiple container display items and wrap them around our contents.
// This enum lists all the potential container display items, in the order
@ -3376,8 +3398,6 @@ void nsIFrame::BuildDisplayListForStackingContext(
ApplyClipProp(transformedCssClip);
}
mozilla::UniquePtr<HitTestInfo> hitTestInfo;
nsDisplayListCollection set(aBuilder);
Maybe<nsRect> clipForMask;
bool insertBackdropRoot;
@ -3390,8 +3410,6 @@ void nsIFrame::BuildDisplayListForStackingContext(
nsDisplayListBuilder::AutoInEventsOnly inEventsSetter(
aBuilder, opacityItemForEventsOnly);
CheckForApzAwareEventHandlers(aBuilder, this);
// If we have a mask, compute a clip to bound the masked content.
// This is necessary in case the content moves with an ancestor
// ASR of the mask.
@ -3420,8 +3438,6 @@ void nsIFrame::BuildDisplayListForStackingContext(
}
aBuilder->AdjustWindowDraggingRegion(this);
aBuilder->BuildCompositorHitTestInfoIfNeeded(this, set.BorderBackground(),
true);
MarkAbsoluteFramesForDisplayList(aBuilder);
aBuilder->Check();
@ -3950,11 +3966,7 @@ void nsIFrame::BuildDisplayListForSimpleChild(nsDisplayListBuilder* aBuilder,
nsDisplayListBuilder::AutoBuildingDisplayList buildingForChild(
aBuilder, aChild, visible, dirty, false);
CheckForApzAwareEventHandlers(aBuilder, aChild);
aBuilder->BuildCompositorHitTestInfoIfNeeded(
aChild, aLists.BorderBackground(),
buildingForChild.IsAnimatedGeometryRoot());
UpdateCurrentHitTestInfo(aBuilder, aChild);
aChild->MarkAbsoluteFramesForDisplayList(aBuilder);
aBuilder->AdjustWindowDraggingRegion(aChild);
@ -4168,9 +4180,11 @@ void nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
nsDisplayListBuilder::AutoBuildingDisplayList buildingForChild(
aBuilder, child, visible, dirty);
UpdateCurrentHitTestInfo(aBuilder, child);
DisplayListClipState::AutoClipMultiple clipState(aBuilder);
nsDisplayListBuilder::AutoCurrentActiveScrolledRootSetter asrSetter(aBuilder);
CheckForApzAwareEventHandlers(aBuilder, child);
if (savedOutOfFlowData) {
aBuilder->SetBuildingInvisibleItems(false);
@ -4241,8 +4255,6 @@ void nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
child->MarkAbsoluteFramesForDisplayList(aBuilder);
const bool differentAGR = buildingForChild.IsAnimatedGeometryRoot();
if (!awayFromCommonPath &&
// Some SVG frames might change opacity without invalidating the frame,
// so exclude them from the fast-path.
@ -4255,10 +4267,6 @@ void nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
// THIS IS THE COMMON CASE.
// Not a pseudo or real stacking context. Do the simple thing and
// return early.
aBuilder->BuildCompositorHitTestInfoIfNeeded(
child, aLists.BorderBackground(), differentAGR);
aBuilder->AdjustWindowDraggingRegion(child);
aBuilder->Check();
child->BuildDisplayList(aBuilder, aLists);
@ -4276,16 +4284,6 @@ void nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
// z-index:non-auto
nsDisplayListCollection pseudoStack(aBuilder);
// If this frame has z-index != 0, then the display item might get sorted
// into a different place in the list, and we can't rely on the previous
// hit test info to still be behind us. Force a new hit test info for this
// item, and for the item after it, so that we always have the right hit
// test info.
const bool mayBeSorted = ZIndex().valueOr(0) != 0;
aBuilder->BuildCompositorHitTestInfoIfNeeded(
child, pseudoStack.BorderBackground(), differentAGR || mayBeSorted);
aBuilder->AdjustWindowDraggingRegion(child);
nsDisplayListBuilder::AutoContainerASRTracker contASRTracker(aBuilder);
aBuilder->Check();
@ -4294,16 +4292,6 @@ void nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
if (aBuilder->DisplayCaret(child, pseudoStack.Outlines())) {
builtContainerItem = false;
}
// If we forced a new hit-test info because this frame is going to be
// sorted, then clear the 'previous' data on the builder so that the next
// item also gets a new hit test info. That way we're guaranteeing hit-test
// info before and after each item that might get moved to a different spot.
if (mayBeSorted) {
aBuilder->SetCompositorHitTestInfo(
nsRect(), CompositorHitTestFlags::eVisibleToHitTest);
}
wrapListASR = contASRTracker.GetContainerASR();
list.AppendToTop(pseudoStack.BorderBackground());
@ -11202,7 +11190,7 @@ CompositorHitTestInfo nsIFrame::GetCompositorHitTestInfo(
// that code, but woven into the top-down recursive display list building
// process.
CompositorHitTestInfo inheritedTouchAction =
aBuilder->GetHitTestInfo() & CompositorHitTestTouchActionMask;
aBuilder->GetCompositorHitTestInfo() & CompositorHitTestTouchActionMask;
nsIFrame* touchActionFrame = this;
if (nsIScrollableFrame* scrollFrame =

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

@ -1737,7 +1737,6 @@ class FLBDisplayListIterator : public FlattenedDisplayListIterator {
nsDisplayItem* next = PeekNext();
const DisplayItemType type = next->GetType();
if (type == DisplayItemType::TYPE_SVG_WRAPPER) {
// We mark SetContainsSVG for the CONTENT_FRAME_TIME_WITH_SVG metric
if (RefPtr<LayerManager> lm = mState->mBuilder->GetWidgetLayerManager()) {
@ -4039,8 +4038,9 @@ void PaintedLayerData::AccumulateHitTestItem(ContainerState* aState,
nsDisplayItem* aItem,
const DisplayItemClip& aClip,
TransformClipNode* aTransform) {
MOZ_ASSERT(aItem->GetType() == DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO);
auto* item = static_cast<nsDisplayCompositorHitTestInfo*>(aItem);
auto* item = aItem->AsPaintedDisplayItem();
MOZ_ASSERT(item);
nsRect area = item->HitTestArea();
const CompositorHitTestInfo& flags = item->HitTestFlags();
@ -4549,10 +4549,7 @@ void ContainerState::ProcessDisplayItems(nsDisplayList* aList) {
nsRect itemContent = item->GetBounds(mBuilder, &snap);
if (itemType == DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO) {
// Override the marker for nsDisplayCompositorHitTestInfo items.
marker = DisplayItemEntryType::HitTestInfo;
itemContent =
static_cast<nsDisplayCompositorHitTestInfo*>(item)->HitTestArea();
itemContent = static_cast<nsPaintedDisplayItem*>(item)->HitTestArea();
}
const bool inEffect = InTransform() || InOpacity();
@ -4606,18 +4603,22 @@ void ContainerState::ProcessDisplayItems(nsDisplayList* aList) {
const DisplayItemClip& itemClip =
itemClipPtr ? *itemClipPtr : DisplayItemClip::NoClip();
if (inEffect && marker == DisplayItemEntryType::HitTestInfo) {
// 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);
if (item->AsPaintedDisplayItem()->GetHitTestInfo().Info() !=
mozilla::gfx::CompositorHitTestInvisibleToHit) {
selectedLayer->AccumulateHitTestItem(this, item, itemClip, nullptr);
}
if (itemType == DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO) {
// The hit test info was processed above.
continue;
}
selectedLayer->Accumulate(this, item->AsPaintedDisplayItem(), nsIntRect(),
nsRect(), itemClip, layerState, aList, marker,
opacityIndices, transformNode);
@ -4678,7 +4679,7 @@ void ContainerState::ProcessDisplayItems(nsDisplayList* aList) {
#ifdef DEBUG
nsRect bounds = itemContent;
if (marker == DisplayItemEntryType::HitTestInfo || inEffect) {
if (inEffect) {
bounds.SetEmpty();
}
@ -5109,9 +5110,6 @@ void ContainerState::ProcessDisplayItems(nsDisplayList* aList) {
? mContainerReferenceFrame
: item->ReferenceFrame();
MOZ_ASSERT(item != mContainerItem ||
marker == DisplayItemEntryType::HitTestInfo);
PaintedLayerData* paintedLayerData = selectedLayer;
if (!paintedLayerData) {
@ -5125,31 +5123,36 @@ void ContainerState::ProcessDisplayItems(nsDisplayList* aList) {
}
MOZ_ASSERT(paintedLayerData);
if (marker == DisplayItemEntryType::HitTestInfo) {
MOZ_ASSERT(!transformNode);
if (item->AsPaintedDisplayItem()->GetHitTestInfo().Info() !=
mozilla::gfx::CompositorHitTestInvisibleToHit) {
paintedLayerData->AccumulateHitTestItem(this, item, itemClip, nullptr);
} else {
paintedLayerData->Accumulate(
this, item->AsPaintedDisplayItem(), itemVisibleRect, itemContent,
itemClip, layerState, aList, marker, opacityIndices, transformNode);
}
if (!paintedLayerData->mLayer) {
// Try to recycle the old layer of this display item.
RefPtr<PaintedLayer> layer = AttemptToRecyclePaintedLayer(
itemAGR, item, topLeft,
inEffect ? containerReferenceFrame : referenceFrame);
if (layer) {
paintedLayerData->mLayer = layer;
if (itemType == DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO) {
// The hit test info was processed above.
continue;
}
auto* userData = GetPaintedDisplayItemLayerUserData(layer);
paintedLayerData->mAssignedDisplayItems.reserve(
userData->mLastItemCount);
paintedLayerData->Accumulate(
this, item->AsPaintedDisplayItem(), itemVisibleRect, itemContent,
itemClip, layerState, aList, marker, opacityIndices, transformNode);
NS_ASSERTION(FindIndexOfLayerIn(mNewChildLayers, layer) < 0,
"Layer already in list???");
mNewChildLayers[paintedLayerData->mNewChildLayersIndex].mLayer =
std::move(layer);
}
if (!paintedLayerData->mLayer) {
// Try to recycle the old layer of this display item.
RefPtr<PaintedLayer> layer = AttemptToRecyclePaintedLayer(
itemAGR, item, topLeft,
inEffect ? containerReferenceFrame : referenceFrame);
if (layer) {
paintedLayerData->mLayer = layer;
auto* userData = GetPaintedDisplayItemLayerUserData(layer);
paintedLayerData->mAssignedDisplayItems.reserve(
userData->mLastItemCount);
NS_ASSERTION(FindIndexOfLayerIn(mNewChildLayers, layer) < 0,
"Layer already in list???");
mNewChildLayers[paintedLayerData->mNewChildLayersIndex].mLayer =
std::move(layer);
}
}

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

@ -77,7 +77,6 @@ enum class DisplayItemEntryType : uint8_t {
PopOpacity,
PushTransform,
PopTransform,
HitTestInfo,
};
/**

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

@ -0,0 +1,58 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "HitTestInfo.h"
#include "mozilla/webrender/WebRenderAPI.h"
#include "nsDisplayList.h"
#include "nsIFrame.h"
namespace mozilla {
using ViewID = layers::ScrollableLayerGuid::ViewID;
ViewID HitTestInfo::GetViewId(wr::DisplayListBuilder& aBuilder,
const ActiveScrolledRoot* aASR) const {
if (mScrollTarget) {
return *mScrollTarget;
}
Maybe<ScrollableLayerGuid::ViewID> fixedTarget =
aBuilder.GetContainingFixedPosScrollTarget(aASR);
if (fixedTarget) {
return *fixedTarget;
}
if (aASR) {
return aASR->GetViewId();
}
return ScrollableLayerGuid::NULL_SCROLL_ID;
}
void HitTestInfo::Initialize(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) {
if (!aBuilder->BuildCompositorHitTestInfo()) {
return;
}
mInfo = aFrame->GetCompositorHitTestInfo(aBuilder);
if (mInfo != gfx::CompositorHitTestInvisibleToHit) {
mArea = aFrame->GetCompositorHitTestArea(aBuilder);
InitializeScrollTarget(aBuilder);
}
}
void HitTestInfo::InitializeScrollTarget(nsDisplayListBuilder* aBuilder) {
if (aBuilder->GetCurrentScrollbarDirection().isSome()) {
// In the case of scrollbar frames, we use the scrollbar's target
// scrollframe instead of the scrollframe with which the scrollbar actually
// moves.
MOZ_ASSERT(Info().contains(CompositorHitTestFlags::eScrollbar));
mScrollTarget = Some(aBuilder->GetCurrentScrollbarTarget());
}
}
} // namespace mozilla

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

@ -0,0 +1,53 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GFX_HITTESTINFO_H
#define GFX_HITTESTINFO_H
#include "mozilla/gfx/CompositorHitTestInfo.h"
#include "mozilla/layers/ScrollableLayerGuid.h"
#include "nsRect.h"
class nsIFrame;
class nsDisplayListBuilder;
namespace mozilla {
struct ActiveScrolledRoot;
/**
* A helper class that manages compositor hit testing information.
*/
class HitTestInfo {
public:
using CompositorHitTestInfo = gfx::CompositorHitTestInfo;
using ViewID = layers::ScrollableLayerGuid::ViewID;
ViewID GetViewId(wr::DisplayListBuilder& aBuilder,
const ActiveScrolledRoot* aASR) const;
void Initialize(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
void InitializeScrollTarget(nsDisplayListBuilder* aBuilder);
void SetAreaAndInfo(const nsRect& aArea, const CompositorHitTestInfo& aInfo) {
mArea = aArea;
mInfo = aInfo;
}
static void Shutdown();
const nsRect& Area() const { return mArea; }
const CompositorHitTestInfo& Info() const { return mInfo; }
private:
nsRect mArea;
CompositorHitTestInfo mInfo;
mozilla::Maybe<ViewID> mScrollTarget;
};
} // namespace mozilla
#endif

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

@ -13,6 +13,7 @@ EXPORTS += [
"DisplayItemClipChain.h",
"DisplayListClipState.h",
"FrameLayerBuilder.h",
"HitTestInfo.h",
"LayerState.h",
"MatrixStack.h",
"nsCSSRenderingBorders.h",
@ -40,6 +41,7 @@ UNIFIED_SOURCES += [
"DisplayListClipState.cpp",
"DottedCornerFinder.cpp",
"FrameLayerBuilder.cpp",
"HitTestInfo.cpp",
"MaskLayerImageCache.cpp",
"nsCSSRendering.cpp",
"nsCSSRenderingBorders.cpp",

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

@ -173,6 +173,25 @@ void UpdateDisplayItemData(nsPaintedDisplayItem* aItem) {
}
}
static bool ItemTypeSupportsHitTesting(const DisplayItemType aType) {
switch (aType) {
case DisplayItemType::TYPE_BACKGROUND:
case DisplayItemType::TYPE_BACKGROUND_COLOR:
case DisplayItemType::TYPE_THEMED_BACKGROUND:
return true;
default:
return false;
}
}
void InitializeHitTestInfo(nsDisplayListBuilder* aBuilder,
nsPaintedDisplayItem* aItem,
const DisplayItemType aType) {
if (ItemTypeSupportsHitTesting(aType)) {
aItem->GetHitTestInfo().Initialize(aBuilder, aItem->Frame());
}
}
/* static */
already_AddRefed<ActiveScrolledRoot> ActiveScrolledRoot::CreateASRForFrame(
const ActiveScrolledRoot* aParent, nsIScrollableFrame* aScrollableFrame,
@ -613,9 +632,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
mBuildAsyncZoomContainer(false),
mContainsBackdropFilter(false),
mIsRelativeToLayoutViewport(false),
mUseOverlayScrollbars(false),
mHitTestArea(),
mHitTestInfo(CompositorHitTestInvisibleToHit) {
mUseOverlayScrollbars(false) {
MOZ_COUNT_CTOR(nsDisplayListBuilder);
mBuildCompositorHitTestInfo = mAsyncPanZoomEnabled && IsForPainting();
@ -2085,7 +2102,7 @@ void nsDisplayListBuilder::AppendNewScrollInfoItemForHoisting(
}
void nsDisplayListBuilder::BuildCompositorHitTestInfoIfNeeded(
nsIFrame* aFrame, nsDisplayList* aList, const bool aBuildNew) {
nsIFrame* aFrame, nsDisplayList* aList) {
MOZ_ASSERT(aFrame);
MOZ_ASSERT(aList);
@ -2094,22 +2111,9 @@ void nsDisplayListBuilder::BuildCompositorHitTestInfoIfNeeded(
}
const CompositorHitTestInfo info = aFrame->GetCompositorHitTestInfo(this);
if (info == CompositorHitTestInvisibleToHit) {
return;
if (info != CompositorHitTestInvisibleToHit) {
aList->AppendNewToTop<nsDisplayCompositorHitTestInfo>(this, aFrame);
}
const nsRect area = aFrame->GetCompositorHitTestArea(this);
if (!aBuildNew && GetHitTestInfo() == info &&
GetHitTestArea().Contains(area)) {
return;
}
auto* item = MakeDisplayItem<nsDisplayCompositorHitTestInfo>(
this, aFrame, info, Some(area));
MOZ_ASSERT(item);
SetCompositorHitTestInfo(area, info);
aList->AppendToTop(item);
}
void nsDisplayListSet::MoveTo(const nsDisplayListSet& aDestination) const {
@ -3544,7 +3548,7 @@ static nsDisplayBackgroundColor* CreateBackgroundColor(
}
/*static*/
bool nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
AppendedBackgroundType nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const nsRect& aBackgroundRect, nsDisplayList* aList,
bool aAllowWillPaintBorderOptimization, ComputedStyle* aComputedStyle,
@ -3590,7 +3594,7 @@ bool nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
if (SpecialCutoutRegionCase(aBuilder, aFrame, aBackgroundRect, aList,
color)) {
return false;
return AppendedBackgroundType::None;
}
const nsStyleBorder* borderStyle = aFrame->StyleBorder();
@ -3659,13 +3663,21 @@ bool nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
bgItemList.AppendToTop(bgItem);
}
aList->AppendToTop(&bgItemList);
return true;
if (!bgItemList.IsEmpty()) {
aList->AppendToTop(&bgItemList);
return AppendedBackgroundType::ThemedBackground;
}
return AppendedBackgroundType::None;
}
if (!bg || !drawBackgroundImage) {
aList->AppendToTop(&bgItemList);
return false;
if (!bgItemList.IsEmpty()) {
aList->AppendToTop(&bgItemList);
return AppendedBackgroundType::Background;
}
return AppendedBackgroundType::None;
}
const ActiveScrolledRoot* asr = aBuilder->CurrentActiveScrolledRoot();
@ -3782,8 +3794,12 @@ bool nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
aBuilder, aFrame, aSecondaryReferenceFrame, &bgItemList, asr));
}
aList->AppendToTop(&bgItemList);
return false;
if (!bgItemList.IsEmpty()) {
aList->AppendToTop(&bgItemList);
return AppendedBackgroundType::Background;
}
return AppendedBackgroundType::None;
}
// Check that the rounded border of aFrame, added to aToReferenceFrame,
@ -4845,90 +4861,12 @@ void nsDisplayEventReceiver::HitTest(nsDisplayListBuilder* aBuilder,
aOutFrames->AppendElement(mFrame);
}
nsDisplayCompositorHitTestInfo::nsDisplayCompositorHitTestInfo(
nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const mozilla::gfx::CompositorHitTestInfo& aHitTestFlags,
const mozilla::Maybe<nsRect>& aArea)
: nsPaintedDisplayItem(aBuilder, aFrame),
mAppUnitsPerDevPixel(mFrame->PresContext()->AppUnitsPerDevPixel()) {
MOZ_COUNT_CTOR(nsDisplayCompositorHitTestInfo);
// We should never even create this display item if we're not building
// compositor hit-test info or if the computed hit info indicated the
// frame is invisible to hit-testing
MOZ_ASSERT(aBuilder->BuildCompositorHitTestInfo());
MOZ_ASSERT(aHitTestFlags != CompositorHitTestInvisibleToHit);
const nsRect& area =
aArea.isSome() ? *aArea : aFrame->GetCompositorHitTestArea(aBuilder);
SetHitTestInfo(area, aHitTestFlags);
InitializeScrollTarget(aBuilder);
}
nsDisplayCompositorHitTestInfo::nsDisplayCompositorHitTestInfo(
nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
mozilla::UniquePtr<HitTestInfo>&& aHitTestInfo)
: nsPaintedDisplayItem(aBuilder, aFrame),
mAppUnitsPerDevPixel(mFrame->PresContext()->AppUnitsPerDevPixel()) {
MOZ_COUNT_CTOR(nsDisplayCompositorHitTestInfo);
SetHitTestInfo(std::move(aHitTestInfo));
InitializeScrollTarget(aBuilder);
}
void nsDisplayCompositorHitTestInfo::InitializeScrollTarget(
nsDisplayListBuilder* aBuilder) {
if (aBuilder->GetCurrentScrollbarDirection().isSome()) {
// In the case of scrollbar frames, we use the scrollbar's target
// scrollframe instead of the scrollframe with which the scrollbar actually
// moves.
MOZ_ASSERT(HitTestFlags().contains(CompositorHitTestFlags::eScrollbar));
mScrollTarget = mozilla::Some(aBuilder->GetCurrentScrollbarTarget());
}
}
bool nsDisplayCompositorHitTestInfo::CreateWebRenderCommands(
mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
mozilla::layers::RenderRootStateManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) {
if (HitTestArea().IsEmpty()) {
return true;
}
// XXX: eventually this scrollId computation and the SetHitTestInfo
// call will get moved out into the WR display item iteration code so that
// we don't need to do it as often, and so that we can do it for other
// display item types as well (reducing the need for as many instances of
// this display item).
ScrollableLayerGuid::ViewID scrollId =
mScrollTarget.valueOrFrom([&]() -> ScrollableLayerGuid::ViewID {
const ActiveScrolledRoot* asr = GetActiveScrolledRoot();
Maybe<ScrollableLayerGuid::ViewID> fixedTarget =
aBuilder.GetContainingFixedPosScrollTarget(asr);
if (fixedTarget) {
return *fixedTarget;
}
if (asr) {
return asr->GetViewId();
}
return ScrollableLayerGuid::NULL_SCROLL_ID;
});
Maybe<SideBits> sideBits =
aBuilder.GetContainingFixedPosSideBits(GetActiveScrolledRoot());
// Insert a transparent rectangle with the hit-test info
const LayoutDeviceRect devRect =
LayoutDeviceRect::FromAppUnits(HitTestArea(), mAppUnitsPerDevPixel);
const wr::LayoutRect rect = wr::ToLayoutRect(devRect);
aBuilder.StartGroup(this);
aBuilder.PushHitTest(rect, rect, !BackfaceIsHidden(), scrollId,
HitTestFlags(), sideBits.valueOr(SideBits::eNone));
aBuilder.FinishGroup();
return true;
}
@ -7360,7 +7298,8 @@ bool nsDisplayAsyncZoom::UpdateScrollData(
//
#ifndef DEBUG
static_assert(sizeof(nsDisplayTransform) < 512, "nsDisplayTransform has grown");
static_assert(sizeof(nsDisplayTransform) <= 512,
"nsDisplayTransform has grown");
#endif
nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder,
@ -10228,13 +10167,12 @@ nsDisplayListBuilder::AutoBuildingDisplayList::AutoBuildingDisplayList(
: mBuilder(aBuilder),
mPrevFrame(aBuilder->mCurrentFrame),
mPrevReferenceFrame(aBuilder->mCurrentReferenceFrame),
mPrevHitTestArea(aBuilder->mHitTestArea),
mPrevHitTestInfo(aBuilder->mHitTestInfo),
mPrevOffset(aBuilder->mCurrentOffsetToReferenceFrame),
mPrevAdditionalOffset(aBuilder->mAdditionalOffset),
mPrevVisibleRect(aBuilder->mVisibleRect),
mPrevDirtyRect(aBuilder->mDirtyRect),
mPrevAGR(aBuilder->mCurrentAGR),
mPrevCompositorHitTestInfo(aBuilder->mCompositorHitTestInfo),
mPrevAncestorHasApzAwareEventHandler(
aBuilder->mAncestorHasApzAwareEventHandler),
mPrevBuildingInvisibleItems(aBuilder->mBuildingInvisibleItems),

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

@ -34,6 +34,7 @@
#include "DisplayListClipState.h"
#include "LayerState.h"
#include "FrameMetrics.h"
#include "HitTestInfo.h"
#include "ImgDrawResult.h"
#include "mozilla/dom/EffectsInfo.h"
#include "mozilla/dom/RemoteBrowser.h"
@ -680,29 +681,20 @@ class nsDisplayListBuilder {
mAllowMergingAndFlattening = aAllow;
}
/**
* Sets the current compositor hit test area and info to |aHitTestArea| and
* |aHitTestInfo|.
* This is used during display list building to determine if the parent frame
* hit test info contains the same information that child frame needs.
*/
void SetCompositorHitTestInfo(const nsRect& aHitTestArea,
const CompositorHitTestInfo& aHitTestInfo) {
mHitTestArea = aHitTestArea;
mHitTestInfo = aHitTestInfo;
void SetCompositorHitTestInfo(const CompositorHitTestInfo& aInfo) {
mCompositorHitTestInfo = aInfo;
}
const nsRect& GetHitTestArea() const { return mHitTestArea; }
const CompositorHitTestInfo& GetHitTestInfo() const { return mHitTestInfo; }
const CompositorHitTestInfo& GetCompositorHitTestInfo() const {
return mCompositorHitTestInfo;
}
/**
* Builds a new nsDisplayCompositorHitTestInfo for the frame |aFrame| if
* needed, and adds it to the top of |aList|. If |aBuildNew| is true, the
* previous hit test info will not be reused.
* needed, and adds it to the top of |aList|.
*/
void BuildCompositorHitTestInfoIfNeeded(nsIFrame* aFrame,
nsDisplayList* aList,
const bool aBuildNew);
nsDisplayList* aList);
bool IsInsidePointerEventsNoneDoc() {
return CurrentPresShellState()->mInsidePointerEventsNoneDoc;
@ -1134,8 +1126,6 @@ class nsDisplayListBuilder {
~AutoBuildingDisplayList() {
mBuilder->mCurrentFrame = mPrevFrame;
mBuilder->mCurrentReferenceFrame = mPrevReferenceFrame;
mBuilder->mHitTestArea = mPrevHitTestArea;
mBuilder->mHitTestInfo = mPrevHitTestInfo;
mBuilder->mCurrentOffsetToReferenceFrame = mPrevOffset;
mBuilder->mVisibleRect = mPrevVisibleRect;
mBuilder->mDirtyRect = mPrevDirtyRect;
@ -1145,6 +1135,7 @@ class nsDisplayListBuilder {
mBuilder->mBuildingInvisibleItems = mPrevBuildingInvisibleItems;
mBuilder->mInInvalidSubtree = mPrevInInvalidSubtree;
mBuilder->mAdditionalOffset = mPrevAdditionalOffset;
mBuilder->mCompositorHitTestInfo = mPrevCompositorHitTestInfo;
}
private:
@ -1152,13 +1143,12 @@ class nsDisplayListBuilder {
AGRState mCurrentAGRState;
const nsIFrame* mPrevFrame;
const nsIFrame* mPrevReferenceFrame;
nsRect mPrevHitTestArea;
CompositorHitTestInfo mPrevHitTestInfo;
nsPoint mPrevOffset;
mozilla::Maybe<nsPoint> mPrevAdditionalOffset;
nsRect mPrevVisibleRect;
nsRect mPrevDirtyRect;
RefPtr<AnimatedGeometryRoot> mPrevAGR;
CompositorHitTestInfo mPrevCompositorHitTestInfo;
bool mPrevAncestorHasApzAwareEventHandler;
bool mPrevBuildingInvisibleItems;
bool mPrevInInvalidSubtree;
@ -1832,7 +1822,6 @@ class nsDisplayListBuilder {
friend class nsDisplayItem;
friend class nsDisplayOwnLayer;
friend struct RetainedDisplayListBuilder;
friend struct HitTestInfo;
AnimatedGeometryRoot* FindAnimatedGeometryRootFor(nsIFrame* aFrame);
AnimatedGeometryRoot* WrapAGRForFrame(
@ -2029,8 +2018,7 @@ class nsDisplayListBuilder {
bool mUseOverlayScrollbars;
mozilla::Maybe<float> mVisibleThreshold;
nsRect mHitTestArea;
CompositorHitTestInfo mHitTestInfo;
mozilla::gfx::CompositorHitTestInfo mCompositorHitTestInfo;
};
class nsDisplayItem;
@ -2083,8 +2071,18 @@ void AssertUniqueItem(nsDisplayItem* aItem);
*/
bool ShouldBuildItemForEvents(const DisplayItemType aType);
/**
* Updates the item DisplayItemData if needed.
*/
void UpdateDisplayItemData(nsPaintedDisplayItem* aItem);
/**
* Initializes the hit test information of |aItem| if the item type supports it.
*/
void InitializeHitTestInfo(nsDisplayListBuilder* aBuilder,
nsPaintedDisplayItem* aItem,
const DisplayItemType aType);
template <typename T, typename F, typename... Args>
MOZ_ALWAYS_INLINE T* MakeDisplayItemWithIndex(nsDisplayListBuilder* aBuilder,
F* aFrame, const uint16_t aIndex,
@ -2112,6 +2110,7 @@ MOZ_ALWAYS_INLINE T* MakeDisplayItemWithIndex(nsDisplayListBuilder* aBuilder,
nsPaintedDisplayItem* paintedItem = item->AsPaintedDisplayItem();
if (paintedItem) {
UpdateDisplayItemData(paintedItem);
InitializeHitTestInfo(aBuilder, paintedItem, type);
}
if (aBuilder->InInvalidSubtree() ||
@ -2164,8 +2163,6 @@ class nsDisplayItemLink {
friend class nsDisplayList;
};
class nsPaintedDisplayItem;
/*
* nsDisplayItemBase is a base-class for all display items. It is mainly
* responsible for handling the frame-display item 1:n relationship, as well as
@ -3255,9 +3252,16 @@ class nsPaintedDisplayItem : public nsDisplayItem {
mCacheIndex = mozilla::Nothing();
}
mozilla::HitTestInfo& GetHitTestInfo() { return mHitTestInfo; }
const nsRect& HitTestArea() const { return mHitTestInfo.Area(); }
const mozilla::gfx::CompositorHitTestInfo& HitTestFlags() const {
return mHitTestInfo.Info();
}
protected:
nsPaintedDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
: nsDisplayItem(aBuilder, aFrame) {}
: nsPaintedDisplayItem(aBuilder, aFrame,
aBuilder->CurrentActiveScrolledRoot()) {}
nsPaintedDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const ActiveScrolledRoot* aActiveScrolledRoot)
@ -3265,12 +3269,15 @@ class nsPaintedDisplayItem : public nsDisplayItem {
nsPaintedDisplayItem(nsDisplayListBuilder* aBuilder,
const nsPaintedDisplayItem& aOther)
: nsDisplayItem(aBuilder, aOther) {}
: nsDisplayItem(aBuilder, aOther), mHitTestInfo(aOther.mHitTestInfo) {}
private:
mozilla::DisplayItemData* mDisplayItemData = nullptr;
mozilla::layers::LayerManager* mDisplayItemDataLayerManager = nullptr;
mozilla::Maybe<uint16_t> mCacheIndex;
protected:
mozilla::HitTestInfo mHitTestInfo;
};
/**
@ -4438,6 +4445,12 @@ class nsDisplaySolidColorRegion : public nsPaintedDisplayItem {
sRGBColor mColor;
};
enum class AppendedBackgroundType : uint8_t {
None,
Background,
ThemedBackground,
};
/**
* A display item to paint one background-image for a frame. Each background
* image layer gets its own nsDisplayBackgroundImage.
@ -4476,12 +4489,14 @@ class nsDisplayBackgroundImage : public nsDisplayImageContainer {
NS_DISPLAY_DECL_NAME("Background", TYPE_BACKGROUND)
// This will create and append new items for all the layers of the
// background. Returns whether we appended a themed background.
// aAllowWillPaintBorderOptimization should usually be left at true, unless
// aFrame has special border drawing that causes opaque borders to not
// actually be opaque.
static bool AppendBackgroundItemsToTop(
/**
* This will create and append new items for all the layers of the
* background. Returns the type of background that was appended.
* aAllowWillPaintBorderOptimization should usually be left at true, unless
* aFrame has special border drawing that causes opaque borders to not
* actually be opaque.
*/
static AppendedBackgroundType AppendBackgroundItemsToTop(
nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const nsRect& aBackgroundRect, nsDisplayList* aList,
bool aAllowWillPaintBorderOptimization = true,
@ -5145,20 +5160,6 @@ class nsDisplayEventReceiver final : public nsDisplayItem {
HitTestState* aState, nsTArray<nsIFrame*>* aOutFrames) final;
};
struct HitTestInfo {
HitTestInfo(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const mozilla::gfx::CompositorHitTestInfo& aHitTestFlags)
: mArea(aFrame->GetCompositorHitTestArea(aBuilder)),
mFlags(aHitTestFlags) {}
HitTestInfo(const nsRect& aArea,
const mozilla::gfx::CompositorHitTestInfo& aHitTestFlags)
: mArea(aArea), mFlags(aHitTestFlags) {}
nsRect mArea;
mozilla::gfx::CompositorHitTestInfo mFlags;
};
/**
* Similar to nsDisplayEventReceiver in that it is used for hit-testing. However
* this gets built when we're doing widget painting and we need to send the
@ -5167,21 +5168,26 @@ struct HitTestInfo {
*/
class nsDisplayCompositorHitTestInfo : public nsPaintedDisplayItem {
public:
nsDisplayCompositorHitTestInfo(
nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const mozilla::gfx::CompositorHitTestInfo& aHitTestFlags,
const mozilla::Maybe<nsRect>& aArea = mozilla::Nothing());
nsDisplayCompositorHitTestInfo(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame)
: nsPaintedDisplayItem(aBuilder, aFrame) {
MOZ_COUNT_CTOR(nsDisplayCompositorHitTestInfo);
mHitTestInfo.Initialize(aBuilder, aFrame);
}
nsDisplayCompositorHitTestInfo(
nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
mozilla::UniquePtr<HitTestInfo>&& aHitTestInfo);
nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, const nsRect& aArea,
const mozilla::gfx::CompositorHitTestInfo& aHitTestFlags)
: nsPaintedDisplayItem(aBuilder, aFrame) {
MOZ_COUNT_CTOR(nsDisplayCompositorHitTestInfo);
mHitTestInfo.SetAreaAndInfo(aArea, aHitTestFlags);
mHitTestInfo.InitializeScrollTarget(aBuilder);
}
MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayCompositorHitTestInfo)
NS_DISPLAY_DECL_NAME("CompositorHitTestInfo", TYPE_COMPOSITOR_HITTEST_INFO)
void InitializeScrollTarget(nsDisplayListBuilder* aBuilder);
bool CreateWebRenderCommands(
mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
@ -5192,26 +5198,6 @@ class nsDisplayCompositorHitTestInfo : public nsPaintedDisplayItem {
int32_t ZIndex() const override;
void SetOverrideZIndex(int32_t aZIndex);
void SetHitTestInfo(mozilla::UniquePtr<HitTestInfo>&& aHitTestInfo) {
MOZ_ASSERT(aHitTestInfo);
MOZ_ASSERT(aHitTestInfo->mFlags !=
mozilla::gfx::CompositorHitTestInvisibleToHit);
mHitTestInfo = std::move(aHitTestInfo);
}
void SetHitTestInfo(
const nsRect& aArea,
const mozilla::gfx::CompositorHitTestInfo& aHitTestFlags) {
MOZ_ASSERT(aHitTestFlags != mozilla::gfx::CompositorHitTestInvisibleToHit);
mHitTestInfo = mozilla::MakeUnique<HitTestInfo>(aArea, aHitTestFlags);
}
const HitTestInfo& GetHitTestInfo() const {
MOZ_ASSERT(mHitTestInfo);
return *mHitTestInfo;
}
/**
* ApplyOpacity() is overriden for opacity flattening.
*/
@ -5228,18 +5214,8 @@ class nsDisplayCompositorHitTestInfo : public nsPaintedDisplayItem {
return nsRect();
}
const nsRect& HitTestArea() const { return mHitTestInfo->mArea; }
const mozilla::gfx::CompositorHitTestInfo& HitTestFlags() const {
return mHitTestInfo->mFlags;
}
private:
mozilla::Maybe<mozilla::layers::ScrollableLayerGuid::ViewID> mScrollTarget;
mozilla::Maybe<int32_t> mOverrideZIndex;
int32_t mAppUnitsPerDevPixel;
mozilla::UniquePtr<HitTestInfo> mHitTestInfo;
};
/**

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

@ -215,6 +215,9 @@ void SVGGeometryFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
styleSVG->mMarkerMid.IsNone() && styleSVG->mMarkerStart.IsNone()) {
return;
}
aBuilder->BuildCompositorHitTestInfoIfNeeded(this,
aLists.BorderBackground());
}
DisplayOutline(aBuilder, aLists);

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

@ -765,6 +765,8 @@ void SVGOuterSVGFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
contentList, contentList);
BuildDisplayListForNonBlockChildren(aBuilder, set);
} else if (IsVisibleForPainting() || !aBuilder->IsForPainting()) {
aBuilder->BuildCompositorHitTestInfoIfNeeded(this,
aLists.BorderBackground());
aLists.Content()->AppendNewToTop<nsDisplayOuterSVG>(aBuilder, this);
}
}

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

@ -463,13 +463,19 @@ void nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
nsRect bgRect = GetRectRelativeToSelf() + aBuilder->ToReferenceFrame(this);
// display background if we need to.
AppendedBackgroundType result = AppendedBackgroundType::None;
if (aBuilder->IsForEventDelivery() ||
!StyleBackground()->IsTransparent(this) ||
StyleDisplay()->HasAppearance()) {
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
result = nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
aBuilder, this, bgRect, aLists.BorderBackground());
}
if (result == AppendedBackgroundType::None) {
aBuilder->BuildCompositorHitTestInfoIfNeeded(this,
aLists.BorderBackground());
}
// display inset box-shadows if we need to.
if (hasBoxShadow) {
aLists.BorderBackground()->AppendNewToTop<nsDisplayBoxShadowInner>(