1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef MOZILLA_GFX_WEBRENDERCOMPOSITABLE_HOLDER_H
8 #define MOZILLA_GFX_WEBRENDERCOMPOSITABLE_HOLDER_H
9 
10 #include <queue>
11 
12 #include "CompositableHost.h"
13 #include "mozilla/gfx/Point.h"
14 #include "mozilla/layers/TextureHost.h"
15 #include "mozilla/Maybe.h"
16 #include "mozilla/webrender/WebRenderAPI.h"
17 #include "mozilla/webrender/WebRenderTypes.h"
18 #include "nsClassHashtable.h"
19 
20 namespace mozilla {
21 
22 namespace wr {
23 class DisplayListBuilder;
24 class WebRenderAPI;
25 }  // namespace wr
26 
27 namespace layers {
28 
29 class CompositableHost;
30 class CompositorVsyncScheduler;
31 class WebRenderImageHost;
32 class WebRenderTextureHost;
33 
34 class AsyncImagePipelineManager final {
35  public:
36   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncImagePipelineManager)
37 
38   explicit AsyncImagePipelineManager(already_AddRefed<wr::WebRenderAPI>&& aApi);
39 
40  protected:
41   ~AsyncImagePipelineManager();
42 
43  public:
44   void Destroy();
45 
46   void AddPipeline(const wr::PipelineId& aPipelineId);
47   void RemovePipeline(const wr::PipelineId& aPipelineId,
48                       const wr::Epoch& aEpoch);
49 
50   void HoldExternalImage(const wr::PipelineId& aPipelineId,
51                          const wr::Epoch& aEpoch,
52                          WebRenderTextureHost* aTexture);
53   void PipelineRendered(const wr::PipelineId& aPipelineId,
54                         const wr::Epoch& aEpoch);
55   void PipelineRemoved(const wr::PipelineId& aPipelineId);
56 
GetCompositionTime()57   TimeStamp GetCompositionTime() const { return mCompositionTime; }
SetCompositionTime(TimeStamp aTimeStamp)58   void SetCompositionTime(TimeStamp aTimeStamp) {
59     mCompositionTime = aTimeStamp;
60     if (!mCompositionTime.IsNull() && !mCompositeUntilTime.IsNull() &&
61         mCompositionTime >= mCompositeUntilTime) {
62       mCompositeUntilTime = TimeStamp();
63     }
64   }
CompositeUntil(TimeStamp aTimeStamp)65   void CompositeUntil(TimeStamp aTimeStamp) {
66     if (mCompositeUntilTime.IsNull() || mCompositeUntilTime < aTimeStamp) {
67       mCompositeUntilTime = aTimeStamp;
68     }
69   }
GetCompositeUntilTime()70   TimeStamp GetCompositeUntilTime() const { return mCompositeUntilTime; }
71 
72   void AddAsyncImagePipeline(const wr::PipelineId& aPipelineId,
73                              WebRenderImageHost* aImageHost);
74   void RemoveAsyncImagePipeline(const wr::PipelineId& aPipelineId,
75                                 wr::TransactionBuilder& aTxn);
76 
77   void UpdateAsyncImagePipeline(const wr::PipelineId& aPipelineId,
78                                 const LayoutDeviceRect& aScBounds,
79                                 const gfx::Matrix4x4& aScTransform,
80                                 const gfx::MaybeIntSize& aScaleToSize,
81                                 const wr::ImageRendering& aFilter,
82                                 const wr::MixBlendMode& aMixBlendMode);
83   void ApplyAsyncImages();
84 
AppendImageCompositeNotification(const ImageCompositeNotificationInfo & aNotification)85   void AppendImageCompositeNotification(
86       const ImageCompositeNotificationInfo& aNotification) {
87     mImageCompositeNotifications.AppendElement(aNotification);
88   }
89 
FlushImageNotifications(nsTArray<ImageCompositeNotificationInfo> * aNotifications)90   void FlushImageNotifications(
91       nsTArray<ImageCompositeNotificationInfo>* aNotifications) {
92     aNotifications->AppendElements(Move(mImageCompositeNotifications));
93   }
94 
95   void SetWillGenerateFrame();
96   bool GetAndResetWillGenerateFrame();
97 
98  private:
GetNextResourceId()99   uint32_t GetNextResourceId() { return ++mResourceId; }
GetNamespace()100   wr::IdNamespace GetNamespace() { return mIdNamespace; }
GenerateImageKey()101   wr::ImageKey GenerateImageKey() {
102     wr::ImageKey key;
103     key.mNamespace = GetNamespace();
104     key.mHandle = GetNextResourceId();
105     return key;
106   }
107 
108   struct ForwardingTextureHost {
ForwardingTextureHostForwardingTextureHost109     ForwardingTextureHost(const wr::Epoch& aEpoch, TextureHost* aTexture)
110         : mEpoch(aEpoch), mTexture(aTexture) {}
111     wr::Epoch mEpoch;
112     CompositableTextureHostRef mTexture;
113   };
114 
115   struct PipelineTexturesHolder {
116     // Holds forwarding WebRenderTextureHosts.
117     std::queue<ForwardingTextureHost> mTextureHosts;
118     Maybe<wr::Epoch> mDestroyedEpoch;
119   };
120 
121   struct AsyncImagePipeline {
122     AsyncImagePipeline();
UpdateAsyncImagePipeline123     void Update(const LayoutDeviceRect& aScBounds,
124                 const gfx::Matrix4x4& aScTransform,
125                 const gfx::MaybeIntSize& aScaleToSize,
126                 const wr::ImageRendering& aFilter,
127                 const wr::MixBlendMode& aMixBlendMode) {
128       mIsChanged |= !mScBounds.IsEqualEdges(aScBounds) ||
129                     mScTransform != aScTransform ||
130                     mScaleToSize != aScaleToSize || mFilter != aFilter ||
131                     mMixBlendMode != aMixBlendMode;
132       mScBounds = aScBounds;
133       mScTransform = aScTransform;
134       mScaleToSize = aScaleToSize;
135       mFilter = aFilter;
136       mMixBlendMode = aMixBlendMode;
137     }
138 
139     bool mInitialised;
140     bool mIsChanged;
141     bool mUseExternalImage;
142     LayoutDeviceRect mScBounds;
143     gfx::Matrix4x4 mScTransform;
144     gfx::MaybeIntSize mScaleToSize;
145     wr::ImageRendering mFilter;
146     wr::MixBlendMode mMixBlendMode;
147     RefPtr<WebRenderImageHost> mImageHost;
148     CompositableTextureHostRef mCurrentTexture;
149     nsTArray<wr::ImageKey> mKeys;
150   };
151 
152   Maybe<TextureHost::ResourceUpdateOp> UpdateImageKeys(
153       wr::TransactionBuilder& aResourceUpdates, AsyncImagePipeline* aPipeline,
154       nsTArray<wr::ImageKey>& aKeys);
155   Maybe<TextureHost::ResourceUpdateOp> UpdateWithoutExternalImage(
156       wr::TransactionBuilder& aResources, TextureHost* aTexture,
157       wr::ImageKey aKey, TextureHost::ResourceUpdateOp);
158 
159   RefPtr<wr::WebRenderAPI> mApi;
160   wr::IdNamespace mIdNamespace;
161   uint32_t mResourceId;
162 
163   nsClassHashtable<nsUint64HashKey, PipelineTexturesHolder>
164       mPipelineTexturesHolders;
165   nsClassHashtable<nsUint64HashKey, AsyncImagePipeline> mAsyncImagePipelines;
166   uint32_t mAsyncImageEpoch;
167   bool mWillGenerateFrame;
168   bool mDestroyed;
169 
170   // Render time for the current composition.
171   TimeStamp mCompositionTime;
172 
173   // When nonnull, during rendering, some compositable indicated that it will
174   // change its rendering at this time. In order not to miss it, we composite
175   // on every vsync until this time occurs (this is the latest such time).
176   TimeStamp mCompositeUntilTime;
177 
178   nsTArray<ImageCompositeNotificationInfo> mImageCompositeNotifications;
179 };
180 
181 }  // namespace layers
182 }  // namespace mozilla
183 
184 #endif /* MOZILLA_GFX_WEBRENDERCOMPOSITABLE_HOLDER_H */
185