summaryrefslogtreecommitdiffstats
path: root/gfx/layers/ipc/SharedSurfacesChild.h
blob: 02e2d6aafe957214e70955344e28da0a400b1f35 (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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */

#ifndef MOZILLA_GFX_SHAREDSURFACESCHILD_H
#define MOZILLA_GFX_SHAREDSURFACESCHILD_H

#include <stdint.h>                            // for uint32_t, uint64_t
#include "mozilla/Attributes.h"                // for override
#include "mozilla/Maybe.h"                     // for Maybe
#include "mozilla/RefPtr.h"                    // for already_AddRefed
#include "mozilla/StaticPtr.h"                 // for StaticRefPtr
#include "mozilla/gfx/UserData.h"              // for UserDataKey
#include "mozilla/layers/LayersSurfaces.h"     // for SurfaceDescriptor
#include "mozilla/webrender/WebRenderTypes.h"  // for wr::ImageKey
#include "nsTArray.h"                          // for AutoTArray
#include "nsThreadUtils.h"                     // for Runnable
#include "ImageTypes.h"                        // for ContainerProducerID

namespace mozilla {
namespace layers {
class AnimationImageKeyData;
}  // namespace layers
}  // namespace mozilla

template <>
struct nsTArray_RelocationStrategy<mozilla::layers::AnimationImageKeyData> {
  typedef nsTArray_RelocateUsingMoveConstructor<
      mozilla::layers::AnimationImageKeyData>
      Type;
};

namespace mozilla {
namespace gfx {
class SourceSurface;
class SourceSurfaceSharedData;
}  // namespace gfx

namespace wr {
class IpcResourceUpdateQueue;
}  // namespace wr

namespace layers {

class CompositorManagerChild;
class RenderRootStateManager;

class SharedSurfacesChild {
 public:
  /**
   * Request that the surface be mapped into the compositor thread's memory
   * space. This is useful for when the caller itself has no present need for
   * the surface to be mapped, but knows there will be such a need in the
   * future. This may be called from any thread, but it may cause a dispatch to
   * the main thread.
   */
  static void Share(gfx::SourceSurfaceSharedData* aSurface);

  /**
   * Request that the surface be mapped into the compositor thread's memory
   * space, and a valid ExternalImageId be generated for it for use with
   * WebRender. This must be called from the main thread.
   */
  static nsresult Share(gfx::SourceSurface* aSurface, wr::ExternalImageId& aId);

  /**
   * Request that the surface be mapped into the compositor thread's memory
   * space, and a valid ExternalImageId be generated for it for use with
   * WebRender. This must be called from the main thread.
   */
  static nsresult Share(gfx::SourceSurface* aSurface,
                        Maybe<SurfaceDescriptor>& aDesc);

  /**
   * Request that the surface be mapped into the compositor thread's memory
   * space, and a valid ImageKey be generated for it for use with WebRender.
   * This must be called from the main thread.
   */
  static nsresult Share(gfx::SourceSurfaceSharedData* aSurface,
                        RenderRootStateManager* aManager,
                        wr::IpcResourceUpdateQueue& aResources,
                        wr::ImageKey& aKey);

  /**
   * Request that the surface be mapped into the compositor thread's memory
   * space, and a valid ImageKey be generated for it for use with WebRender.
   * This must be called from the main thread.
   */
  static nsresult Share(gfx::SourceSurface* aSurface,
                        RenderRootStateManager* aManager,
                        wr::IpcResourceUpdateQueue& aResources,
                        wr::ImageKey& aKey);

  /**
   * Get the external ID, if any, bound to the shared surface. Used for memory
   * reporting purposes.
   */
  static Maybe<wr::ExternalImageId> GetExternalId(
      const gfx::SourceSurfaceSharedData* aSurface);

  /**
   * Get the surface (or its underlying surface) as a SourceSurfaceSharedData
   * pointer, if valid.
   */
  static gfx::SourceSurfaceSharedData* AsSourceSurfaceSharedData(
      gfx::SourceSurface* aSurface);

  class ImageKeyData {
   public:
    ImageKeyData(RenderRootStateManager* aManager,
                 const wr::ImageKey& aImageKey);
    virtual ~ImageKeyData();

    ImageKeyData(ImageKeyData&& aOther);
    ImageKeyData& operator=(ImageKeyData&& aOther);
    ImageKeyData(const ImageKeyData&) = delete;
    ImageKeyData& operator=(const ImageKeyData&) = delete;

    void MergeDirtyRect(const Maybe<gfx::IntRect>& aDirtyRect);

    Maybe<gfx::IntRect> TakeDirtyRect() { return std::move(mDirtyRect); }

    RefPtr<RenderRootStateManager> mManager;
    Maybe<gfx::IntRect> mDirtyRect;
    wr::ImageKey mImageKey;
  };

 private:
  SharedSurfacesChild() = delete;
  ~SharedSurfacesChild() = delete;

  friend class SharedSurfacesAnimation;

  class SharedUserData final : public Runnable {
   public:
    SharedUserData();
    virtual ~SharedUserData();

    SharedUserData(const SharedUserData& aOther) = delete;
    SharedUserData& operator=(const SharedUserData& aOther) = delete;

    SharedUserData(SharedUserData&& aOther) = delete;
    SharedUserData& operator=(SharedUserData&& aOther) = delete;

    static void Destroy(void* aClosure);

    NS_IMETHOD Run() override;

    const wr::ExternalImageId& Id() const { return mId; }

    void ClearShared() {
      mKeys.Clear();
      mShared = false;
    }

    bool IsShared() const { return mShared; }

    void MarkShared(const wr::ExternalImageId& aId) {
      MOZ_ASSERT(!mShared);
      mId = aId;
      mShared = true;
    }

    wr::ImageKey UpdateKey(RenderRootStateManager* aManager,
                           wr::IpcResourceUpdateQueue& aResources,
                           const Maybe<gfx::IntRect>& aDirtyRect);

   protected:
    AutoTArray<ImageKeyData, 1> mKeys;
    wr::ExternalImageId mId;
    bool mShared : 1;
  };

  static nsresult ShareInternal(gfx::SourceSurfaceSharedData* aSurface,
                                SharedUserData** aUserData);

  static void Unshare(const wr::ExternalImageId& aId, bool aReleaseId,
                      nsTArray<ImageKeyData>& aKeys);

  static void DestroySharedUserData(void* aClosure);

  static gfx::UserDataKey sSharedKey;
};

class AnimationImageKeyData final : public SharedSurfacesChild::ImageKeyData {
 public:
  AnimationImageKeyData(RenderRootStateManager* aManager,
                        const wr::ImageKey& aImageKey);

  virtual ~AnimationImageKeyData();

  AnimationImageKeyData(AnimationImageKeyData&& aOther);
  AnimationImageKeyData& operator=(AnimationImageKeyData&& aOther);

  AutoTArray<RefPtr<gfx::SourceSurfaceSharedData>, 2> mPendingRelease;
};

/**
 * This helper class owns a single ImageKey which will map to different external
 * image IDs representing different frames in an animation.
 */
class SharedSurfacesAnimation final {
 public:
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedSurfacesAnimation)

  SharedSurfacesAnimation() = default;

  void Destroy();

  /**
   * Set the animation to display the given frame.
   * @param aSurface    The current frame.
   * @param aDirtyRect  Dirty rect representing the change between the new frame
   *                    and the previous frame. We will request only the delta
   *                    be reuploaded by WebRender.
   */
  nsresult SetCurrentFrame(gfx::SourceSurfaceSharedData* aSurface,
                           const gfx::IntRect& aDirtyRect);

  /**
   * Generate an ImageKey for the given frame.
   * @param aSurface  The current frame. This should match what was cached via
   *                  SetCurrentFrame, but if it does not, it will need to
   *                  regenerate the cached ImageKey.
   */
  nsresult UpdateKey(gfx::SourceSurfaceSharedData* aSurface,
                     RenderRootStateManager* aManager,
                     wr::IpcResourceUpdateQueue& aResources,
                     wr::ImageKey& aKey);

  /**
   * Release our reference to all frames up to and including the frame which
   * has an external image ID which matches aId.
   */
  void ReleasePreviousFrame(RenderRootStateManager* aManager,
                            const wr::ExternalImageId& aId);

  /**
   * Destroy any state information bound for the given layer manager. Any
   * image keys are already invalid.
   */
  void Invalidate(RenderRootStateManager* aManager);

 private:
  ~SharedSurfacesAnimation();

  void HoldSurfaceForRecycling(AnimationImageKeyData& aEntry,
                               gfx::SourceSurfaceSharedData* aSurface);

  AutoTArray<AnimationImageKeyData, 1> mKeys;
  wr::ExternalImageId mId;
};

}  // namespace layers
}  // namespace mozilla

#endif