|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 /** |
|
7 * SurfaceCache is a service for caching temporary surfaces in imagelib. |
|
8 */ |
|
9 |
|
10 #ifndef MOZILLA_IMAGELIB_SURFACECACHE_H_ |
|
11 #define MOZILLA_IMAGELIB_SURFACECACHE_H_ |
|
12 |
|
13 #include "mozilla/HashFunctions.h" // for HashGeneric and AddToHash |
|
14 #include "gfxPoint.h" // for gfxSize |
|
15 #include "nsCOMPtr.h" // for already_AddRefed |
|
16 #include "mozilla/gfx/Point.h" // for mozilla::gfx::IntSize |
|
17 #include "SVGImageContext.h" // for SVGImageContext |
|
18 |
|
19 class gfxDrawable; |
|
20 |
|
21 namespace mozilla { |
|
22 |
|
23 namespace gfx { |
|
24 class DrawTarget; |
|
25 } // namespace gfx |
|
26 |
|
27 namespace image { |
|
28 |
|
29 class Image; |
|
30 |
|
31 /* |
|
32 * ImageKey contains the information we need to look up all cached surfaces for |
|
33 * a particular image. |
|
34 */ |
|
35 typedef Image* ImageKey; |
|
36 |
|
37 /* |
|
38 * SurfaceKey contains the information we need to look up a specific cached |
|
39 * surface. Together with an ImageKey, this uniquely identifies the surface. |
|
40 * |
|
41 * XXX(seth): Right now this is specialized to the needs of VectorImage. We'll |
|
42 * generalize it in bug 919071. |
|
43 */ |
|
44 class SurfaceKey |
|
45 { |
|
46 typedef gfx::IntSize IntSize; |
|
47 public: |
|
48 SurfaceKey(const IntSize& aSize, |
|
49 const gfxSize aScale, |
|
50 const SVGImageContext* aSVGContext, |
|
51 const float aAnimationTime, |
|
52 const uint32_t aFlags) |
|
53 : mSize(aSize) |
|
54 , mScale(aScale) |
|
55 , mSVGContextIsValid(aSVGContext != nullptr) |
|
56 , mAnimationTime(aAnimationTime) |
|
57 , mFlags(aFlags) |
|
58 { |
|
59 // XXX(seth): Would love to use Maybe<T> here, but see bug 913586. |
|
60 if (mSVGContextIsValid) |
|
61 mSVGContext = *aSVGContext; |
|
62 } |
|
63 |
|
64 bool operator==(const SurfaceKey& aOther) const |
|
65 { |
|
66 bool matchesSVGContext = aOther.mSVGContextIsValid == mSVGContextIsValid && |
|
67 (!mSVGContextIsValid || aOther.mSVGContext == mSVGContext); |
|
68 return aOther.mSize == mSize && |
|
69 aOther.mScale == mScale && |
|
70 matchesSVGContext && |
|
71 aOther.mAnimationTime == mAnimationTime && |
|
72 aOther.mFlags == mFlags; |
|
73 } |
|
74 |
|
75 uint32_t Hash() const |
|
76 { |
|
77 uint32_t hash = HashGeneric(mSize.width, mSize.height); |
|
78 hash = AddToHash(hash, mScale.width, mScale.height); |
|
79 hash = AddToHash(hash, mSVGContextIsValid, mSVGContext.Hash()); |
|
80 hash = AddToHash(hash, mAnimationTime, mFlags); |
|
81 return hash; |
|
82 } |
|
83 |
|
84 IntSize Size() const { return mSize; } |
|
85 |
|
86 private: |
|
87 IntSize mSize; |
|
88 gfxSize mScale; |
|
89 SVGImageContext mSVGContext; |
|
90 bool mSVGContextIsValid; |
|
91 float mAnimationTime; |
|
92 uint32_t mFlags; |
|
93 }; |
|
94 |
|
95 /** |
|
96 * SurfaceCache is an imagelib-global service that allows caching of temporary |
|
97 * surfaces. Surfaces expire from the cache automatically if they go too long |
|
98 * without being accessed. |
|
99 * |
|
100 * SurfaceCache is not thread-safe; it should only be accessed from the main |
|
101 * thread. |
|
102 */ |
|
103 struct SurfaceCache |
|
104 { |
|
105 typedef gfx::IntSize IntSize; |
|
106 |
|
107 /* |
|
108 * Initialize static data. Called during imagelib module initialization. |
|
109 */ |
|
110 static void Initialize(); |
|
111 |
|
112 /* |
|
113 * Release static data. Called during imagelib module shutdown. |
|
114 */ |
|
115 static void Shutdown(); |
|
116 |
|
117 /* |
|
118 * Look up a surface in the cache. |
|
119 * |
|
120 * @param aImageKey Key data identifying which image the surface belongs to. |
|
121 * @param aSurfaceKey Key data which uniquely identifies the requested surface. |
|
122 * |
|
123 * @return the requested surface, or nullptr if not found. |
|
124 */ |
|
125 static already_AddRefed<gfxDrawable> Lookup(const ImageKey aImageKey, |
|
126 const SurfaceKey& aSurfaceKey); |
|
127 |
|
128 /* |
|
129 * Insert a surface into the cache. It is an error to call this function |
|
130 * without first calling Lookup to verify that the surface is not already in |
|
131 * the cache. |
|
132 * |
|
133 * @param aTarget The new surface (in the form of a DrawTarget) to insert |
|
134 * into the cache. |
|
135 * @param aImageKey Key data identifying which image the surface belongs to. |
|
136 * @param aSurfaceKey Key data which uniquely identifies the requested surface. |
|
137 */ |
|
138 static void Insert(mozilla::gfx::DrawTarget* aTarget, |
|
139 const ImageKey aImageKey, |
|
140 const SurfaceKey& aSurfaceKey); |
|
141 |
|
142 /* |
|
143 * Checks if a surface of a given size could possibly be stored in the cache. |
|
144 * If CanHold() returns false, Insert() will always fail to insert the |
|
145 * surface, but the inverse is not true: Insert() may take more information |
|
146 * into account than just image size when deciding whether to cache the |
|
147 * surface, so Insert() may still fail even if CanHold() returns true. |
|
148 * |
|
149 * Use CanHold() to avoid the need to create a temporary surface when we know |
|
150 * for sure the cache can't hold it. |
|
151 * |
|
152 * @param aSize The dimensions of a surface in pixels. |
|
153 * |
|
154 * @return false if the surface cache can't hold a surface of that size. |
|
155 */ |
|
156 static bool CanHold(const IntSize& aSize); |
|
157 |
|
158 /* |
|
159 * Evicts any cached surfaces associated with the given image from the cache. |
|
160 * This MUST be called, at a minimum, when the image is destroyed. If |
|
161 * another image were allocated at the same address it could result in |
|
162 * subtle, difficult-to-reproduce bugs. |
|
163 * |
|
164 * @param aImageKey The image which should be removed from the cache. |
|
165 */ |
|
166 static void Discard(const ImageKey aImageKey); |
|
167 |
|
168 /* |
|
169 * Evicts all caches surfaces from ths cache. |
|
170 */ |
|
171 static void DiscardAll(); |
|
172 |
|
173 private: |
|
174 virtual ~SurfaceCache() = 0; // Forbid instantiation. |
|
175 }; |
|
176 |
|
177 } // namespace image |
|
178 } // namespace mozilla |
|
179 |
|
180 #endif // MOZILLA_IMAGELIB_SURFACECACHE_H_ |