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