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 "WebRenderLayerManager.h"
8 
9 #include "Layers.h"
10 
11 #include "GeckoProfiler.h"
12 #include "mozilla/StaticPrefs_apz.h"
13 #include "mozilla/StaticPrefs_layers.h"
14 #include "mozilla/dom/BrowserChild.h"
15 #include "mozilla/gfx/DrawEventRecorder.h"
16 #include "mozilla/gfx/gfxVars.h"
17 #include "mozilla/layers/CompositorBridgeChild.h"
18 #include "mozilla/layers/StackingContextHelper.h"
19 #include "mozilla/layers/TextureClient.h"
20 #include "mozilla/layers/TransactionIdAllocator.h"
21 #include "mozilla/layers/WebRenderBridgeChild.h"
22 #include "mozilla/layers/UpdateImageHelper.h"
23 #include "nsDisplayList.h"
24 #include "nsLayoutUtils.h"
25 #include "WebRenderCanvasRenderer.h"
26 #include "LayerUserData.h"
27 
28 #ifdef XP_WIN
29 #  include "gfxDWriteFonts.h"
30 #  include "mozilla/WindowsProcessMitigations.h"
31 #endif
32 
33 namespace mozilla {
34 
35 using namespace gfx;
36 
37 namespace layers {
38 
WebRenderLayerManager(nsIWidget * aWidget)39 WebRenderLayerManager::WebRenderLayerManager(nsIWidget* aWidget)
40     : mWidget(aWidget),
41       mLatestTransactionId{0},
42       mNeedsComposite(false),
43       mIsFirstPaint(false),
44       mDestroyed(false),
45       mTarget(nullptr),
46       mPaintSequenceNumber(0),
47       mWebRenderCommandBuilder(this) {
48   MOZ_COUNT_CTOR(WebRenderLayerManager);
49   mStateManager.mLayerManager = this;
50 
51   if (XRE_IsContentProcess() &&
52       StaticPrefs::gfx_webrender_enable_item_cache_AtStartup()) {
53     static const size_t kInitialCacheSize = 1024;
54     static const size_t kMaximumCacheSize = 10240;
55 
56     mDisplayItemCache.SetCapacity(kInitialCacheSize, kMaximumCacheSize);
57   }
58 }
59 
AsKnowsCompositor()60 KnowsCompositor* WebRenderLayerManager::AsKnowsCompositor() { return mWrChild; }
61 
Initialize(PCompositorBridgeChild * aCBChild,wr::PipelineId aLayersId,TextureFactoryIdentifier * aTextureFactoryIdentifier,nsCString & aError)62 bool WebRenderLayerManager::Initialize(
63     PCompositorBridgeChild* aCBChild, wr::PipelineId aLayersId,
64     TextureFactoryIdentifier* aTextureFactoryIdentifier, nsCString& aError) {
65   MOZ_ASSERT(mWrChild == nullptr);
66   MOZ_ASSERT(aTextureFactoryIdentifier);
67 
68   // When we fail to initialize WebRender, it is useful to know if it has ever
69   // succeeded, or if this is the first attempt.
70   static bool hasInitialized = false;
71 
72   WindowKind windowKind;
73   if (mWidget->WindowType() != eWindowType_popup) {
74     windowKind = WindowKind::MAIN;
75   } else {
76     windowKind = WindowKind::SECONDARY;
77   }
78 
79   LayoutDeviceIntSize size = mWidget->GetClientSize();
80   // Check widget size
81   if (size.width < 0 || size.width > wr::MAX_RENDER_TASK_SIZE ||
82       size.height < 0 || size.height > wr::MAX_RENDER_TASK_SIZE) {
83     gfxCriticalNoteOnce << "Widget size is not valid " << size
84                         << " isParent: " << XRE_IsParentProcess();
85   }
86 
87   PWebRenderBridgeChild* bridge =
88       aCBChild->SendPWebRenderBridgeConstructor(aLayersId, size, windowKind);
89   if (!bridge) {
90     // This should only fail if we attempt to access a layer we don't have
91     // permission for, or more likely, the GPU process crashed again during
92     // reinitialization. We can expect to be notified again to reinitialize
93     // (which may or may not be using WebRender).
94     gfxCriticalNote << "Failed to create WebRenderBridgeChild.";
95     aError.Assign(hasInitialized
96                       ? "FEATURE_FAILURE_WEBRENDER_INITIALIZE_IPDL_POST"_ns
97                       : "FEATURE_FAILURE_WEBRENDER_INITIALIZE_IPDL_FIRST"_ns);
98     return false;
99   }
100 
101   TextureFactoryIdentifier textureFactoryIdentifier;
102   wr::MaybeIdNamespace idNamespace;
103   // Sync ipc
104   if (!bridge->SendEnsureConnected(&textureFactoryIdentifier, &idNamespace,
105                                    &aError)) {
106     gfxCriticalNote << "Failed as lost WebRenderBridgeChild.";
107     aError.Assign(hasInitialized
108                       ? "FEATURE_FAILURE_WEBRENDER_INITIALIZE_SYNC_POST"_ns
109                       : "FEATURE_FAILURE_WEBRENDER_INITIALIZE_SYNC_FIRST"_ns);
110     return false;
111   }
112 
113   if (textureFactoryIdentifier.mParentBackend == LayersBackend::LAYERS_NONE ||
114       idNamespace.isNothing()) {
115     gfxCriticalNote << "Failed to connect WebRenderBridgeChild.";
116     aError.Append(hasInitialized ? "_POST"_ns : "_FIRST"_ns);
117     return false;
118   }
119 
120   mWrChild = static_cast<WebRenderBridgeChild*>(bridge);
121   WrBridge()->SetWebRenderLayerManager(this);
122   WrBridge()->IdentifyTextureHost(textureFactoryIdentifier);
123   WrBridge()->SetNamespace(idNamespace.ref());
124   *aTextureFactoryIdentifier = textureFactoryIdentifier;
125 
126   mDLBuilder = MakeUnique<wr::DisplayListBuilder>(
127       WrBridge()->GetPipeline(), WrBridge()->GetWebRenderBackend());
128 
129   hasInitialized = true;
130   return true;
131 }
132 
Destroy()133 void WebRenderLayerManager::Destroy() { DoDestroy(/* aIsSync */ false); }
134 
DoDestroy(bool aIsSync)135 void WebRenderLayerManager::DoDestroy(bool aIsSync) {
136   MOZ_ASSERT(NS_IsMainThread());
137 
138   if (IsDestroyed()) {
139     return;
140   }
141 
142   mDLBuilder = nullptr;
143   mUserData.Destroy();
144   mPartialPrerenderedAnimations.Clear();
145 
146   mStateManager.Destroy();
147 
148   if (WrBridge()) {
149     WrBridge()->Destroy(aIsSync);
150   }
151 
152   mWebRenderCommandBuilder.Destroy();
153 
154   if (mTransactionIdAllocator) {
155     // Make sure to notify the refresh driver just in case it's waiting on a
156     // pending transaction. Do this at the top of the event loop so we don't
157     // cause a paint to occur during compositor shutdown.
158     RefPtr<TransactionIdAllocator> allocator = mTransactionIdAllocator;
159     TransactionId id = mLatestTransactionId;
160 
161     RefPtr<Runnable> task = NS_NewRunnableFunction(
162         "TransactionIdAllocator::NotifyTransactionCompleted",
163         [allocator, id]() -> void {
164           allocator->ClearPendingTransactions();
165           allocator->NotifyTransactionCompleted(id);
166         });
167     NS_DispatchToMainThread(task.forget());
168   }
169 
170   // Forget the widget pointer in case we outlive our owning widget.
171   mWidget = nullptr;
172   mDestroyed = true;
173 }
174 
~WebRenderLayerManager()175 WebRenderLayerManager::~WebRenderLayerManager() {
176   Destroy();
177   MOZ_COUNT_DTOR(WebRenderLayerManager);
178 }
179 
GetCompositorBridgeChild()180 CompositorBridgeChild* WebRenderLayerManager::GetCompositorBridgeChild() {
181   return WrBridge()->GetCompositorBridgeChild();
182 }
183 
GetBackendName(nsAString & name)184 void WebRenderLayerManager::GetBackendName(nsAString& name) {
185   if (WrBridge()->UsingSoftwareWebRenderD3D11()) {
186     name.AssignLiteral("WebRender (Software D3D11)");
187   } else if (WrBridge()->UsingSoftwareWebRenderOpenGL()) {
188     name.AssignLiteral("WebRender (Software OpenGL)");
189   } else if (WrBridge()->UsingSoftwareWebRender()) {
190     name.AssignLiteral("WebRender (Software)");
191   } else {
192     name.AssignLiteral("WebRender");
193   }
194 }
195 
StartFrameTimeRecording(int32_t aBufferSize)196 uint32_t WebRenderLayerManager::StartFrameTimeRecording(int32_t aBufferSize) {
197   CompositorBridgeChild* renderer = GetCompositorBridgeChild();
198   if (renderer) {
199     uint32_t startIndex;
200     renderer->SendStartFrameTimeRecording(aBufferSize, &startIndex);
201     return startIndex;
202   }
203   return -1;
204 }
205 
StopFrameTimeRecording(uint32_t aStartIndex,nsTArray<float> & aFrameIntervals)206 void WebRenderLayerManager::StopFrameTimeRecording(
207     uint32_t aStartIndex, nsTArray<float>& aFrameIntervals) {
208   CompositorBridgeChild* renderer = GetCompositorBridgeChild();
209   if (renderer) {
210     renderer->SendStopFrameTimeRecording(aStartIndex, &aFrameIntervals);
211   }
212 }
213 
TakeCompositionPayloads(nsTArray<CompositionPayload> & aPayloads)214 void WebRenderLayerManager::TakeCompositionPayloads(
215     nsTArray<CompositionPayload>& aPayloads) {
216   aPayloads.Clear();
217 
218   std::swap(mPayload, aPayloads);
219 }
220 
BeginTransactionWithTarget(gfxContext * aTarget,const nsCString & aURL)221 bool WebRenderLayerManager::BeginTransactionWithTarget(gfxContext* aTarget,
222                                                        const nsCString& aURL) {
223   mTarget = aTarget;
224   return BeginTransaction(aURL);
225 }
226 
BeginTransaction(const nsCString & aURL)227 bool WebRenderLayerManager::BeginTransaction(const nsCString& aURL) {
228   if (!WrBridge()->IPCOpen()) {
229     gfxCriticalNote << "IPC Channel is already torn down unexpectedly\n";
230     return false;
231   }
232 
233   mTransactionStart = TimeStamp::Now();
234   mURL = aURL;
235 
236   // Increment the paint sequence number even if test logging isn't
237   // enabled in this process; it may be enabled in the parent process,
238   // and the parent process expects unique sequence numbers.
239   ++mPaintSequenceNumber;
240   if (StaticPrefs::apz_test_logging_enabled()) {
241     mApzTestData.StartNewPaint(mPaintSequenceNumber);
242   }
243   return true;
244 }
245 
EndEmptyTransaction(EndTransactionFlags aFlags)246 bool WebRenderLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags) {
247   // If we haven't sent a display list (since creation or since the last time we
248   // sent ClearDisplayList to the parent) then we can't do an empty transaction
249   // because the parent doesn't have a display list for us and we need to send a
250   // display list first.
251   if (!WrBridge()->GetSentDisplayList()) {
252     return false;
253   }
254 
255   mDisplayItemCache.SkipWaitingForPartialDisplayList();
256 
257   // Since we don't do repeat transactions right now, just set the time
258   mAnimationReadyTime = TimeStamp::Now();
259 
260   mLatestTransactionId =
261       mTransactionIdAllocator->GetTransactionId(/*aThrottle*/ true);
262 
263   if (aFlags & EndTransactionFlags::END_NO_COMPOSITE &&
264       !mWebRenderCommandBuilder.NeedsEmptyTransaction()) {
265     if (mPendingScrollUpdates.IsEmpty()) {
266       MOZ_ASSERT(!mTarget);
267       WrBridge()->SendSetFocusTarget(mFocusTarget);
268       // Revoke TransactionId to trigger next paint.
269       mTransactionIdAllocator->RevokeTransactionId(mLatestTransactionId);
270       mLatestTransactionId = mLatestTransactionId.Prev();
271       return true;
272     }
273   }
274 
275   LayoutDeviceIntSize size = mWidget->GetClientSize();
276   WrBridge()->BeginTransaction();
277 
278   mWebRenderCommandBuilder.EmptyTransaction();
279 
280   // Get the time of when the refresh driver start its tick (if available),
281   // otherwise use the time of when LayerManager::BeginTransaction was called.
282   TimeStamp refreshStart = mTransactionIdAllocator->GetTransactionStart();
283   if (!refreshStart) {
284     refreshStart = mTransactionStart;
285   }
286 
287   // Skip the synchronization for buffer since we also skip the painting during
288   // device-reset status.
289   if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) {
290     if (WrBridge()->GetSyncObject() &&
291         WrBridge()->GetSyncObject()->IsSyncObjectValid()) {
292       WrBridge()->GetSyncObject()->Synchronize();
293     }
294   }
295 
296   GetCompositorBridgeChild()->EndCanvasTransaction();
297 
298   Maybe<TransactionData> transactionData;
299   if (mStateManager.mAsyncResourceUpdates || !mPendingScrollUpdates.IsEmpty() ||
300       WrBridge()->HasWebRenderParentCommands()) {
301     transactionData.emplace();
302     transactionData->mIdNamespace = WrBridge()->GetNamespace();
303     transactionData->mPaintSequenceNumber = mPaintSequenceNumber;
304     if (mStateManager.mAsyncResourceUpdates) {
305       mStateManager.mAsyncResourceUpdates->Flush(
306           transactionData->mResourceUpdates, transactionData->mSmallShmems,
307           transactionData->mLargeShmems);
308     }
309     transactionData->mScrollUpdates = std::move(mPendingScrollUpdates);
310     for (const auto& scrollId : transactionData->mScrollUpdates.Keys()) {
311       nsLayoutUtils::NotifyPaintSkipTransaction(/*scroll id=*/scrollId);
312     }
313   }
314 
315   Maybe<wr::IpcResourceUpdateQueue> nothing;
316   WrBridge()->EndEmptyTransaction(mFocusTarget, std::move(transactionData),
317                                   mLatestTransactionId,
318                                   mTransactionIdAllocator->GetVsyncId(),
319                                   mTransactionIdAllocator->GetVsyncStart(),
320                                   refreshStart, mTransactionStart, mURL);
321   mTransactionStart = TimeStamp();
322 
323   MakeSnapshotIfRequired(size);
324   return true;
325 }
326 
EndTransactionWithoutLayer(nsDisplayList * aDisplayList,nsDisplayListBuilder * aDisplayListBuilder,WrFiltersHolder && aFilters,WebRenderBackgroundData * aBackground,const double aGeckoDLBuildTime)327 void WebRenderLayerManager::EndTransactionWithoutLayer(
328     nsDisplayList* aDisplayList, nsDisplayListBuilder* aDisplayListBuilder,
329     WrFiltersHolder&& aFilters, WebRenderBackgroundData* aBackground,
330     const double aGeckoDLBuildTime) {
331   AUTO_PROFILER_TRACING_MARKER("Paint", "RenderLayers", GRAPHICS);
332 
333   // Since we don't do repeat transactions right now, just set the time
334   mAnimationReadyTime = TimeStamp::Now();
335 
336   WrBridge()->BeginTransaction();
337 
338   LayoutDeviceIntSize size = mWidget->GetClientSize();
339 
340   mDLBuilder->Begin(&mDisplayItemCache);
341 
342   wr::IpcResourceUpdateQueue resourceUpdates(WrBridge());
343   wr::usize builderDumpIndex = 0;
344   bool containsSVGGroup = false;
345   bool dumpEnabled =
346       mWebRenderCommandBuilder.ShouldDumpDisplayList(aDisplayListBuilder);
347   Maybe<AutoDisplayItemCacheSuppressor> cacheSuppressor;
348   if (dumpEnabled) {
349     cacheSuppressor.emplace(&mDisplayItemCache);
350     printf_stderr("-- WebRender display list build --\n");
351   }
352 
353   if (XRE_IsContentProcess() &&
354       StaticPrefs::gfx_webrender_debug_dl_dump_content_serialized()) {
355     mDLBuilder->DumpSerializedDisplayList();
356   }
357 
358   if (aDisplayList) {
359     MOZ_ASSERT(aDisplayListBuilder && !aBackground);
360     mDisplayItemCache.SetDisplayList(aDisplayListBuilder, aDisplayList);
361 
362     mWebRenderCommandBuilder.BuildWebRenderCommands(
363         *mDLBuilder, resourceUpdates, aDisplayList, aDisplayListBuilder,
364         mScrollData, std::move(aFilters));
365 
366     aDisplayListBuilder->NotifyAndClearScrollFrames();
367 
368     builderDumpIndex = mWebRenderCommandBuilder.GetBuilderDumpIndex();
369     containsSVGGroup = mWebRenderCommandBuilder.GetContainsSVGGroup();
370   } else {
371     // ViewToPaint does not have frame yet, then render only background clolor.
372     MOZ_ASSERT(!aDisplayListBuilder && aBackground);
373     aBackground->AddWebRenderCommands(*mDLBuilder);
374     if (dumpEnabled) {
375       printf_stderr("(no display list; background only)\n");
376       builderDumpIndex =
377           mDLBuilder->Dump(/*indent*/ 1, Some(builderDumpIndex), Nothing());
378     }
379   }
380 
381   mWidget->AddWindowOverlayWebRenderCommands(WrBridge(), *mDLBuilder,
382                                              resourceUpdates);
383   if (dumpEnabled) {
384     printf_stderr("(window overlay)\n");
385     Unused << mDLBuilder->Dump(/*indent*/ 1, Some(builderDumpIndex), Nothing());
386   }
387 
388   if (AsyncPanZoomEnabled()) {
389     if (mIsFirstPaint) {
390       mScrollData.SetIsFirstPaint();
391       mIsFirstPaint = false;
392     }
393     mScrollData.SetPaintSequenceNumber(mPaintSequenceNumber);
394     if (dumpEnabled) {
395       std::stringstream str;
396       str << mScrollData;
397       print_stderr(str);
398     }
399   }
400 
401   // Since we're sending a full mScrollData that will include the new scroll
402   // offsets, and we can throw away the pending scroll updates we had kept for
403   // an empty transaction.
404   auto scrollIdsUpdated = ClearPendingScrollInfoUpdate();
405   for (ScrollableLayerGuid::ViewID update : scrollIdsUpdated) {
406     nsLayoutUtils::NotifyPaintSkipTransaction(update);
407   }
408 
409   mLatestTransactionId =
410       mTransactionIdAllocator->GetTransactionId(/*aThrottle*/ true);
411 
412   // Get the time of when the refresh driver start its tick (if available),
413   // otherwise use the time of when LayerManager::BeginTransaction was called.
414   TimeStamp refreshStart = mTransactionIdAllocator->GetTransactionStart();
415   if (!refreshStart) {
416     refreshStart = mTransactionStart;
417   }
418 
419   if (mStateManager.mAsyncResourceUpdates) {
420     if (resourceUpdates.IsEmpty()) {
421       resourceUpdates.ReplaceResources(
422           std::move(mStateManager.mAsyncResourceUpdates.ref()));
423     } else {
424       WrBridge()->UpdateResources(mStateManager.mAsyncResourceUpdates.ref());
425     }
426     mStateManager.mAsyncResourceUpdates.reset();
427   }
428   mStateManager.DiscardImagesInTransaction(resourceUpdates);
429 
430   WrBridge()->RemoveExpiredFontKeys(resourceUpdates);
431 
432   // Skip the synchronization for buffer since we also skip the painting during
433   // device-reset status.
434   if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) {
435     if (WrBridge()->GetSyncObject() &&
436         WrBridge()->GetSyncObject()->IsSyncObjectValid()) {
437       WrBridge()->GetSyncObject()->Synchronize();
438     }
439   }
440 
441   GetCompositorBridgeChild()->EndCanvasTransaction();
442 
443   {
444     AUTO_PROFILER_TRACING_MARKER("Paint", "ForwardDPTransaction", GRAPHICS);
445     DisplayListData dlData;
446     mDLBuilder->End(dlData);
447     resourceUpdates.Flush(dlData.mResourceUpdates, dlData.mSmallShmems,
448                           dlData.mLargeShmems);
449     dlData.mRect =
450         LayoutDeviceRect(LayoutDevicePoint(), LayoutDeviceSize(size));
451     dlData.mScrollData.emplace(std::move(mScrollData));
452     dlData.mDLDesc.gecko_display_list_type =
453         aDisplayListBuilder && aDisplayListBuilder->PartialBuildFailed()
454             ? wr::GeckoDisplayListType::Full(aGeckoDLBuildTime)
455             : wr::GeckoDisplayListType::Partial(aGeckoDLBuildTime);
456 
457     bool ret = WrBridge()->EndTransaction(
458         std::move(dlData), mLatestTransactionId, containsSVGGroup,
459         mTransactionIdAllocator->GetVsyncId(),
460         mTransactionIdAllocator->GetVsyncStart(), refreshStart,
461         mTransactionStart, mURL);
462     if (!ret) {
463       // Failed to send display list, reset display item cache state.
464       mDisplayItemCache.Clear();
465     }
466 
467     WrBridge()->SendSetFocusTarget(mFocusTarget);
468     mFocusTarget = FocusTarget();
469   }
470 
471   // Discard animations after calling WrBridge()->EndTransaction().
472   // It updates mWrEpoch in WebRenderBridgeParent. The updated mWrEpoch is
473   // necessary for deleting animations at the correct time.
474   mStateManager.DiscardCompositorAnimations();
475 
476   mTransactionStart = TimeStamp();
477 
478   MakeSnapshotIfRequired(size);
479   mNeedsComposite = false;
480 }
481 
SetFocusTarget(const FocusTarget & aFocusTarget)482 void WebRenderLayerManager::SetFocusTarget(const FocusTarget& aFocusTarget) {
483   mFocusTarget = aFocusTarget;
484 }
485 
AsyncPanZoomEnabled() const486 bool WebRenderLayerManager::AsyncPanZoomEnabled() const {
487   return mWidget->AsyncPanZoomEnabled();
488 }
489 
MakeSnapshotIfRequired(LayoutDeviceIntSize aSize)490 void WebRenderLayerManager::MakeSnapshotIfRequired(LayoutDeviceIntSize aSize) {
491   if (!mTarget || aSize.IsEmpty()) {
492     return;
493   }
494 
495   // XXX Add other TextureData supports.
496   // Only BufferTexture is supported now.
497 
498   // TODO: fixup for proper surface format.
499   // The GLES spec only guarantees that RGBA can be used with glReadPixels,
500   // so on Android we use RGBA.
501   SurfaceFormat format =
502 #ifdef MOZ_WIDGET_ANDROID
503       SurfaceFormat::R8G8B8A8;
504 #else
505       SurfaceFormat::B8G8R8A8;
506 #endif
507   RefPtr<TextureClient> texture = TextureClient::CreateForRawBufferAccess(
508       WrBridge(), format, aSize.ToUnknownSize(), BackendType::SKIA,
509       TextureFlags::SNAPSHOT);
510   if (!texture) {
511     return;
512   }
513 
514   texture->InitIPDLActor(WrBridge());
515   if (!texture->GetIPDLActor()) {
516     return;
517   }
518 
519   IntRect bounds = ToOutsideIntRect(mTarget->GetClipExtents());
520   bool needsYFlip = false;
521   if (!WrBridge()->SendGetSnapshot(texture->GetIPDLActor(), &needsYFlip)) {
522     return;
523   }
524 
525   TextureClientAutoLock autoLock(texture, OpenMode::OPEN_READ_ONLY);
526   if (!autoLock.Succeeded()) {
527     return;
528   }
529   RefPtr<DrawTarget> drawTarget = texture->BorrowDrawTarget();
530   if (!drawTarget || !drawTarget->IsValid()) {
531     return;
532   }
533   RefPtr<SourceSurface> snapshot = drawTarget->Snapshot();
534   /*
535     static int count = 0;
536     char filename[100];
537     snprintf(filename, 100, "output%d.png", count++);
538     printf_stderr("Writing to :%s\n", filename);
539     gfxUtils::WriteAsPNG(snapshot, filename);
540     */
541 
542   Rect dst(bounds.X(), bounds.Y(), bounds.Width(), bounds.Height());
543   Rect src(0, 0, bounds.Width(), bounds.Height());
544 
545   Matrix m;
546   if (needsYFlip) {
547     m = Matrix::Scaling(1.0, -1.0).PostTranslate(0.0, aSize.height);
548   }
549   SurfacePattern pattern(snapshot, ExtendMode::CLAMP, m);
550   DrawTarget* dt = mTarget->GetDrawTarget();
551   MOZ_RELEASE_ASSERT(dt);
552   dt->FillRect(dst, pattern);
553 
554   mTarget = nullptr;
555 }
556 
DiscardImages()557 void WebRenderLayerManager::DiscardImages() {
558   wr::IpcResourceUpdateQueue resources(WrBridge());
559   mStateManager.DiscardImagesInTransaction(resources);
560   WrBridge()->UpdateResources(resources);
561 }
562 
DiscardLocalImages()563 void WebRenderLayerManager::DiscardLocalImages() {
564   mStateManager.DiscardLocalImages();
565 }
566 
SetLayersObserverEpoch(LayersObserverEpoch aEpoch)567 void WebRenderLayerManager::SetLayersObserverEpoch(LayersObserverEpoch aEpoch) {
568   if (WrBridge()->IPCOpen()) {
569     WrBridge()->SendSetLayersObserverEpoch(aEpoch);
570   }
571 }
572 
DidComposite(TransactionId aTransactionId,const mozilla::TimeStamp & aCompositeStart,const mozilla::TimeStamp & aCompositeEnd)573 void WebRenderLayerManager::DidComposite(
574     TransactionId aTransactionId, const mozilla::TimeStamp& aCompositeStart,
575     const mozilla::TimeStamp& aCompositeEnd) {
576   if (IsDestroyed()) {
577     return;
578   }
579 
580   MOZ_ASSERT(mWidget);
581 
582   // Notifying the observers may tick the refresh driver which can cause
583   // a lot of different things to happen that may affect the lifetime of
584   // this layer manager. So let's make sure this object stays alive until
585   // the end of the method invocation.
586   RefPtr<WebRenderLayerManager> selfRef = this;
587 
588   // |aTransactionId| will be > 0 if the compositor is acknowledging a shadow
589   // layers transaction.
590   if (aTransactionId.IsValid()) {
591     nsIWidgetListener* listener = mWidget->GetWidgetListener();
592     if (listener) {
593       listener->DidCompositeWindow(aTransactionId, aCompositeStart,
594                                    aCompositeEnd);
595     }
596     listener = mWidget->GetAttachedWidgetListener();
597     if (listener) {
598       listener->DidCompositeWindow(aTransactionId, aCompositeStart,
599                                    aCompositeEnd);
600     }
601     if (mTransactionIdAllocator) {
602       mTransactionIdAllocator->NotifyTransactionCompleted(aTransactionId);
603     }
604   }
605 }
606 
ClearCachedResources()607 void WebRenderLayerManager::ClearCachedResources() {
608   if (!WrBridge()->IPCOpen()) {
609     gfxCriticalNote << "IPC Channel is already torn down unexpectedly\n";
610     return;
611   }
612   WrBridge()->BeginClearCachedResources();
613   // We flush any pending async resource updates before we clear the display
614   // list items because some resources (e.g. images) might be shared between
615   // multiple layer managers, not get freed here, and we want to keep their
616   // states consistent.
617   mStateManager.FlushAsyncResourceUpdates();
618   mWebRenderCommandBuilder.ClearCachedResources();
619   DiscardImages();
620   mStateManager.ClearCachedResources();
621   WrBridge()->EndClearCachedResources();
622 }
623 
WrUpdated()624 void WebRenderLayerManager::WrUpdated() {
625   ClearAsyncAnimations();
626   mStateManager.mAsyncResourceUpdates.reset();
627   mWebRenderCommandBuilder.ClearCachedResources();
628   DiscardLocalImages();
629   mDisplayItemCache.Clear();
630 
631   if (mWidget) {
632     if (dom::BrowserChild* browserChild = mWidget->GetOwningBrowserChild()) {
633       browserChild->SchedulePaint();
634     }
635   }
636 }
637 
UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier & aNewIdentifier)638 void WebRenderLayerManager::UpdateTextureFactoryIdentifier(
639     const TextureFactoryIdentifier& aNewIdentifier) {
640   WrBridge()->IdentifyTextureHost(aNewIdentifier);
641 }
642 
GetTextureFactoryIdentifier()643 TextureFactoryIdentifier WebRenderLayerManager::GetTextureFactoryIdentifier() {
644   return WrBridge()->GetTextureFactoryIdentifier();
645 }
646 
SetTransactionIdAllocator(TransactionIdAllocator * aAllocator)647 void WebRenderLayerManager::SetTransactionIdAllocator(
648     TransactionIdAllocator* aAllocator) {
649   // When changing the refresh driver, the previous refresh driver may never
650   // receive updates of pending transactions it's waiting for. So clear the
651   // waiting state before assigning another refresh driver.
652   if (mTransactionIdAllocator && (aAllocator != mTransactionIdAllocator)) {
653     mTransactionIdAllocator->ClearPendingTransactions();
654 
655     // We should also reset the transaction id of the new allocator to previous
656     // allocator's last transaction id, so that completed transactions for
657     // previous allocator will be ignored and won't confuse the new allocator.
658     if (aAllocator) {
659       aAllocator->ResetInitialTransactionId(
660           mTransactionIdAllocator->LastTransactionId());
661     }
662   }
663 
664   mTransactionIdAllocator = aAllocator;
665 }
666 
GetLastTransactionId()667 TransactionId WebRenderLayerManager::GetLastTransactionId() {
668   return mLatestTransactionId;
669 }
670 
FlushRendering(wr::RenderReasons aReasons)671 void WebRenderLayerManager::FlushRendering(wr::RenderReasons aReasons) {
672   CompositorBridgeChild* cBridge = GetCompositorBridgeChild();
673   if (!cBridge) {
674     return;
675   }
676   MOZ_ASSERT(mWidget);
677 
678   // If value of IsResizingNativeWidget() is nothing, we assume that resizing
679   // might happen.
680   bool resizing = mWidget && mWidget->IsResizingNativeWidget().valueOr(true);
681 
682   if (resizing) {
683     aReasons = aReasons | wr::RenderReasons::RESIZE;
684   }
685 
686   // Limit async FlushRendering to !resizing and Win DComp.
687   // XXX relax the limitation
688   if (WrBridge()->GetCompositorUseDComp() && !resizing) {
689     cBridge->SendFlushRenderingAsync(aReasons);
690   } else if (mWidget->SynchronouslyRepaintOnResize() ||
691              StaticPrefs::layers_force_synchronous_resize()) {
692     cBridge->SendFlushRendering(aReasons);
693   } else {
694     cBridge->SendFlushRenderingAsync(aReasons);
695   }
696 }
697 
WaitOnTransactionProcessed()698 void WebRenderLayerManager::WaitOnTransactionProcessed() {
699   CompositorBridgeChild* bridge = GetCompositorBridgeChild();
700   if (bridge) {
701     bridge->SendWaitOnTransactionProcessed();
702   }
703 }
704 
SendInvalidRegion(const nsIntRegion & aRegion)705 void WebRenderLayerManager::SendInvalidRegion(const nsIntRegion& aRegion) {
706   // XXX Webrender does not support invalid region yet.
707 
708 #ifdef XP_WIN
709   // When DWM is disabled, each window does not have own back buffer. They would
710   // paint directly to a buffer that was to be displayed by the video card.
711   // WM_PAINT via SendInvalidRegion() requests necessary re-paint.
712   const bool needsInvalidate = !gfx::gfxVars::DwmCompositionEnabled();
713 #else
714   const bool needsInvalidate = true;
715 #endif
716   if (needsInvalidate && WrBridge()) {
717     WrBridge()->SendInvalidateRenderedFrame();
718   }
719 }
720 
ScheduleComposite(wr::RenderReasons aReasons)721 void WebRenderLayerManager::ScheduleComposite(wr::RenderReasons aReasons) {
722   WrBridge()->SendScheduleComposite(aReasons);
723 }
724 
725 already_AddRefed<PersistentBufferProvider>
CreatePersistentBufferProvider(const gfx::IntSize & aSize,gfx::SurfaceFormat aFormat)726 WebRenderLayerManager::CreatePersistentBufferProvider(
727     const gfx::IntSize& aSize, gfx::SurfaceFormat aFormat) {
728   if (!gfxPlatform::UseRemoteCanvas()) {
729 #ifdef XP_WIN
730     // Any kind of hardware acceleration is incompatible with Win32k Lockdown
731     // We don't initialize devices here so that PersistentBufferProviderShared
732     // will fall back to using a piece of shared memory as a backing for the
733     // canvas
734     if (!IsWin32kLockedDown()) {
735       gfxPlatform::GetPlatform()->EnsureDevicesInitialized();
736     }
737 #else
738     gfxPlatform::GetPlatform()->EnsureDevicesInitialized();
739 #endif
740   }
741 
742   RefPtr<PersistentBufferProvider> provider =
743       PersistentBufferProviderShared::Create(aSize, aFormat,
744                                              AsKnowsCompositor());
745   if (provider) {
746     return provider.forget();
747   }
748 
749   return WindowRenderer::CreatePersistentBufferProvider(aSize, aFormat);
750 }
751 
ClearAsyncAnimations()752 void WebRenderLayerManager::ClearAsyncAnimations() {
753   mStateManager.ClearAsyncAnimations();
754 }
755 
WrReleasedImages(const nsTArray<wr::ExternalImageKeyPair> & aPairs)756 void WebRenderLayerManager::WrReleasedImages(
757     const nsTArray<wr::ExternalImageKeyPair>& aPairs) {
758   mStateManager.WrReleasedImages(aPairs);
759 }
760 
GetFrameUniformity(FrameUniformityData * aOutData)761 void WebRenderLayerManager::GetFrameUniformity(FrameUniformityData* aOutData) {
762   WrBridge()->SendGetFrameUniformity(aOutData);
763 }
764 
765 /*static*/
LayerUserDataDestroy(void * data)766 void WebRenderLayerManager::LayerUserDataDestroy(void* data) {
767   delete static_cast<LayerUserData*>(data);
768 }
769 
RemoveUserData(void * aKey)770 UniquePtr<LayerUserData> WebRenderLayerManager::RemoveUserData(void* aKey) {
771   UniquePtr<LayerUserData> d(static_cast<LayerUserData*>(
772       mUserData.Remove(static_cast<gfx::UserDataKey*>(aKey))));
773   return d;
774 }
775 
776 std::unordered_set<ScrollableLayerGuid::ViewID>
ClearPendingScrollInfoUpdate()777 WebRenderLayerManager::ClearPendingScrollInfoUpdate() {
778   std::unordered_set<ScrollableLayerGuid::ViewID> scrollIds(
779       mPendingScrollUpdates.Keys().cbegin(),
780       mPendingScrollUpdates.Keys().cend());
781   mPendingScrollUpdates.Clear();
782   return scrollIds;
783 }
784 
785 }  // namespace layers
786 }  // namespace mozilla
787