Bug 1637114 [wpt PR 23518] - Handle k-rate AudioParam inputs for AudioWorkletNode...
[gecko.git] / layout / painting / MaskLayerImageCache.h
blob7e20f72a2060a4beec2ff2e855fee004a590b0ed
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef MASKLAYERIMAGECACHE_H_
8 #define MASKLAYERIMAGECACHE_H_
10 #include "DisplayItemClip.h"
11 #include "nsPresContext.h"
12 #include "mozilla/gfx/Matrix.h"
13 #include "mozilla/UniquePtr.h"
15 namespace mozilla {
17 namespace layers {
18 class ImageContainer;
19 class KnowsCompositor;
20 } // namespace layers
22 /**
23 * Keeps a record of image containers for mask layers, containers are mapped
24 * from the rounded rects used to create them.
25 * The cache stores MaskLayerImageEntries indexed by MaskLayerImageKeys.
26 * Each MaskLayerImageEntry owns a heap-allocated MaskLayerImageKey
27 * (heap-allocated so that a mask layer's userdata can keep a pointer to the
28 * key for its image, in spite of the hashtable moving its entries around).
29 * The key consists of the rounded rects used to create the mask,
30 * an nsRefPtr to the ImageContainer containing the image, and a count
31 * of the number of layers currently using this ImageContainer.
32 * When the key's layer count is zero, the cache
33 * may remove the entry, which deletes the key object.
35 class MaskLayerImageCache {
36 typedef mozilla::layers::ImageContainer ImageContainer;
37 typedef mozilla::layers::KnowsCompositor KnowsCompositor;
39 public:
40 MaskLayerImageCache();
41 ~MaskLayerImageCache();
43 /**
44 * Representation of a rounded rectangle in device pixel coordinates, in
45 * contrast to DisplayItemClip::RoundedRect, which uses app units.
46 * In particular, our internal representation uses a gfxRect, rather than
47 * an nsRect, so this class is easier to use with transforms.
49 struct PixelRoundedRect {
50 PixelRoundedRect() = delete;
52 PixelRoundedRect(const DisplayItemClip::RoundedRect& aRRect,
53 nsPresContext* aPresContext)
54 : mRect(aPresContext->AppUnitsToGfxUnits(aRRect.mRect.x),
55 aPresContext->AppUnitsToGfxUnits(aRRect.mRect.y),
56 aPresContext->AppUnitsToGfxUnits(aRRect.mRect.width),
57 aPresContext->AppUnitsToGfxUnits(aRRect.mRect.height)) {
58 MOZ_COUNT_CTOR(PixelRoundedRect);
59 for (const auto corner : mozilla::AllPhysicalHalfCorners()) {
60 mRadii[corner] =
61 aPresContext->AppUnitsToGfxUnits(aRRect.mRadii[corner]);
65 PixelRoundedRect(const PixelRoundedRect& aPRR) : mRect(aPRR.mRect) {
66 MOZ_COUNT_CTOR(PixelRoundedRect);
67 for (const auto corner : mozilla::AllPhysicalHalfCorners()) {
68 mRadii[corner] = aPRR.mRadii[corner];
72 MOZ_COUNTED_DTOR(PixelRoundedRect)
74 // Applies the scale and translate components of aTransform.
75 // It is an error to pass a matrix which does more than just scale
76 // and translate.
77 void ScaleAndTranslate(const gfx::Matrix& aTransform) {
78 NS_ASSERTION(aTransform._12 == 0 && aTransform._21 == 0,
79 "Transform has a component other than scale and translate");
81 mRect = aTransform.TransformBounds(mRect);
83 for (size_t i = 0; i < ArrayLength(mRadii); i += 2) {
84 mRadii[i] *= aTransform._11;
85 mRadii[i + 1] *= aTransform._22;
89 bool operator==(const PixelRoundedRect& aOther) const {
90 if (!mRect.IsEqualInterior(aOther.mRect)) {
91 return false;
94 for (const auto corner : mozilla::AllPhysicalHalfCorners()) {
95 if (mRadii[corner] != aOther.mRadii[corner]) {
96 return false;
99 return true;
101 bool operator!=(const PixelRoundedRect& aOther) const {
102 return !(*this == aOther);
105 // Create a hash for this object.
106 PLDHashNumber Hash() const {
107 PLDHashNumber hash = HashBytes(&mRect.x, 4 * sizeof(gfxFloat));
108 hash = AddToHash(hash, HashBytes(mRadii, 8 * sizeof(gfxFloat)));
110 return hash;
113 gfx::Rect mRect;
114 // Indices into mRadii are the enum HalfCorner constants in gfx/2d/Types.h
115 gfxFloat mRadii[8];
118 struct MaskLayerImageKeyRef;
121 * A key to identify cached image containers.
122 * The const-ness of this class is with respect to its use as a key into a
123 * hashtable, so anything not used to create the hash is mutable.
124 * mLayerCount counts the number of mask layers which have a reference to
125 * MaskLayerImageEntry::mContainer; it is maintained by MaskLayerUserData,
126 * which keeps a reference to the key. There will usually be mLayerCount + 1
127 * pointers to a key object (the +1 being from the hashtable entry), but this
128 * invariant may be temporarily broken.
130 struct MaskLayerImageKey {
131 friend struct MaskLayerImageKeyRef;
133 MaskLayerImageKey();
134 MaskLayerImageKey(const MaskLayerImageKey& aKey);
136 ~MaskLayerImageKey();
138 bool HasZeroLayerCount() const { return mLayerCount == 0; }
140 PLDHashNumber Hash() const {
141 PLDHashNumber hash = 0;
143 for (uint32_t i = 0; i < mRoundedClipRects.Length(); ++i) {
144 hash = AddToHash(hash, mRoundedClipRects[i].Hash());
146 hash = AddToHash(hash, mKnowsCompositor.get());
148 return hash;
151 bool operator==(const MaskLayerImageKey& aOther) const {
152 return mKnowsCompositor == aOther.mKnowsCompositor &&
153 mRoundedClipRects == aOther.mRoundedClipRects;
156 nsTArray<PixelRoundedRect> mRoundedClipRects;
157 RefPtr<KnowsCompositor> mKnowsCompositor;
159 private:
160 void IncLayerCount() const { ++mLayerCount; }
161 void DecLayerCount() const {
162 NS_ASSERTION(mLayerCount > 0, "Inconsistent layer count");
163 --mLayerCount;
165 mutable uint32_t mLayerCount;
169 * This struct maintains a reference to a MaskLayerImageKey, via a variant on
170 * refcounting. When a key is passed in via Reset(), we increment the
171 * passed-in key's mLayerCount, and we decrement its mLayerCount when we're
172 * destructed (or when the key is replaced via a second Reset() call).
174 * However, unlike standard refcounting smart-pointers, this object does
175 * *not* delete the tracked MaskLayerImageKey -- instead, deletion happens
176 * in MaskLayerImageCache::Sweep(), for any keys whose mLayerCount is 0.
178 struct MaskLayerImageKeyRef {
179 ~MaskLayerImageKeyRef() {
180 if (mRawPtr) {
181 mRawPtr->DecLayerCount();
185 MaskLayerImageKeyRef() : mRawPtr(nullptr) {}
186 MaskLayerImageKeyRef(const MaskLayerImageKeyRef&) = delete;
187 void operator=(const MaskLayerImageKeyRef&) = delete;
189 void Reset(const MaskLayerImageKey* aPtr) {
190 MOZ_ASSERT(
191 aPtr, "Cannot initialize a MaskLayerImageKeyRef with a null pointer");
192 aPtr->IncLayerCount();
193 if (mRawPtr) {
194 mRawPtr->DecLayerCount();
196 mRawPtr = aPtr;
199 private:
200 const MaskLayerImageKey* mRawPtr;
203 // Find an image container for aKey, returns nullptr if there is no suitable
204 // cached image. If there is an image, then aKey is set to point at the stored
205 // key for the image.
206 ImageContainer* FindImageFor(const MaskLayerImageKey** aKey);
208 // Add an image container with a key to the cache
209 // The image container used will be set as the container in aKey and aKey
210 // itself will be linked from this cache
211 void PutImage(const MaskLayerImageKey* aKey, ImageContainer* aContainer);
213 // Sweep the cache for old image containers that can be deleted
214 void Sweep();
216 protected:
217 class MaskLayerImageEntry : public PLDHashEntryHdr {
218 public:
219 typedef const MaskLayerImageKey& KeyType;
220 typedef const MaskLayerImageKey* KeyTypePointer;
222 explicit MaskLayerImageEntry(KeyTypePointer aKey) : mKey(aKey) {
223 MOZ_COUNT_CTOR(MaskLayerImageEntry);
225 MaskLayerImageEntry(const MaskLayerImageEntry& aOther)
226 : mKey(aOther.mKey.get()) {
227 NS_ERROR("ALLOW_MEMMOVE == true, should never be called");
229 MOZ_COUNTED_DTOR(MaskLayerImageEntry)
231 // KeyEquals(): does this entry match this key?
232 bool KeyEquals(KeyTypePointer aKey) const { return *mKey == *aKey; }
234 // KeyToPointer(): Convert KeyType to KeyTypePointer
235 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
237 // HashKey(): calculate the hash number
238 static PLDHashNumber HashKey(KeyTypePointer aKey) { return aKey->Hash(); }
240 // ALLOW_MEMMOVE can we move this class with memmove(), or do we have
241 // to use the copy constructor?
242 enum { ALLOW_MEMMOVE = true };
244 bool operator==(const MaskLayerImageEntry& aOther) const {
245 return KeyEquals(aOther.mKey.get());
248 mozilla::UniquePtr<const MaskLayerImageKey> mKey;
249 RefPtr<ImageContainer> mContainer;
252 nsTHashtable<MaskLayerImageEntry> mMaskImageContainers;
255 } // namespace mozilla
257 #endif