/src/mozilla-central/gfx/layers/wr/WebRenderImageHost.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | #include "WebRenderImageHost.h" |
8 | | |
9 | | #include "LayersLogging.h" |
10 | | #include "mozilla/Move.h" |
11 | | #include "mozilla/layers/Compositor.h" // for Compositor |
12 | | #include "mozilla/layers/CompositorVsyncScheduler.h" // for CompositorVsyncScheduler |
13 | | #include "mozilla/layers/Effects.h" // for TexturedEffect, Effect, etc |
14 | | #include "mozilla/layers/LayerManagerComposite.h" // for TexturedEffect, Effect, etc |
15 | | #include "mozilla/layers/WebRenderBridgeParent.h" |
16 | | #include "mozilla/layers/AsyncImagePipelineManager.h" |
17 | | #include "nsAString.h" |
18 | | #include "nsDebug.h" // for NS_WARNING, NS_ASSERTION |
19 | | #include "nsPrintfCString.h" // for nsPrintfCString |
20 | | #include "nsString.h" // for nsAutoCString |
21 | | |
22 | | namespace mozilla { |
23 | | |
24 | | using namespace gfx; |
25 | | |
26 | | namespace layers { |
27 | | |
28 | | class ISurfaceAllocator; |
29 | | |
30 | | WebRenderImageHost::WebRenderImageHost(const TextureInfo& aTextureInfo) |
31 | | : CompositableHost(aTextureInfo) |
32 | | , ImageComposite() |
33 | | , mWrBridge(nullptr) |
34 | | , mWrBridgeBindings(0) |
35 | | , mUseAsyncImagePipeline(false) |
36 | 0 | {} |
37 | | |
38 | | WebRenderImageHost::~WebRenderImageHost() |
39 | 0 | { |
40 | 0 | MOZ_ASSERT(!mWrBridge); |
41 | 0 | } |
42 | | |
43 | | void |
44 | | WebRenderImageHost::UseTextureHost(const nsTArray<TimedTexture>& aTextures) |
45 | 0 | { |
46 | 0 | CompositableHost::UseTextureHost(aTextures); |
47 | 0 | MOZ_ASSERT(aTextures.Length() >= 1); |
48 | 0 |
|
49 | 0 | nsTArray<TimedImage> newImages; |
50 | 0 |
|
51 | 0 | for (uint32_t i = 0; i < aTextures.Length(); ++i) { |
52 | 0 | const TimedTexture& t = aTextures[i]; |
53 | 0 | MOZ_ASSERT(t.mTexture); |
54 | 0 | if (i + 1 < aTextures.Length() && |
55 | 0 | t.mProducerID == mLastProducerID && t.mFrameID < mLastFrameID) { |
56 | 0 | // Ignore frames before a frame that we already composited. We don't |
57 | 0 | // ever want to display these frames. This could be important if |
58 | 0 | // the frame producer adjusts timestamps (e.g. to track the audio clock) |
59 | 0 | // and the new frame times are earlier. |
60 | 0 | continue; |
61 | 0 | } |
62 | 0 | TimedImage& img = *newImages.AppendElement(); |
63 | 0 | img.mTextureHost = t.mTexture; |
64 | 0 | img.mTimeStamp = t.mTimeStamp; |
65 | 0 | img.mPictureRect = t.mPictureRect; |
66 | 0 | img.mFrameID = t.mFrameID; |
67 | 0 | img.mProducerID = t.mProducerID; |
68 | 0 | img.mTextureHost->SetCropRect(img.mPictureRect); |
69 | 0 | img.mTextureHost->Updated(); |
70 | 0 | } |
71 | 0 |
|
72 | 0 | SetImages(std::move(newImages)); |
73 | 0 |
|
74 | 0 | if (mWrBridge && mWrBridge->CompositorScheduler() && GetAsyncRef()) { |
75 | 0 | // Will check if we will generate frame. |
76 | 0 | mWrBridge->CompositorScheduler()->ScheduleComposition(); |
77 | 0 | } |
78 | 0 |
|
79 | 0 | // Video producers generally send replacement images with the same frameID but |
80 | 0 | // slightly different timestamps in order to sync with the audio clock. This |
81 | 0 | // means that any CompositeUntil() call we made in Composite() may no longer |
82 | 0 | // guarantee that we'll composite until the next frame is ready. Fix that here. |
83 | 0 | if (mWrBridge && mLastFrameID >= 0) { |
84 | 0 | MOZ_ASSERT(mWrBridge->AsyncImageManager()); |
85 | 0 | for (const auto& img : Images()) { |
86 | 0 | bool frameComesAfter = |
87 | 0 | img.mFrameID > mLastFrameID || img.mProducerID != mLastProducerID; |
88 | 0 | if (frameComesAfter && !img.mTimeStamp.IsNull()) { |
89 | 0 | mWrBridge->AsyncImageManager()->CompositeUntil( |
90 | 0 | img.mTimeStamp + TimeDuration::FromMilliseconds(BIAS_TIME_MS)); |
91 | 0 | break; |
92 | 0 | } |
93 | 0 | } |
94 | 0 | } |
95 | 0 | } |
96 | | |
97 | | void |
98 | | WebRenderImageHost::UseComponentAlphaTextures(TextureHost* aTextureOnBlack, |
99 | | TextureHost* aTextureOnWhite) |
100 | 0 | { |
101 | 0 | MOZ_ASSERT_UNREACHABLE("unexpected to be called"); |
102 | 0 | } |
103 | | |
104 | | void |
105 | | WebRenderImageHost::CleanupResources() |
106 | 0 | { |
107 | 0 | ClearImages(); |
108 | 0 | SetCurrentTextureHost(nullptr); |
109 | 0 | } |
110 | | |
111 | | void |
112 | | WebRenderImageHost::RemoveTextureHost(TextureHost* aTexture) |
113 | 0 | { |
114 | 0 | CompositableHost::RemoveTextureHost(aTexture); |
115 | 0 | RemoveImagesWithTextureHost(aTexture); |
116 | 0 | } |
117 | | |
118 | | TimeStamp |
119 | | WebRenderImageHost::GetCompositionTime() const |
120 | 0 | { |
121 | 0 | TimeStamp time; |
122 | 0 | if (mWrBridge) { |
123 | 0 | MOZ_ASSERT(mWrBridge->AsyncImageManager()); |
124 | 0 | time = mWrBridge->AsyncImageManager()->GetCompositionTime(); |
125 | 0 | } |
126 | 0 | return time; |
127 | 0 | } |
128 | | |
129 | | TextureHost* |
130 | | WebRenderImageHost::GetAsTextureHost(IntRect* aPictureRect) |
131 | 0 | { |
132 | 0 | const TimedImage* img = ChooseImage(); |
133 | 0 | if (img) { |
134 | 0 | return img->mTextureHost; |
135 | 0 | } |
136 | 0 | return nullptr; |
137 | 0 | } |
138 | | |
139 | | TextureHost* |
140 | | WebRenderImageHost::GetAsTextureHostForComposite() |
141 | 0 | { |
142 | 0 | if (!mWrBridge) { |
143 | 0 | return nullptr; |
144 | 0 | } |
145 | 0 | |
146 | 0 | int imageIndex = ChooseImageIndex(); |
147 | 0 | if (imageIndex < 0) { |
148 | 0 | SetCurrentTextureHost(nullptr); |
149 | 0 | return nullptr; |
150 | 0 | } |
151 | 0 | |
152 | 0 | if (uint32_t(imageIndex) + 1 < ImagesCount()) { |
153 | 0 | MOZ_ASSERT(mWrBridge->AsyncImageManager()); |
154 | 0 | mWrBridge->AsyncImageManager()->CompositeUntil( |
155 | 0 | GetImage(imageIndex + 1)->mTimeStamp + |
156 | 0 | TimeDuration::FromMilliseconds(BIAS_TIME_MS)); |
157 | 0 | } |
158 | 0 |
|
159 | 0 | const TimedImage* img = GetImage(imageIndex); |
160 | 0 |
|
161 | 0 | if (mLastFrameID != img->mFrameID || mLastProducerID != img->mProducerID) { |
162 | 0 | if (mAsyncRef) { |
163 | 0 | ImageCompositeNotificationInfo info; |
164 | 0 | info.mImageBridgeProcessId = mAsyncRef.mProcessId; |
165 | 0 | info.mNotification = ImageCompositeNotification( |
166 | 0 | mAsyncRef.mHandle, |
167 | 0 | img->mTimeStamp, mWrBridge->AsyncImageManager()->GetCompositionTime(), |
168 | 0 | img->mFrameID, img->mProducerID); |
169 | 0 | mWrBridge->AsyncImageManager()->AppendImageCompositeNotification(info); |
170 | 0 | } |
171 | 0 | mLastFrameID = img->mFrameID; |
172 | 0 | mLastProducerID = img->mProducerID; |
173 | 0 | } |
174 | 0 | SetCurrentTextureHost(img->mTextureHost); |
175 | 0 |
|
176 | 0 | UpdateBias(imageIndex); |
177 | 0 |
|
178 | 0 | return mCurrentTextureHost; |
179 | 0 | } |
180 | | |
181 | | void |
182 | | WebRenderImageHost::SetCurrentTextureHost(TextureHost* aTexture) |
183 | 0 | { |
184 | 0 | if (aTexture == mCurrentTextureHost.get()) { |
185 | 0 | return; |
186 | 0 | } |
187 | 0 | |
188 | 0 | mCurrentTextureHost = aTexture; |
189 | 0 | } |
190 | | |
191 | | void WebRenderImageHost::Attach(Layer* aLayer, |
192 | | TextureSourceProvider* aProvider, |
193 | | AttachFlags aFlags) |
194 | 0 | { |
195 | 0 | } |
196 | | |
197 | | void |
198 | | WebRenderImageHost::Composite(Compositor* aCompositor, |
199 | | LayerComposite* aLayer, |
200 | | EffectChain& aEffectChain, |
201 | | float aOpacity, |
202 | | const gfx::Matrix4x4& aTransform, |
203 | | const gfx::SamplingFilter aSamplingFilter, |
204 | | const gfx::IntRect& aClipRect, |
205 | | const nsIntRegion* aVisibleRegion, |
206 | | const Maybe<gfx::Polygon>& aGeometry) |
207 | 0 | { |
208 | 0 | MOZ_ASSERT_UNREACHABLE("unexpected to be called"); |
209 | 0 | } |
210 | | |
211 | | void |
212 | | WebRenderImageHost::SetTextureSourceProvider(TextureSourceProvider* aProvider) |
213 | 0 | { |
214 | 0 | if (mTextureSourceProvider != aProvider) { |
215 | 0 | for (const auto& img : Images()) { |
216 | 0 | img.mTextureHost->SetTextureSourceProvider(aProvider); |
217 | 0 | } |
218 | 0 | } |
219 | 0 | CompositableHost::SetTextureSourceProvider(aProvider); |
220 | 0 | } |
221 | | |
222 | | void |
223 | | WebRenderImageHost::PrintInfo(std::stringstream& aStream, const char* aPrefix) |
224 | 0 | { |
225 | 0 | aStream << aPrefix; |
226 | 0 | aStream << nsPrintfCString("WebRenderImageHost (0x%p)", this).get(); |
227 | 0 |
|
228 | 0 | nsAutoCString pfx(aPrefix); |
229 | 0 | pfx += " "; |
230 | 0 | for (const auto& img : Images()) { |
231 | 0 | aStream << "\n"; |
232 | 0 | img.mTextureHost->PrintInfo(aStream, pfx.get()); |
233 | 0 | AppendToString(aStream, img.mPictureRect, " [picture-rect=", "]"); |
234 | 0 | } |
235 | 0 | } |
236 | | |
237 | | void |
238 | | WebRenderImageHost::Dump(std::stringstream& aStream, |
239 | | const char* aPrefix, |
240 | | bool aDumpHtml) |
241 | 0 | { |
242 | 0 | for (const auto& img : Images()) { |
243 | 0 | aStream << aPrefix; |
244 | 0 | aStream << (aDumpHtml ? "<ul><li>TextureHost: " |
245 | 0 | : "TextureHost: "); |
246 | 0 | DumpTextureHost(aStream, img.mTextureHost); |
247 | 0 | aStream << (aDumpHtml ? " </li></ul> " : " "); |
248 | 0 | } |
249 | 0 | } |
250 | | |
251 | | already_AddRefed<gfx::DataSourceSurface> |
252 | | WebRenderImageHost::GetAsSurface() |
253 | 0 | { |
254 | 0 | const TimedImage* img = ChooseImage(); |
255 | 0 | if (img) { |
256 | 0 | return img->mTextureHost->GetAsSurface(); |
257 | 0 | } |
258 | 0 | return nullptr; |
259 | 0 | } |
260 | | |
261 | | bool |
262 | | WebRenderImageHost::Lock() |
263 | 0 | { |
264 | 0 | MOZ_ASSERT_UNREACHABLE("unexpected to be called"); |
265 | 0 | return false; |
266 | 0 | } |
267 | | |
268 | | void |
269 | | WebRenderImageHost::Unlock() |
270 | 0 | { |
271 | 0 | MOZ_ASSERT_UNREACHABLE("unexpected to be called"); |
272 | 0 | } |
273 | | |
274 | | IntSize |
275 | | WebRenderImageHost::GetImageSize() |
276 | 0 | { |
277 | 0 | const TimedImage* img = ChooseImage(); |
278 | 0 | if (img) { |
279 | 0 | return IntSize(img->mPictureRect.Width(), img->mPictureRect.Height()); |
280 | 0 | } |
281 | 0 | return IntSize(); |
282 | 0 | } |
283 | | |
284 | | void |
285 | | WebRenderImageHost::SetWrBridge(WebRenderBridgeParent* aWrBridge) |
286 | 0 | { |
287 | 0 | // For image hosts created through ImageBridgeParent, there may be multiple |
288 | 0 | // references to it due to the order of creation and freeing of layers by |
289 | 0 | // the layer tree. However this should be limited to things such as video |
290 | 0 | // which will not be reused across different WebRenderBridgeParent objects. |
291 | 0 | MOZ_ASSERT(aWrBridge); |
292 | 0 | MOZ_ASSERT(!mWrBridge || mWrBridge == aWrBridge); |
293 | 0 | mWrBridge = aWrBridge; |
294 | 0 | ++mWrBridgeBindings; |
295 | 0 | } |
296 | | |
297 | | void |
298 | | WebRenderImageHost::ClearWrBridge() |
299 | 0 | { |
300 | 0 | MOZ_ASSERT(mWrBridgeBindings > 0); |
301 | 0 | --mWrBridgeBindings; |
302 | 0 | if (mWrBridgeBindings == 0) { |
303 | 0 | SetCurrentTextureHost(nullptr); |
304 | 0 | mWrBridge = nullptr; |
305 | 0 | } |
306 | 0 | } |
307 | | |
308 | | } // namespace layers |
309 | | } // namespace mozilla |