Bug 1404181 - Part 10: Track theme geometry contributions per-frame so that can remove contributions from invalidated frames. r?mstange
MozReview-Commit-ID: JjTOGiaeWAn
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -3096,17 +3096,17 @@ static void
RegisterThemeGeometry(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsITheme::ThemeGeometryType aType)
{
if (aBuilder->IsInChromeDocumentOrPopup() && !aBuilder->IsInTransform()) {
nsIFrame* displayRoot = nsLayoutUtils::GetDisplayRootFrame(aFrame);
nsPoint offset = aBuilder->IsInSubdocument() ? aBuilder->ToReferenceFrame(aFrame)
: aFrame->GetOffsetTo(displayRoot);
nsRect borderBox = nsRect(offset, aFrame->GetSize());
- aBuilder->RegisterThemeGeometry(aType,
+ aBuilder->RegisterThemeGeometry(aType, aFrame,
LayoutDeviceIntRect::FromUnknownRect(
borderBox.ToNearestPixels(
aFrame->PresContext()->AppUnitsPerDevPixel())));
}
}
// Return the bounds of the viewport relative to |aFrame|'s reference frame.
// Returns Nothing() if transforming into |aFrame|'s coordinate space fails.
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -812,51 +812,74 @@ public:
/**
* Mark all child frames that Preserve3D() as needing display.
* Because these frames include transforms set on their parent, dirty rects
* for intermediate frames may be empty, yet child frames could still be visible.
*/
void MarkPreserve3DFramesForDisplayList(nsIFrame* aDirtyFrame);
- const nsTArray<ThemeGeometry>& GetThemeGeometries() { return mThemeGeometries; }
-
/**
* Returns true if we need to descend into this frame when building
* the display list, even though it doesn't intersect the dirty
* rect, because it may have out-of-flows that do so.
*/
bool ShouldDescendIntoFrame(nsIFrame* aFrame, bool aVisible) const {
return
(aFrame->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) ||
(aVisible && aFrame->ForceDescendIntoIfVisible()) ||
GetIncludeAllOutOfFlows();
}
/**
+ * Returns the list of registered theme geometries.
+ */
+ nsTArray<ThemeGeometry> GetThemeGeometries() const
+ {
+ nsTArray<ThemeGeometry> geometries;
+
+ for (auto iter = mThemeGeometries.ConstIter(); !iter.Done(); iter.Next()) {
+ geometries.AppendElements(*iter.Data());
+ }
+
+ return geometries;
+ }
+
+ /**
* Notifies the builder that a particular themed widget exists
* at the given rectangle within the currently built display list.
* For certain appearance values (currently only NS_THEME_TOOLBAR and
* NS_THEME_WINDOW_TITLEBAR) this gets called during every display list
* construction, for every themed widget of the right type within the
* display list, except for themed widgets which are transformed or have
* effects applied to them (e.g. CSS opacity or filters).
*
* @param aWidgetType the -moz-appearance value for the themed widget
* @param aRect the device-pixel rect relative to the widget's displayRoot
* for the themed widget
*/
- void RegisterThemeGeometry(uint8_t aWidgetType,
+ void RegisterThemeGeometry(uint8_t aWidgetType, nsIFrame* aFrame,
const mozilla::LayoutDeviceIntRect& aRect) {
if (mIsPaintingToWindow) {
- mThemeGeometries.AppendElement(ThemeGeometry(aWidgetType, aRect));
+ nsTArray<ThemeGeometry>* geometries =
+ mThemeGeometries.LookupOrAdd(aFrame);
+
+ geometries->AppendElement(ThemeGeometry(aWidgetType, aRect));
}
}
/**
+ * Removes theme geometries associated with the given frame.
+ */
+ void UnregisterThemeGeometry(nsIFrame* aFrame)
+ {
+ mThemeGeometries.Remove(aFrame);
+ }
+
+ /**
* Adjusts mWindowDraggingRegion to take into account aFrame. If aFrame's
* -moz-window-dragging value is |drag|, its border box is added to the
* collected dragging region; if the value is |no-drag|, the border box is
* subtracted from the region; if the value is |default|, that frame does
* not influence the window dragging region.
*/
void AdjustWindowDraggingRegion(nsIFrame* aFrame);
@@ -1620,17 +1643,17 @@ private:
static const size_t kArenaAlignment =
mozilla::tl::Max<NS_ALIGNMENT_OF(void*), NS_ALIGNMENT_OF(double)>::value;
mozilla::ArenaAllocator<4096, kArenaAlignment> mPool;
nsCOMPtr<nsISelection> mBoundingSelection;
AutoTArray<PresShellState,8> mPresShellStates;
AutoTArray<nsIFrame*,400> mFramesMarkedForDisplay;
- AutoTArray<ThemeGeometry,2> mThemeGeometries;
+ nsClassHashtable<nsPtrHashKey<nsIFrame>, nsTArray<ThemeGeometry>> mThemeGeometries;
nsDisplayTableItem* mCurrentTableItem;
DisplayListClipState mClipState;
const ActiveScrolledRoot* mCurrentActiveScrolledRoot;
const ActiveScrolledRoot* mCurrentContainerASR;
// mCurrentFrame is the frame that we're currently calling (or about to call)
// BuildDisplayList on.
const nsIFrame* mCurrentFrame;
// The reference frame for mCurrentFrame.
@@ -3692,16 +3715,22 @@ protected:
* A display item to paint the native theme background for a frame.
*/
class nsDisplayThemedBackground : public nsDisplayItem {
public:
nsDisplayThemedBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
const nsRect& aBackgroundRect);
virtual ~nsDisplayThemedBackground();
+ void Destroy(nsDisplayListBuilder* aBuilder) override
+ {
+ aBuilder->UnregisterThemeGeometry(mFrame);
+ nsDisplayItem::Destroy(aBuilder);
+ }
+
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override;
virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const override;
virtual bool MustPaintOnContentSide() const override { return true; }
/**
--- a/layout/xul/tree/nsTreeBodyFrame.cpp
+++ b/layout/xul/tree/nsTreeBodyFrame.cpp
@@ -2783,16 +2783,22 @@ public:
}
#endif
nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
{
return new nsDisplayItemGenericImageGeometry(this, aBuilder);
}
+ void Destroy(nsDisplayListBuilder* aBuilder) override
+ {
+ aBuilder->UnregisterThemeGeometry(mFrame);
+ nsDisplayItem::Destroy(aBuilder);
+ }
+
void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
const nsDisplayItemGeometry* aGeometry,
nsRegion *aInvalidRegion) const override
{
auto geometry =
static_cast<const nsDisplayItemGenericImageGeometry*>(aGeometry);
if (aBuilder->ShouldSyncDecodeImages() &&
@@ -2873,17 +2879,17 @@ nsTreeBodyFrame::BuildDisplayList(nsDisp
if (appearance) {
if (theme->ThemeSupportsWidget(PresContext(), this, appearance)) {
nsITheme::ThemeGeometryType type =
theme->ThemeGeometryTypeForWidget(this, appearance);
if (type != nsITheme::eThemeGeometryTypeUnknown) {
nsRect rowRect(mInnerBox.x, mInnerBox.y + mRowHeight *
(i - FirstVisibleRow()), mInnerBox.width,
mRowHeight);
- aBuilder->RegisterThemeGeometry(type,
+ aBuilder->RegisterThemeGeometry(type, this,
LayoutDeviceIntRect::FromUnknownRect(
(rowRect + aBuilder->ToReferenceFrame(this)).ToNearestPixels(
PresContext()->AppUnitsPerDevPixel())));
}
}
}
}
}