Bug 1586798 - Use WalkerFront from the currently selected element in onTagEdit()...
[gecko.git] / image / Image.h
blob098aba453e6ff2344ddd98fa4f13853ad1e8485c
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/. */
6 #ifndef mozilla_image_Image_h
7 #define mozilla_image_Image_h
9 #include "mozilla/Maybe.h"
10 #include "mozilla/MemoryReporting.h"
11 #include "mozilla/Tuple.h"
12 #include "mozilla/TimeStamp.h"
13 #include "gfx2DGlue.h"
14 #include "imgIContainer.h"
15 #include "ImageContainer.h"
16 #include "LookupResult.h"
17 #include "nsStringFwd.h"
18 #include "ProgressTracker.h"
19 #include "SurfaceCache.h"
21 class nsIRequest;
22 class nsIInputStream;
24 namespace mozilla {
25 namespace image {
27 class Image;
29 ///////////////////////////////////////////////////////////////////////////////
30 // Memory Reporting
31 ///////////////////////////////////////////////////////////////////////////////
33 struct MemoryCounter {
34 MemoryCounter()
35 : mSource(0),
36 mDecodedHeap(0),
37 mDecodedNonHeap(0),
38 mExternalHandles(0),
39 mFrameIndex(0),
40 mExternalId(0) {}
42 void SetSource(size_t aCount) { mSource = aCount; }
43 size_t Source() const { return mSource; }
44 void SetDecodedHeap(size_t aCount) { mDecodedHeap = aCount; }
45 size_t DecodedHeap() const { return mDecodedHeap; }
46 void SetDecodedNonHeap(size_t aCount) { mDecodedNonHeap = aCount; }
47 size_t DecodedNonHeap() const { return mDecodedNonHeap; }
48 void SetExternalHandles(size_t aCount) { mExternalHandles = aCount; }
49 size_t ExternalHandles() const { return mExternalHandles; }
50 void SetFrameIndex(size_t aIndex) { mFrameIndex = aIndex; }
51 size_t FrameIndex() const { return mFrameIndex; }
52 void SetExternalId(uint64_t aId) { mExternalId = aId; }
53 uint64_t ExternalId() const { return mExternalId; }
55 MemoryCounter& operator+=(const MemoryCounter& aOther) {
56 mSource += aOther.mSource;
57 mDecodedHeap += aOther.mDecodedHeap;
58 mDecodedNonHeap += aOther.mDecodedNonHeap;
59 mExternalHandles += aOther.mExternalHandles;
60 return *this;
63 private:
64 size_t mSource;
65 size_t mDecodedHeap;
66 size_t mDecodedNonHeap;
67 size_t mExternalHandles;
68 size_t mFrameIndex;
69 uint64_t mExternalId;
72 enum class SurfaceMemoryCounterType { NORMAL, COMPOSITING, COMPOSITING_PREV };
74 struct SurfaceMemoryCounter {
75 SurfaceMemoryCounter(
76 const SurfaceKey& aKey, bool aIsLocked, bool aCannotSubstitute,
77 bool aIsFactor2,
78 SurfaceMemoryCounterType aType = SurfaceMemoryCounterType::NORMAL)
79 : mKey(aKey),
80 mType(aType),
81 mIsLocked(aIsLocked),
82 mCannotSubstitute(aCannotSubstitute),
83 mIsFactor2(aIsFactor2) {}
85 const SurfaceKey& Key() const { return mKey; }
86 MemoryCounter& Values() { return mValues; }
87 const MemoryCounter& Values() const { return mValues; }
88 SurfaceMemoryCounterType Type() const { return mType; }
89 bool IsLocked() const { return mIsLocked; }
90 bool CannotSubstitute() const { return mCannotSubstitute; }
91 bool IsFactor2() const { return mIsFactor2; }
93 private:
94 const SurfaceKey mKey;
95 MemoryCounter mValues;
96 const SurfaceMemoryCounterType mType;
97 const bool mIsLocked;
98 const bool mCannotSubstitute;
99 const bool mIsFactor2;
102 struct ImageMemoryCounter {
103 ImageMemoryCounter(Image* aImage, SizeOfState& aState, bool aIsUsed);
105 nsCString& URI() { return mURI; }
106 const nsCString& URI() const { return mURI; }
107 const nsTArray<SurfaceMemoryCounter>& Surfaces() const { return mSurfaces; }
108 const gfx::IntSize IntrinsicSize() const { return mIntrinsicSize; }
109 const MemoryCounter& Values() const { return mValues; }
110 uint16_t Type() const { return mType; }
111 bool IsUsed() const { return mIsUsed; }
113 bool IsNotable() const {
114 const size_t NotableThreshold = 16 * 1024;
115 size_t total =
116 mValues.Source() + mValues.DecodedHeap() + mValues.DecodedNonHeap();
117 return total >= NotableThreshold;
120 private:
121 nsCString mURI;
122 nsTArray<SurfaceMemoryCounter> mSurfaces;
123 gfx::IntSize mIntrinsicSize;
124 MemoryCounter mValues;
125 uint16_t mType;
126 const bool mIsUsed;
129 ///////////////////////////////////////////////////////////////////////////////
130 // Image Base Types
131 ///////////////////////////////////////////////////////////////////////////////
133 class Image : public imgIContainer {
134 public:
136 * Flags for Image initialization.
138 * Meanings:
140 * INIT_FLAG_NONE: Lack of flags
142 * INIT_FLAG_DISCARDABLE: The container should be discardable
144 * INIT_FLAG_DECODE_IMMEDIATELY: The container should decode as soon as
145 * possible, regardless of what our heuristics say.
147 * INIT_FLAG_TRANSIENT: The container is likely to exist for only a short time
148 * before being destroyed. (For example, containers for
149 * multipart/x-mixed-replace image parts fall into this category.) If this
150 * flag is set, INIT_FLAG_DISCARDABLE and INIT_FLAG_DECODE_ONLY_ON_DRAW must
151 * not be set.
153 * INIT_FLAG_SYNC_LOAD: The container is being loaded synchronously, so
154 * it should avoid relying on async workers to get the container ready.
156 static const uint32_t INIT_FLAG_NONE = 0x0;
157 static const uint32_t INIT_FLAG_DISCARDABLE = 0x1;
158 static const uint32_t INIT_FLAG_DECODE_IMMEDIATELY = 0x2;
159 static const uint32_t INIT_FLAG_TRANSIENT = 0x4;
160 static const uint32_t INIT_FLAG_SYNC_LOAD = 0x8;
162 virtual already_AddRefed<ProgressTracker> GetProgressTracker() = 0;
163 virtual void SetProgressTracker(ProgressTracker* aProgressTracker) {}
166 * The size, in bytes, occupied by the compressed source data of the image.
167 * If MallocSizeOf does not work on this platform, uses a fallback approach to
168 * ensure that something reasonable is always returned.
170 virtual size_t SizeOfSourceWithComputedFallback(
171 SizeOfState& aState) const = 0;
174 * Collect an accounting of the memory occupied by the image's surfaces (which
175 * together make up its decoded data). Each surface is recorded as a separate
176 * SurfaceMemoryCounter, stored in @aCounters.
178 virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
179 MallocSizeOf aMallocSizeOf) const = 0;
181 virtual void IncrementAnimationConsumers() = 0;
182 virtual void DecrementAnimationConsumers() = 0;
183 #ifdef DEBUG
184 virtual uint32_t GetAnimationConsumers() = 0;
185 #endif
188 * Called from OnDataAvailable when the stream associated with the image has
189 * received new image data. The arguments are the same as OnDataAvailable's,
190 * but by separating this functionality into a different method we don't
191 * interfere with subclasses which wish to implement nsIStreamListener.
193 * Images should not do anything that could send out notifications until they
194 * have received their first OnImageDataAvailable notification; in
195 * particular, this means that instantiating decoders should be deferred
196 * until OnImageDataAvailable is called.
198 virtual nsresult OnImageDataAvailable(nsIRequest* aRequest,
199 nsISupports* aContext,
200 nsIInputStream* aInStr,
201 uint64_t aSourceOffset,
202 uint32_t aCount) = 0;
205 * Called from OnStopRequest when the image's underlying request completes.
207 * @param aRequest The completed request.
208 * @param aContext Context from Necko's OnStopRequest.
209 * @param aStatus A success or failure code.
210 * @param aLastPart Whether this is the final part of the underlying request.
212 virtual nsresult OnImageDataComplete(nsIRequest* aRequest,
213 nsISupports* aContext, nsresult aStatus,
214 bool aLastPart) = 0;
217 * Called when the SurfaceCache discards a surface belonging to this image.
219 virtual void OnSurfaceDiscarded(const SurfaceKey& aSurfaceKey) = 0;
221 virtual void SetInnerWindowID(uint64_t aInnerWindowId) = 0;
222 virtual uint64_t InnerWindowID() const = 0;
224 virtual bool HasError() = 0;
225 virtual void SetHasError() = 0;
227 virtual nsIURI* GetURI() const = 0;
230 class ImageResource : public Image {
231 public:
232 already_AddRefed<ProgressTracker> GetProgressTracker() override {
233 RefPtr<ProgressTracker> progressTracker = mProgressTracker;
234 MOZ_ASSERT(progressTracker);
235 return progressTracker.forget();
238 void SetProgressTracker(ProgressTracker* aProgressTracker) final {
239 MOZ_ASSERT(aProgressTracker);
240 MOZ_ASSERT(!mProgressTracker);
241 mProgressTracker = aProgressTracker;
244 virtual void IncrementAnimationConsumers() override;
245 virtual void DecrementAnimationConsumers() override;
246 #ifdef DEBUG
247 virtual uint32_t GetAnimationConsumers() override {
248 return mAnimationConsumers;
250 #endif
252 virtual void OnSurfaceDiscarded(const SurfaceKey& aSurfaceKey) override {}
254 virtual void SetInnerWindowID(uint64_t aInnerWindowId) override {
255 mInnerWindowId = aInnerWindowId;
257 virtual uint64_t InnerWindowID() const override { return mInnerWindowId; }
259 virtual bool HasError() override { return mError; }
260 virtual void SetHasError() override { mError = true; }
263 * Returns a non-AddRefed pointer to the URI associated with this image.
264 * Illegal to use off-main-thread.
266 nsIURI* GetURI() const override { return mURI; }
268 protected:
269 explicit ImageResource(nsIURI* aURI);
270 ~ImageResource();
272 layers::ContainerProducerID GetImageProducerId() const {
273 return mImageProducerID;
276 bool GetSpecTruncatedTo1k(nsCString& aSpec) const;
278 // Shared functionality for implementors of imgIContainer. Every
279 // implementation of attribute animationMode should forward here.
280 nsresult GetAnimationModeInternal(uint16_t* aAnimationMode);
281 nsresult SetAnimationModeInternal(uint16_t aAnimationMode);
284 * Helper for RequestRefresh.
286 * If we've had a "recent" refresh (i.e. if this image is being used in
287 * multiple documents & some other document *just* called RequestRefresh() on
288 * this image with a timestamp close to aTime), this method returns true.
290 * Otherwise, this method updates mLastRefreshTime to aTime & returns false.
292 bool HadRecentRefresh(const TimeStamp& aTime);
295 * Decides whether animation should or should not be happening,
296 * and makes sure the right thing is being done.
298 virtual void EvaluateAnimation();
301 * Extended by child classes, if they have additional
302 * conditions for being able to animate.
304 virtual bool ShouldAnimate() {
305 return mAnimationConsumers > 0 && mAnimationMode != kDontAnimMode;
308 virtual nsresult StartAnimation() = 0;
309 virtual nsresult StopAnimation() = 0;
311 void SendOnUnlockedDraw(uint32_t aFlags);
313 #ifdef DEBUG
314 // Records the image drawing for startup performance testing.
315 void NotifyDrawingObservers();
316 #endif
318 // Member data shared by all implementations of this abstract class
319 RefPtr<ProgressTracker> mProgressTracker;
320 nsCOMPtr<nsIURI> mURI;
321 TimeStamp mLastRefreshTime;
322 uint64_t mInnerWindowId;
323 uint32_t mAnimationConsumers;
324 uint16_t mAnimationMode; // Enum values in imgIContainer
325 bool mInitialized : 1; // Have we been initialized?
326 bool mAnimating : 1; // Are we currently animating?
327 bool mError : 1; // Error handling
330 * Attempt to find a matching cached surface in the SurfaceCache, and if not
331 * available, request the production of such a surface (either synchronously
332 * or asynchronously).
334 * If the draw result is BAD_IMAGE, BAD_ARGS or NOT_READY, the size will be
335 * the same as aSize. If it is TEMPORARY_ERROR, INCOMPLETE, or SUCCESS, the
336 * size is a hint as to what we expect the surface size to be, once the best
337 * fitting size is available. It may or may not match the size of the surface
338 * returned at this moment. This is useful for choosing how to store the final
339 * result (e.g. if going into an ImageContainer, ideally we would share the
340 * same container for many requested sizes, if they all end up with the same
341 * best fit size in the end).
343 * A valid surface should only be returned for SUCCESS and INCOMPLETE.
345 * Any other draw result is invalid.
347 virtual Tuple<ImgDrawResult, gfx::IntSize, RefPtr<gfx::SourceSurface>>
348 GetFrameInternal(const gfx::IntSize& aSize,
349 const Maybe<SVGImageContext>& aSVGContext,
350 uint32_t aWhichFrame, uint32_t aFlags) {
351 return MakeTuple(ImgDrawResult::BAD_IMAGE, aSize,
352 RefPtr<gfx::SourceSurface>());
356 * Calculate the estimated size to use for an image container with the given
357 * parameters. It may not be the same as the given size, and it may not be
358 * the same as the size of the surface in the image container, but it is the
359 * best effort estimate.
361 virtual Tuple<ImgDrawResult, gfx::IntSize> GetImageContainerSize(
362 layers::LayerManager* aManager, const gfx::IntSize& aSize,
363 uint32_t aFlags) {
364 return MakeTuple(ImgDrawResult::NOT_SUPPORTED, gfx::IntSize(0, 0));
367 ImgDrawResult GetImageContainerImpl(layers::LayerManager* aManager,
368 const gfx::IntSize& aSize,
369 const Maybe<SVGImageContext>& aSVGContext,
370 uint32_t aFlags,
371 layers::ImageContainer** aContainer);
374 * Re-requests the appropriate frames for each image container using
375 * GetFrameInternal.
376 * @returns True if any image containers were updated, else false.
378 bool UpdateImageContainer(const Maybe<gfx::IntRect>& aDirtyRect);
380 void ReleaseImageContainer();
382 private:
383 void SetCurrentImage(layers::ImageContainer* aContainer,
384 gfx::SourceSurface* aSurface,
385 const Maybe<gfx::IntRect>& aDirtyRect);
387 struct ImageContainerEntry {
388 ImageContainerEntry(const gfx::IntSize& aSize,
389 const Maybe<SVGImageContext>& aSVGContext,
390 layers::ImageContainer* aContainer, uint32_t aFlags)
391 : mSize(aSize),
392 mSVGContext(aSVGContext),
393 mContainer(aContainer),
394 mLastDrawResult(ImgDrawResult::NOT_READY),
395 mFlags(aFlags) {}
397 gfx::IntSize mSize;
398 Maybe<SVGImageContext> mSVGContext;
399 // A weak pointer to our ImageContainer, which stays alive only as long as
400 // the layer system needs it.
401 WeakPtr<layers::ImageContainer> mContainer;
402 // If mContainer is non-null, this contains the ImgDrawResult we obtained
403 // the last time we updated it.
404 ImgDrawResult mLastDrawResult;
405 // Cached flags to use for decoding. FLAG_ASYNC_NOTIFY should always be set
406 // but FLAG_HIGH_QUALITY_SCALING may vary.
407 uint32_t mFlags;
410 AutoTArray<ImageContainerEntry, 1> mImageContainers;
411 layers::ImageContainer::ProducerID mImageProducerID;
412 layers::ImageContainer::FrameID mLastFrameID;
415 } // namespace image
416 } // namespace mozilla
418 #endif // mozilla_image_Image_h