summaryrefslogtreecommitdiffstats
path: root/gfx/layers/wr/AsyncImagePipelineManager.h
blob: 7f8e68ae41257aa3f33668bb29d53b74e0716f57 (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
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
/* -*- 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_WEBRENDERCOMPOSITABLE_HOLDER_H
#define MOZILLA_GFX_WEBRENDERCOMPOSITABLE_HOLDER_H

#include <vector>

#include "CompositableHost.h"
#include "mozilla/gfx/Point.h"
#include "mozilla/ipc/FileDescriptor.h"
#include "mozilla/layers/RemoteTextureMap.h"
#include "mozilla/layers/TextureHost.h"
#include "mozilla/Maybe.h"
#include "mozilla/webrender/WebRenderAPI.h"
#include "mozilla/webrender/WebRenderTypes.h"
#include "nsClassHashtable.h"

namespace mozilla {

namespace wr {
class DisplayListBuilder;
class WebRenderAPI;
class WebRenderPipelineInfo;
}  // namespace wr

namespace layers {

class CompositableHost;
class CompositorVsyncScheduler;
class WebRenderImageHost;
class WebRenderTextureHost;

class AsyncImagePipelineManager final {
 public:
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncImagePipelineManager)

  explicit AsyncImagePipelineManager(RefPtr<wr::WebRenderAPI>&& aApi,
                                     bool aUseCompositorWnd);

 protected:
  ~AsyncImagePipelineManager();

 public:
  void Destroy();

  bool UseCompositorWnd() const { return mUseCompositorWnd; }

  void AddPipeline(const wr::PipelineId& aPipelineId,
                   WebRenderBridgeParent* aWrBridge);
  void RemovePipeline(const wr::PipelineId& aPipelineId,
                      const wr::Epoch& aEpoch);
  WebRenderBridgeParent* GetWrBridge(const wr::PipelineId& aPipelineId);

  void HoldExternalImage(const wr::PipelineId& aPipelineId,
                         const wr::Epoch& aEpoch, TextureHost* aTexture);
  void HoldExternalImage(const wr::PipelineId& aPipelineId,
                         const wr::Epoch& aEpoch,
                         const wr::ExternalImageId& aImageId);

  // This is called from the Renderer thread to notify this class about the
  // pipelines in the most recently completed update.
  // @param aInfo PipelineInfo for the update
  // @param aLatestFrameId RenderedFrameId if a frame has been submitted for
  //                       rendering, invalid if not
  // @param aLastCompletedFrameId RenderedFrameId for the last completed frame
  void NotifyPipelinesUpdated(RefPtr<const wr::WebRenderPipelineInfo> aInfo,
                              wr::RenderedFrameId aLatestFrameId,
                              wr::RenderedFrameId aLastCompletedFrameId,
                              ipc::FileDescriptor&& aFenceFd);

  // This is run on the compositor thread to process mRenderSubmittedUpdates. We
  // make this public because we need to invoke it from other places.
  void ProcessPipelineUpdates();

  TimeStamp GetCompositionTime() const { return mCompositionTime; }
  CompositionOpportunityId GetCompositionOpportunityId() const {
    return mCompositionOpportunityId;
  }

  void SetCompositionInfo(TimeStamp aTimeStamp,
                          CompositionOpportunityId aCompositionOpportunityId) {
    mCompositionTime = aTimeStamp;
    mCompositionOpportunityId = aCompositionOpportunityId;
    if (!mCompositionTime.IsNull() && !mCompositeUntilTime.IsNull() &&
        mCompositionTime >= mCompositeUntilTime) {
      mCompositeUntilTime = TimeStamp();
    }
  }
  void CompositeUntil(TimeStamp aTimeStamp) {
    if (mCompositeUntilTime.IsNull() || mCompositeUntilTime < aTimeStamp) {
      mCompositeUntilTime = aTimeStamp;
    }
  }
  TimeStamp GetCompositeUntilTime() const { return mCompositeUntilTime; }

  void AddAsyncImagePipeline(const wr::PipelineId& aPipelineId,
                             WebRenderImageHost* aImageHost);
  void RemoveAsyncImagePipeline(const wr::PipelineId& aPipelineId,
                                wr::TransactionBuilder& aTxn);

  void UpdateAsyncImagePipeline(const wr::PipelineId& aPipelineId,
                                const LayoutDeviceRect& aScBounds,
                                wr::WrRotation aRotation,
                                const wr::ImageRendering& aFilter,
                                const wr::MixBlendMode& aMixBlendMode);
  void ApplyAsyncImagesOfImageBridge(wr::TransactionBuilder& aSceneBuilderTxn,
                                     wr::TransactionBuilder& aFastTxn);
  void ApplyAsyncImageForPipeline(
      const wr::PipelineId& aPipelineId, wr::TransactionBuilder& aTxn,
      wr::TransactionBuilder& aTxnForImageBridge,
      AsyncImagePipelineOps* aPendingOps,
      RemoteTextureInfoList* aPendingRemoteTextures);

  void ApplyAsyncImageForPipeline(const wr::PipelineId& aPipelineId,
                                  TextureHost* aTexture,
                                  wr::TransactionBuilder& aTxn);

  void SetEmptyDisplayList(const wr::PipelineId& aPipelineId,
                           wr::TransactionBuilder& aTxn,
                           wr::TransactionBuilder& aTxnForImageBridge);

  void AppendImageCompositeNotification(
      const ImageCompositeNotificationInfo& aNotification) {
    mImageCompositeNotifications.AppendElement(aNotification);
  }

  void FlushImageNotifications(
      nsTArray<ImageCompositeNotificationInfo>* aNotifications) {
    aNotifications->AppendElements(std::move(mImageCompositeNotifications));
  }

  void SetWillGenerateFrame();
  bool GetAndResetWillGenerateFrame();

  static wr::ExternalImageId GetNextExternalImageId();

  void SetTextureFactoryIdentifier(
      const TextureFactoryIdentifier& aTextureFactoryIdentifier) {
    mTextureFactoryIdentifier = aTextureFactoryIdentifier;
  }

  TextureFactoryIdentifier GetTextureFactoryIdentifier() const {
    return mTextureFactoryIdentifier;
  }

 private:
  void ProcessPipelineRendered(const wr::PipelineId& aPipelineId,
                               const wr::Epoch& aEpoch,
                               wr::RenderedFrameId aRenderedFrameId);
  void ProcessPipelineRemoved(const wr::RemovedPipeline& aRemovedPipeline,
                              wr::RenderedFrameId aRenderedFrameId);

  wr::Epoch GetNextImageEpoch();
  uint32_t GetNextResourceId() { return ++mResourceId; }
  wr::IdNamespace GetNamespace() { return mIdNamespace; }
  wr::ImageKey GenerateImageKey() {
    wr::ImageKey key;
    key.mNamespace = GetNamespace();
    key.mHandle = GetNextResourceId();
    return key;
  }

  struct ForwardingTextureHost {
    ForwardingTextureHost(const wr::Epoch& aEpoch, TextureHost* aTexture)
        : mEpoch(aEpoch), mTexture(aTexture) {}
    wr::Epoch mEpoch;
    CompositableTextureHostRef mTexture;
  };

  struct ForwardingExternalImage {
    ForwardingExternalImage(const wr::Epoch& aEpoch,
                            const wr::ExternalImageId& aImageId)
        : mEpoch(aEpoch), mImageId(aImageId) {}
    ~ForwardingExternalImage();
    wr::Epoch mEpoch;
    wr::ExternalImageId mImageId;
  };

  struct PipelineTexturesHolder {
    // Holds forwarding WebRenderTextureHosts.
    std::vector<ForwardingTextureHost> mTextureHostsUntilRenderSubmitted;
    // TextureHosts that must be held until rendering has completed. UniquePtr
    // is used to make the entries movable, ideally ForwardingTextureHost would
    // be fully movable.
    std::vector<UniquePtr<ForwardingTextureHost>>
        mTextureHostsUntilRenderCompleted;
    std::vector<UniquePtr<ForwardingExternalImage>> mExternalImages;
    Maybe<wr::Epoch> mDestroyedEpoch;
    WebRenderBridgeParent* MOZ_NON_OWNING_REF mWrBridge = nullptr;
  };

  struct AsyncImagePipeline {
    AsyncImagePipeline(wr::PipelineId aPipelineId,
                       layers::WebRenderBackend aBackend);
    void Update(const LayoutDeviceRect& aScBounds, wr::WrRotation aRotation,
                const wr::ImageRendering& aFilter,
                const wr::MixBlendMode& aMixBlendMode) {
      mIsChanged |= !mScBounds.IsEqualEdges(aScBounds) ||
                    mRotation != aRotation || mFilter != aFilter ||
                    mMixBlendMode != aMixBlendMode;
      mScBounds = aScBounds;
      mRotation = aRotation;
      mFilter = aFilter;
      mMixBlendMode = aMixBlendMode;
    }

    bool mInitialised;
    bool mIsChanged;
    bool mUseExternalImage;
    LayoutDeviceRect mScBounds;
    wr::WrRotation mRotation;
    wr::ImageRendering mFilter;
    wr::MixBlendMode mMixBlendMode;
    RefPtr<WebRenderImageHost> mImageHost;
    CompositableTextureHostRef mCurrentTexture;
    nsTArray<wr::ImageKey> mKeys;
    wr::DisplayListBuilder mDLBuilder;
  };

  void ApplyAsyncImageForPipeline(const wr::Epoch& aEpoch,
                                  const wr::PipelineId& aPipelineId,
                                  AsyncImagePipeline* aPipeline,
                                  TextureHost* aTexture,
                                  wr::TransactionBuilder& aSceneBuilderTxn,
                                  wr::TransactionBuilder& aMaybeFastTxn);
  Maybe<TextureHost::ResourceUpdateOp> UpdateImageKeys(
      const wr::Epoch& aEpoch, const wr::PipelineId& aPipelineId,
      AsyncImagePipeline* aPipeline, TextureHost* aTexture,
      nsTArray<wr::ImageKey>& aKeys, wr::TransactionBuilder& aSceneBuilderTxn,
      wr::TransactionBuilder& aMaybeFastTxn);
  Maybe<TextureHost::ResourceUpdateOp> UpdateWithoutExternalImage(
      TextureHost* aTexture, wr::ImageKey aKey, TextureHost::ResourceUpdateOp,
      wr::TransactionBuilder& aTxn);

  void CheckForTextureHostsNotUsedByGPU();

  RefPtr<wr::WebRenderAPI> mApi;
  bool mUseCompositorWnd;
  TextureFactoryIdentifier mTextureFactoryIdentifier;

  const wr::IdNamespace mIdNamespace;
  const bool mUseTripleBuffering;
  uint32_t mResourceId;

  nsClassHashtable<nsUint64HashKey, PipelineTexturesHolder>
      mPipelineTexturesHolders;
  nsClassHashtable<nsUint64HashKey, AsyncImagePipeline> mAsyncImagePipelines;
  wr::Epoch mAsyncImageEpoch;
  bool mWillGenerateFrame;
  bool mDestroyed;

#ifdef XP_WIN
  bool mUseWebRenderDCompVideoHwOverlayWin;
  bool mUseWebRenderDCompVideoSwOverlayWin;
#endif

  // Render time for the current composition.
  TimeStamp mCompositionTime;

  // CompositionOpportunityId of the current composition.
  CompositionOpportunityId mCompositionOpportunityId;

  // When nonnull, during rendering, some compositable indicated that it will
  // change its rendering at this time. In order not to miss it, we composite
  // on every vsync until this time occurs (this is the latest such time).
  TimeStamp mCompositeUntilTime;

  nsTArray<ImageCompositeNotificationInfo> mImageCompositeNotifications;

  struct WebRenderPipelineInfoHolder {
    WebRenderPipelineInfoHolder(RefPtr<const wr::WebRenderPipelineInfo>&& aInfo,
                                ipc::FileDescriptor&& aFenceFd);
    ~WebRenderPipelineInfoHolder();
    RefPtr<const wr::WebRenderPipelineInfo> mInfo;
    ipc::FileDescriptor mFenceFd;
  };

  std::vector<std::pair<wr::RenderedFrameId, WebRenderPipelineInfoHolder>>
      mRenderSubmittedUpdates;
  Mutex mRenderSubmittedUpdatesLock MOZ_UNANNOTATED;

  Atomic<uint64_t> mLastCompletedFrameId;
  std::vector<std::pair<wr::RenderedFrameId,
                        std::vector<UniquePtr<ForwardingTextureHost>>>>
      mTexturesInUseByGPU;
  ipc::FileDescriptor mReleaseFenceFd;
};

}  // namespace layers
}  // namespace mozilla

#endif /* MOZILLA_GFX_WEBRENDERCOMPOSITABLE_HOLDER_H */