Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set sw=4 ts=8 et 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 "mozilla/layers/WebRenderBridgeParent.h"
8 :
9 : #include "apz/src/AsyncPanZoomController.h"
10 : #include "CompositableHost.h"
11 : #include "gfxPrefs.h"
12 : #include "GeckoProfiler.h"
13 : #include "GLContext.h"
14 : #include "GLContextProvider.h"
15 : #include "mozilla/Range.h"
16 : #include "mozilla/layers/AnimationHelper.h"
17 : #include "mozilla/layers/APZCTreeManager.h"
18 : #include "mozilla/layers/Compositor.h"
19 : #include "mozilla/layers/CompositorBridgeParent.h"
20 : #include "mozilla/layers/CompositorThread.h"
21 : #include "mozilla/layers/CompositorVsyncScheduler.h"
22 : #include "mozilla/layers/ImageBridgeParent.h"
23 : #include "mozilla/layers/ImageDataSerializer.h"
24 : #include "mozilla/layers/TextureHost.h"
25 : #include "mozilla/layers/WebRenderCompositableHolder.h"
26 : #include "mozilla/layers/WebRenderImageHost.h"
27 : #include "mozilla/layers/WebRenderTextureHost.h"
28 : #include "mozilla/TimeStamp.h"
29 : #include "mozilla/Unused.h"
30 : #include "mozilla/webrender/RenderThread.h"
31 : #include "mozilla/widget/CompositorWidget.h"
32 :
33 0 : bool is_in_main_thread()
34 : {
35 0 : return NS_IsMainThread();
36 : }
37 :
38 0 : bool is_in_compositor_thread()
39 : {
40 0 : return mozilla::layers::CompositorThreadHolder::IsInCompositorThread();
41 : }
42 :
43 0 : bool is_in_render_thread()
44 : {
45 0 : return mozilla::wr::RenderThread::IsInRenderThread();
46 : }
47 :
48 0 : bool is_glcontext_egl(void* glcontext_ptr)
49 : {
50 0 : MOZ_ASSERT(glcontext_ptr);
51 :
52 0 : mozilla::gl::GLContext* glcontext = reinterpret_cast<mozilla::gl::GLContext*>(glcontext_ptr);
53 0 : if (!glcontext) {
54 0 : return false;
55 : }
56 0 : return glcontext->GetContextType() == mozilla::gl::GLContextType::EGL;
57 : }
58 :
59 0 : void gfx_critical_note(const char* msg)
60 : {
61 0 : gfxCriticalNote << msg;
62 0 : }
63 :
64 0 : void* get_proc_address_from_glcontext(void* glcontext_ptr, const char* procname)
65 : {
66 0 : MOZ_ASSERT(glcontext_ptr);
67 :
68 0 : mozilla::gl::GLContext* glcontext = reinterpret_cast<mozilla::gl::GLContext*>(glcontext_ptr);
69 0 : if (!glcontext) {
70 0 : return nullptr;
71 : }
72 0 : PRFuncPtr p = glcontext->LookupSymbol(procname);
73 0 : return reinterpret_cast<void*>(p);
74 : }
75 :
76 : namespace mozilla {
77 : namespace layers {
78 :
79 : using namespace mozilla::gfx;
80 :
81 : class MOZ_STACK_CLASS AutoWebRenderBridgeParentAsyncMessageSender
82 : {
83 : public:
84 0 : explicit AutoWebRenderBridgeParentAsyncMessageSender(WebRenderBridgeParent* aWebRenderBridgeParent,
85 : InfallibleTArray<OpDestroy>* aDestroyActors = nullptr)
86 0 : : mWebRenderBridgeParent(aWebRenderBridgeParent)
87 0 : , mActorsToDestroy(aDestroyActors)
88 : {
89 0 : mWebRenderBridgeParent->SetAboutToSendAsyncMessages();
90 0 : }
91 :
92 0 : ~AutoWebRenderBridgeParentAsyncMessageSender()
93 0 : {
94 0 : mWebRenderBridgeParent->SendPendingAsyncMessages();
95 0 : if (mActorsToDestroy) {
96 : // Destroy the actors after sending the async messages because the latter may contain
97 : // references to some actors.
98 0 : for (const auto& op : *mActorsToDestroy) {
99 0 : mWebRenderBridgeParent->DestroyActor(op);
100 : }
101 : }
102 0 : }
103 : private:
104 : WebRenderBridgeParent* mWebRenderBridgeParent;
105 : InfallibleTArray<OpDestroy>* mActorsToDestroy;
106 : };
107 :
108 : /* static */ uint32_t WebRenderBridgeParent::sIdNameSpace = 0;
109 :
110 0 : WebRenderBridgeParent::WebRenderBridgeParent(CompositorBridgeParentBase* aCompositorBridge,
111 : const wr::PipelineId& aPipelineId,
112 : widget::CompositorWidget* aWidget,
113 : CompositorVsyncScheduler* aScheduler,
114 : RefPtr<wr::WebRenderAPI>&& aApi,
115 : RefPtr<WebRenderCompositableHolder>&& aHolder,
116 0 : RefPtr<CompositorAnimationStorage>&& aAnimStorage)
117 : : mCompositorBridge(aCompositorBridge)
118 : , mPipelineId(aPipelineId)
119 : , mWidget(aWidget)
120 : , mApi(aApi)
121 : , mCompositableHolder(aHolder)
122 : , mCompositorScheduler(aScheduler)
123 : , mAnimStorage(aAnimStorage)
124 : , mChildLayerObserverEpoch(0)
125 : , mParentLayerObserverEpoch(0)
126 : , mWrEpoch(0)
127 0 : , mIdNameSpace(AllocIdNameSpace())
128 : , mPaused(false)
129 : , mDestroyed(false)
130 0 : , mForceRendering(false)
131 : {
132 0 : MOZ_ASSERT(mCompositableHolder);
133 0 : MOZ_ASSERT(mAnimStorage);
134 0 : mCompositableHolder->AddPipeline(mPipelineId);
135 0 : if (mWidget) {
136 0 : MOZ_ASSERT(!mCompositorScheduler);
137 0 : mCompositorScheduler = new CompositorVsyncScheduler(this, mWidget);
138 : }
139 0 : }
140 :
141 0 : WebRenderBridgeParent::WebRenderBridgeParent()
142 : : mCompositorBridge(nullptr)
143 : , mChildLayerObserverEpoch(0)
144 : , mParentLayerObserverEpoch(0)
145 : , mWrEpoch(0)
146 0 : , mIdNameSpace(AllocIdNameSpace())
147 : , mPaused(false)
148 : , mDestroyed(true)
149 0 : , mForceRendering(false)
150 : {
151 0 : }
152 :
153 : /* static */ WebRenderBridgeParent*
154 0 : WebRenderBridgeParent::CeateDestroyed()
155 : {
156 0 : return new WebRenderBridgeParent();
157 : }
158 :
159 0 : WebRenderBridgeParent::~WebRenderBridgeParent()
160 : {
161 0 : }
162 :
163 : mozilla::ipc::IPCResult
164 0 : WebRenderBridgeParent::RecvCreate(const gfx::IntSize& aSize)
165 : {
166 0 : if (mDestroyed) {
167 0 : return IPC_OK();
168 : }
169 :
170 0 : MOZ_ASSERT(mApi);
171 :
172 : #ifdef MOZ_WIDGET_ANDROID
173 : // XXX temporary hack.
174 : // XXX Remove it when APZ is supported.
175 : // XXX Broken by Dynamic Toolbar v3. See: Bug 1335895
176 : // RefPtr<UiCompositorControllerParent> uiController = UiCompositorControllerParent::GetFromRootLayerTreeId(/* Root Layer Tree ID */);
177 : // if (uiController) {
178 : // uiController->ToolbarAnimatorMessageFromCompositor(/*FIRST_PAINT*/ 5);
179 : // }
180 : #endif
181 :
182 0 : return IPC_OK();
183 : }
184 :
185 : mozilla::ipc::IPCResult
186 0 : WebRenderBridgeParent::RecvShutdown()
187 : {
188 0 : return HandleShutdown();
189 : }
190 :
191 : mozilla::ipc::IPCResult
192 0 : WebRenderBridgeParent::RecvShutdownSync()
193 : {
194 0 : return HandleShutdown();
195 : }
196 :
197 : mozilla::ipc::IPCResult
198 0 : WebRenderBridgeParent::HandleShutdown()
199 : {
200 0 : Destroy();
201 0 : IProtocol* mgr = Manager();
202 0 : if (!Send__delete__(this)) {
203 0 : return IPC_FAIL_NO_REASON(mgr);
204 : }
205 0 : return IPC_OK();
206 : }
207 :
208 : void
209 0 : WebRenderBridgeParent::Destroy()
210 : {
211 0 : if (mDestroyed) {
212 0 : return;
213 : }
214 0 : mDestroyed = true;
215 0 : ClearResources();
216 : }
217 :
218 : mozilla::ipc::IPCResult
219 0 : WebRenderBridgeParent::RecvAddImage(const wr::ImageKey& aImageKey,
220 : const gfx::IntSize& aSize,
221 : const uint32_t& aStride,
222 : const gfx::SurfaceFormat& aFormat,
223 : const ByteBuffer& aBuffer)
224 : {
225 0 : if (mDestroyed) {
226 0 : return IPC_OK();
227 : }
228 :
229 : // Check if key is obsoleted.
230 0 : if (aImageKey.mNamespace != mIdNameSpace) {
231 0 : return IPC_OK();
232 : }
233 :
234 0 : MOZ_ASSERT(mApi);
235 0 : MOZ_ASSERT(mActiveImageKeys.find(wr::AsUint64(aImageKey)) == mActiveImageKeys.end());
236 :
237 0 : wr::ImageDescriptor descriptor(aSize, aStride, aFormat);
238 0 : mActiveImageKeys.insert(wr::AsUint64(aImageKey));
239 0 : mApi->AddImage(aImageKey, descriptor,
240 0 : aBuffer.AsSlice());
241 :
242 0 : return IPC_OK();
243 : }
244 :
245 : mozilla::ipc::IPCResult
246 0 : WebRenderBridgeParent::RecvAddBlobImage(const wr::ImageKey& aImageKey,
247 : const gfx::IntSize& aSize,
248 : const uint32_t& aStride,
249 : const gfx::SurfaceFormat& aFormat,
250 : const ByteBuffer& aBuffer)
251 : {
252 0 : if (mDestroyed) {
253 0 : return IPC_OK();
254 : }
255 :
256 : // Check if key is obsoleted.
257 0 : if (aImageKey.mNamespace != mIdNameSpace) {
258 0 : return IPC_OK();
259 : }
260 :
261 0 : MOZ_ASSERT(mApi);
262 0 : MOZ_ASSERT(mActiveImageKeys.find(wr::AsUint64(aImageKey)) == mActiveImageKeys.end());
263 :
264 0 : wr::ImageDescriptor descriptor(aSize, aStride, aFormat);
265 0 : mActiveImageKeys.insert(wr::AsUint64(aImageKey));
266 0 : mApi->AddBlobImage(aImageKey, descriptor,
267 0 : aBuffer.AsSlice());
268 :
269 0 : return IPC_OK();
270 : }
271 :
272 : mozilla::ipc::IPCResult
273 0 : WebRenderBridgeParent::RecvAddRawFont(const wr::FontKey& aFontKey,
274 : const ByteBuffer& aBuffer,
275 : const uint32_t& aFontIndex)
276 : {
277 0 : if (mDestroyed) {
278 0 : return IPC_OK();
279 : }
280 :
281 : // Check if key is obsoleted.
282 0 : if (aFontKey.mNamespace != mIdNameSpace) {
283 0 : return IPC_OK();
284 : }
285 :
286 0 : MOZ_ASSERT(mApi);
287 0 : MOZ_ASSERT(mFontKeys.find(wr::AsUint64(aFontKey)) == mFontKeys.end());
288 :
289 0 : auto slice = aBuffer.AsSlice();
290 0 : mFontKeys.insert(wr::AsUint64(aFontKey));
291 0 : mApi->AddRawFont(aFontKey, slice, aFontIndex);
292 :
293 0 : return IPC_OK();
294 : }
295 :
296 : mozilla::ipc::IPCResult
297 0 : WebRenderBridgeParent::RecvDeleteFont(const wr::FontKey& aFontKey)
298 : {
299 0 : if (mDestroyed) {
300 0 : return IPC_OK();
301 : }
302 0 : MOZ_ASSERT(mApi);
303 :
304 : // Check if key is obsoleted.
305 0 : if (aFontKey.mNamespace != mIdNameSpace) {
306 0 : return IPC_OK();
307 : }
308 :
309 0 : if (mFontKeys.find(wr::AsUint64(aFontKey)) != mFontKeys.end()) {
310 0 : mFontKeys.erase(wr::AsUint64(aFontKey));
311 0 : mApi->DeleteFont(aFontKey);
312 : } else {
313 0 : MOZ_ASSERT_UNREACHABLE("invalid FontKey");
314 : }
315 :
316 0 : return IPC_OK();
317 : }
318 :
319 : mozilla::ipc::IPCResult
320 0 : WebRenderBridgeParent::RecvUpdateImage(const wr::ImageKey& aImageKey,
321 : const gfx::IntSize& aSize,
322 : const gfx::SurfaceFormat& aFormat,
323 : const ByteBuffer& aBuffer)
324 : {
325 0 : if (mDestroyed) {
326 0 : return IPC_OK();
327 : }
328 0 : MOZ_ASSERT(mApi);
329 :
330 : // Check if key is obsoleted.
331 0 : if (aImageKey.mNamespace != mIdNameSpace) {
332 0 : return IPC_OK();
333 : }
334 :
335 0 : wr::ImageDescriptor descriptor(aSize, aFormat);
336 0 : mApi->UpdateImageBuffer(aImageKey, descriptor, aBuffer.AsSlice());
337 :
338 0 : return IPC_OK();
339 : }
340 :
341 : mozilla::ipc::IPCResult
342 0 : WebRenderBridgeParent::RecvDeleteImage(const wr::ImageKey& aImageKey)
343 : {
344 0 : if (mDestroyed) {
345 0 : return IPC_OK();
346 : }
347 0 : MOZ_ASSERT(mApi);
348 :
349 : // Check if key is obsoleted.
350 0 : if (aImageKey.mNamespace != mIdNameSpace) {
351 0 : return IPC_OK();
352 : }
353 :
354 0 : if (mActiveImageKeys.find(wr::AsUint64(aImageKey)) != mActiveImageKeys.end()) {
355 0 : mActiveImageKeys.erase(wr::AsUint64(aImageKey));
356 0 : mKeysToDelete.push_back(aImageKey);
357 : } else {
358 0 : MOZ_ASSERT_UNREACHABLE("invalid ImageKey");
359 : }
360 0 : return IPC_OK();
361 : }
362 :
363 : mozilla::ipc::IPCResult
364 0 : WebRenderBridgeParent::RecvDeleteCompositorAnimations(InfallibleTArray<uint64_t>&& aIds)
365 : {
366 0 : if (mDestroyed) {
367 0 : return IPC_OK();
368 : }
369 :
370 0 : for (uint32_t i = 0; i < aIds.Length(); i++) {
371 0 : if (mActiveAnimations.find(aIds[i]) != mActiveAnimations.end()) {
372 0 : mAnimStorage->ClearById(aIds[i]);
373 0 : mActiveAnimations.erase(aIds[i]);
374 : } else {
375 0 : NS_ERROR("Tried to delete invalid animation");
376 : }
377 : }
378 :
379 0 : return IPC_OK();
380 : }
381 :
382 :
383 : mozilla::ipc::IPCResult
384 0 : WebRenderBridgeParent::RecvDPBegin(const gfx::IntSize& aSize)
385 : {
386 0 : if (mDestroyed) {
387 0 : return IPC_OK();
388 : }
389 0 : return IPC_OK();
390 : }
391 :
392 : void
393 0 : WebRenderBridgeParent::HandleDPEnd(const gfx::IntSize& aSize,
394 : InfallibleTArray<WebRenderParentCommand>&& aCommands,
395 : InfallibleTArray<OpDestroy>&& aToDestroy,
396 : const uint64_t& aFwdTransactionId,
397 : const uint64_t& aTransactionId,
398 : const WrSize& aContentSize,
399 : const ByteBuffer& dl,
400 : const WrBuiltDisplayListDescriptor& dlDesc,
401 : const WebRenderScrollData& aScrollData,
402 : const uint32_t& aIdNameSpace)
403 : {
404 0 : AutoProfilerTracing tracing("Paint", "DPTransaction");
405 0 : UpdateFwdTransactionId(aFwdTransactionId);
406 0 : AutoClearReadLocks clearLocks(mReadLocks);
407 :
408 0 : if (mDestroyed) {
409 0 : for (const auto& op : aToDestroy) {
410 0 : DestroyActor(op);
411 : }
412 0 : return;
413 : }
414 : // This ensures that destroy operations are always processed. It is not safe
415 : // to early-return from RecvDPEnd without doing so.
416 0 : AutoWebRenderBridgeParentAsyncMessageSender autoAsyncMessageSender(this, &aToDestroy);
417 :
418 0 : ++mWrEpoch; // Update webrender epoch
419 0 : ProcessWebRenderCommands(aSize, aCommands, wr::NewEpoch(mWrEpoch),
420 0 : aContentSize, dl, dlDesc, aIdNameSpace);
421 0 : HoldPendingTransactionId(mWrEpoch, aTransactionId);
422 :
423 0 : mScrollData = aScrollData;
424 0 : UpdateAPZ();
425 :
426 0 : if (mIdNameSpace != aIdNameSpace) {
427 : // Pretend we composited since someone is wating for this event,
428 : // though DisplayList was not pushed to webrender.
429 0 : TimeStamp now = TimeStamp::Now();
430 0 : mCompositorBridge->DidComposite(wr::AsUint64(mPipelineId), now, now);
431 : }
432 : }
433 :
434 : CompositorBridgeParent*
435 0 : WebRenderBridgeParent::GetRootCompositorBridgeParent() const
436 : {
437 0 : if (!mCompositorBridge) {
438 0 : return nullptr;
439 : }
440 :
441 0 : if (mWidget) {
442 : // This WebRenderBridgeParent is attached to the root
443 : // CompositorBridgeParent.
444 0 : return static_cast<CompositorBridgeParent*>(mCompositorBridge);
445 : }
446 :
447 : // Otherwise, this WebRenderBridgeParent is attached to a
448 : // CrossProcessCompositorBridgeParent so we have an extra level of
449 : // indirection to unravel.
450 : CompositorBridgeParent::LayerTreeState* lts =
451 0 : CompositorBridgeParent::GetIndirectShadowTree(GetLayersId());
452 0 : MOZ_ASSERT(lts);
453 0 : return lts->mParent;
454 : }
455 :
456 : void
457 0 : WebRenderBridgeParent::UpdateAPZ()
458 : {
459 0 : CompositorBridgeParent* cbp = GetRootCompositorBridgeParent();
460 0 : if (!cbp) {
461 0 : return;
462 : }
463 0 : uint64_t rootLayersId = cbp->RootLayerTreeId();
464 0 : RefPtr<WebRenderBridgeParent> rootWrbp = cbp->GetWebRenderBridgeParent();
465 0 : if (!rootWrbp) {
466 0 : return;
467 : }
468 0 : if (RefPtr<APZCTreeManager> apzc = cbp->GetAPZCTreeManager()) {
469 0 : apzc->UpdateFocusState(rootLayersId, GetLayersId(),
470 0 : mScrollData.GetFocusTarget());
471 0 : apzc->UpdateHitTestingTree(rootLayersId, rootWrbp->GetScrollData(),
472 0 : mScrollData.IsFirstPaint(), GetLayersId(),
473 0 : mScrollData.GetPaintSequenceNumber());
474 : }
475 : }
476 :
477 : bool
478 0 : WebRenderBridgeParent::PushAPZStateToWR(nsTArray<WrTransformProperty>& aTransformArray)
479 : {
480 0 : CompositorBridgeParent* cbp = GetRootCompositorBridgeParent();
481 0 : if (!cbp) {
482 0 : return false;
483 : }
484 0 : if (RefPtr<APZCTreeManager> apzc = cbp->GetAPZCTreeManager()) {
485 0 : TimeStamp animationTime = cbp->GetTestingTimeStamp().valueOr(
486 0 : mCompositorScheduler->GetLastComposeTime());
487 0 : TimeDuration frameInterval = cbp->GetVsyncInterval();
488 : // As with the non-webrender codepath in AsyncCompositionManager, we want to
489 : // use the timestamp for the next vsync when advancing animations.
490 0 : if (frameInterval != TimeDuration::Forever()) {
491 0 : animationTime += frameInterval;
492 : }
493 0 : return apzc->PushStateToWR(mApi, animationTime, aTransformArray);
494 : }
495 0 : return false;
496 : }
497 :
498 : const WebRenderScrollData&
499 0 : WebRenderBridgeParent::GetScrollData() const
500 : {
501 0 : MOZ_ASSERT(mozilla::layers::CompositorThreadHolder::IsInCompositorThread());
502 0 : return mScrollData;
503 : }
504 :
505 : mozilla::ipc::IPCResult
506 0 : WebRenderBridgeParent::RecvDPEnd(const gfx::IntSize& aSize,
507 : InfallibleTArray<WebRenderParentCommand>&& aCommands,
508 : InfallibleTArray<OpDestroy>&& aToDestroy,
509 : const uint64_t& aFwdTransactionId,
510 : const uint64_t& aTransactionId,
511 : const WrSize& aContentSize,
512 : const ByteBuffer& dl,
513 : const WrBuiltDisplayListDescriptor& dlDesc,
514 : const WebRenderScrollData& aScrollData,
515 : const uint32_t& aIdNameSpace)
516 : {
517 0 : if (mDestroyed) {
518 0 : return IPC_OK();
519 : }
520 0 : HandleDPEnd(aSize, Move(aCommands), Move(aToDestroy), aFwdTransactionId, aTransactionId,
521 0 : aContentSize, dl, dlDesc, aScrollData, aIdNameSpace);
522 0 : return IPC_OK();
523 : }
524 :
525 : mozilla::ipc::IPCResult
526 0 : WebRenderBridgeParent::RecvDPSyncEnd(const gfx::IntSize &aSize,
527 : InfallibleTArray<WebRenderParentCommand>&& aCommands,
528 : InfallibleTArray<OpDestroy>&& aToDestroy,
529 : const uint64_t& aFwdTransactionId,
530 : const uint64_t& aTransactionId,
531 : const WrSize& aContentSize,
532 : const ByteBuffer& dl,
533 : const WrBuiltDisplayListDescriptor& dlDesc,
534 : const WebRenderScrollData& aScrollData,
535 : const uint32_t& aIdNameSpace)
536 : {
537 0 : if (mDestroyed) {
538 0 : return IPC_OK();
539 : }
540 0 : HandleDPEnd(aSize, Move(aCommands), Move(aToDestroy), aFwdTransactionId, aTransactionId,
541 0 : aContentSize, dl, dlDesc, aScrollData, aIdNameSpace);
542 0 : return IPC_OK();
543 : }
544 :
545 : mozilla::ipc::IPCResult
546 0 : WebRenderBridgeParent::RecvParentCommands(nsTArray<WebRenderParentCommand>&& aCommands)
547 : {
548 0 : if (mDestroyed) {
549 0 : return IPC_OK();
550 : }
551 0 : ProcessWebRenderParentCommands(aCommands);
552 0 : return IPC_OK();
553 : }
554 :
555 : void
556 0 : WebRenderBridgeParent::ProcessWebRenderParentCommands(InfallibleTArray<WebRenderParentCommand>& aCommands)
557 : {
558 0 : for (InfallibleTArray<WebRenderParentCommand>::index_type i = 0; i < aCommands.Length(); ++i) {
559 0 : const WebRenderParentCommand& cmd = aCommands[i];
560 0 : switch (cmd.type()) {
561 : case WebRenderParentCommand::TOpAddExternalImage: {
562 0 : const OpAddExternalImage& op = cmd.get_OpAddExternalImage();
563 0 : Range<const wr::ImageKey> keys(&op.key(), 1);
564 : // Check if key is obsoleted.
565 0 : if (keys[0].mNamespace != mIdNameSpace) {
566 0 : break;
567 : }
568 0 : MOZ_ASSERT(mExternalImageIds.Get(wr::AsUint64(op.externalImageId())).get());
569 0 : MOZ_ASSERT(mActiveImageKeys.find(wr::AsUint64(keys[0])) == mActiveImageKeys.end());
570 0 : mActiveImageKeys.insert(wr::AsUint64(keys[0]));
571 :
572 0 : RefPtr<WebRenderImageHost> host = mExternalImageIds.Get(wr::AsUint64(op.externalImageId()));
573 0 : if (!host) {
574 0 : NS_ERROR("CompositableHost does not exist");
575 0 : break;
576 : }
577 0 : TextureHost* texture = host->GetAsTextureHostForComposite();
578 0 : if (!texture) {
579 0 : NS_ERROR("TextureHost does not exist");
580 0 : break;
581 : }
582 0 : WebRenderTextureHost* wrTexture = texture->AsWebRenderTextureHost();
583 0 : if (wrTexture) {
584 0 : wrTexture->AddWRImage(mApi, keys, wrTexture->GetExternalImageKey());
585 0 : break;
586 : }
587 0 : RefPtr<DataSourceSurface> dSurf = host->GetAsSurface();
588 0 : if (!dSurf) {
589 0 : NS_ERROR("TextureHost does not return DataSourceSurface");
590 0 : break;
591 : }
592 :
593 : DataSourceSurface::MappedSurface map;
594 0 : if (!dSurf->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
595 0 : NS_ERROR("DataSourceSurface failed to map");
596 0 : break;
597 : }
598 :
599 0 : IntSize size = dSurf->GetSize();
600 0 : wr::ImageDescriptor descriptor(size, map.mStride, dSurf->GetFormat());
601 0 : auto slice = Range<uint8_t>(map.mData, size.height * map.mStride);
602 0 : mApi->AddImage(keys[0], descriptor, slice);
603 :
604 0 : dSurf->Unmap();
605 0 : break;
606 : }
607 : case WebRenderParentCommand::TOpUpdateAsyncImagePipeline: {
608 0 : const OpUpdateAsyncImagePipeline& op = cmd.get_OpUpdateAsyncImagePipeline();
609 0 : mCompositableHolder->UpdateAsyncImagePipeline(op.pipelineId(),
610 0 : op.scBounds(),
611 0 : op.scTransform(),
612 0 : op.scaleToSize(),
613 : op.filter(),
614 0 : op.mixBlendMode());
615 0 : break;
616 : }
617 : case WebRenderParentCommand::TCompositableOperation: {
618 0 : if (!ReceiveCompositableUpdate(cmd.get_CompositableOperation())) {
619 0 : NS_ERROR("ReceiveCompositableUpdate failed");
620 : }
621 0 : break;
622 : }
623 : case WebRenderParentCommand::TOpAddCompositorAnimations: {
624 0 : const OpAddCompositorAnimations& op = cmd.get_OpAddCompositorAnimations();
625 0 : CompositorAnimations data(Move(op.data()));
626 0 : if (data.animations().Length()) {
627 0 : mAnimStorage->SetAnimations(data.id(), data.animations());
628 0 : mActiveAnimations.insert(data.id());
629 : // Store the default opacity
630 0 : if (op.opacity().type() == OptionalOpacity::Tfloat) {
631 0 : mAnimStorage->SetAnimatedValue(data.id(), op.opacity().get_float());
632 : }
633 : // Store the default transform
634 0 : if (op.transform().type() == OptionalTransform::TMatrix4x4) {
635 0 : Matrix4x4 transform(Move(op.transform().get_Matrix4x4()));
636 0 : mAnimStorage->SetAnimatedValue(data.id(), Move(transform));
637 : }
638 : }
639 0 : break;
640 : }
641 : default: {
642 : // other commands are handle on the child
643 0 : break;
644 : }
645 : }
646 : }
647 0 : }
648 :
649 : void
650 0 : WebRenderBridgeParent::ProcessWebRenderCommands(const gfx::IntSize &aSize,
651 : InfallibleTArray<WebRenderParentCommand>& aCommands, const wr::Epoch& aEpoch,
652 : const WrSize& aContentSize, const ByteBuffer& dl,
653 : const WrBuiltDisplayListDescriptor& dlDesc,
654 : const uint32_t& aIdNameSpace)
655 : {
656 0 : mCompositableHolder->SetCompositionTime(TimeStamp::Now());
657 0 : ProcessWebRenderParentCommands(aCommands);
658 :
659 : // The command is obsoleted.
660 : // Do not set the command to webrender since it causes crash in webrender.
661 0 : if (mIdNameSpace != aIdNameSpace) {
662 0 : return;
663 : }
664 :
665 0 : if (mWidget) {
666 0 : LayoutDeviceIntSize size = mWidget->GetClientSize();
667 0 : mApi->SetWindowParameters(size);
668 : }
669 0 : gfx::Color color = mWidget ? gfx::Color(0.3f, 0.f, 0.f, 1.f) : gfx::Color(0.f, 0.f, 0.f, 0.f);
670 0 : mApi->SetRootDisplayList(color, aEpoch, LayerSize(aSize.width, aSize.height),
671 : mPipelineId, aContentSize,
672 0 : dlDesc, dl.mData, dl.mLength);
673 :
674 0 : ScheduleComposition();
675 0 : DeleteOldImages();
676 :
677 0 : if (ShouldParentObserveEpoch()) {
678 0 : mCompositorBridge->ObserveLayerUpdate(GetLayersId(), GetChildLayerObserverEpoch(), true);
679 : }
680 : }
681 :
682 : mozilla::ipc::IPCResult
683 0 : WebRenderBridgeParent::RecvDPGetSnapshot(PTextureParent* aTexture)
684 : {
685 0 : if (mDestroyed) {
686 0 : return IPC_OK();
687 : }
688 0 : MOZ_ASSERT(!mPaused);
689 :
690 0 : RefPtr<TextureHost> texture = TextureHost::AsTextureHost(aTexture);
691 0 : if (!texture) {
692 : // We kill the content process rather than have it continue with an invalid
693 : // snapshot, that may be too harsh and we could decide to return some sort
694 : // of error to the child process and let it deal with it...
695 0 : return IPC_FAIL_NO_REASON(this);
696 : }
697 :
698 : // XXX Add other TextureHost supports.
699 : // Only BufferTextureHost is supported now.
700 0 : BufferTextureHost* bufferTexture = texture->AsBufferTextureHost();
701 0 : if (!bufferTexture) {
702 : // We kill the content process rather than have it continue with an invalid
703 : // snapshot, that may be too harsh and we could decide to return some sort
704 : // of error to the child process and let it deal with it...
705 0 : return IPC_FAIL_NO_REASON(this);
706 : }
707 :
708 0 : MOZ_ASSERT(bufferTexture->GetBufferDescriptor().type() == BufferDescriptor::TRGBDescriptor);
709 0 : DebugOnly<uint32_t> stride = ImageDataSerializer::GetRGBStride(bufferTexture->GetBufferDescriptor().get_RGBDescriptor());
710 0 : uint8_t* buffer = bufferTexture->GetBuffer();
711 0 : IntSize size = bufferTexture->GetSize();
712 :
713 : // We only support B8G8R8A8 for now.
714 0 : MOZ_ASSERT(buffer);
715 0 : MOZ_ASSERT(bufferTexture->GetFormat() == SurfaceFormat::B8G8R8A8);
716 0 : uint32_t buffer_size = size.width * size.height * 4;
717 :
718 : // Assert the stride of the buffer is what webrender expects
719 0 : MOZ_ASSERT((uint32_t)(size.width * 4) == stride);
720 :
721 0 : mForceRendering = true;
722 :
723 0 : if (mCompositorScheduler->NeedsComposite()) {
724 0 : mCompositorScheduler->CancelCurrentCompositeTask();
725 0 : mCompositorScheduler->ForceComposeToTarget(nullptr, nullptr);
726 : }
727 :
728 0 : mApi->Readback(size, buffer, buffer_size);
729 :
730 0 : mForceRendering = false;
731 :
732 0 : return IPC_OK();
733 : }
734 :
735 : mozilla::ipc::IPCResult
736 0 : WebRenderBridgeParent::RecvAddPipelineIdForAsyncCompositable(const wr::PipelineId& aPipelineId,
737 : const CompositableHandle& aHandle)
738 : {
739 0 : if (mDestroyed) {
740 0 : return IPC_OK();
741 : }
742 :
743 0 : MOZ_ASSERT(!mAsyncCompositables.Get(wr::AsUint64(aPipelineId)).get());
744 :
745 0 : RefPtr<ImageBridgeParent> imageBridge = ImageBridgeParent::GetInstance(OtherPid());
746 0 : if (!imageBridge) {
747 0 : return IPC_FAIL_NO_REASON(this);
748 : }
749 0 : RefPtr<CompositableHost> host = imageBridge->FindCompositable(aHandle);
750 0 : if (!host) {
751 0 : return IPC_FAIL_NO_REASON(this);
752 : }
753 0 : MOZ_ASSERT(host->AsWebRenderImageHost());
754 0 : WebRenderImageHost* wrHost = host->AsWebRenderImageHost();
755 0 : if (!wrHost) {
756 0 : return IPC_OK();
757 : }
758 :
759 0 : wrHost->SetWrBridge(this);
760 0 : mAsyncCompositables.Put(wr::AsUint64(aPipelineId), wrHost);
761 0 : mCompositableHolder->AddAsyncImagePipeline(aPipelineId, wrHost);
762 :
763 0 : return IPC_OK();
764 : }
765 :
766 : mozilla::ipc::IPCResult
767 0 : WebRenderBridgeParent::RecvRemovePipelineIdForAsyncCompositable(const wr::PipelineId& aPipelineId)
768 : {
769 0 : if (mDestroyed) {
770 0 : return IPC_OK();
771 : }
772 :
773 0 : WebRenderImageHost* wrHost = mAsyncCompositables.Get(wr::AsUint64(aPipelineId)).get();
774 0 : if (!wrHost) {
775 0 : return IPC_OK();
776 : }
777 :
778 0 : wrHost->ClearWrBridge();
779 0 : mCompositableHolder->RemoveAsyncImagePipeline(mApi, aPipelineId);
780 0 : mAsyncCompositables.Remove(wr::AsUint64(aPipelineId));
781 0 : return IPC_OK();
782 : }
783 :
784 : mozilla::ipc::IPCResult
785 0 : WebRenderBridgeParent::RecvAddExternalImageIdForCompositable(const ExternalImageId& aImageId,
786 : const CompositableHandle& aHandle)
787 : {
788 0 : if (mDestroyed) {
789 0 : return IPC_OK();
790 : }
791 0 : MOZ_ASSERT(!mExternalImageIds.Get(wr::AsUint64(aImageId)).get());
792 :
793 0 : RefPtr<CompositableHost> host = FindCompositable(aHandle);
794 0 : MOZ_ASSERT(host->AsWebRenderImageHost());
795 0 : WebRenderImageHost* wrHost = host->AsWebRenderImageHost();
796 0 : if (!wrHost) {
797 0 : return IPC_OK();
798 : }
799 :
800 0 : wrHost->SetWrBridge(this);
801 0 : mExternalImageIds.Put(wr::AsUint64(aImageId), wrHost);
802 :
803 0 : return IPC_OK();
804 : }
805 :
806 : mozilla::ipc::IPCResult
807 0 : WebRenderBridgeParent::RecvRemoveExternalImageId(const ExternalImageId& aImageId)
808 : {
809 0 : if (mDestroyed) {
810 0 : return IPC_OK();
811 : }
812 0 : WebRenderImageHost* wrHost = mExternalImageIds.Get(wr::AsUint64(aImageId)).get();
813 0 : if (!wrHost) {
814 0 : return IPC_OK();
815 : }
816 :
817 0 : wrHost->ClearWrBridge();
818 0 : mExternalImageIds.Remove(wr::AsUint64(aImageId));
819 :
820 0 : return IPC_OK();
821 : }
822 :
823 : mozilla::ipc::IPCResult
824 0 : WebRenderBridgeParent::RecvSetLayerObserverEpoch(const uint64_t& aLayerObserverEpoch)
825 : {
826 0 : if (mDestroyed) {
827 0 : return IPC_OK();
828 : }
829 0 : mChildLayerObserverEpoch = aLayerObserverEpoch;
830 0 : return IPC_OK();
831 : }
832 :
833 : mozilla::ipc::IPCResult
834 0 : WebRenderBridgeParent::RecvClearCachedResources()
835 : {
836 0 : if (mDestroyed) {
837 0 : return IPC_OK();
838 : }
839 0 : mCompositorBridge->ObserveLayerUpdate(GetLayersId(), GetChildLayerObserverEpoch(), false);
840 :
841 : // Clear resources
842 : // XXX Can we clear more resources?
843 0 : ++mWrEpoch; // Update webrender epoch
844 0 : mApi->ClearRootDisplayList(wr::NewEpoch(mWrEpoch), mPipelineId);
845 : // Schedule composition to clean up Pipeline
846 0 : mCompositorScheduler->ScheduleComposition();
847 : // Remove animations.
848 0 : for (std::unordered_set<uint64_t>::iterator iter = mActiveAnimations.begin(); iter != mActiveAnimations.end(); iter++) {
849 0 : mAnimStorage->ClearById(*iter);
850 : }
851 0 : mActiveAnimations.clear();
852 0 : return IPC_OK();
853 : }
854 :
855 : void
856 0 : WebRenderBridgeParent::UpdateWebRender(CompositorVsyncScheduler* aScheduler,
857 : wr::WebRenderAPI* aApi,
858 : WebRenderCompositableHolder* aHolder,
859 : CompositorAnimationStorage* aAnimStorage)
860 : {
861 0 : MOZ_ASSERT(!mWidget);
862 0 : MOZ_ASSERT(aScheduler);
863 0 : MOZ_ASSERT(aApi);
864 0 : MOZ_ASSERT(aHolder);
865 0 : MOZ_ASSERT(aAnimStorage);
866 :
867 0 : if (mDestroyed) {
868 0 : return;
869 : }
870 :
871 : // Update id name space to identify obsoleted keys.
872 : // Since usage of invalid keys could cause crash in webrender.
873 0 : mIdNameSpace = AllocIdNameSpace();
874 : // XXX Remove it when webrender supports sharing/moving Keys between different webrender instances.
875 : // XXX It requests client to update/reallocate webrender related resources,
876 : // but parent side does not wait end of the update.
877 : // The code could become simpler if we could serialise old keys deallocation and new keys allocation.
878 : // But we do not do it, it is because client side deallocate old layers/webrender keys
879 : // after new layers/webrender keys allocation.
880 : // Without client side's layout refactoring, we could not finish all old layers/webrender keys removals
881 : // before new layer/webrender keys allocation. In future, we could address the problem.
882 0 : Unused << SendWrUpdated(mIdNameSpace);
883 0 : CompositorBridgeParentBase* cBridge = mCompositorBridge;
884 : // XXX Stop to clear resources if webreder supports resources sharing between different webrender instances.
885 0 : ClearResources();
886 0 : mCompositorBridge = cBridge;
887 0 : mCompositorScheduler = aScheduler;
888 0 : mApi = aApi;
889 0 : mCompositableHolder = aHolder;
890 0 : mAnimStorage = aAnimStorage;
891 :
892 0 : ++mWrEpoch; // Update webrender epoch
893 : // Register pipeline to updated CompositableHolder.
894 0 : mCompositableHolder->AddPipeline(mPipelineId);
895 : }
896 :
897 : mozilla::ipc::IPCResult
898 0 : WebRenderBridgeParent::RecvForceComposite()
899 : {
900 0 : if (mDestroyed) {
901 0 : return IPC_OK();
902 : }
903 0 : ScheduleComposition();
904 0 : return IPC_OK();
905 : }
906 :
907 : already_AddRefed<AsyncPanZoomController>
908 0 : WebRenderBridgeParent::GetTargetAPZC(const FrameMetrics::ViewID& aScrollId)
909 : {
910 0 : RefPtr<AsyncPanZoomController> apzc;
911 0 : if (CompositorBridgeParent* cbp = GetRootCompositorBridgeParent()) {
912 0 : if (RefPtr<APZCTreeManager> apzctm = cbp->GetAPZCTreeManager()) {
913 0 : apzc = apzctm->GetTargetAPZC(GetLayersId(), aScrollId);
914 : }
915 : }
916 0 : return apzc.forget();
917 : }
918 :
919 : mozilla::ipc::IPCResult
920 0 : WebRenderBridgeParent::RecvSetConfirmedTargetAPZC(const uint64_t& aBlockId,
921 : nsTArray<ScrollableLayerGuid>&& aTargets)
922 : {
923 0 : if (mDestroyed) {
924 0 : return IPC_OK();
925 : }
926 0 : mCompositorBridge->SetConfirmedTargetAPZC(GetLayersId(), aBlockId, aTargets);
927 0 : return IPC_OK();
928 : }
929 :
930 : mozilla::ipc::IPCResult
931 0 : WebRenderBridgeParent::RecvSetTestSampleTime(const TimeStamp& aTime)
932 : {
933 0 : if (!mCompositorBridge->SetTestSampleTime(GetLayersId(), aTime)) {
934 0 : return IPC_FAIL_NO_REASON(this);
935 : }
936 0 : return IPC_OK();
937 : }
938 :
939 : mozilla::ipc::IPCResult
940 0 : WebRenderBridgeParent::RecvLeaveTestMode()
941 : {
942 0 : mCompositorBridge->LeaveTestMode(GetLayersId());
943 0 : return IPC_OK();
944 : }
945 :
946 : mozilla::ipc::IPCResult
947 0 : WebRenderBridgeParent::RecvGetAnimationOpacity(const uint64_t& aCompositorAnimationsId,
948 : float* aOpacity,
949 : bool* aHasAnimationOpacity)
950 : {
951 0 : if (mDestroyed) {
952 0 : return IPC_FAIL_NO_REASON(this);
953 : }
954 :
955 0 : MOZ_ASSERT(mAnimStorage);
956 0 : AdvanceAnimations();
957 :
958 0 : Maybe<float> opacity = mAnimStorage->GetAnimationOpacity(aCompositorAnimationsId);
959 0 : if (opacity) {
960 0 : *aOpacity = *opacity;
961 0 : *aHasAnimationOpacity = true;
962 : } else {
963 0 : *aHasAnimationOpacity = false;
964 : }
965 0 : return IPC_OK();
966 : }
967 :
968 : mozilla::ipc::IPCResult
969 0 : WebRenderBridgeParent::RecvGetAnimationTransform(const uint64_t& aCompositorAnimationsId,
970 : MaybeTransform* aTransform)
971 : {
972 0 : if (mDestroyed) {
973 0 : return IPC_FAIL_NO_REASON(this);
974 : }
975 :
976 0 : MOZ_ASSERT(mAnimStorage);
977 0 : AdvanceAnimations();
978 :
979 0 : Maybe<Matrix4x4> transform = mAnimStorage->GetAnimationTransform(aCompositorAnimationsId);
980 0 : if (transform) {
981 0 : *aTransform = *transform;
982 : } else {
983 0 : *aTransform = mozilla::void_t();
984 : }
985 0 : return IPC_OK();
986 : }
987 :
988 : mozilla::ipc::IPCResult
989 0 : WebRenderBridgeParent::RecvSetAsyncScrollOffset(const FrameMetrics::ViewID& aScrollId,
990 : const float& aX,
991 : const float& aY)
992 : {
993 0 : if (mDestroyed) {
994 0 : return IPC_OK();
995 : }
996 0 : RefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aScrollId);
997 0 : if (!apzc) {
998 0 : return IPC_FAIL_NO_REASON(this);
999 : }
1000 0 : apzc->SetTestAsyncScrollOffset(CSSPoint(aX, aY));
1001 0 : return IPC_OK();
1002 : }
1003 :
1004 : mozilla::ipc::IPCResult
1005 0 : WebRenderBridgeParent::RecvSetAsyncZoom(const FrameMetrics::ViewID& aScrollId,
1006 : const float& aZoom)
1007 : {
1008 0 : if (mDestroyed) {
1009 0 : return IPC_OK();
1010 : }
1011 0 : RefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aScrollId);
1012 0 : if (!apzc) {
1013 0 : return IPC_FAIL_NO_REASON(this);
1014 : }
1015 0 : apzc->SetTestAsyncZoom(LayerToParentLayerScale(aZoom));
1016 0 : return IPC_OK();
1017 : }
1018 :
1019 : mozilla::ipc::IPCResult
1020 0 : WebRenderBridgeParent::RecvFlushApzRepaints()
1021 : {
1022 0 : if (mDestroyed) {
1023 0 : return IPC_OK();
1024 : }
1025 0 : mCompositorBridge->FlushApzRepaints(GetLayersId());
1026 0 : return IPC_OK();
1027 : }
1028 :
1029 : mozilla::ipc::IPCResult
1030 0 : WebRenderBridgeParent::RecvGetAPZTestData(APZTestData* aOutData)
1031 : {
1032 0 : mCompositorBridge->GetAPZTestData(GetLayersId(), aOutData);
1033 0 : return IPC_OK();
1034 : }
1035 :
1036 : void
1037 0 : WebRenderBridgeParent::ActorDestroy(ActorDestroyReason aWhy)
1038 : {
1039 0 : Destroy();
1040 0 : }
1041 :
1042 : void
1043 0 : WebRenderBridgeParent::AdvanceAnimations()
1044 : {
1045 0 : TimeStamp animTime = mCompositorScheduler->GetLastComposeTime();
1046 0 : if (CompositorBridgeParent* cbp = GetRootCompositorBridgeParent()) {
1047 0 : animTime = cbp->GetTestingTimeStamp().valueOr(animTime);
1048 : }
1049 0 : AnimationHelper::SampleAnimations(mAnimStorage, animTime);
1050 0 : }
1051 :
1052 : void
1053 0 : WebRenderBridgeParent::SampleAnimations(nsTArray<WrOpacityProperty>& aOpacityArray,
1054 : nsTArray<WrTransformProperty>& aTransformArray)
1055 : {
1056 0 : AdvanceAnimations();
1057 :
1058 : // return the animated data if has
1059 0 : if (mAnimStorage->AnimatedValueCount()) {
1060 0 : for(auto iter = mAnimStorage->ConstAnimatedValueTableIter();
1061 0 : !iter.Done(); iter.Next()) {
1062 0 : AnimatedValue * value = iter.UserData();
1063 0 : if (value->mType == AnimatedValue::TRANSFORM) {
1064 0 : aTransformArray.AppendElement(
1065 0 : wr::ToWrTransformProperty(iter.Key(), value->mTransform.mTransformInDevSpace));
1066 0 : } else if (value->mType == AnimatedValue::OPACITY) {
1067 0 : aOpacityArray.AppendElement(
1068 0 : wr::ToWrOpacityProperty(iter.Key(), value->mOpacity));
1069 : }
1070 : }
1071 : }
1072 0 : }
1073 :
1074 : void
1075 0 : WebRenderBridgeParent::CompositeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect)
1076 : {
1077 0 : AutoProfilerTracing tracing("Paint", "CompositeToTraget");
1078 0 : if (mPaused) {
1079 0 : return;
1080 : }
1081 :
1082 0 : const uint32_t maxPendingFrameCount = 2;
1083 :
1084 0 : if (!mForceRendering &&
1085 0 : wr::RenderThread::Get()->GetPendingFrameCount(mApi->GetId()) > maxPendingFrameCount) {
1086 : // Render thread is busy, try next time.
1087 0 : ScheduleComposition();
1088 0 : return;
1089 : }
1090 :
1091 0 : bool scheduleComposite = false;
1092 0 : nsTArray<WrOpacityProperty> opacityArray;
1093 0 : nsTArray<WrTransformProperty> transformArray;
1094 :
1095 0 : mCompositableHolder->SetCompositionTime(TimeStamp::Now());
1096 0 : mCompositableHolder->ApplyAsyncImages(mApi);
1097 :
1098 0 : if (gfxPrefs::WebRenderOMTAEnabled()) {
1099 0 : SampleAnimations(opacityArray, transformArray);
1100 :
1101 0 : if (!transformArray.IsEmpty() || !opacityArray.IsEmpty()) {
1102 0 : scheduleComposite = true;
1103 : }
1104 : }
1105 :
1106 0 : if (PushAPZStateToWR(transformArray)) {
1107 0 : scheduleComposite = true;
1108 : }
1109 :
1110 0 : if (!transformArray.IsEmpty() || !opacityArray.IsEmpty()) {
1111 0 : mApi->GenerateFrame(opacityArray, transformArray);
1112 : } else {
1113 0 : mApi->GenerateFrame();
1114 : }
1115 :
1116 0 : if (!mCompositableHolder->GetCompositeUntilTime().IsNull()) {
1117 0 : scheduleComposite = true;
1118 : }
1119 :
1120 0 : if (scheduleComposite) {
1121 0 : ScheduleComposition();
1122 : }
1123 : }
1124 :
1125 : void
1126 0 : WebRenderBridgeParent::HoldPendingTransactionId(uint32_t aWrEpoch, uint64_t aTransactionId)
1127 : {
1128 : // The transaction ID might get reset to 1 if the page gets reloaded, see
1129 : // https://bugzilla.mozilla.org/show_bug.cgi?id=1145295#c41
1130 : // Otherwise, it should be continually increasing.
1131 0 : MOZ_ASSERT(aTransactionId == 1 || aTransactionId > LastPendingTransactionId());
1132 : // Handle TransactionIdAllocator(RefreshDriver) change.
1133 0 : if (aTransactionId == 1) {
1134 0 : FlushPendingTransactionIds();
1135 : }
1136 0 : mPendingTransactionIds.push(PendingTransactionId(wr::NewEpoch(aWrEpoch), aTransactionId));
1137 0 : }
1138 :
1139 : uint64_t
1140 0 : WebRenderBridgeParent::LastPendingTransactionId()
1141 : {
1142 0 : uint64_t id = 0;
1143 0 : if (!mPendingTransactionIds.empty()) {
1144 0 : id = mPendingTransactionIds.back().mId;
1145 : }
1146 0 : return id;
1147 : }
1148 :
1149 : uint64_t
1150 0 : WebRenderBridgeParent::FlushPendingTransactionIds()
1151 : {
1152 0 : uint64_t id = 0;
1153 0 : while (!mPendingTransactionIds.empty()) {
1154 0 : id = mPendingTransactionIds.front().mId;
1155 0 : mPendingTransactionIds.pop();
1156 : }
1157 0 : return id;
1158 : }
1159 :
1160 : uint64_t
1161 0 : WebRenderBridgeParent::FlushTransactionIdsForEpoch(const wr::Epoch& aEpoch)
1162 : {
1163 0 : uint64_t id = 0;
1164 0 : while (!mPendingTransactionIds.empty()) {
1165 0 : id = mPendingTransactionIds.front().mId;
1166 0 : if (mPendingTransactionIds.front().mEpoch == aEpoch) {
1167 0 : mPendingTransactionIds.pop();
1168 0 : break;
1169 : }
1170 0 : mPendingTransactionIds.pop();
1171 : }
1172 0 : return id;
1173 : }
1174 :
1175 : uint64_t
1176 0 : WebRenderBridgeParent::GetLayersId() const
1177 : {
1178 0 : return wr::AsUint64(mPipelineId);
1179 : }
1180 :
1181 : void
1182 0 : WebRenderBridgeParent::DeleteOldImages()
1183 : {
1184 0 : for (wr::ImageKey key : mKeysToDelete) {
1185 0 : mApi->DeleteImage(key);
1186 : }
1187 0 : mKeysToDelete.clear();
1188 0 : }
1189 :
1190 : void
1191 0 : WebRenderBridgeParent::ScheduleComposition()
1192 : {
1193 0 : if (mCompositorScheduler) {
1194 0 : mCompositorScheduler->ScheduleComposition();
1195 : }
1196 0 : }
1197 :
1198 : void
1199 0 : WebRenderBridgeParent::FlushRendering(bool aIsSync)
1200 : {
1201 0 : if (mDestroyed) {
1202 0 : return;
1203 : }
1204 :
1205 0 : if (!mCompositorScheduler->NeedsComposite()) {
1206 0 : return;
1207 : }
1208 :
1209 0 : mForceRendering = true;
1210 0 : mCompositorScheduler->CancelCurrentCompositeTask();
1211 0 : mCompositorScheduler->ForceComposeToTarget(nullptr, nullptr);
1212 0 : if (aIsSync) {
1213 0 : mApi->WaitFlushed();
1214 : }
1215 0 : mForceRendering = false;
1216 : }
1217 :
1218 : void
1219 0 : WebRenderBridgeParent::Pause()
1220 : {
1221 0 : MOZ_ASSERT(mWidget);
1222 : #ifdef MOZ_WIDGET_ANDROID
1223 : if (!mWidget || mDestroyed) {
1224 : return;
1225 : }
1226 : mApi->Pause();
1227 : #endif
1228 0 : mPaused = true;
1229 0 : }
1230 :
1231 : bool
1232 0 : WebRenderBridgeParent::Resume()
1233 : {
1234 0 : MOZ_ASSERT(mWidget);
1235 : #ifdef MOZ_WIDGET_ANDROID
1236 : if (!mWidget || mDestroyed) {
1237 : return false;
1238 : }
1239 :
1240 : if (!mApi->Resume()) {
1241 : return false;
1242 : }
1243 : #endif
1244 0 : mPaused = false;
1245 0 : return true;
1246 : }
1247 :
1248 : void
1249 0 : WebRenderBridgeParent::ClearResources()
1250 : {
1251 0 : if (!mApi) {
1252 0 : return;
1253 : }
1254 :
1255 0 : ++mWrEpoch; // Update webrender epoch
1256 0 : mApi->ClearRootDisplayList(wr::NewEpoch(mWrEpoch), mPipelineId);
1257 : // Schedule composition to clean up Pipeline
1258 0 : mCompositorScheduler->ScheduleComposition();
1259 : // XXX webrender does not hava a way to delete a group of resources/keys,
1260 : // then delete keys one by one.
1261 0 : for (std::unordered_set<uint64_t>::iterator iter = mFontKeys.begin(); iter != mFontKeys.end(); iter++) {
1262 0 : mApi->DeleteFont(wr::AsFontKey(*iter));
1263 : }
1264 0 : mFontKeys.clear();
1265 0 : for (std::unordered_set<uint64_t>::iterator iter = mActiveImageKeys.begin(); iter != mActiveImageKeys.end(); iter++) {
1266 0 : mKeysToDelete.push_back(wr::AsImageKey(*iter));
1267 : }
1268 0 : mActiveImageKeys.clear();
1269 0 : DeleteOldImages();
1270 0 : for (auto iter = mExternalImageIds.Iter(); !iter.Done(); iter.Next()) {
1271 0 : iter.Data()->ClearWrBridge();
1272 : }
1273 0 : mExternalImageIds.Clear();
1274 0 : for (auto iter = mAsyncCompositables.Iter(); !iter.Done(); iter.Next()) {
1275 0 : wr::PipelineId pipelineId = wr::AsPipelineId(iter.Key());
1276 0 : RefPtr<WebRenderImageHost> host = iter.Data();
1277 0 : MOZ_ASSERT(host->GetAsyncRef());
1278 0 : host->ClearWrBridge();
1279 0 : mCompositableHolder->RemoveAsyncImagePipeline(mApi, pipelineId);
1280 : }
1281 0 : mAsyncCompositables.Clear();
1282 :
1283 0 : mCompositableHolder->RemovePipeline(mPipelineId, wr::NewEpoch(mWrEpoch));
1284 :
1285 0 : for (std::unordered_set<uint64_t>::iterator iter = mActiveAnimations.begin(); iter != mActiveAnimations.end(); iter++) {
1286 0 : mAnimStorage->ClearById(*iter);
1287 : }
1288 0 : mActiveAnimations.clear();
1289 :
1290 0 : if (mWidget) {
1291 0 : mCompositorScheduler->Destroy();
1292 : }
1293 0 : mAnimStorage = nullptr;
1294 0 : mCompositorScheduler = nullptr;
1295 0 : mApi = nullptr;
1296 0 : mCompositorBridge = nullptr;
1297 : }
1298 :
1299 : bool
1300 0 : WebRenderBridgeParent::ShouldParentObserveEpoch()
1301 : {
1302 0 : if (mParentLayerObserverEpoch == mChildLayerObserverEpoch) {
1303 0 : return false;
1304 : }
1305 :
1306 0 : mParentLayerObserverEpoch = mChildLayerObserverEpoch;
1307 0 : return true;
1308 : }
1309 :
1310 : void
1311 0 : WebRenderBridgeParent::SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage)
1312 : {
1313 0 : MOZ_ASSERT_UNREACHABLE("unexpected to be called");
1314 : }
1315 :
1316 : void
1317 0 : WebRenderBridgeParent::SendPendingAsyncMessages()
1318 : {
1319 0 : MOZ_ASSERT(mCompositorBridge);
1320 0 : mCompositorBridge->SendPendingAsyncMessages();
1321 0 : }
1322 :
1323 : void
1324 0 : WebRenderBridgeParent::SetAboutToSendAsyncMessages()
1325 : {
1326 0 : MOZ_ASSERT(mCompositorBridge);
1327 0 : mCompositorBridge->SetAboutToSendAsyncMessages();
1328 0 : }
1329 :
1330 : void
1331 0 : WebRenderBridgeParent::NotifyNotUsed(PTextureParent* aTexture, uint64_t aTransactionId)
1332 : {
1333 0 : MOZ_ASSERT_UNREACHABLE("unexpected to be called");
1334 : }
1335 :
1336 : base::ProcessId
1337 0 : WebRenderBridgeParent::GetChildProcessId()
1338 : {
1339 0 : return OtherPid();
1340 : }
1341 :
1342 : bool
1343 0 : WebRenderBridgeParent::IsSameProcess() const
1344 : {
1345 0 : return OtherPid() == base::GetCurrentProcId();
1346 : }
1347 :
1348 : mozilla::ipc::IPCResult
1349 0 : WebRenderBridgeParent::RecvNewCompositable(const CompositableHandle& aHandle,
1350 : const TextureInfo& aInfo)
1351 : {
1352 0 : if (mDestroyed) {
1353 0 : return IPC_OK();
1354 : }
1355 0 : if (!AddCompositable(aHandle, aInfo)) {
1356 0 : return IPC_FAIL_NO_REASON(this);
1357 : }
1358 0 : return IPC_OK();
1359 : }
1360 :
1361 : mozilla::ipc::IPCResult
1362 0 : WebRenderBridgeParent::RecvReleaseCompositable(const CompositableHandle& aHandle)
1363 : {
1364 0 : if (mDestroyed) {
1365 0 : return IPC_OK();
1366 : }
1367 0 : ReleaseCompositable(aHandle);
1368 0 : return IPC_OK();
1369 : }
1370 :
1371 : mozilla::ipc::IPCResult
1372 0 : WebRenderBridgeParent::RecvInitReadLocks(ReadLockArray&& aReadLocks)
1373 : {
1374 0 : if (mDestroyed) {
1375 0 : return IPC_OK();
1376 : }
1377 0 : if (!AddReadLocks(Move(aReadLocks))) {
1378 0 : return IPC_FAIL_NO_REASON(this);
1379 : }
1380 0 : return IPC_OK();
1381 : }
1382 :
1383 : void
1384 0 : WebRenderBridgeParent::SetWebRenderProfilerEnabled(bool aEnabled)
1385 : {
1386 0 : if (mWidget) {
1387 : // Only set the flag to "root" WebRenderBridgeParent.
1388 0 : mApi->SetProfilerEnabled(aEnabled);
1389 : }
1390 0 : }
1391 :
1392 : TextureFactoryIdentifier
1393 0 : WebRenderBridgeParent::GetTextureFactoryIdentifier()
1394 : {
1395 0 : MOZ_ASSERT(mApi);
1396 :
1397 : return TextureFactoryIdentifier(LayersBackend::LAYERS_WR,
1398 : XRE_GetProcessType(),
1399 : mApi->GetMaxTextureSize(),
1400 0 : mApi->GetUseANGLE());
1401 : }
1402 :
1403 : } // namespace layers
1404 : } // namespace mozilla
|