diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /layout/painting/nsDisplayListInvalidation.h | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'layout/painting/nsDisplayListInvalidation.h')
-rw-r--r-- | layout/painting/nsDisplayListInvalidation.h | 369 |
1 files changed, 369 insertions, 0 deletions
diff --git a/layout/painting/nsDisplayListInvalidation.h b/layout/painting/nsDisplayListInvalidation.h new file mode 100644 index 0000000000..382b5ff038 --- /dev/null +++ b/layout/painting/nsDisplayListInvalidation.h @@ -0,0 +1,369 @@ +/* -*- 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 NSDISPLAYLISTINVALIDATION_H_ +#define NSDISPLAYLISTINVALIDATION_H_ + +#include "mozilla/Attributes.h" +#include "FrameLayerBuilder.h" +#include "nsRect.h" +#include "nsColor.h" +#include "gfxRect.h" +#include "mozilla/gfx/MatrixFwd.h" + +class nsDisplayBackgroundImage; +class nsCharClipDisplayItem; +class nsDisplayItem; +class nsDisplayListBuilder; +class nsDisplayTableItem; +class nsDisplayThemedBackground; +class nsDisplayEffectsBase; +class nsDisplayMasksAndClipPaths; +class nsDisplayFilters; + +namespace mozilla { +namespace gfx { +struct sRGBColor; +} +} // namespace mozilla + +/** + * 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); } + + virtual bool InvalidateForSyncDecodeImages() const { return false; } + + /** + * 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); + + 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::ImgDrawResult::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::ImgDrawResult aResult) { + MOZ_ASSERT(aResult != mozilla::image::ImgDrawResult::NOT_SUPPORTED, + "ImgDrawResult::NOT_SUPPORTED should be handled already!"); + + 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::ImgDrawResult::SUCCESS || + mLastDrawResult == mozilla::image::ImgDrawResult::BAD_IMAGE) { + return false; + } + + return true; + } + + private: + mozilla::image::ImgDrawResult 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) {} + + bool InvalidateForSyncDecodeImages() const override { + return ShouldInvalidateToSyncDecodeImages(); + } +}; + +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); + + bool InvalidateForSyncDecodeImages() const override { + return ShouldInvalidateToSyncDecodeImages(); + } +}; + +class nsDisplayBackgroundGeometry + : public nsDisplayItemGeometry, + public nsImageGeometryMixin<nsDisplayBackgroundGeometry> { + public: + nsDisplayBackgroundGeometry(nsDisplayBackgroundImage* aItem, + nsDisplayListBuilder* aBuilder); + + void MoveBy(const nsPoint& aOffset) override; + + bool InvalidateForSyncDecodeImages() const override { + return ShouldInvalidateToSyncDecodeImages(); + } + + nsRect mPositioningArea; + nsRect mDestRect; +}; + +class nsDisplayThemedBackgroundGeometry : public nsDisplayItemGeometry { + public: + nsDisplayThemedBackgroundGeometry(nsDisplayThemedBackground* aItem, + nsDisplayListBuilder* aBuilder); + + void MoveBy(const nsPoint& aOffset) override; + + nsRect mPositioningArea; + bool mWindowIsActive; +}; + +class nsDisplayTreeBodyGeometry + : public nsDisplayItemGenericGeometry, + public nsImageGeometryMixin<nsDisplayTreeBodyGeometry> { + public: + nsDisplayTreeBodyGeometry(nsDisplayItem* aItem, + nsDisplayListBuilder* aBuilder, + bool aWindowIsActive) + : nsDisplayItemGenericGeometry(aItem, aBuilder), + nsImageGeometryMixin(aItem, aBuilder), + mWindowIsActive(aWindowIsActive) {} + + bool InvalidateForSyncDecodeImages() const override { + return ShouldInvalidateToSyncDecodeImages(); + } + + bool mWindowIsActive = false; +}; + +class nsDisplayBoxShadowInnerGeometry : public nsDisplayItemGeometry { + public: + nsDisplayBoxShadowInnerGeometry(nsDisplayItem* aItem, + nsDisplayListBuilder* aBuilder); + + 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::sRGBColor aColor) + : nsDisplayItemBoundsGeometry(aItem, aBuilder), + mRegion(aRegion), + mColor(aColor) {} + + void MoveBy(const nsPoint& aOffset) override; + + nsRegion mRegion; + mozilla::gfx::sRGBColor mColor; +}; + +class nsDisplaySVGEffectGeometry : public nsDisplayItemGeometry { + public: + nsDisplaySVGEffectGeometry(nsDisplayEffectsBase* aItem, + nsDisplayListBuilder* aBuilder); + + void MoveBy(const nsPoint& aOffset) override; + + gfxRect mBBox; + gfxPoint mUserSpaceOffset; + nsPoint mFrameOffsetToReferenceFrame; + float mOpacity; + bool mHandleOpacity; +}; + +class nsDisplayMasksAndClipPathsGeometry + : public nsDisplaySVGEffectGeometry, + public nsImageGeometryMixin<nsDisplayMasksAndClipPathsGeometry> { + public: + nsDisplayMasksAndClipPathsGeometry(nsDisplayMasksAndClipPaths* aItem, + nsDisplayListBuilder* aBuilder); + + bool InvalidateForSyncDecodeImages() const override { + return ShouldInvalidateToSyncDecodeImages(); + } + + nsTArray<nsRect> mDestRects; +}; + +class nsDisplayFiltersGeometry + : public nsDisplaySVGEffectGeometry, + public nsImageGeometryMixin<nsDisplayFiltersGeometry> { + public: + nsDisplayFiltersGeometry(nsDisplayFilters* aItem, + nsDisplayListBuilder* aBuilder); + + bool InvalidateForSyncDecodeImages() const override { + return ShouldInvalidateToSyncDecodeImages(); + } +}; + +class nsDisplayTableItemGeometry + : public nsDisplayItemGenericGeometry, + public nsImageGeometryMixin<nsDisplayTableItemGeometry> { + public: + nsDisplayTableItemGeometry(nsDisplayTableItem* aItem, + nsDisplayListBuilder* aBuilder, + const nsPoint& aFrameOffsetToViewport); + + bool InvalidateForSyncDecodeImages() const override { + return ShouldInvalidateToSyncDecodeImages(); + } + + nsPoint mFrameOffsetToViewport; +}; + +class nsDisplayOpacityGeometry : public nsDisplayItemGenericGeometry { + public: + nsDisplayOpacityGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder, + float aOpacity) + : nsDisplayItemGenericGeometry(aItem, aBuilder), mOpacity(aOpacity) {} + + float mOpacity; +}; + +class nsDisplayTransformGeometry : public nsDisplayItemGeometry { + public: + nsDisplayTransformGeometry(nsDisplayItem* aItem, + nsDisplayListBuilder* aBuilder, + const mozilla::gfx::Matrix4x4Flagged& aTransform, + int32_t aAppUnitsPerDevPixel) + : nsDisplayItemGeometry(aItem, aBuilder), + mTransform(aTransform), + mAppUnitsPerDevPixel(aAppUnitsPerDevPixel) {} + + void MoveBy(const nsPoint& aOffset) override { + nsDisplayItemGeometry::MoveBy(aOffset); + mTransform.PostTranslate( + NSAppUnitsToFloatPixels(aOffset.x, mAppUnitsPerDevPixel), + NSAppUnitsToFloatPixels(aOffset.y, mAppUnitsPerDevPixel), 0.0f); + } + + mozilla::gfx::Matrix4x4Flagged mTransform; + int32_t mAppUnitsPerDevPixel; +}; + +#endif /*NSDISPLAYLISTINVALIDATION_H_*/ |