1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/base/MaskLayerImageCache.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,253 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef MASKLAYERIMAGECACHE_H_ 1.10 +#define MASKLAYERIMAGECACHE_H_ 1.11 + 1.12 +#include "DisplayItemClip.h" 1.13 +#include "nsPresContext.h" 1.14 +#include "mozilla/gfx/Matrix.h" 1.15 + 1.16 +namespace mozilla { 1.17 + 1.18 +namespace layers { 1.19 +class ImageContainer; 1.20 +} 1.21 + 1.22 +/** 1.23 + * Keeps a record of image containers for mask layers, containers are mapped 1.24 + * from the rounded rects used to create them. 1.25 + * The cache stores MaskLayerImageEntries indexed by MaskLayerImageKeys. 1.26 + * Each MaskLayerImageEntry owns a heap-allocated MaskLayerImageKey 1.27 + * (heap-allocated so that a mask layer's userdata can keep a pointer to the 1.28 + * key for its image, in spite of the hashtable moving its entries around). 1.29 + * The key consists of the rounded rects used to create the mask, 1.30 + * an nsRefPtr to the ImageContainer containing the image, and a count 1.31 + * of the number of layers currently using this ImageContainer. 1.32 + * When the key's layer count is zero, the cache 1.33 + * may remove the entry, which deletes the key object. 1.34 + */ 1.35 +class MaskLayerImageCache 1.36 +{ 1.37 + typedef mozilla::layers::ImageContainer ImageContainer; 1.38 +public: 1.39 + MaskLayerImageCache(); 1.40 + ~MaskLayerImageCache(); 1.41 + 1.42 + /** 1.43 + * Representation of a rounded rectangle in device pixel coordinates, in 1.44 + * contrast to DisplayItemClip::RoundedRect, which uses app units. 1.45 + * In particular, our internal representation uses a gfxRect, rather than 1.46 + * an nsRect, so this class is easier to use with transforms. 1.47 + */ 1.48 + struct PixelRoundedRect 1.49 + { 1.50 + PixelRoundedRect(const DisplayItemClip::RoundedRect& aRRect, 1.51 + nsPresContext* aPresContext) 1.52 + : mRect(aPresContext->AppUnitsToGfxUnits(aRRect.mRect.x), 1.53 + aPresContext->AppUnitsToGfxUnits(aRRect.mRect.y), 1.54 + aPresContext->AppUnitsToGfxUnits(aRRect.mRect.width), 1.55 + aPresContext->AppUnitsToGfxUnits(aRRect.mRect.height)) 1.56 + { 1.57 + MOZ_COUNT_CTOR(PixelRoundedRect); 1.58 + NS_FOR_CSS_HALF_CORNERS(corner) { 1.59 + mRadii[corner] = aPresContext->AppUnitsToGfxUnits(aRRect.mRadii[corner]); 1.60 + } 1.61 + } 1.62 + PixelRoundedRect(const PixelRoundedRect& aPRR) 1.63 + : mRect(aPRR.mRect) 1.64 + { 1.65 + MOZ_COUNT_CTOR(PixelRoundedRect); 1.66 + NS_FOR_CSS_HALF_CORNERS(corner) { 1.67 + mRadii[corner] = aPRR.mRadii[corner]; 1.68 + } 1.69 + } 1.70 + 1.71 + ~PixelRoundedRect() 1.72 + { 1.73 + MOZ_COUNT_DTOR(PixelRoundedRect); 1.74 + } 1.75 + 1.76 + // Applies the scale and translate components of aTransform. 1.77 + // It is an error to pass a matrix which does more than just scale 1.78 + // and translate. 1.79 + void ScaleAndTranslate(const gfx::Matrix& aTransform) 1.80 + { 1.81 + NS_ASSERTION(aTransform._12 == 0 && aTransform._21 == 0, 1.82 + "Transform has a component other than scale and translate"); 1.83 + 1.84 + mRect = aTransform.TransformBounds(mRect); 1.85 + 1.86 + for (size_t i = 0; i < ArrayLength(mRadii); i += 2) { 1.87 + mRadii[i] *= aTransform._11; 1.88 + mRadii[i + 1] *= aTransform._22; 1.89 + } 1.90 + } 1.91 + 1.92 + bool operator==(const PixelRoundedRect& aOther) const { 1.93 + if (!mRect.IsEqualInterior(aOther.mRect)) { 1.94 + return false; 1.95 + } 1.96 + 1.97 + NS_FOR_CSS_HALF_CORNERS(corner) { 1.98 + if (mRadii[corner] != aOther.mRadii[corner]) { 1.99 + return false; 1.100 + } 1.101 + } 1.102 + return true; 1.103 + } 1.104 + bool operator!=(const PixelRoundedRect& aOther) const { 1.105 + return !(*this == aOther); 1.106 + } 1.107 + 1.108 + // Create a hash for this object. 1.109 + PLDHashNumber Hash() const 1.110 + { 1.111 + PLDHashNumber hash = HashBytes(&mRect.x, 4*sizeof(gfxFloat)); 1.112 + hash = AddToHash(hash, HashBytes(mRadii, 8*sizeof(gfxFloat))); 1.113 + 1.114 + return hash; 1.115 + } 1.116 + 1.117 + gfx::Rect mRect; 1.118 + // Indices into mRadii are the NS_CORNER_* constants in nsStyleConsts.h 1.119 + gfxFloat mRadii[8]; 1.120 + 1.121 + private: 1.122 + PixelRoundedRect() MOZ_DELETE; 1.123 + }; 1.124 + 1.125 + /** 1.126 + * A key to identify cached image containers. 1.127 + * The const-ness of this class is with respect to its use as a key into a 1.128 + * hashtable, so anything not used to create the hash is mutable. 1.129 + * mLayerCount counts the number of mask layers which have a reference to 1.130 + * MaskLayerImageEntry::mContainer; it is maintained by MaskLayerUserData, 1.131 + * which keeps a reference to the key. There will usually be mLayerCount + 1 1.132 + * pointers to a key object (the +1 being from the hashtable entry), but this 1.133 + * invariant may be temporarily broken. 1.134 + */ 1.135 + struct MaskLayerImageKey 1.136 + { 1.137 + MaskLayerImageKey() 1.138 + : mLayerCount(0) 1.139 + , mRoundedClipRects() 1.140 + { 1.141 + MOZ_COUNT_CTOR(MaskLayerImageKey); 1.142 + } 1.143 + MaskLayerImageKey(const MaskLayerImageKey& aKey) 1.144 + : mLayerCount(aKey.mLayerCount) 1.145 + , mRoundedClipRects(aKey.mRoundedClipRects) 1.146 + { 1.147 + MOZ_COUNT_CTOR(MaskLayerImageKey); 1.148 + } 1.149 + 1.150 + ~MaskLayerImageKey() 1.151 + { 1.152 + MOZ_COUNT_DTOR(MaskLayerImageKey); 1.153 + } 1.154 + 1.155 + void AddRef() const { ++mLayerCount; } 1.156 + void Release() const 1.157 + { 1.158 + NS_ASSERTION(mLayerCount > 0, "Inconsistent layer count"); 1.159 + --mLayerCount; 1.160 + } 1.161 + 1.162 + PLDHashNumber Hash() const 1.163 + { 1.164 + PLDHashNumber hash = 0; 1.165 + 1.166 + for (uint32_t i = 0; i < mRoundedClipRects.Length(); ++i) { 1.167 + hash = AddToHash(hash, mRoundedClipRects[i].Hash()); 1.168 + } 1.169 + 1.170 + return hash; 1.171 + } 1.172 + 1.173 + bool operator==(const MaskLayerImageKey& aOther) const 1.174 + { 1.175 + return mRoundedClipRects == aOther.mRoundedClipRects; 1.176 + } 1.177 + 1.178 + mutable uint32_t mLayerCount; 1.179 + nsTArray<PixelRoundedRect> mRoundedClipRects; 1.180 + }; 1.181 + 1.182 + 1.183 + // Find an image container for aKey, returns nullptr if there is no suitable 1.184 + // cached image. If there is an image, then aKey is set to point at the stored 1.185 + // key for the image. 1.186 + ImageContainer* FindImageFor(const MaskLayerImageKey** aKey); 1.187 + 1.188 + // Add an image container with a key to the cache 1.189 + // The image container used will be set as the container in aKey and aKey 1.190 + // itself will be linked from this cache 1.191 + void PutImage(const MaskLayerImageKey* aKey, 1.192 + ImageContainer* aContainer); 1.193 + 1.194 + // Sweep the cache for old image containers that can be deleted 1.195 + void Sweep(); 1.196 + 1.197 +protected: 1.198 + 1.199 + class MaskLayerImageEntry : public PLDHashEntryHdr 1.200 + { 1.201 + public: 1.202 + typedef const MaskLayerImageKey& KeyType; 1.203 + typedef const MaskLayerImageKey* KeyTypePointer; 1.204 + 1.205 + MaskLayerImageEntry(KeyTypePointer aKey) : mKey(aKey) 1.206 + { 1.207 + MOZ_COUNT_CTOR(MaskLayerImageEntry); 1.208 + } 1.209 + MaskLayerImageEntry(const MaskLayerImageEntry& aOther) 1.210 + : mKey(aOther.mKey.get()) 1.211 + { 1.212 + NS_ERROR("ALLOW_MEMMOVE == true, should never be called"); 1.213 + } 1.214 + ~MaskLayerImageEntry() 1.215 + { 1.216 + MOZ_COUNT_DTOR(MaskLayerImageEntry); 1.217 + } 1.218 + 1.219 + // KeyEquals(): does this entry match this key? 1.220 + bool KeyEquals(KeyTypePointer aKey) const 1.221 + { 1.222 + return *mKey == *aKey; 1.223 + } 1.224 + 1.225 + // KeyToPointer(): Convert KeyType to KeyTypePointer 1.226 + static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; } 1.227 + 1.228 + // HashKey(): calculate the hash number 1.229 + static PLDHashNumber HashKey(KeyTypePointer aKey) 1.230 + { 1.231 + return aKey->Hash(); 1.232 + } 1.233 + 1.234 + // ALLOW_MEMMOVE can we move this class with memmove(), or do we have 1.235 + // to use the copy constructor? 1.236 + enum { ALLOW_MEMMOVE = true }; 1.237 + 1.238 + bool operator==(const MaskLayerImageEntry& aOther) const 1.239 + { 1.240 + return KeyEquals(aOther.mKey); 1.241 + } 1.242 + 1.243 + nsAutoPtr<const MaskLayerImageKey> mKey; 1.244 + nsRefPtr<ImageContainer> mContainer; 1.245 + }; 1.246 + 1.247 + nsTHashtable<MaskLayerImageEntry> mMaskImageContainers; 1.248 + 1.249 + // helper funtion for Sweep(), called for each entry in the hashtable 1.250 + static PLDHashOperator SweepFunc(MaskLayerImageEntry* aEntry, void* aUserArg); 1.251 +}; 1.252 + 1.253 +} 1.254 + 1.255 + 1.256 +#endif