FrameAnimator.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2. *
  3. * This Source Code Form is subject to the terms of the Mozilla Public
  4. * License, v. 2.0. If a copy of the MPL was not distributed with this
  5. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6. #ifndef mozilla_image_FrameAnimator_h
  7. #define mozilla_image_FrameAnimator_h
  8. #include "mozilla/Maybe.h"
  9. #include "mozilla/MemoryReporting.h"
  10. #include "mozilla/TimeStamp.h"
  11. #include "gfxTypes.h"
  12. #include "imgFrame.h"
  13. #include "nsCOMPtr.h"
  14. #include "nsRect.h"
  15. #include "SurfaceCache.h"
  16. namespace mozilla {
  17. namespace image {
  18. class RasterImage;
  19. class AnimationState
  20. {
  21. public:
  22. explicit AnimationState(uint16_t aAnimationMode)
  23. : mFrameCount(0)
  24. , mCurrentAnimationFrameIndex(0)
  25. , mLoopRemainingCount(-1)
  26. , mLoopCount(-1)
  27. , mFirstFrameTimeout(FrameTimeout::FromRawMilliseconds(0))
  28. , mAnimationMode(aAnimationMode)
  29. , mDoneDecoding(false)
  30. { }
  31. /**
  32. * Call when this image is finished decoding so we know that there aren't any
  33. * more frames coming.
  34. */
  35. void SetDoneDecoding(bool aDone);
  36. /**
  37. * Call when you need to re-start animating. Ensures we start from the first
  38. * frame.
  39. */
  40. void ResetAnimation();
  41. /**
  42. * The animation mode of the image.
  43. *
  44. * Constants defined in imgIContainer.idl.
  45. */
  46. void SetAnimationMode(uint16_t aAnimationMode);
  47. /// Update the number of frames of animation this image is known to have.
  48. void UpdateKnownFrameCount(uint32_t aFrameCount);
  49. /// @return the number of frames of animation we know about so far.
  50. uint32_t KnownFrameCount() const { return mFrameCount; }
  51. /// @return the number of frames this animation has, if we know for sure.
  52. /// (In other words, if decoding is finished.) Otherwise, returns Nothing().
  53. Maybe<uint32_t> FrameCount() const;
  54. /**
  55. * Get or set the area of the image to invalidate when we loop around to the
  56. * first frame.
  57. */
  58. void SetFirstFrameRefreshArea(const gfx::IntRect& aRefreshArea);
  59. gfx::IntRect FirstFrameRefreshArea() const { return mFirstFrameRefreshArea; }
  60. /**
  61. * If the animation frame time has not yet been set, set it to
  62. * TimeStamp::Now().
  63. */
  64. void InitAnimationFrameTimeIfNecessary();
  65. /**
  66. * Set the animation frame time to @aTime.
  67. */
  68. void SetAnimationFrameTime(const TimeStamp& aTime);
  69. /**
  70. * The current frame we're on, from 0 to (numFrames - 1).
  71. */
  72. uint32_t GetCurrentAnimationFrameIndex() const;
  73. /*
  74. * Set number of times to loop the image.
  75. * @note -1 means loop forever.
  76. */
  77. void SetLoopCount(int32_t aLoopCount) { mLoopCount = aLoopCount; }
  78. int32_t LoopCount() const { return mLoopCount; }
  79. /// Set the @aLength of a single loop through this image.
  80. void SetLoopLength(FrameTimeout aLength) { mLoopLength = Some(aLength); }
  81. /**
  82. * @return the length of a single loop of this image. If this image is not
  83. * finished decoding, is not animated, or it is animated but does not loop,
  84. * returns FrameTimeout::Forever().
  85. */
  86. FrameTimeout LoopLength() const;
  87. /*
  88. * Get or set the timeout for the first frame. This is used to allow animation
  89. * scheduling even before a full decode runs for this image.
  90. */
  91. void SetFirstFrameTimeout(FrameTimeout aTimeout) { mFirstFrameTimeout = aTimeout; }
  92. FrameTimeout FirstFrameTimeout() const { return mFirstFrameTimeout; }
  93. private:
  94. friend class FrameAnimator;
  95. //! Area of the first frame that needs to be redrawn on subsequent loops.
  96. gfx::IntRect mFirstFrameRefreshArea;
  97. //! the time that the animation advanced to the current frame
  98. TimeStamp mCurrentAnimationFrameTime;
  99. //! The number of frames of animation this image has.
  100. uint32_t mFrameCount;
  101. //! The current frame index we're on, in the range [0, mFrameCount).
  102. uint32_t mCurrentAnimationFrameIndex;
  103. //! number of loops remaining before animation stops (-1 no stop)
  104. int32_t mLoopRemainingCount;
  105. //! The total number of loops for the image.
  106. int32_t mLoopCount;
  107. //! The length of a single loop through this image.
  108. Maybe<FrameTimeout> mLoopLength;
  109. //! The timeout for the first frame of this image.
  110. FrameTimeout mFirstFrameTimeout;
  111. //! The animation mode of this image. Constants defined in imgIContainer.
  112. uint16_t mAnimationMode;
  113. //! Whether this image is done being decoded.
  114. bool mDoneDecoding;
  115. };
  116. /**
  117. * RefreshResult is used to let callers know how the state of the animation
  118. * changed during a call to FrameAnimator::RequestRefresh().
  119. */
  120. struct RefreshResult
  121. {
  122. RefreshResult()
  123. : mFrameAdvanced(false)
  124. , mAnimationFinished(false)
  125. { }
  126. /// Merges another RefreshResult's changes into this RefreshResult.
  127. void Accumulate(const RefreshResult& aOther)
  128. {
  129. mFrameAdvanced = mFrameAdvanced || aOther.mFrameAdvanced;
  130. mAnimationFinished = mAnimationFinished || aOther.mAnimationFinished;
  131. mDirtyRect = mDirtyRect.Union(aOther.mDirtyRect);
  132. }
  133. // The region of the image that has changed.
  134. gfx::IntRect mDirtyRect;
  135. // If true, we changed frames at least once. Note that, due to looping, we
  136. // could still have ended up on the same frame!
  137. bool mFrameAdvanced : 1;
  138. // Whether the animation has finished playing.
  139. bool mAnimationFinished : 1;
  140. };
  141. class FrameAnimator
  142. {
  143. public:
  144. FrameAnimator(RasterImage* aImage, const gfx::IntSize& aSize)
  145. : mImage(aImage)
  146. , mSize(aSize)
  147. , mLastCompositedFrameIndex(-1)
  148. {
  149. MOZ_COUNT_CTOR(FrameAnimator);
  150. }
  151. ~FrameAnimator()
  152. {
  153. MOZ_COUNT_DTOR(FrameAnimator);
  154. }
  155. /**
  156. * Re-evaluate what frame we're supposed to be on, and do whatever blending
  157. * is necessary to get us to that frame.
  158. *
  159. * Returns the result of that blending, including whether the current frame
  160. * changed and what the resulting dirty rectangle is.
  161. */
  162. RefreshResult RequestRefresh(AnimationState& aState, const TimeStamp& aTime);
  163. /**
  164. * If we have a composited frame for @aFrameNum, returns it. Otherwise,
  165. * returns an empty LookupResult. It is an error to call this method with
  166. * aFrameNum == 0, because the first frame is never composited.
  167. */
  168. LookupResult GetCompositedFrame(uint32_t aFrameNum);
  169. /**
  170. * Collect an accounting of the memory occupied by the compositing surfaces we
  171. * use during animation playback. All of the actual animation frames are
  172. * stored in the SurfaceCache, so we don't need to report them here.
  173. */
  174. void CollectSizeOfCompositingSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
  175. MallocSizeOf aMallocSizeOf) const;
  176. private: // methods
  177. /**
  178. * Advances the animation. Typically, this will advance a single frame, but it
  179. * may advance multiple frames. This may happen if we have infrequently
  180. * "ticking" refresh drivers (e.g. in background tabs), or extremely short-
  181. * lived animation frames.
  182. *
  183. * @param aTime the time that the animation should advance to. This will
  184. * typically be <= TimeStamp::Now().
  185. *
  186. * @returns a RefreshResult that shows whether the frame was successfully
  187. * advanced, and its resulting dirty rect.
  188. */
  189. RefreshResult AdvanceFrame(AnimationState& aState, TimeStamp aTime);
  190. /**
  191. * Get the @aIndex-th frame in the frame index, ignoring results of blending.
  192. */
  193. RawAccessFrameRef GetRawFrame(uint32_t aFrameNum) const;
  194. /// @return the given frame's timeout.
  195. FrameTimeout GetTimeoutForFrame(uint32_t aFrameNum) const;
  196. /**
  197. * Get the time the frame we're currently displaying is supposed to end.
  198. *
  199. * In the error case, returns an "infinity" timestamp.
  200. */
  201. TimeStamp GetCurrentImgFrameEndTime(AnimationState& aState) const;
  202. bool DoBlend(gfx::IntRect* aDirtyRect,
  203. uint32_t aPrevFrameIndex,
  204. uint32_t aNextFrameIndex);
  205. /** Clears an area of <aFrame> with transparent black.
  206. *
  207. * @param aFrameData Target Frame data
  208. * @param aFrameRect The rectangle of the data pointed ot by aFrameData
  209. *
  210. * @note Does also clears the transparency mask
  211. */
  212. static void ClearFrame(uint8_t* aFrameData, const gfx::IntRect& aFrameRect);
  213. //! @overload
  214. static void ClearFrame(uint8_t* aFrameData, const gfx::IntRect& aFrameRect,
  215. const gfx::IntRect& aRectToClear);
  216. //! Copy one frame's image and mask into another
  217. static bool CopyFrameImage(const uint8_t* aDataSrc, const gfx::IntRect& aRectSrc,
  218. uint8_t* aDataDest, const gfx::IntRect& aRectDest);
  219. /**
  220. * Draws one frame's image to into another, at the position specified by
  221. * aSrcRect.
  222. *
  223. * @aSrcData the raw data of the current frame being drawn
  224. * @aSrcRect the size of the source frame, and the position of that frame in
  225. * the composition frame
  226. * @aSrcPaletteLength the length (in bytes) of the palette at the beginning
  227. * of the source data (0 if image is not paletted)
  228. * @aSrcHasAlpha whether the source data represents an image with alpha
  229. * @aDstPixels the raw data of the composition frame where the current frame
  230. * is drawn into (32-bit ARGB)
  231. * @aDstRect the size of the composition frame
  232. * @aBlendMethod the blend method for how to blend src on the composition
  233. * frame.
  234. */
  235. static nsresult DrawFrameTo(const uint8_t* aSrcData,
  236. const gfx::IntRect& aSrcRect,
  237. uint32_t aSrcPaletteLength, bool aSrcHasAlpha,
  238. uint8_t* aDstPixels, const gfx::IntRect& aDstRect,
  239. BlendMethod aBlendMethod,
  240. const Maybe<gfx::IntRect>& aBlendRect);
  241. private: // data
  242. //! A weak pointer to our owning image.
  243. RasterImage* mImage;
  244. //! The intrinsic size of the image.
  245. gfx::IntSize mSize;
  246. /** For managing blending of frames
  247. *
  248. * Some animations will use the compositingFrame to composite images
  249. * and just hand this back to the caller when it is time to draw the frame.
  250. * NOTE: When clearing compositingFrame, remember to set
  251. * lastCompositedFrameIndex to -1. Code assume that if
  252. * lastCompositedFrameIndex >= 0 then compositingFrame exists.
  253. */
  254. RawAccessFrameRef mCompositingFrame;
  255. /** the previous composited frame, for DISPOSE_RESTORE_PREVIOUS
  256. *
  257. * The Previous Frame (all frames composited up to the current) needs to be
  258. * stored in cases where the image specifies it wants the last frame back
  259. * when it's done with the current frame.
  260. */
  261. RawAccessFrameRef mCompositingPrevFrame;
  262. //! Track the last composited frame for Optimizations (See DoComposite code)
  263. int32_t mLastCompositedFrameIndex;
  264. };
  265. } // namespace image
  266. } // namespace mozilla
  267. #endif // mozilla_image_FrameAnimator_h