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  * An ISurfaceProvider for animated images.
8  */
9 
10 #ifndef mozilla_image_AnimationSurfaceProvider_h
11 #define mozilla_image_AnimationSurfaceProvider_h
12 
13 #include "mozilla/UniquePtr.h"
14 
15 #include "Decoder.h"
16 #include "FrameAnimator.h"
17 #include "IDecodingTask.h"
18 #include "ISurfaceProvider.h"
19 #include "AnimationFrameBuffer.h"
20 
21 namespace mozilla {
22 namespace image {
23 
24 /**
25  * An ISurfaceProvider that manages the decoding of animated images and
26  * dynamically generates surfaces for the current playback state of the
27  * animation.
28  */
29 class AnimationSurfaceProvider final : public ISurfaceProvider,
30                                        public IDecodingTask,
31                                        public IDecoderFrameRecycler {
32  public:
33   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AnimationSurfaceProvider, override)
34 
35   AnimationSurfaceProvider(NotNull<RasterImage*> aImage,
36                            const SurfaceKey& aSurfaceKey,
37                            NotNull<Decoder*> aDecoder, size_t aCurrentFrame);
38 
39   //////////////////////////////////////////////////////////////////////////////
40   // ISurfaceProvider implementation.
41   //////////////////////////////////////////////////////////////////////////////
42 
43  public:
44   // We use the ISurfaceProvider constructor of DrawableSurface to indicate that
45   // our surfaces are computed lazily.
Surface()46   DrawableSurface Surface() override {
47     return DrawableSurface(WrapNotNull(this));
48   }
49 
50   bool IsFinished() const override;
51   bool IsFullyDecoded() const override;
52   size_t LogicalSizeInBytes() const override;
53   void AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
54                               const AddSizeOfCb& aCallback) override;
55   void Reset() override;
56   void Advance(size_t aFrame) override;
57 
58  protected:
59   DrawableFrameRef DrawableRef(size_t aFrame) override;
60   already_AddRefed<imgFrame> GetFrame(size_t aFrame) override;
61 
62   // Animation frames are always locked. This is because we only want to release
63   // their memory atomically (due to the surface cache discarding them). If they
64   // were unlocked, the OS could end up releasing the memory of random frames
65   // from the middle of the animation, which is not worth the complexity of
66   // dealing with.
IsLocked()67   bool IsLocked() const override { return true; }
SetLocked(bool)68   void SetLocked(bool) override {}
69 
70   //////////////////////////////////////////////////////////////////////////////
71   // IDecodingTask implementation.
72   //////////////////////////////////////////////////////////////////////////////
73 
74  public:
75   void Run() override;
76   bool ShouldPreferSyncRun() const override;
77 
78   // Full decodes are low priority compared to metadata decodes because they
79   // don't block layout or page load.
Priority()80   TaskPriority Priority() const override { return TaskPriority::eLow; }
81 
82   //////////////////////////////////////////////////////////////////////////////
83   // IDecoderFrameRecycler implementation.
84   //////////////////////////////////////////////////////////////////////////////
85 
86  public:
87   RawAccessFrameRef RecycleFrame(gfx::IntRect& aRecycleRect) override;
88 
89  private:
90   virtual ~AnimationSurfaceProvider();
91 
92   void DropImageReference();
93   void AnnounceSurfaceAvailable();
94   void FinishDecoding();
95   void RequestFrameDiscarding();
96 
97   // @returns Whether or not we should continue decoding.
98   bool CheckForNewFrameAtYield();
99 
100   // @returns Whether or not we should restart decoding.
101   bool CheckForNewFrameAtTerminalState();
102 
103   /// The image associated with our decoder.
104   RefPtr<RasterImage> mImage;
105 
106   /// A mutex to protect mDecoder. Always taken before mFramesMutex.
107   mutable Mutex mDecodingMutex;
108 
109   /// The decoder used to decode this animation.
110   RefPtr<Decoder> mDecoder;
111 
112   /// A mutex to protect mFrames. Always taken after mDecodingMutex.
113   mutable Mutex mFramesMutex;
114 
115   /// The frames of this animation, in order.
116   UniquePtr<AnimationFrameBuffer> mFrames;
117 };
118 
119 }  // namespace image
120 }  // namespace mozilla
121 
122 #endif  // mozilla_image_AnimationSurfaceProvider_h
123