summaryrefslogtreecommitdiffstats
path: root/image/AnimationSurfaceProvider.h
blob: bf87f37ac4c9c8cf96ec8b66b7534ad210e176d2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/**
 * An ISurfaceProvider for animated images.
 */

#ifndef mozilla_image_AnimationSurfaceProvider_h
#define mozilla_image_AnimationSurfaceProvider_h

#include "FrameAnimator.h"
#include "IDecodingTask.h"
#include "ISurfaceProvider.h"

namespace mozilla {
namespace image {

/**
 * An ISurfaceProvider that manages the decoding of animated images and
 * dynamically generates surfaces for the current playback state of the
 * animation.
 */
class AnimationSurfaceProvider final
  : public ISurfaceProvider
  , public IDecodingTask
{
public:
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AnimationSurfaceProvider, override)

  AnimationSurfaceProvider(NotNull<RasterImage*> aImage,
                           const SurfaceKey& aSurfaceKey,
                           NotNull<Decoder*> aDecoder);


  //////////////////////////////////////////////////////////////////////////////
  // ISurfaceProvider implementation.
  //////////////////////////////////////////////////////////////////////////////

public:
  // We use the ISurfaceProvider constructor of DrawableSurface to indicate that
  // our surfaces are computed lazily.
  DrawableSurface Surface() override { return DrawableSurface(WrapNotNull(this)); }

  bool IsFinished() const override;
  size_t LogicalSizeInBytes() const override;
  void AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
                              size_t& aHeapSizeOut,
                              size_t& aNonHeapSizeOut) override;

protected:
  DrawableFrameRef DrawableRef(size_t aFrame) override;

  // Animation frames are always locked. This is because we only want to release
  // their memory atomically (due to the surface cache discarding them). If they
  // were unlocked, the OS could end up releasing the memory of random frames
  // from the middle of the animation, which is not worth the complexity of
  // dealing with.
  bool IsLocked() const override { return true; }
  void SetLocked(bool) override { }


  //////////////////////////////////////////////////////////////////////////////
  // IDecodingTask implementation.
  //////////////////////////////////////////////////////////////////////////////

public:
  void Run() override;
  bool ShouldPreferSyncRun() const override;

  // Full decodes are low priority compared to metadata decodes because they
  // don't block layout or page load.
  TaskPriority Priority() const override { return TaskPriority::eLow; }

private:
  virtual ~AnimationSurfaceProvider();

  void DropImageReference();
  void CheckForNewFrameAtYield();
  void CheckForNewFrameAtTerminalState();
  void AnnounceSurfaceAvailable();
  void FinishDecoding();

  /// The image associated with our decoder.
  RefPtr<RasterImage> mImage;

  /// A mutex to protect mDecoder. Always taken before mFramesMutex.
  mutable Mutex mDecodingMutex;

  /// The decoder used to decode this animation.
  RefPtr<Decoder> mDecoder;

  /// A mutex to protect mFrames. Always taken after mDecodingMutex.
  mutable Mutex mFramesMutex;

  /// The frames of this animation, in order.
  nsTArray<RawAccessFrameRef> mFrames;
};

} // namespace image
} // namespace mozilla

#endif // mozilla_image_AnimationSurfaceProvider_h