Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include "WebRenderLayerManager.h"
7 :
8 : #include "gfxPrefs.h"
9 : #include "GeckoProfiler.h"
10 : #include "LayersLogging.h"
11 : #include "mozilla/gfx/DrawEventRecorder.h"
12 : #include "mozilla/layers/CompositorBridgeChild.h"
13 : #include "mozilla/layers/StackingContextHelper.h"
14 : #include "mozilla/layers/TextureClient.h"
15 : #include "mozilla/layers/WebRenderBridgeChild.h"
16 : #include "mozilla/layers/UpdateImageHelper.h"
17 : #include "WebRenderCanvasLayer.h"
18 : #include "WebRenderColorLayer.h"
19 : #include "WebRenderContainerLayer.h"
20 : #include "WebRenderImageLayer.h"
21 : #include "WebRenderPaintedLayer.h"
22 : #include "WebRenderPaintedLayerBlob.h"
23 : #include "WebRenderTextLayer.h"
24 : #include "WebRenderDisplayItemLayer.h"
25 :
26 : namespace mozilla {
27 :
28 : using namespace gfx;
29 :
30 : namespace layers {
31 :
32 0 : WebRenderLayerManager::WebRenderLayerManager(nsIWidget* aWidget)
33 : : mWidget(aWidget)
34 : , mLatestTransactionId(0)
35 : , mNeedsComposite(false)
36 : , mIsFirstPaint(false)
37 : , mEndTransactionWithoutLayers(false)
38 : , mTarget(nullptr)
39 0 : , mPaintSequenceNumber(0)
40 : {
41 0 : MOZ_COUNT_CTOR(WebRenderLayerManager);
42 0 : }
43 :
44 : KnowsCompositor*
45 0 : WebRenderLayerManager::AsKnowsCompositor()
46 : {
47 0 : return mWrChild;
48 : }
49 :
50 : void
51 0 : WebRenderLayerManager::Initialize(PCompositorBridgeChild* aCBChild,
52 : wr::PipelineId aLayersId,
53 : TextureFactoryIdentifier* aTextureFactoryIdentifier)
54 : {
55 0 : MOZ_ASSERT(mWrChild == nullptr);
56 0 : MOZ_ASSERT(aTextureFactoryIdentifier);
57 :
58 0 : LayoutDeviceIntSize size = mWidget->GetClientSize();
59 0 : TextureFactoryIdentifier textureFactoryIdentifier;
60 : uint32_t id_namespace;
61 : PWebRenderBridgeChild* bridge = aCBChild->SendPWebRenderBridgeConstructor(aLayersId,
62 : size,
63 : &textureFactoryIdentifier,
64 0 : &id_namespace);
65 0 : MOZ_ASSERT(bridge);
66 0 : mWrChild = static_cast<WebRenderBridgeChild*>(bridge);
67 0 : WrBridge()->SendCreate(size.ToUnknownSize());
68 0 : WrBridge()->IdentifyTextureHost(textureFactoryIdentifier);
69 0 : WrBridge()->SetNamespace(id_namespace);
70 0 : *aTextureFactoryIdentifier = textureFactoryIdentifier;
71 0 : }
72 :
73 : void
74 0 : WebRenderLayerManager::Destroy()
75 : {
76 0 : DoDestroy(/* aIsSync */ false);
77 0 : }
78 :
79 : void
80 0 : WebRenderLayerManager::DoDestroy(bool aIsSync)
81 : {
82 0 : if (IsDestroyed()) {
83 0 : return;
84 : }
85 :
86 0 : mWidget->CleanupWebRenderWindowOverlay(WrBridge());
87 :
88 0 : LayerManager::Destroy();
89 0 : DiscardImages();
90 0 : DiscardCompositorAnimations();
91 0 : WrBridge()->Destroy(aIsSync);
92 :
93 0 : if (mTransactionIdAllocator) {
94 : // Make sure to notify the refresh driver just in case it's waiting on a
95 : // pending transaction. Do this at the top of the event loop so we don't
96 : // cause a paint to occur during compositor shutdown.
97 0 : RefPtr<TransactionIdAllocator> allocator = mTransactionIdAllocator;
98 0 : uint64_t id = mLatestTransactionId;
99 :
100 0 : RefPtr<Runnable> task = NS_NewRunnableFunction(
101 : "TransactionIdAllocator::NotifyTransactionCompleted",
102 0 : [allocator, id] () -> void {
103 0 : allocator->NotifyTransactionCompleted(id);
104 0 : });
105 0 : NS_DispatchToMainThread(task.forget());
106 : }
107 :
108 : // Forget the widget pointer in case we outlive our owning widget.
109 0 : mWidget = nullptr;
110 : }
111 :
112 0 : WebRenderLayerManager::~WebRenderLayerManager()
113 : {
114 0 : Destroy();
115 0 : MOZ_COUNT_DTOR(WebRenderLayerManager);
116 0 : }
117 :
118 : CompositorBridgeChild*
119 0 : WebRenderLayerManager::GetCompositorBridgeChild()
120 : {
121 0 : return WrBridge()->GetCompositorBridgeChild();
122 : }
123 :
124 : int32_t
125 0 : WebRenderLayerManager::GetMaxTextureSize() const
126 : {
127 0 : return WrBridge()->GetMaxTextureSize();
128 : }
129 :
130 : bool
131 0 : WebRenderLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
132 : {
133 0 : mTarget = aTarget;
134 0 : return BeginTransaction();
135 : }
136 :
137 : bool
138 0 : WebRenderLayerManager::BeginTransaction()
139 : {
140 : // Increment the paint sequence number even if test logging isn't
141 : // enabled in this process; it may be enabled in the parent process,
142 : // and the parent process expects unique sequence numbers.
143 0 : ++mPaintSequenceNumber;
144 0 : if (gfxPrefs::APZTestLoggingEnabled()) {
145 0 : mApzTestData.StartNewPaint(mPaintSequenceNumber);
146 : }
147 0 : return true;
148 : }
149 :
150 : bool
151 0 : WebRenderLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags)
152 : {
153 0 : if (!mRoot) {
154 0 : return false;
155 : }
156 :
157 : // We might used painted layer images so don't delete them yet.
158 0 : return EndTransactionInternal(nullptr, nullptr, aFlags);
159 : }
160 :
161 : /*static*/ int32_t
162 0 : PopulateScrollData(WebRenderScrollData& aTarget, Layer* aLayer)
163 : {
164 0 : MOZ_ASSERT(aLayer);
165 :
166 : // We want to allocate a WebRenderLayerScrollData object for this layer,
167 : // but don't keep a pointer to it since it might get memmove'd during the
168 : // recursion below. Instead keep the index and get the pointer later.
169 0 : size_t index = aTarget.AddNewLayerData();
170 :
171 0 : int32_t descendants = 0;
172 0 : for (Layer* child = aLayer->GetLastChild(); child; child = child->GetPrevSibling()) {
173 0 : descendants += PopulateScrollData(aTarget, child);
174 : }
175 0 : aTarget.GetLayerDataMutable(index)->Initialize(aTarget, aLayer, descendants);
176 0 : return descendants + 1;
177 : }
178 :
179 : void
180 0 : WebRenderLayerManager::CreateWebRenderCommandsFromDisplayList(nsDisplayList* aDisplayList,
181 : nsDisplayListBuilder* aDisplayListBuilder,
182 : StackingContextHelper& aSc,
183 : wr::DisplayListBuilder& aBuilder)
184 : {
185 0 : nsDisplayList savedItems;
186 : nsDisplayItem* item;
187 0 : while ((item = aDisplayList->RemoveBottom()) != nullptr) {
188 0 : nsDisplayItem::Type itemType = item->GetType();
189 :
190 : // If the item is a event regions item, but is empty (has no regions in it)
191 : // then we should just throw it out
192 0 : if (itemType == nsDisplayItem::TYPE_LAYER_EVENT_REGIONS) {
193 : nsDisplayLayerEventRegions* eventRegions =
194 0 : static_cast<nsDisplayLayerEventRegions*>(item);
195 0 : if (eventRegions->IsEmpty()) {
196 0 : item->~nsDisplayItem();
197 0 : continue;
198 : }
199 : }
200 :
201 : // Peek ahead to the next item and try merging with it or swapping with it
202 : // if necessary.
203 : nsDisplayItem* aboveItem;
204 0 : while ((aboveItem = aDisplayList->GetBottom()) != nullptr) {
205 0 : if (aboveItem->TryMerge(item)) {
206 0 : aDisplayList->RemoveBottom();
207 0 : item->~nsDisplayItem();
208 0 : item = aboveItem;
209 0 : itemType = item->GetType();
210 : } else {
211 0 : break;
212 : }
213 : }
214 :
215 : nsDisplayList* itemSameCoordinateSystemChildren
216 0 : = item->GetSameCoordinateSystemChildren();
217 0 : if (item->ShouldFlattenAway(aDisplayListBuilder)) {
218 0 : aDisplayList->AppendToBottom(itemSameCoordinateSystemChildren);
219 0 : item->~nsDisplayItem();
220 0 : continue;
221 : }
222 :
223 0 : savedItems.AppendToTop(item);
224 :
225 0 : if (!item->CreateWebRenderCommands(aBuilder, aSc, mParentCommands, this,
226 0 : aDisplayListBuilder)) {
227 0 : PushItemAsImage(item, aBuilder, aSc, aDisplayListBuilder);
228 : }
229 : }
230 0 : aDisplayList->AppendToTop(&savedItems);
231 0 : }
232 :
233 : void
234 0 : WebRenderLayerManager::EndTransactionWithoutLayer(nsDisplayList* aDisplayList,
235 : nsDisplayListBuilder* aDisplayListBuilder)
236 : {
237 0 : MOZ_ASSERT(aDisplayList && aDisplayListBuilder);
238 0 : mEndTransactionWithoutLayers = true;
239 0 : DiscardImages();
240 0 : WrBridge()->RemoveExpiredFontKeys();
241 : EndTransactionInternal(nullptr,
242 : nullptr,
243 : EndTransactionFlags::END_DEFAULT,
244 : aDisplayList,
245 0 : aDisplayListBuilder);
246 0 : }
247 :
248 : Maybe<wr::ImageKey>
249 0 : WebRenderLayerManager::CreateImageKey(nsDisplayItem* aItem,
250 : ImageContainer* aContainer,
251 : mozilla::wr::DisplayListBuilder& aBuilder,
252 : const StackingContextHelper& aSc,
253 : gfx::IntSize& aSize)
254 : {
255 0 : RefPtr<WebRenderImageData> imageData = CreateOrRecycleWebRenderUserData<WebRenderImageData>(aItem);
256 0 : MOZ_ASSERT(imageData);
257 :
258 0 : if (aContainer->IsAsync()) {
259 : bool snap;
260 0 : nsRect bounds = aItem->GetBounds(nullptr, &snap);
261 0 : int32_t appUnitsPerDevPixel = aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
262 : LayerRect rect = ViewAs<LayerPixel>(
263 0 : LayoutDeviceRect::FromAppUnits(bounds, appUnitsPerDevPixel),
264 0 : PixelCastJustification::WebRenderHasUnitResolution);
265 0 : LayerRect scBounds(0, 0, rect.width, rect.height);
266 0 : imageData->CreateAsyncImageWebRenderCommands(aBuilder,
267 : aContainer,
268 : aSc,
269 : rect,
270 : scBounds,
271 0 : gfx::Matrix4x4(),
272 0 : Nothing(),
273 : wr::ImageRendering::Auto,
274 0 : wr::MixBlendMode::Normal);
275 0 : return Nothing();
276 : }
277 :
278 0 : AutoLockImage autoLock(aContainer);
279 0 : if (!autoLock.HasImage()) {
280 0 : return Nothing();
281 : }
282 0 : mozilla::layers::Image* image = autoLock.GetImage();
283 0 : aSize = image->GetSize();
284 :
285 0 : return imageData->UpdateImageKey(aContainer);
286 : }
287 :
288 : bool
289 0 : WebRenderLayerManager::PushImage(nsDisplayItem* aItem,
290 : ImageContainer* aContainer,
291 : mozilla::wr::DisplayListBuilder& aBuilder,
292 : const StackingContextHelper& aSc,
293 : const LayerRect& aRect)
294 : {
295 0 : gfx::IntSize size;
296 0 : Maybe<wr::ImageKey> key = CreateImageKey(aItem, aContainer, aBuilder, aSc, size);
297 0 : if (!key) {
298 0 : return false;
299 : }
300 :
301 0 : wr::ImageRendering filter = wr::ImageRendering::Auto;
302 0 : auto r = aSc.ToRelativeWrRect(aRect);
303 0 : aBuilder.PushImage(r, r, filter, key.value());
304 :
305 0 : return true;
306 : }
307 :
308 : static void
309 0 : PaintItemByDrawTarget(nsDisplayItem* aItem,
310 : DrawTarget* aDT,
311 : const LayerRect& aImageRect,
312 : const LayerPoint& aOffset,
313 : nsDisplayListBuilder* aDisplayListBuilder)
314 : {
315 0 : aDT->ClearRect(aImageRect.ToUnknownRect());
316 0 : RefPtr<gfxContext> context = gfxContext::CreateOrNull(aDT, aOffset.ToUnknownPoint());
317 0 : MOZ_ASSERT(context);
318 0 : aItem->Paint(aDisplayListBuilder, context);
319 :
320 0 : if (gfxPrefs::WebRenderHighlightPaintedLayers()) {
321 0 : aDT->SetTransform(Matrix());
322 0 : aDT->FillRect(Rect(0, 0, aImageRect.width, aImageRect.height), ColorPattern(Color(1.0, 0.0, 0.0, 0.5)));
323 : }
324 0 : if (aItem->Frame()->PresContext()->GetPaintFlashing()) {
325 0 : aDT->SetTransform(Matrix());
326 0 : float r = float(rand()) / RAND_MAX;
327 0 : float g = float(rand()) / RAND_MAX;
328 0 : float b = float(rand()) / RAND_MAX;
329 0 : aDT->FillRect(Rect(0, 0, aImageRect.width, aImageRect.height), ColorPattern(Color(r, g, b, 0.5)));
330 : }
331 0 : }
332 :
333 : bool
334 0 : WebRenderLayerManager::PushItemAsImage(nsDisplayItem* aItem,
335 : wr::DisplayListBuilder& aBuilder,
336 : const StackingContextHelper& aSc,
337 : nsDisplayListBuilder* aDisplayListBuilder)
338 : {
339 0 : RefPtr<WebRenderFallbackData> fallbackData = CreateOrRecycleWebRenderUserData<WebRenderFallbackData>(aItem);
340 :
341 : bool snap;
342 0 : nsRect itemBounds = aItem->GetBounds(aDisplayListBuilder, &snap);
343 0 : nsRect clippedBounds = itemBounds;
344 :
345 0 : const DisplayItemClip& clip = aItem->GetClip();
346 0 : if (clip.HasClip()) {
347 0 : clippedBounds = itemBounds.Intersect(clip.GetClipRect());
348 : }
349 :
350 0 : const int32_t appUnitsPerDevPixel = aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
351 : LayerRect bounds = ViewAs<LayerPixel>(
352 0 : LayoutDeviceRect::FromAppUnits(clippedBounds, appUnitsPerDevPixel),
353 0 : PixelCastJustification::WebRenderHasUnitResolution);
354 :
355 0 : LayerIntSize imageSize = RoundedToInt(bounds.Size());
356 0 : LayerRect imageRect;
357 0 : imageRect.SizeTo(LayerSize(imageSize));
358 0 : if (imageSize.width == 0 || imageSize.height == 0) {
359 0 : return true;
360 : }
361 :
362 0 : nsPoint shift = clippedBounds.TopLeft() - itemBounds.TopLeft();
363 : LayerPoint offset = ViewAs<LayerPixel>(
364 0 : LayoutDevicePoint::FromAppUnits(aItem->ToReferenceFrame() + shift, appUnitsPerDevPixel),
365 0 : PixelCastJustification::WebRenderHasUnitResolution);
366 :
367 0 : nsRegion invalidRegion;
368 0 : nsAutoPtr<nsDisplayItemGeometry> geometry = fallbackData->GetGeometry();
369 :
370 0 : if (geometry) {
371 0 : nsPoint shift = itemBounds.TopLeft() - geometry->mBounds.TopLeft();
372 0 : geometry->MoveBy(shift);
373 0 : aItem->ComputeInvalidationRegion(aDisplayListBuilder, geometry, &invalidRegion);
374 0 : nsRect lastBounds = fallbackData->GetBounds();
375 0 : lastBounds.MoveBy(shift);
376 :
377 0 : if (!lastBounds.IsEqualInterior(clippedBounds)) {
378 0 : invalidRegion.OrWith(lastBounds);
379 0 : invalidRegion.OrWith(clippedBounds);
380 : }
381 : }
382 :
383 0 : if (!geometry || !invalidRegion.IsEmpty()) {
384 0 : if (gfxPrefs::WebRenderBlobImages()) {
385 0 : RefPtr<gfx::DrawEventRecorderMemory> recorder = MakeAndAddRef<gfx::DrawEventRecorderMemory>();
386 : RefPtr<gfx::DrawTarget> dummyDt =
387 0 : gfx::Factory::CreateDrawTarget(gfx::BackendType::SKIA, gfx::IntSize(1, 1), gfx::SurfaceFormat::B8G8R8X8);
388 0 : RefPtr<gfx::DrawTarget> dt = gfx::Factory::CreateRecordingDrawTarget(recorder, dummyDt, imageSize.ToUnknownSize());
389 0 : PaintItemByDrawTarget(aItem, dt, imageRect, offset, aDisplayListBuilder);
390 0 : recorder->Finish();
391 :
392 0 : wr::ByteBuffer bytes(recorder->mOutputStream.mLength, (uint8_t*)recorder->mOutputStream.mData);
393 0 : wr::ImageKey key = WrBridge()->GetNextImageKey();
394 0 : WrBridge()->SendAddBlobImage(key, imageSize.ToUnknownSize(), imageSize.width * 4, dt->GetFormat(), bytes);
395 0 : fallbackData->SetKey(key);
396 : } else {
397 0 : fallbackData->CreateImageClientIfNeeded();
398 0 : RefPtr<ImageClient> imageClient = fallbackData->GetImageClient();
399 0 : RefPtr<ImageContainer> imageContainer = LayerManager::CreateImageContainer();
400 :
401 : {
402 0 : UpdateImageHelper helper(imageContainer, imageClient, imageSize.ToUnknownSize());
403 : {
404 0 : RefPtr<gfx::DrawTarget> dt = helper.GetDrawTarget();
405 0 : PaintItemByDrawTarget(aItem, dt, imageRect, offset, aDisplayListBuilder);
406 : }
407 0 : if (!helper.UpdateImage()) {
408 0 : return false;
409 : }
410 : }
411 :
412 : // Force update the key in fallback data since we repaint the image in this path.
413 : // If not force update, fallbackData may reuse the original key because it
414 : // doesn't know UpdateImageHelper already updated the image container.
415 0 : if (!fallbackData->UpdateImageKey(imageContainer, true)) {
416 0 : return false;
417 : }
418 : }
419 :
420 0 : geometry = aItem->AllocateGeometry(aDisplayListBuilder);
421 : }
422 :
423 : // Update current bounds to fallback data
424 0 : fallbackData->SetGeometry(Move(geometry));
425 0 : fallbackData->SetBounds(clippedBounds);
426 :
427 0 : MOZ_ASSERT(fallbackData->GetKey());
428 :
429 0 : WrRect dest = aSc.ToRelativeWrRect(imageRect + offset);
430 0 : aBuilder.PushImage(dest,
431 : dest,
432 : wr::ImageRendering::Auto,
433 0 : fallbackData->GetKey().value());
434 0 : return true;
435 : }
436 :
437 : void
438 0 : WebRenderLayerManager::EndTransaction(DrawPaintedLayerCallback aCallback,
439 : void* aCallbackData,
440 : EndTransactionFlags aFlags)
441 : {
442 0 : mEndTransactionWithoutLayers = false;
443 0 : DiscardImages();
444 0 : WrBridge()->RemoveExpiredFontKeys();
445 0 : EndTransactionInternal(aCallback, aCallbackData, aFlags);
446 0 : }
447 :
448 : bool
449 0 : WebRenderLayerManager::EndTransactionInternal(DrawPaintedLayerCallback aCallback,
450 : void* aCallbackData,
451 : EndTransactionFlags aFlags,
452 : nsDisplayList* aDisplayList,
453 : nsDisplayListBuilder* aDisplayListBuilder)
454 : {
455 0 : AutoProfilerTracing tracing("Paint", "RenderLayers");
456 0 : mPaintedLayerCallback = aCallback;
457 0 : mPaintedLayerCallbackData = aCallbackData;
458 0 : mTransactionIncomplete = false;
459 :
460 0 : if (gfxPrefs::LayersDump()) {
461 0 : this->Dump();
462 : }
463 :
464 : // Since we don't do repeat transactions right now, just set the time
465 0 : mAnimationReadyTime = TimeStamp::Now();
466 :
467 0 : LayoutDeviceIntSize size = mWidget->GetClientSize();
468 0 : if (!WrBridge()->DPBegin(size.ToUnknownSize())) {
469 0 : return false;
470 : }
471 0 : DiscardCompositorAnimations();
472 :
473 0 : WrSize contentSize { (float)size.width, (float)size.height };
474 0 : wr::DisplayListBuilder builder(WrBridge()->GetPipeline(), contentSize);
475 :
476 0 : if (mEndTransactionWithoutLayers) {
477 : // aDisplayList being null here means this is an empty transaction following a layers-free
478 : // transaction, so we reuse the previously built displaylist.
479 0 : if (aDisplayList && aDisplayListBuilder) {
480 0 : StackingContextHelper sc;
481 0 : mParentCommands.Clear();
482 0 : CreateWebRenderCommandsFromDisplayList(aDisplayList, aDisplayListBuilder, sc, builder);
483 0 : builder.Finalize(contentSize, mBuiltDisplayList);
484 : }
485 :
486 0 : builder.PushBuiltDisplayList(mBuiltDisplayList);
487 0 : WrBridge()->AddWebRenderParentCommands(mParentCommands);
488 : } else {
489 0 : mRoot->StartPendingAnimations(mAnimationReadyTime);
490 0 : StackingContextHelper sc;
491 :
492 0 : WebRenderLayer::ToWebRenderLayer(mRoot)->RenderLayer(builder, sc);
493 : }
494 :
495 0 : mWidget->AddWindowOverlayWebRenderCommands(WrBridge(), builder);
496 0 : WrBridge()->ClearReadLocks();
497 :
498 : // We can't finish this transaction so return. This usually
499 : // happens in an empty transaction where we can't repaint a painted layer.
500 : // In this case, leave the transaction open and let a full transaction happen.
501 0 : if (mTransactionIncomplete) {
502 0 : DiscardLocalImages();
503 0 : WrBridge()->ProcessWebRenderParentCommands();
504 0 : return false;
505 : }
506 :
507 0 : WebRenderScrollData scrollData;
508 0 : if (AsyncPanZoomEnabled()) {
509 0 : scrollData.SetFocusTarget(mFocusTarget);
510 0 : mFocusTarget = FocusTarget();
511 :
512 0 : if (mIsFirstPaint) {
513 0 : scrollData.SetIsFirstPaint();
514 0 : mIsFirstPaint = false;
515 : }
516 0 : scrollData.SetPaintSequenceNumber(mPaintSequenceNumber);
517 0 : if (mRoot) {
518 0 : PopulateScrollData(scrollData, mRoot.get());
519 : }
520 : }
521 :
522 0 : bool sync = mTarget != nullptr;
523 0 : mLatestTransactionId = mTransactionIdAllocator->GetTransactionId(/*aThrottle*/ true);
524 :
525 : {
526 : AutoProfilerTracing
527 0 : tracing("Paint", sync ? "ForwardDPTransactionSync":"ForwardDPTransaction");
528 0 : WrBridge()->DPEnd(builder, size.ToUnknownSize(), sync, mLatestTransactionId, scrollData);
529 : }
530 :
531 0 : MakeSnapshotIfRequired(size);
532 0 : mNeedsComposite = false;
533 :
534 0 : ClearDisplayItemLayers();
535 :
536 : // this may result in Layers being deleted, which results in
537 : // PLayer::Send__delete__() and DeallocShmem()
538 0 : mKeepAlive.Clear();
539 0 : ClearMutatedLayers();
540 :
541 0 : return true;
542 : }
543 :
544 : void
545 0 : WebRenderLayerManager::SetFocusTarget(const FocusTarget& aFocusTarget)
546 : {
547 0 : mFocusTarget = aFocusTarget;
548 0 : }
549 :
550 : bool
551 0 : WebRenderLayerManager::AsyncPanZoomEnabled() const
552 : {
553 0 : return mWidget->AsyncPanZoomEnabled();
554 : }
555 :
556 : void
557 0 : WebRenderLayerManager::MakeSnapshotIfRequired(LayoutDeviceIntSize aSize)
558 : {
559 0 : if (!mTarget || aSize.IsEmpty()) {
560 0 : return;
561 : }
562 :
563 : // XXX Add other TextureData supports.
564 : // Only BufferTexture is supported now.
565 :
566 : // TODO: fixup for proper surface format.
567 : RefPtr<TextureClient> texture =
568 0 : TextureClient::CreateForRawBufferAccess(WrBridge(),
569 : SurfaceFormat::B8G8R8A8,
570 : aSize.ToUnknownSize(),
571 : BackendType::SKIA,
572 0 : TextureFlags::SNAPSHOT);
573 0 : if (!texture) {
574 0 : return;
575 : }
576 :
577 0 : texture->InitIPDLActor(WrBridge());
578 0 : if (!texture->GetIPDLActor()) {
579 0 : return;
580 : }
581 :
582 0 : IntRect bounds = ToOutsideIntRect(mTarget->GetClipExtents());
583 0 : if (!WrBridge()->SendDPGetSnapshot(texture->GetIPDLActor())) {
584 0 : return;
585 : }
586 :
587 0 : TextureClientAutoLock autoLock(texture, OpenMode::OPEN_READ_ONLY);
588 0 : if (!autoLock.Succeeded()) {
589 0 : return;
590 : }
591 0 : RefPtr<DrawTarget> drawTarget = texture->BorrowDrawTarget();
592 0 : if (!drawTarget || !drawTarget->IsValid()) {
593 0 : return;
594 : }
595 0 : RefPtr<SourceSurface> snapshot = drawTarget->Snapshot();
596 : /*
597 : static int count = 0;
598 : char filename[100];
599 : snprintf(filename, 100, "output%d.png", count++);
600 : printf_stderr("Writing to :%s\n", filename);
601 : gfxUtils::WriteAsPNG(snapshot, filename);
602 : */
603 :
604 0 : Rect dst(bounds.x, bounds.y, bounds.width, bounds.height);
605 0 : Rect src(0, 0, bounds.width, bounds.height);
606 :
607 : // The data we get from webrender is upside down. So flip and translate up so the image is rightside up.
608 : // Webrender always does a full screen readback.
609 : SurfacePattern pattern(snapshot, ExtendMode::CLAMP,
610 0 : Matrix::Scaling(1.0, -1.0).PostTranslate(0.0, aSize.height));
611 0 : DrawTarget* dt = mTarget->GetDrawTarget();
612 0 : MOZ_RELEASE_ASSERT(dt);
613 0 : dt->FillRect(dst, pattern);
614 :
615 0 : mTarget = nullptr;
616 : }
617 :
618 : void
619 0 : WebRenderLayerManager::AddImageKeyForDiscard(wr::ImageKey key)
620 : {
621 0 : mImageKeys.push_back(key);
622 0 : }
623 :
624 : void
625 0 : WebRenderLayerManager::DiscardImages()
626 : {
627 0 : if (WrBridge()->IPCOpen()) {
628 0 : for (auto key : mImageKeys) {
629 0 : WrBridge()->SendDeleteImage(key);
630 : }
631 : }
632 0 : mImageKeys.clear();
633 0 : }
634 :
635 : void
636 0 : WebRenderLayerManager::AddCompositorAnimationsIdForDiscard(uint64_t aId)
637 : {
638 0 : mDiscardedCompositorAnimationsIds.AppendElement(aId);
639 0 : }
640 :
641 : void
642 0 : WebRenderLayerManager::DiscardCompositorAnimations()
643 : {
644 0 : if (WrBridge()->IPCOpen() && !mDiscardedCompositorAnimationsIds.IsEmpty()) {
645 0 : WrBridge()->
646 0 : SendDeleteCompositorAnimations(mDiscardedCompositorAnimationsIds);
647 : }
648 0 : mDiscardedCompositorAnimationsIds.Clear();
649 0 : }
650 :
651 : void
652 0 : WebRenderLayerManager::DiscardLocalImages()
653 : {
654 : // Removes images but doesn't tell the parent side about them
655 : // This is useful in empty / failed transactions where we created
656 : // image keys but didn't tell the parent about them yet.
657 0 : mImageKeys.clear();
658 0 : }
659 :
660 : void
661 0 : WebRenderLayerManager::Mutated(Layer* aLayer)
662 : {
663 0 : LayerManager::Mutated(aLayer);
664 0 : AddMutatedLayer(aLayer);
665 0 : }
666 :
667 : void
668 0 : WebRenderLayerManager::MutatedSimple(Layer* aLayer)
669 : {
670 0 : LayerManager::Mutated(aLayer);
671 0 : AddMutatedLayer(aLayer);
672 0 : }
673 :
674 : void
675 0 : WebRenderLayerManager::AddMutatedLayer(Layer* aLayer)
676 : {
677 0 : mMutatedLayers.AppendElement(aLayer);
678 0 : }
679 :
680 : void
681 0 : WebRenderLayerManager::ClearMutatedLayers()
682 : {
683 0 : mMutatedLayers.Clear();
684 0 : }
685 :
686 : bool
687 0 : WebRenderLayerManager::IsMutatedLayer(Layer* aLayer)
688 : {
689 0 : return mMutatedLayers.Contains(aLayer);
690 : }
691 :
692 : void
693 0 : WebRenderLayerManager::Hold(Layer* aLayer)
694 : {
695 0 : mKeepAlive.AppendElement(aLayer);
696 0 : }
697 :
698 : void
699 0 : WebRenderLayerManager::SetLayerObserverEpoch(uint64_t aLayerObserverEpoch)
700 : {
701 0 : WrBridge()->SendSetLayerObserverEpoch(aLayerObserverEpoch);
702 0 : }
703 :
704 : void
705 0 : WebRenderLayerManager::DidComposite(uint64_t aTransactionId,
706 : const mozilla::TimeStamp& aCompositeStart,
707 : const mozilla::TimeStamp& aCompositeEnd)
708 : {
709 0 : MOZ_ASSERT(mWidget);
710 :
711 : // |aTransactionId| will be > 0 if the compositor is acknowledging a shadow
712 : // layers transaction.
713 0 : if (aTransactionId) {
714 0 : nsIWidgetListener *listener = mWidget->GetWidgetListener();
715 0 : if (listener) {
716 0 : listener->DidCompositeWindow(aTransactionId, aCompositeStart, aCompositeEnd);
717 : }
718 0 : listener = mWidget->GetAttachedWidgetListener();
719 0 : if (listener) {
720 0 : listener->DidCompositeWindow(aTransactionId, aCompositeStart, aCompositeEnd);
721 : }
722 0 : mTransactionIdAllocator->NotifyTransactionCompleted(aTransactionId);
723 : }
724 :
725 : // These observers fire whether or not we were in a transaction.
726 0 : for (size_t i = 0; i < mDidCompositeObservers.Length(); i++) {
727 0 : mDidCompositeObservers[i]->DidComposite();
728 : }
729 0 : }
730 :
731 : void
732 0 : WebRenderLayerManager::ClearLayer(Layer* aLayer)
733 : {
734 0 : aLayer->ClearCachedResources();
735 0 : for (Layer* child = aLayer->GetFirstChild(); child;
736 : child = child->GetNextSibling()) {
737 0 : ClearLayer(child);
738 : }
739 0 : }
740 :
741 : void
742 0 : WebRenderLayerManager::ClearCachedResources(Layer* aSubtree)
743 : {
744 0 : WrBridge()->SendClearCachedResources();
745 0 : if (aSubtree) {
746 0 : ClearLayer(aSubtree);
747 0 : } else if (mRoot) {
748 0 : ClearLayer(mRoot);
749 : }
750 0 : }
751 :
752 : void
753 0 : WebRenderLayerManager::UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aNewIdentifier,
754 : uint64_t aDeviceResetSeqNo)
755 : {
756 0 : WrBridge()->IdentifyTextureHost(aNewIdentifier);
757 0 : }
758 :
759 : TextureFactoryIdentifier
760 0 : WebRenderLayerManager::GetTextureFactoryIdentifier()
761 : {
762 0 : return WrBridge()->GetTextureFactoryIdentifier();
763 : }
764 :
765 : void
766 0 : WebRenderLayerManager::AddDidCompositeObserver(DidCompositeObserver* aObserver)
767 : {
768 0 : if (!mDidCompositeObservers.Contains(aObserver)) {
769 0 : mDidCompositeObservers.AppendElement(aObserver);
770 : }
771 0 : }
772 :
773 : void
774 0 : WebRenderLayerManager::RemoveDidCompositeObserver(DidCompositeObserver* aObserver)
775 : {
776 0 : mDidCompositeObservers.RemoveElement(aObserver);
777 0 : }
778 :
779 : void
780 0 : WebRenderLayerManager::FlushRendering()
781 : {
782 0 : CompositorBridgeChild* cBridge = GetCompositorBridgeChild();
783 0 : if (!cBridge) {
784 0 : return;
785 : }
786 0 : MOZ_ASSERT(mWidget);
787 :
788 0 : if (mWidget->SynchronouslyRepaintOnResize() || gfxPrefs::LayersForceSynchronousResize()) {
789 0 : cBridge->SendFlushRendering();
790 : } else {
791 0 : cBridge->SendFlushRenderingAsync();
792 : }
793 : }
794 :
795 : void
796 0 : WebRenderLayerManager::WaitOnTransactionProcessed()
797 : {
798 0 : CompositorBridgeChild* bridge = GetCompositorBridgeChild();
799 0 : if (bridge) {
800 0 : bridge->SendWaitOnTransactionProcessed();
801 : }
802 0 : }
803 :
804 : void
805 0 : WebRenderLayerManager::SendInvalidRegion(const nsIntRegion& aRegion)
806 : {
807 : // XXX Webrender does not support invalid region yet.
808 0 : }
809 :
810 : void
811 0 : WebRenderLayerManager::ScheduleComposite()
812 : {
813 0 : WrBridge()->SendForceComposite();
814 0 : }
815 :
816 : void
817 0 : WebRenderLayerManager::SetRoot(Layer* aLayer)
818 : {
819 0 : mRoot = aLayer;
820 0 : }
821 :
822 : already_AddRefed<PaintedLayer>
823 0 : WebRenderLayerManager::CreatePaintedLayer()
824 : {
825 0 : if (gfxPrefs::WebRenderBlobImages()) {
826 0 : return MakeAndAddRef<WebRenderPaintedLayerBlob>(this);
827 : } else {
828 0 : return MakeAndAddRef<WebRenderPaintedLayer>(this);
829 : }
830 : }
831 :
832 : already_AddRefed<ContainerLayer>
833 0 : WebRenderLayerManager::CreateContainerLayer()
834 : {
835 0 : return MakeAndAddRef<WebRenderContainerLayer>(this);
836 : }
837 :
838 : already_AddRefed<ImageLayer>
839 0 : WebRenderLayerManager::CreateImageLayer()
840 : {
841 0 : return MakeAndAddRef<WebRenderImageLayer>(this);
842 : }
843 :
844 : already_AddRefed<CanvasLayer>
845 0 : WebRenderLayerManager::CreateCanvasLayer()
846 : {
847 0 : return MakeAndAddRef<WebRenderCanvasLayer>(this);
848 : }
849 :
850 : already_AddRefed<ReadbackLayer>
851 0 : WebRenderLayerManager::CreateReadbackLayer()
852 : {
853 0 : return nullptr;
854 : }
855 :
856 : already_AddRefed<ColorLayer>
857 0 : WebRenderLayerManager::CreateColorLayer()
858 : {
859 0 : return MakeAndAddRef<WebRenderColorLayer>(this);
860 : }
861 :
862 : already_AddRefed<RefLayer>
863 0 : WebRenderLayerManager::CreateRefLayer()
864 : {
865 0 : return MakeAndAddRef<WebRenderRefLayer>(this);
866 : }
867 :
868 : already_AddRefed<TextLayer>
869 0 : WebRenderLayerManager::CreateTextLayer()
870 : {
871 0 : return MakeAndAddRef<WebRenderTextLayer>(this);
872 : }
873 :
874 : already_AddRefed<BorderLayer>
875 0 : WebRenderLayerManager::CreateBorderLayer()
876 : {
877 0 : return nullptr;
878 : }
879 :
880 : already_AddRefed<DisplayItemLayer>
881 0 : WebRenderLayerManager::CreateDisplayItemLayer()
882 : {
883 0 : return MakeAndAddRef<WebRenderDisplayItemLayer>(this);
884 : }
885 :
886 : } // namespace layers
887 : } // namespace mozilla
|