Image.h 10 KB

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