|
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 "ClientLayerManager.h" |
|
7 #include "CompositorChild.h" // for CompositorChild |
|
8 #include "GeckoProfiler.h" // for PROFILER_LABEL |
|
9 #include "gfxPrefs.h" // for gfxPrefs::LayersTileWidth/Height |
|
10 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc |
|
11 #include "mozilla/Hal.h" |
|
12 #include "mozilla/dom/ScreenOrientation.h" // for ScreenOrientation |
|
13 #include "mozilla/dom/TabChild.h" // for TabChild |
|
14 #include "mozilla/hal_sandbox/PHal.h" // for ScreenConfiguration |
|
15 #include "mozilla/layers/CompositableClient.h" |
|
16 #include "mozilla/layers/ContentClient.h" |
|
17 #include "mozilla/layers/ISurfaceAllocator.h" |
|
18 #include "mozilla/layers/LayersMessages.h" // for EditReply, etc |
|
19 #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor |
|
20 #include "mozilla/layers/PLayerChild.h" // for PLayerChild |
|
21 #include "mozilla/layers/LayerTransactionChild.h" |
|
22 #include "mozilla/layers/TextureClientPool.h" // for TextureClientPool |
|
23 #include "mozilla/layers/SimpleTextureClientPool.h" // for SimpleTextureClientPool |
|
24 #include "nsAString.h" |
|
25 #include "nsIWidget.h" // for nsIWidget |
|
26 #include "nsIWidgetListener.h" |
|
27 #include "nsTArray.h" // for AutoInfallibleTArray |
|
28 #include "nsXULAppAPI.h" // for XRE_GetProcessType, etc |
|
29 #include "TiledLayerBuffer.h" |
|
30 #ifdef MOZ_WIDGET_ANDROID |
|
31 #include "AndroidBridge.h" |
|
32 #endif |
|
33 |
|
34 using namespace mozilla::dom; |
|
35 using namespace mozilla::gfx; |
|
36 |
|
37 namespace mozilla { |
|
38 namespace layers { |
|
39 |
|
40 ClientLayerManager::ClientLayerManager(nsIWidget* aWidget) |
|
41 : mPhase(PHASE_NONE) |
|
42 , mWidget(aWidget) |
|
43 , mTargetRotation(ROTATION_0) |
|
44 , mRepeatTransaction(false) |
|
45 , mIsRepeatTransaction(false) |
|
46 , mTransactionIncomplete(false) |
|
47 , mCompositorMightResample(false) |
|
48 , mNeedsComposite(false) |
|
49 , mForwarder(new ShadowLayerForwarder) |
|
50 { |
|
51 MOZ_COUNT_CTOR(ClientLayerManager); |
|
52 } |
|
53 |
|
54 ClientLayerManager::~ClientLayerManager() |
|
55 { |
|
56 mRoot = nullptr; |
|
57 |
|
58 MOZ_COUNT_DTOR(ClientLayerManager); |
|
59 } |
|
60 |
|
61 int32_t |
|
62 ClientLayerManager::GetMaxTextureSize() const |
|
63 { |
|
64 return mForwarder->GetMaxTextureSize(); |
|
65 } |
|
66 |
|
67 void |
|
68 ClientLayerManager::SetDefaultTargetConfiguration(BufferMode aDoubleBuffering, |
|
69 ScreenRotation aRotation) |
|
70 { |
|
71 mTargetRotation = aRotation; |
|
72 if (mWidget) { |
|
73 mTargetBounds = mWidget->GetNaturalBounds(); |
|
74 } |
|
75 } |
|
76 |
|
77 void |
|
78 ClientLayerManager::SetRoot(Layer* aLayer) |
|
79 { |
|
80 if (mRoot != aLayer) { |
|
81 // Have to hold the old root and its children in order to |
|
82 // maintain the same view of the layer tree in this process as |
|
83 // the parent sees. Otherwise layers can be destroyed |
|
84 // mid-transaction and bad things can happen (v. bug 612573) |
|
85 if (mRoot) { |
|
86 Hold(mRoot); |
|
87 } |
|
88 mForwarder->SetRoot(Hold(aLayer)); |
|
89 NS_ASSERTION(aLayer, "Root can't be null"); |
|
90 NS_ASSERTION(aLayer->Manager() == this, "Wrong manager"); |
|
91 NS_ASSERTION(InConstruction(), "Only allowed in construction phase"); |
|
92 mRoot = aLayer; |
|
93 } |
|
94 } |
|
95 |
|
96 void |
|
97 ClientLayerManager::Mutated(Layer* aLayer) |
|
98 { |
|
99 LayerManager::Mutated(aLayer); |
|
100 |
|
101 NS_ASSERTION(InConstruction() || InDrawing(), "wrong phase"); |
|
102 mForwarder->Mutated(Hold(aLayer)); |
|
103 } |
|
104 |
|
105 void |
|
106 ClientLayerManager::BeginTransactionWithTarget(gfxContext* aTarget) |
|
107 { |
|
108 mInTransaction = true; |
|
109 |
|
110 #ifdef MOZ_LAYERS_HAVE_LOG |
|
111 MOZ_LAYERS_LOG(("[----- BeginTransaction")); |
|
112 Log(); |
|
113 #endif |
|
114 |
|
115 NS_ASSERTION(!InTransaction(), "Nested transactions not allowed"); |
|
116 mPhase = PHASE_CONSTRUCTION; |
|
117 |
|
118 NS_ABORT_IF_FALSE(mKeepAlive.IsEmpty(), "uncommitted txn?"); |
|
119 nsRefPtr<gfxContext> targetContext = aTarget; |
|
120 |
|
121 // If the last transaction was incomplete (a failed DoEmptyTransaction), |
|
122 // don't signal a new transaction to ShadowLayerForwarder. Carry on adding |
|
123 // to the previous transaction. |
|
124 ScreenOrientation orientation; |
|
125 if (TabChild* window = mWidget->GetOwningTabChild()) { |
|
126 orientation = window->GetOrientation(); |
|
127 } else { |
|
128 hal::ScreenConfiguration currentConfig; |
|
129 hal::GetCurrentScreenConfiguration(¤tConfig); |
|
130 orientation = currentConfig.orientation(); |
|
131 } |
|
132 nsIntRect clientBounds; |
|
133 mWidget->GetClientBounds(clientBounds); |
|
134 clientBounds.x = clientBounds.y = 0; |
|
135 mForwarder->BeginTransaction(mTargetBounds, mTargetRotation, clientBounds, orientation); |
|
136 |
|
137 // If we're drawing on behalf of a context with async pan/zoom |
|
138 // enabled, then the entire buffer of thebes layers might be |
|
139 // composited (including resampling) asynchronously before we get |
|
140 // a chance to repaint, so we have to ensure that it's all valid |
|
141 // and not rotated. |
|
142 if (mWidget) { |
|
143 if (TabChild* window = mWidget->GetOwningTabChild()) { |
|
144 mCompositorMightResample = window->IsAsyncPanZoomEnabled(); |
|
145 } |
|
146 } |
|
147 |
|
148 // If we have a non-default target, we need to let our shadow manager draw |
|
149 // to it. This will happen at the end of the transaction. |
|
150 if (aTarget && XRE_GetProcessType() == GeckoProcessType_Default) { |
|
151 mShadowTarget = aTarget; |
|
152 } |
|
153 } |
|
154 |
|
155 void |
|
156 ClientLayerManager::BeginTransaction() |
|
157 { |
|
158 mInTransaction = true; |
|
159 BeginTransactionWithTarget(nullptr); |
|
160 } |
|
161 |
|
162 bool |
|
163 ClientLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback, |
|
164 void* aCallbackData, |
|
165 EndTransactionFlags) |
|
166 { |
|
167 PROFILER_LABEL("ClientLayerManager", "EndTransactionInternal"); |
|
168 #ifdef MOZ_LAYERS_HAVE_LOG |
|
169 MOZ_LAYERS_LOG((" ----- (beginning paint)")); |
|
170 Log(); |
|
171 #endif |
|
172 profiler_tracing("Paint", "Rasterize", TRACING_INTERVAL_START); |
|
173 |
|
174 NS_ASSERTION(InConstruction(), "Should be in construction phase"); |
|
175 mPhase = PHASE_DRAWING; |
|
176 |
|
177 ClientLayer* root = ClientLayer::ToClientLayer(GetRoot()); |
|
178 |
|
179 mTransactionIncomplete = false; |
|
180 |
|
181 // Apply pending tree updates before recomputing effective |
|
182 // properties. |
|
183 GetRoot()->ApplyPendingUpdatesToSubtree(); |
|
184 |
|
185 mThebesLayerCallback = aCallback; |
|
186 mThebesLayerCallbackData = aCallbackData; |
|
187 |
|
188 GetRoot()->ComputeEffectiveTransforms(Matrix4x4()); |
|
189 |
|
190 root->RenderLayer(); |
|
191 if (!mRepeatTransaction && !GetRoot()->GetInvalidRegion().IsEmpty()) { |
|
192 GetRoot()->Mutated(); |
|
193 } |
|
194 |
|
195 mThebesLayerCallback = nullptr; |
|
196 mThebesLayerCallbackData = nullptr; |
|
197 |
|
198 // Go back to the construction phase if the transaction isn't complete. |
|
199 // Layout will update the layer tree and call EndTransaction(). |
|
200 mPhase = mTransactionIncomplete ? PHASE_CONSTRUCTION : PHASE_NONE; |
|
201 |
|
202 NS_ASSERTION(!aCallback || !mTransactionIncomplete, |
|
203 "If callback is not null, transaction must be complete"); |
|
204 |
|
205 return !mTransactionIncomplete; |
|
206 } |
|
207 |
|
208 void |
|
209 ClientLayerManager::EndTransaction(DrawThebesLayerCallback aCallback, |
|
210 void* aCallbackData, |
|
211 EndTransactionFlags aFlags) |
|
212 { |
|
213 if (mWidget) { |
|
214 mWidget->PrepareWindowEffects(); |
|
215 } |
|
216 EndTransactionInternal(aCallback, aCallbackData, aFlags); |
|
217 ForwardTransaction(!(aFlags & END_NO_REMOTE_COMPOSITE)); |
|
218 |
|
219 if (mRepeatTransaction) { |
|
220 mRepeatTransaction = false; |
|
221 mIsRepeatTransaction = true; |
|
222 BeginTransaction(); |
|
223 ClientLayerManager::EndTransaction(aCallback, aCallbackData, aFlags); |
|
224 mIsRepeatTransaction = false; |
|
225 } else { |
|
226 MakeSnapshotIfRequired(); |
|
227 } |
|
228 |
|
229 for (size_t i = 0; i < mTexturePools.Length(); i++) { |
|
230 mTexturePools[i]->ReturnDeferredClients(); |
|
231 } |
|
232 } |
|
233 |
|
234 bool |
|
235 ClientLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags) |
|
236 { |
|
237 mInTransaction = false; |
|
238 |
|
239 if (!mRoot) { |
|
240 return false; |
|
241 } |
|
242 if (!EndTransactionInternal(nullptr, nullptr, aFlags)) { |
|
243 // Return without calling ForwardTransaction. This leaves the |
|
244 // ShadowLayerForwarder transaction open; the following |
|
245 // EndTransaction will complete it. |
|
246 return false; |
|
247 } |
|
248 if (mWidget) { |
|
249 mWidget->PrepareWindowEffects(); |
|
250 } |
|
251 ForwardTransaction(!(aFlags & END_NO_REMOTE_COMPOSITE)); |
|
252 MakeSnapshotIfRequired(); |
|
253 return true; |
|
254 } |
|
255 |
|
256 CompositorChild * |
|
257 ClientLayerManager::GetRemoteRenderer() |
|
258 { |
|
259 if (!mWidget) { |
|
260 return nullptr; |
|
261 } |
|
262 |
|
263 return mWidget->GetRemoteRenderer(); |
|
264 } |
|
265 |
|
266 void |
|
267 ClientLayerManager::Composite() |
|
268 { |
|
269 if (LayerTransactionChild* manager = mForwarder->GetShadowManager()) { |
|
270 manager->SendForceComposite(); |
|
271 } |
|
272 } |
|
273 |
|
274 void |
|
275 ClientLayerManager::DidComposite() |
|
276 { |
|
277 MOZ_ASSERT(mWidget); |
|
278 nsIWidgetListener *listener = mWidget->GetWidgetListener(); |
|
279 if (listener) { |
|
280 listener->DidCompositeWindow(); |
|
281 } |
|
282 listener = mWidget->GetAttachedWidgetListener(); |
|
283 if (listener) { |
|
284 listener->DidCompositeWindow(); |
|
285 } |
|
286 } |
|
287 |
|
288 void |
|
289 ClientLayerManager::MakeSnapshotIfRequired() |
|
290 { |
|
291 if (!mShadowTarget) { |
|
292 return; |
|
293 } |
|
294 if (mWidget) { |
|
295 if (CompositorChild* remoteRenderer = GetRemoteRenderer()) { |
|
296 nsIntRect bounds; |
|
297 mWidget->GetBounds(bounds); |
|
298 IntSize widgetSize = bounds.Size().ToIntSize(); |
|
299 SurfaceDescriptor inSnapshot, snapshot; |
|
300 if (mForwarder->AllocSurfaceDescriptor(widgetSize, |
|
301 gfxContentType::COLOR_ALPHA, |
|
302 &inSnapshot) && |
|
303 // The compositor will usually reuse |snapshot| and return |
|
304 // it through |outSnapshot|, but if it doesn't, it's |
|
305 // responsible for freeing |snapshot|. |
|
306 remoteRenderer->SendMakeSnapshot(inSnapshot, &snapshot)) { |
|
307 RefPtr<DataSourceSurface> surf = GetSurfaceForDescriptor(snapshot); |
|
308 DrawTarget* dt = mShadowTarget->GetDrawTarget(); |
|
309 Rect widgetRect(Point(0, 0), Size(widgetSize.width, widgetSize.height)); |
|
310 dt->DrawSurface(surf, widgetRect, widgetRect, |
|
311 DrawSurfaceOptions(), |
|
312 DrawOptions(1.0f, CompositionOp::OP_OVER)); |
|
313 } |
|
314 if (IsSurfaceDescriptorValid(snapshot)) { |
|
315 mForwarder->DestroySharedSurface(&snapshot); |
|
316 } |
|
317 } |
|
318 } |
|
319 mShadowTarget = nullptr; |
|
320 } |
|
321 |
|
322 void |
|
323 ClientLayerManager::FlushRendering() |
|
324 { |
|
325 if (mWidget) { |
|
326 if (CompositorChild* remoteRenderer = mWidget->GetRemoteRenderer()) { |
|
327 remoteRenderer->SendFlushRendering(); |
|
328 } |
|
329 } |
|
330 } |
|
331 |
|
332 void |
|
333 ClientLayerManager::SendInvalidRegion(const nsIntRegion& aRegion) |
|
334 { |
|
335 if (mWidget) { |
|
336 if (CompositorChild* remoteRenderer = mWidget->GetRemoteRenderer()) { |
|
337 remoteRenderer->SendNotifyRegionInvalidated(aRegion); |
|
338 } |
|
339 } |
|
340 } |
|
341 |
|
342 uint32_t |
|
343 ClientLayerManager::StartFrameTimeRecording(int32_t aBufferSize) |
|
344 { |
|
345 CompositorChild* renderer = GetRemoteRenderer(); |
|
346 if (renderer) { |
|
347 uint32_t startIndex; |
|
348 renderer->SendStartFrameTimeRecording(aBufferSize, &startIndex); |
|
349 return startIndex; |
|
350 } |
|
351 return -1; |
|
352 } |
|
353 |
|
354 void |
|
355 ClientLayerManager::StopFrameTimeRecording(uint32_t aStartIndex, |
|
356 nsTArray<float>& aFrameIntervals) |
|
357 { |
|
358 CompositorChild* renderer = GetRemoteRenderer(); |
|
359 if (renderer) { |
|
360 renderer->SendStopFrameTimeRecording(aStartIndex, &aFrameIntervals); |
|
361 } |
|
362 } |
|
363 |
|
364 void |
|
365 ClientLayerManager::ForwardTransaction(bool aScheduleComposite) |
|
366 { |
|
367 mPhase = PHASE_FORWARD; |
|
368 |
|
369 // forward this transaction's changeset to our LayerManagerComposite |
|
370 bool sent; |
|
371 AutoInfallibleTArray<EditReply, 10> replies; |
|
372 if (HasShadowManager() && mForwarder->EndTransaction(&replies, mRegionToClear, aScheduleComposite, &sent)) { |
|
373 for (nsTArray<EditReply>::size_type i = 0; i < replies.Length(); ++i) { |
|
374 const EditReply& reply = replies[i]; |
|
375 |
|
376 switch (reply.type()) { |
|
377 case EditReply::TOpContentBufferSwap: { |
|
378 MOZ_LAYERS_LOG(("[LayersForwarder] DoubleBufferSwap")); |
|
379 |
|
380 const OpContentBufferSwap& obs = reply.get_OpContentBufferSwap(); |
|
381 |
|
382 CompositableClient* compositable = |
|
383 CompositableClient::FromIPDLActor(obs.compositableChild()); |
|
384 ContentClientRemote* contentClient = |
|
385 static_cast<ContentClientRemote*>(compositable); |
|
386 MOZ_ASSERT(contentClient); |
|
387 |
|
388 contentClient->SwapBuffers(obs.frontUpdatedRegion()); |
|
389 |
|
390 break; |
|
391 } |
|
392 case EditReply::TOpTextureSwap: { |
|
393 MOZ_LAYERS_LOG(("[LayersForwarder] TextureSwap")); |
|
394 |
|
395 const OpTextureSwap& ots = reply.get_OpTextureSwap(); |
|
396 |
|
397 CompositableClient* compositable = |
|
398 CompositableClient::FromIPDLActor(ots.compositableChild()); |
|
399 MOZ_ASSERT(compositable); |
|
400 compositable->SetDescriptorFromReply(ots.textureId(), ots.image()); |
|
401 break; |
|
402 } |
|
403 case EditReply::TReturnReleaseFence: { |
|
404 const ReturnReleaseFence& rep = reply.get_ReturnReleaseFence(); |
|
405 FenceHandle fence = rep.fence(); |
|
406 PTextureChild* child = rep.textureChild(); |
|
407 |
|
408 if (!fence.IsValid() || !child) { |
|
409 break; |
|
410 } |
|
411 RefPtr<TextureClient> texture = TextureClient::AsTextureClient(child); |
|
412 if (texture) { |
|
413 texture->SetReleaseFenceHandle(fence); |
|
414 } |
|
415 break; |
|
416 } |
|
417 |
|
418 default: |
|
419 NS_RUNTIMEABORT("not reached"); |
|
420 } |
|
421 } |
|
422 |
|
423 if (sent) { |
|
424 mNeedsComposite = false; |
|
425 } |
|
426 } else if (HasShadowManager()) { |
|
427 NS_WARNING("failed to forward Layers transaction"); |
|
428 } |
|
429 |
|
430 mForwarder->RemoveTexturesIfNecessary(); |
|
431 mPhase = PHASE_NONE; |
|
432 |
|
433 // this may result in Layers being deleted, which results in |
|
434 // PLayer::Send__delete__() and DeallocShmem() |
|
435 mKeepAlive.Clear(); |
|
436 } |
|
437 |
|
438 ShadowableLayer* |
|
439 ClientLayerManager::Hold(Layer* aLayer) |
|
440 { |
|
441 NS_ABORT_IF_FALSE(HasShadowManager(), |
|
442 "top-level tree, no shadow tree to remote to"); |
|
443 |
|
444 ShadowableLayer* shadowable = ClientLayer::ToClientLayer(aLayer); |
|
445 NS_ABORT_IF_FALSE(shadowable, "trying to remote an unshadowable layer"); |
|
446 |
|
447 mKeepAlive.AppendElement(aLayer); |
|
448 return shadowable; |
|
449 } |
|
450 |
|
451 bool |
|
452 ClientLayerManager::IsCompositingCheap() |
|
453 { |
|
454 // Whether compositing is cheap depends on the parent backend. |
|
455 return mForwarder->mShadowManager && |
|
456 LayerManager::IsCompositingCheap(mForwarder->GetCompositorBackendType()); |
|
457 } |
|
458 |
|
459 void |
|
460 ClientLayerManager::SetIsFirstPaint() |
|
461 { |
|
462 mForwarder->SetIsFirstPaint(); |
|
463 } |
|
464 |
|
465 TextureClientPool* |
|
466 ClientLayerManager::GetTexturePool(SurfaceFormat aFormat) |
|
467 { |
|
468 for (size_t i = 0; i < mTexturePools.Length(); i++) { |
|
469 if (mTexturePools[i]->GetFormat() == aFormat) { |
|
470 return mTexturePools[i]; |
|
471 } |
|
472 } |
|
473 |
|
474 mTexturePools.AppendElement( |
|
475 new TextureClientPool(aFormat, IntSize(gfxPrefs::LayersTileWidth(), |
|
476 gfxPrefs::LayersTileHeight()), |
|
477 mForwarder)); |
|
478 |
|
479 return mTexturePools.LastElement(); |
|
480 } |
|
481 |
|
482 SimpleTextureClientPool* |
|
483 ClientLayerManager::GetSimpleTileTexturePool(SurfaceFormat aFormat) |
|
484 { |
|
485 int index = (int) aFormat; |
|
486 mSimpleTilePools.EnsureLengthAtLeast(index+1); |
|
487 |
|
488 if (mSimpleTilePools[index].get() == nullptr) { |
|
489 mSimpleTilePools[index] = new SimpleTextureClientPool(aFormat, IntSize(gfxPrefs::LayersTileWidth(), |
|
490 gfxPrefs::LayersTileHeight()), |
|
491 mForwarder); |
|
492 } |
|
493 |
|
494 return mSimpleTilePools[index]; |
|
495 } |
|
496 |
|
497 void |
|
498 ClientLayerManager::ClearCachedResources(Layer* aSubtree) |
|
499 { |
|
500 MOZ_ASSERT(!HasShadowManager() || !aSubtree); |
|
501 if (LayerTransactionChild* manager = mForwarder->GetShadowManager()) { |
|
502 manager->SendClearCachedResources(); |
|
503 } |
|
504 if (aSubtree) { |
|
505 ClearLayer(aSubtree); |
|
506 } else if (mRoot) { |
|
507 ClearLayer(mRoot); |
|
508 } |
|
509 for (size_t i = 0; i < mTexturePools.Length(); i++) { |
|
510 mTexturePools[i]->Clear(); |
|
511 } |
|
512 } |
|
513 |
|
514 void |
|
515 ClientLayerManager::ClearLayer(Layer* aLayer) |
|
516 { |
|
517 ClientLayer::ToClientLayer(aLayer)->ClearCachedResources(); |
|
518 for (Layer* child = aLayer->GetFirstChild(); child; |
|
519 child = child->GetNextSibling()) { |
|
520 ClearLayer(child); |
|
521 } |
|
522 } |
|
523 |
|
524 void |
|
525 ClientLayerManager::GetBackendName(nsAString& aName) |
|
526 { |
|
527 switch (mForwarder->GetCompositorBackendType()) { |
|
528 case LayersBackend::LAYERS_BASIC: aName.AssignLiteral("Basic"); return; |
|
529 case LayersBackend::LAYERS_OPENGL: aName.AssignLiteral("OpenGL"); return; |
|
530 case LayersBackend::LAYERS_D3D9: aName.AssignLiteral("Direct3D 9"); return; |
|
531 case LayersBackend::LAYERS_D3D10: aName.AssignLiteral("Direct3D 10"); return; |
|
532 case LayersBackend::LAYERS_D3D11: aName.AssignLiteral("Direct3D 11"); return; |
|
533 default: NS_RUNTIMEABORT("Invalid backend"); |
|
534 } |
|
535 } |
|
536 |
|
537 bool |
|
538 ClientLayerManager::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, |
|
539 ParentLayerRect& aCompositionBounds, |
|
540 CSSToParentLayerScale& aZoom, |
|
541 bool aDrawingCritical) |
|
542 { |
|
543 aZoom.scale = 1.0; |
|
544 #ifdef MOZ_WIDGET_ANDROID |
|
545 Layer* primaryScrollable = GetPrimaryScrollableLayer(); |
|
546 if (primaryScrollable) { |
|
547 const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics(); |
|
548 |
|
549 // This is derived from the code in |
|
550 // gfx/layers/ipc/CompositorParent.cpp::TransformShadowTree. |
|
551 CSSToLayerScale paintScale = metrics.LayersPixelsPerCSSPixel(); |
|
552 const CSSRect& metricsDisplayPort = |
|
553 (aDrawingCritical && !metrics.mCriticalDisplayPort.IsEmpty()) ? |
|
554 metrics.mCriticalDisplayPort : metrics.mDisplayPort; |
|
555 LayerRect displayPort = (metricsDisplayPort + metrics.GetScrollOffset()) * paintScale; |
|
556 |
|
557 return AndroidBridge::Bridge()->ProgressiveUpdateCallback( |
|
558 aHasPendingNewThebesContent, displayPort, paintScale.scale, aDrawingCritical, |
|
559 aCompositionBounds, aZoom); |
|
560 } |
|
561 #endif |
|
562 |
|
563 return false; |
|
564 } |
|
565 |
|
566 ClientLayer::~ClientLayer() |
|
567 { |
|
568 if (HasShadow()) { |
|
569 PLayerChild::Send__delete__(GetShadow()); |
|
570 } |
|
571 MOZ_COUNT_DTOR(ClientLayer); |
|
572 } |
|
573 |
|
574 } |
|
575 } |