Bug 1422057 - Add hash function and boilerplate for deduplicating DisplayItemClipChain via std::set. r?mstange
MozReview-Commit-ID: I2eos3vwFF0
--- a/layout/painting/DisplayItemClipChain.cpp
+++ b/layout/painting/DisplayItemClipChain.cpp
@@ -28,16 +28,37 @@ DisplayItemClipChain::Equal(const Displa
return false;
}
return aClip1->mASR == aClip2->mASR &&
aClip1->mClip == aClip2->mClip &&
Equal(aClip1->mParent, aClip2->mParent);
}
+uint32_t
+DisplayItemClipChain::Hash(const DisplayItemClipChain* aClip)
+{
+ if (!aClip) {
+ return 0;
+ }
+
+ // We include the number of rounded rects in the hash but not their contents.
+ // This is to keep the hash fast, because most clips will not have rounded
+ // rects and including them will slow down the hash in the common case. Note
+ // that the ::Equal check still checks the rounded rect contents, so in case
+ // of hash collisions the clip chains can still be distinguished using that.
+ uint32_t hash = HashGeneric(aClip->mASR, aClip->mClip.GetRoundedRectCount());
+ if (aClip->mClip.HasClip()) {
+ const nsRect& rect = aClip->mClip.GetClipRect();
+ hash = AddToHash(hash, rect.x, rect.y, rect.width, rect.height);
+ }
+
+ return hash;
+}
+
/* static */ nsCString
DisplayItemClipChain::ToString(const DisplayItemClipChain* aClipChain)
{
nsAutoCString str;
for (auto* sc = aClipChain; sc; sc = sc->mParent) {
if (sc->mASR) {
str.AppendPrintf("0x%p <%s> [0x%p]", sc, sc->mClip.ToString().get(), sc->mASR->mScrollableFrame);
} else {
--- a/layout/painting/DisplayItemClipChain.h
+++ b/layout/painting/DisplayItemClipChain.h
@@ -39,16 +39,21 @@ struct DisplayItemClipChain {
/**
* Get the display item clip in this chain that moves with aASR, or nullptr
* if no such clip exists. aClipChain can be null.
*/
static const DisplayItemClip* ClipForASR(const DisplayItemClipChain* aClipChain,
const ActiveScrolledRoot* aASR);
static bool Equal(const DisplayItemClipChain* aClip1, const DisplayItemClipChain* aClip2);
+ /**
+ * Hash function that returns the same value for any two clips A and B
+ * where Equal(A, B) is true.
+ */
+ static uint32_t Hash(const DisplayItemClipChain* aClip);
static nsCString ToString(const DisplayItemClipChain* aClipChain);
bool HasRoundedCorners() const;
void AddRef() {
mRefCount++;
}
@@ -66,11 +71,31 @@ struct DisplayItemClipChain {
DisplayItemClipChain() {}
DisplayItemClip mClip;
const ActiveScrolledRoot* mASR;
RefPtr<const DisplayItemClipChain> mParent;
mutable uint32_t mRefCount = 0;
};
+struct DisplayItemClipChainHasher
+{
+ typedef const DisplayItemClipChain* Key;
+
+ std::size_t operator()(const Key& aKey) const
+ {
+ return DisplayItemClipChain::Hash(aKey);
+ }
+};
+
+struct DisplayItemClipChainEqualer
+{
+ typedef const DisplayItemClipChain* Key;
+
+ bool operator()(const Key& lhs, const Key& rhs) const
+ {
+ return DisplayItemClipChain::Equal(lhs, rhs);
+ }
+};
+
} // namespace mozilla
#endif /* DISPLAYITEMCLIPCHAIN_H_ */