summaryrefslogtreecommitdiffstats
path: root/layout/base/nsDisplayListInvalidation.h
diff options
context:
space:
mode:
Diffstat (limited to 'layout/base/nsDisplayListInvalidation.h')
-rw-r--r--layout/base/nsDisplayListInvalidation.h322
1 files changed, 322 insertions, 0 deletions
diff --git a/layout/base/nsDisplayListInvalidation.h b/layout/base/nsDisplayListInvalidation.h
new file mode 100644
index 000000000..250ca94ce
--- /dev/null
+++ b/layout/base/nsDisplayListInvalidation.h
@@ -0,0 +1,322 @@
+/*-*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * 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 NSDISPLAYLISTINVALIDATION_H_
+#define NSDISPLAYLISTINVALIDATION_H_
+
+#include "mozilla/Attributes.h"
+#include "FrameLayerBuilder.h"
+#include "imgIContainer.h"
+#include "nsRect.h"
+#include "nsColor.h"
+#include "gfxRect.h"
+
+class nsDisplayBackgroundImage;
+class nsCharClipDisplayItem;
+class nsDisplayItem;
+class nsDisplayListBuilder;
+class nsDisplayTableItem;
+class nsDisplayThemedBackground;
+class nsDisplaySVGEffects;
+class nsDisplayMask;
+class nsDisplayFilter;
+
+namespace mozilla {
+namespace gfx {
+struct Color;
+}
+}
+
+/**
+ * This stores the geometry of an nsDisplayItem, and the area
+ * that will be affected when painting the item.
+ *
+ * It is used to retain information about display items so they
+ * can be compared against new display items in the next paint.
+ */
+class nsDisplayItemGeometry
+{
+public:
+ nsDisplayItemGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder);
+ virtual ~nsDisplayItemGeometry();
+
+ /**
+ * Compute the area required to be invalidated if this
+ * display item is removed.
+ */
+ const nsRect& ComputeInvalidationRegion() { return mBounds; }
+
+ /**
+ * Shifts all retained areas of the nsDisplayItemGeometry by the given offset.
+ *
+ * This is used to compensate for scrolling, since the destination buffer
+ * can scroll without requiring a full repaint.
+ *
+ * @param aOffset Offset to shift by.
+ */
+ virtual void MoveBy(const nsPoint& aOffset)
+ {
+ mBounds.MoveBy(aOffset);
+ }
+
+ /**
+ * Bounds of the display item
+ */
+ nsRect mBounds;
+};
+
+/**
+ * A default geometry implementation, used by nsDisplayItem. Retains
+ * and compares the bounds, and border rect.
+ *
+ * This should be sufficient for the majority of display items.
+ */
+class nsDisplayItemGenericGeometry : public nsDisplayItemGeometry
+{
+public:
+ nsDisplayItemGenericGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder);
+
+ virtual void MoveBy(const nsPoint& aOffset) override;
+
+ nsRect mBorderRect;
+};
+
+bool ShouldSyncDecodeImages(nsDisplayListBuilder* aBuilder);
+
+/**
+ * nsImageGeometryMixin is a mixin for geometry items that draw images.
+ * Geometry items that include this mixin can track drawing results and use
+ * that information to inform invalidation decisions.
+ *
+ * This mixin uses CRTP; its template parameter should be the type of the class
+ * that is inheriting from it. See nsDisplayItemGenericImageGeometry for an
+ * example.
+ */
+template <typename T>
+class nsImageGeometryMixin
+{
+public:
+ nsImageGeometryMixin(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder)
+ : mLastDrawResult(mozilla::image::DrawResult::NOT_READY)
+ , mWaitingForPaint(false)
+ {
+ // Transfer state from the previous version of this geometry item.
+ auto lastGeometry =
+ static_cast<T*>(mozilla::FrameLayerBuilder::GetMostRecentGeometry(aItem));
+ if (lastGeometry) {
+ mLastDrawResult = lastGeometry->mLastDrawResult;
+ mWaitingForPaint = lastGeometry->mWaitingForPaint;
+ }
+
+ // If our display item is going to invalidate to trigger sync decoding of
+ // images, mark ourselves as waiting for a paint. If we actually get
+ // painted, UpdateDrawResult will get called, and we'll clear the flag.
+ if (ShouldSyncDecodeImages(aBuilder) &&
+ ShouldInvalidateToSyncDecodeImages()) {
+ mWaitingForPaint = true;
+ }
+ }
+
+ static void UpdateDrawResult(nsDisplayItem* aItem,
+ mozilla::image::DrawResult aResult)
+ {
+ auto lastGeometry =
+ static_cast<T*>(mozilla::FrameLayerBuilder::GetMostRecentGeometry(aItem));
+ if (lastGeometry) {
+ lastGeometry->mLastDrawResult = aResult;
+ lastGeometry->mWaitingForPaint = false;
+ }
+ }
+
+ bool ShouldInvalidateToSyncDecodeImages() const
+ {
+ if (mWaitingForPaint) {
+ // We previously invalidated for sync decoding and haven't gotten painted
+ // since them. This suggests that our display item is completely occluded
+ // and there's no point in invalidating again - and because the reftest
+ // harness takes a new snapshot every time we invalidate, doing so might
+ // lead to an invalidation loop if we're in a reftest.
+ return false;
+ }
+
+ if (mLastDrawResult == mozilla::image::DrawResult::SUCCESS ||
+ mLastDrawResult == mozilla::image::DrawResult::BAD_IMAGE) {
+ return false;
+ }
+
+ return true;
+ }
+
+private:
+ mozilla::image::DrawResult mLastDrawResult;
+ bool mWaitingForPaint;
+};
+
+/**
+ * nsDisplayItemGenericImageGeometry is a generic geometry item class that
+ * includes nsImageGeometryMixin.
+ *
+ * This should be sufficient for most display items that draw images.
+ */
+class nsDisplayItemGenericImageGeometry
+ : public nsDisplayItemGenericGeometry
+ , public nsImageGeometryMixin<nsDisplayItemGenericImageGeometry>
+{
+public:
+ nsDisplayItemGenericImageGeometry(nsDisplayItem* aItem,
+ nsDisplayListBuilder* aBuilder)
+ : nsDisplayItemGenericGeometry(aItem, aBuilder)
+ , nsImageGeometryMixin(aItem, aBuilder)
+ { }
+};
+
+class nsDisplayItemBoundsGeometry : public nsDisplayItemGeometry
+{
+public:
+ nsDisplayItemBoundsGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder);
+
+ bool mHasRoundedCorners;
+};
+
+class nsDisplayBorderGeometry
+ : public nsDisplayItemGeometry
+ , public nsImageGeometryMixin<nsDisplayBorderGeometry>
+{
+public:
+ nsDisplayBorderGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder);
+
+ virtual void MoveBy(const nsPoint& aOffset) override;
+
+ nsRect mContentRect;
+};
+
+class nsDisplayBackgroundGeometry
+ : public nsDisplayItemGeometry
+ , public nsImageGeometryMixin<nsDisplayBackgroundGeometry>
+{
+public:
+ nsDisplayBackgroundGeometry(nsDisplayBackgroundImage* aItem, nsDisplayListBuilder* aBuilder);
+
+ virtual void MoveBy(const nsPoint& aOffset) override;
+
+ nsRect mPositioningArea;
+ nsRect mDestRect;
+};
+
+class nsDisplayThemedBackgroundGeometry : public nsDisplayItemGeometry
+{
+public:
+ nsDisplayThemedBackgroundGeometry(nsDisplayThemedBackground* aItem, nsDisplayListBuilder* aBuilder);
+
+ virtual void MoveBy(const nsPoint& aOffset) override;
+
+ nsRect mPositioningArea;
+ bool mWindowIsActive;
+};
+
+class nsDisplayBoxShadowInnerGeometry : public nsDisplayItemGeometry
+{
+public:
+ nsDisplayBoxShadowInnerGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder);
+
+ virtual void MoveBy(const nsPoint& aOffset) override;
+
+ nsRect mPaddingRect;
+};
+
+class nsDisplayBoxShadowOuterGeometry : public nsDisplayItemGenericGeometry
+{
+public:
+ nsDisplayBoxShadowOuterGeometry(nsDisplayItem* aItem,
+ nsDisplayListBuilder* aBuilder,
+ float aOpacity);
+
+ float mOpacity;
+};
+
+class nsDisplaySolidColorGeometry : public nsDisplayItemBoundsGeometry
+{
+public:
+ nsDisplaySolidColorGeometry(nsDisplayItem* aItem,
+ nsDisplayListBuilder* aBuilder,
+ nscolor aColor)
+ : nsDisplayItemBoundsGeometry(aItem, aBuilder)
+ , mColor(aColor)
+ { }
+
+ nscolor mColor;
+};
+
+class nsDisplaySolidColorRegionGeometry : public nsDisplayItemBoundsGeometry
+{
+public:
+ nsDisplaySolidColorRegionGeometry(nsDisplayItem* aItem,
+ nsDisplayListBuilder* aBuilder,
+ const nsRegion& aRegion,
+ mozilla::gfx::Color aColor)
+ : nsDisplayItemBoundsGeometry(aItem, aBuilder)
+ , mRegion(aRegion)
+ , mColor(aColor)
+ { }
+
+ virtual void MoveBy(const nsPoint& aOffset) override;
+
+ nsRegion mRegion;
+ mozilla::gfx::Color mColor;
+};
+
+class nsDisplaySVGEffectGeometry : public nsDisplayItemGeometry
+{
+public:
+ nsDisplaySVGEffectGeometry(nsDisplaySVGEffects* aItem,
+ nsDisplayListBuilder* aBuilder);
+
+ virtual void MoveBy(const nsPoint& aOffset) override;
+
+ gfxRect mBBox;
+ gfxPoint mUserSpaceOffset;
+ nsPoint mFrameOffsetToReferenceFrame;
+};
+
+class nsDisplayMaskGeometry : public nsDisplaySVGEffectGeometry
+ , public nsImageGeometryMixin<nsDisplayMaskGeometry>
+{
+public:
+ nsDisplayMaskGeometry(nsDisplayMask* aItem, nsDisplayListBuilder* aBuilder);
+
+ nsTArray<nsRect> mDestRects;
+};
+
+class nsDisplayFilterGeometry : public nsDisplaySVGEffectGeometry
+ , public nsImageGeometryMixin<nsDisplayFilterGeometry>
+{
+public:
+ nsDisplayFilterGeometry(nsDisplayFilter* aItem,
+ nsDisplayListBuilder* aBuilder);
+};
+
+class nsCharClipGeometry : public nsDisplayItemGenericGeometry
+{
+public:
+ nsCharClipGeometry(nsCharClipDisplayItem* aItem,
+ nsDisplayListBuilder* aBuilder);
+
+ nscoord mVisIStartEdge;
+ nscoord mVisIEndEdge;
+};
+
+class nsDisplayTableItemGeometry
+ : public nsDisplayItemGenericGeometry
+ , public nsImageGeometryMixin<nsDisplayTableItemGeometry>
+{
+public:
+ nsDisplayTableItemGeometry(nsDisplayTableItem* aItem,
+ nsDisplayListBuilder* aBuilder,
+ const nsPoint& aFrameOffsetToViewport);
+
+ nsPoint mFrameOffsetToViewport;
+};
+
+#endif /*NSDISPLAYLISTINVALIDATION_H_*/