Line data Source code
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 : #ifndef mozilla_image_Image_h
7 : #define mozilla_image_Image_h
8 :
9 : #include "mozilla/MemoryReporting.h"
10 : #include "mozilla/TimeStamp.h"
11 : #include "gfx2DGlue.h"
12 : #include "imgIContainer.h"
13 : #include "ImageURL.h"
14 : #include "nsStringFwd.h"
15 : #include "ProgressTracker.h"
16 : #include "SurfaceCache.h"
17 :
18 : class nsIRequest;
19 : class nsIInputStream;
20 :
21 : namespace mozilla {
22 : namespace image {
23 :
24 : class Image;
25 :
26 : ///////////////////////////////////////////////////////////////////////////////
27 : // Memory Reporting
28 : ///////////////////////////////////////////////////////////////////////////////
29 :
30 : struct MemoryCounter
31 : {
32 0 : MemoryCounter()
33 0 : : mSource(0)
34 : , mDecodedHeap(0)
35 : , mDecodedNonHeap(0)
36 0 : , mSharedHandles(0)
37 0 : { }
38 :
39 0 : void SetSource(size_t aCount) { mSource = aCount; }
40 0 : size_t Source() const { return mSource; }
41 0 : void SetDecodedHeap(size_t aCount) { mDecodedHeap = aCount; }
42 0 : size_t DecodedHeap() const { return mDecodedHeap; }
43 0 : void SetDecodedNonHeap(size_t aCount) { mDecodedNonHeap = aCount; }
44 0 : size_t DecodedNonHeap() const { return mDecodedNonHeap; }
45 0 : void SetSharedHandles(size_t aCount) { mSharedHandles = aCount; }
46 0 : size_t SharedHandles() const { return mSharedHandles; }
47 :
48 0 : MemoryCounter& operator+=(const MemoryCounter& aOther)
49 : {
50 0 : mSource += aOther.mSource;
51 0 : mDecodedHeap += aOther.mDecodedHeap;
52 0 : mDecodedNonHeap += aOther.mDecodedNonHeap;
53 0 : mSharedHandles += aOther.mSharedHandles;
54 0 : return *this;
55 : }
56 :
57 : private:
58 : size_t mSource;
59 : size_t mDecodedHeap;
60 : size_t mDecodedNonHeap;
61 : size_t mSharedHandles;
62 : };
63 :
64 : enum class SurfaceMemoryCounterType
65 : {
66 : NORMAL,
67 : COMPOSITING,
68 : COMPOSITING_PREV
69 : };
70 :
71 0 : struct SurfaceMemoryCounter
72 : {
73 0 : SurfaceMemoryCounter(const SurfaceKey& aKey,
74 : bool aIsLocked,
75 : SurfaceMemoryCounterType aType =
76 : SurfaceMemoryCounterType::NORMAL)
77 0 : : mKey(aKey)
78 : , mType(aType)
79 0 : , mIsLocked(aIsLocked)
80 0 : { }
81 :
82 0 : const SurfaceKey& Key() const { return mKey; }
83 0 : MemoryCounter& Values() { return mValues; }
84 0 : const MemoryCounter& Values() const { return mValues; }
85 0 : SurfaceMemoryCounterType Type() const { return mType; }
86 0 : bool IsLocked() const { return mIsLocked; }
87 :
88 : private:
89 : const SurfaceKey mKey;
90 : MemoryCounter mValues;
91 : const SurfaceMemoryCounterType mType;
92 : const bool mIsLocked;
93 : };
94 :
95 0 : struct ImageMemoryCounter
96 : {
97 : ImageMemoryCounter(Image* aImage,
98 : MallocSizeOf aMallocSizeOf,
99 : bool aIsUsed);
100 :
101 0 : nsCString& URI() { return mURI; }
102 0 : const nsCString& URI() const { return mURI; }
103 0 : const nsTArray<SurfaceMemoryCounter>& Surfaces() const { return mSurfaces; }
104 0 : const gfx::IntSize IntrinsicSize() const { return mIntrinsicSize; }
105 0 : const MemoryCounter& Values() const { return mValues; }
106 0 : uint16_t Type() const { return mType; }
107 0 : bool IsUsed() const { return mIsUsed; }
108 :
109 0 : bool IsNotable() const
110 : {
111 0 : const size_t NotableThreshold = 16 * 1024;
112 0 : size_t total = mValues.Source() + mValues.DecodedHeap()
113 0 : + mValues.DecodedNonHeap();
114 0 : return total >= NotableThreshold;
115 : }
116 :
117 : private:
118 : nsCString mURI;
119 : nsTArray<SurfaceMemoryCounter> mSurfaces;
120 : gfx::IntSize mIntrinsicSize;
121 : MemoryCounter mValues;
122 : uint16_t mType;
123 : const bool mIsUsed;
124 : };
125 :
126 :
127 : ///////////////////////////////////////////////////////////////////////////////
128 : // Image Base Types
129 : ///////////////////////////////////////////////////////////////////////////////
130 :
131 97 : class Image : public imgIContainer
132 : {
133 : public:
134 : /**
135 : * Flags for Image initialization.
136 : *
137 : * Meanings:
138 : *
139 : * INIT_FLAG_NONE: Lack of flags
140 : *
141 : * INIT_FLAG_DISCARDABLE: The container should be discardable
142 : *
143 : * INIT_FLAG_DECODE_IMMEDIATELY: The container should decode as soon as
144 : * possible, regardless of what our heuristics say.
145 : *
146 : * INIT_FLAG_TRANSIENT: The container is likely to exist for only a short time
147 : * before being destroyed. (For example, containers for
148 : * multipart/x-mixed-replace image parts fall into this category.) If this
149 : * flag is set, INIT_FLAG_DISCARDABLE and INIT_FLAG_DECODE_ONLY_ON_DRAW must
150 : * not be set.
151 : *
152 : * INIT_FLAG_SYNC_LOAD: The container is being loaded synchronously, so
153 : * it should avoid relying on async workers to get the container ready.
154 : */
155 : static const uint32_t INIT_FLAG_NONE = 0x0;
156 : static const uint32_t INIT_FLAG_DISCARDABLE = 0x1;
157 : static const uint32_t INIT_FLAG_DECODE_IMMEDIATELY = 0x2;
158 : static const uint32_t INIT_FLAG_TRANSIENT = 0x4;
159 : static const uint32_t INIT_FLAG_SYNC_LOAD = 0x8;
160 :
161 : virtual already_AddRefed<ProgressTracker> GetProgressTracker() = 0;
162 0 : virtual void SetProgressTracker(ProgressTracker* aProgressTracker) {}
163 :
164 : /**
165 : * The size, in bytes, occupied by the compressed source data of the image.
166 : * If MallocSizeOf does not work on this platform, uses a fallback approach to
167 : * ensure that something reasonable is always returned.
168 : */
169 : virtual size_t
170 : SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const = 0;
171 :
172 : /**
173 : * Collect an accounting of the memory occupied by the image's surfaces (which
174 : * together make up its decoded data). Each surface is recorded as a separate
175 : * SurfaceMemoryCounter, stored in @aCounters.
176 : */
177 : virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
178 : MallocSizeOf aMallocSizeOf) const = 0;
179 :
180 : virtual void IncrementAnimationConsumers() = 0;
181 : virtual void DecrementAnimationConsumers() = 0;
182 : #ifdef DEBUG
183 : virtual uint32_t GetAnimationConsumers() = 0;
184 : #endif
185 :
186 : /**
187 : * Called from OnDataAvailable when the stream associated with the image has
188 : * received new image data. The arguments are the same as OnDataAvailable's,
189 : * but by separating this functionality into a different method we don't
190 : * interfere with subclasses which wish to implement nsIStreamListener.
191 : *
192 : * Images should not do anything that could send out notifications until they
193 : * have received their first OnImageDataAvailable notification; in
194 : * particular, this means that instantiating decoders should be deferred
195 : * until OnImageDataAvailable is called.
196 : */
197 : virtual nsresult OnImageDataAvailable(nsIRequest* aRequest,
198 : nsISupports* aContext,
199 : nsIInputStream* aInStr,
200 : uint64_t aSourceOffset,
201 : uint32_t aCount) = 0;
202 :
203 : /**
204 : * Called from OnStopRequest when the image's underlying request completes.
205 : *
206 : * @param aRequest The completed request.
207 : * @param aContext Context from Necko's OnStopRequest.
208 : * @param aStatus A success or failure code.
209 : * @param aLastPart Whether this is the final part of the underlying request.
210 : */
211 : virtual nsresult OnImageDataComplete(nsIRequest* aRequest,
212 : nsISupports* aContext,
213 : nsresult aStatus,
214 : bool aLastPart) = 0;
215 :
216 : /**
217 : * Called when the SurfaceCache discards a surface belonging to this image.
218 : */
219 : virtual void OnSurfaceDiscarded(const SurfaceKey& aSurfaceKey) = 0;
220 :
221 : virtual void SetInnerWindowID(uint64_t aInnerWindowId) = 0;
222 : virtual uint64_t InnerWindowID() const = 0;
223 :
224 : virtual bool HasError() = 0;
225 : virtual void SetHasError() = 0;
226 :
227 : virtual ImageURL* GetURI() = 0;
228 :
229 0 : virtual void ReportUseCounters() { }
230 : };
231 :
232 : class ImageResource : public Image
233 : {
234 : public:
235 2306 : already_AddRefed<ProgressTracker> GetProgressTracker() override
236 : {
237 4612 : RefPtr<ProgressTracker> progressTracker = mProgressTracker;
238 2306 : MOZ_ASSERT(progressTracker);
239 4612 : return progressTracker.forget();
240 : }
241 :
242 41 : void SetProgressTracker(
243 : ProgressTracker* aProgressTracker) override final
244 : {
245 41 : MOZ_ASSERT(aProgressTracker);
246 41 : MOZ_ASSERT(!mProgressTracker);
247 41 : mProgressTracker = aProgressTracker;
248 41 : }
249 :
250 : virtual void IncrementAnimationConsumers() override;
251 : virtual void DecrementAnimationConsumers() override;
252 : #ifdef DEBUG
253 0 : virtual uint32_t GetAnimationConsumers() override
254 : {
255 0 : return mAnimationConsumers;
256 : }
257 : #endif
258 :
259 0 : virtual void OnSurfaceDiscarded(const SurfaceKey& aSurfaceKey) override { }
260 :
261 40 : virtual void SetInnerWindowID(uint64_t aInnerWindowId) override
262 : {
263 40 : mInnerWindowId = aInnerWindowId;
264 40 : }
265 0 : virtual uint64_t InnerWindowID() const override { return mInnerWindowId; }
266 :
267 97 : virtual bool HasError() override { return mError; }
268 1 : virtual void SetHasError() override { mError = true; }
269 :
270 : /*
271 : * Returns a non-AddRefed pointer to the URI associated with this image.
272 : * Illegal to use off-main-thread.
273 : */
274 71 : virtual ImageURL* GetURI() override { return mURI.get(); }
275 :
276 : protected:
277 : explicit ImageResource(ImageURL* aURI);
278 : ~ImageResource();
279 :
280 : // Shared functionality for implementors of imgIContainer. Every
281 : // implementation of attribute animationMode should forward here.
282 : nsresult GetAnimationModeInternal(uint16_t* aAnimationMode);
283 : nsresult SetAnimationModeInternal(uint16_t aAnimationMode);
284 :
285 : /**
286 : * Helper for RequestRefresh.
287 : *
288 : * If we've had a "recent" refresh (i.e. if this image is being used in
289 : * multiple documents & some other document *just* called RequestRefresh() on
290 : * this image with a timestamp close to aTime), this method returns true.
291 : *
292 : * Otherwise, this method updates mLastRefreshTime to aTime & returns false.
293 : */
294 : bool HadRecentRefresh(const TimeStamp& aTime);
295 :
296 : /**
297 : * Decides whether animation should or should not be happening,
298 : * and makes sure the right thing is being done.
299 : */
300 : virtual void EvaluateAnimation();
301 :
302 : /**
303 : * Extended by child classes, if they have additional
304 : * conditions for being able to animate.
305 : */
306 37 : virtual bool ShouldAnimate() {
307 37 : return mAnimationConsumers > 0 && mAnimationMode != kDontAnimMode;
308 : }
309 :
310 : virtual nsresult StartAnimation() = 0;
311 : virtual nsresult StopAnimation() = 0;
312 :
313 : void SendOnUnlockedDraw(uint32_t aFlags);
314 :
315 : // Member data shared by all implementations of this abstract class
316 : RefPtr<ProgressTracker> mProgressTracker;
317 : RefPtr<ImageURL> mURI;
318 : TimeStamp mLastRefreshTime;
319 : uint64_t mInnerWindowId;
320 : uint32_t mAnimationConsumers;
321 : uint16_t mAnimationMode; // Enum values in imgIContainer
322 : bool mInitialized:1; // Have we been initalized?
323 : bool mAnimating:1; // Are we currently animating?
324 : bool mError:1; // Error handling
325 : };
326 :
327 : } // namespace image
328 : } // namespace mozilla
329 :
330 : #endif // mozilla_image_Image_h
|