Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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/. */
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
34 using namespace mozilla::dom;
35 using namespace mozilla::gfx;
37 namespace mozilla {
38 namespace layers {
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 }
54 ClientLayerManager::~ClientLayerManager()
55 {
56 mRoot = nullptr;
58 MOZ_COUNT_DTOR(ClientLayerManager);
59 }
61 int32_t
62 ClientLayerManager::GetMaxTextureSize() const
63 {
64 return mForwarder->GetMaxTextureSize();
65 }
67 void
68 ClientLayerManager::SetDefaultTargetConfiguration(BufferMode aDoubleBuffering,
69 ScreenRotation aRotation)
70 {
71 mTargetRotation = aRotation;
72 if (mWidget) {
73 mTargetBounds = mWidget->GetNaturalBounds();
74 }
75 }
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 }
96 void
97 ClientLayerManager::Mutated(Layer* aLayer)
98 {
99 LayerManager::Mutated(aLayer);
101 NS_ASSERTION(InConstruction() || InDrawing(), "wrong phase");
102 mForwarder->Mutated(Hold(aLayer));
103 }
105 void
106 ClientLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
107 {
108 mInTransaction = true;
110 #ifdef MOZ_LAYERS_HAVE_LOG
111 MOZ_LAYERS_LOG(("[----- BeginTransaction"));
112 Log();
113 #endif
115 NS_ASSERTION(!InTransaction(), "Nested transactions not allowed");
116 mPhase = PHASE_CONSTRUCTION;
118 NS_ABORT_IF_FALSE(mKeepAlive.IsEmpty(), "uncommitted txn?");
119 nsRefPtr<gfxContext> targetContext = aTarget;
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);
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 }
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 }
155 void
156 ClientLayerManager::BeginTransaction()
157 {
158 mInTransaction = true;
159 BeginTransactionWithTarget(nullptr);
160 }
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);
174 NS_ASSERTION(InConstruction(), "Should be in construction phase");
175 mPhase = PHASE_DRAWING;
177 ClientLayer* root = ClientLayer::ToClientLayer(GetRoot());
179 mTransactionIncomplete = false;
181 // Apply pending tree updates before recomputing effective
182 // properties.
183 GetRoot()->ApplyPendingUpdatesToSubtree();
185 mThebesLayerCallback = aCallback;
186 mThebesLayerCallbackData = aCallbackData;
188 GetRoot()->ComputeEffectiveTransforms(Matrix4x4());
190 root->RenderLayer();
191 if (!mRepeatTransaction && !GetRoot()->GetInvalidRegion().IsEmpty()) {
192 GetRoot()->Mutated();
193 }
195 mThebesLayerCallback = nullptr;
196 mThebesLayerCallbackData = nullptr;
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;
202 NS_ASSERTION(!aCallback || !mTransactionIncomplete,
203 "If callback is not null, transaction must be complete");
205 return !mTransactionIncomplete;
206 }
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));
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 }
229 for (size_t i = 0; i < mTexturePools.Length(); i++) {
230 mTexturePools[i]->ReturnDeferredClients();
231 }
232 }
234 bool
235 ClientLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags)
236 {
237 mInTransaction = false;
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 }
256 CompositorChild *
257 ClientLayerManager::GetRemoteRenderer()
258 {
259 if (!mWidget) {
260 return nullptr;
261 }
263 return mWidget->GetRemoteRenderer();
264 }
266 void
267 ClientLayerManager::Composite()
268 {
269 if (LayerTransactionChild* manager = mForwarder->GetShadowManager()) {
270 manager->SendForceComposite();
271 }
272 }
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 }
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 }
322 void
323 ClientLayerManager::FlushRendering()
324 {
325 if (mWidget) {
326 if (CompositorChild* remoteRenderer = mWidget->GetRemoteRenderer()) {
327 remoteRenderer->SendFlushRendering();
328 }
329 }
330 }
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 }
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 }
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 }
364 void
365 ClientLayerManager::ForwardTransaction(bool aScheduleComposite)
366 {
367 mPhase = PHASE_FORWARD;
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];
376 switch (reply.type()) {
377 case EditReply::TOpContentBufferSwap: {
378 MOZ_LAYERS_LOG(("[LayersForwarder] DoubleBufferSwap"));
380 const OpContentBufferSwap& obs = reply.get_OpContentBufferSwap();
382 CompositableClient* compositable =
383 CompositableClient::FromIPDLActor(obs.compositableChild());
384 ContentClientRemote* contentClient =
385 static_cast<ContentClientRemote*>(compositable);
386 MOZ_ASSERT(contentClient);
388 contentClient->SwapBuffers(obs.frontUpdatedRegion());
390 break;
391 }
392 case EditReply::TOpTextureSwap: {
393 MOZ_LAYERS_LOG(("[LayersForwarder] TextureSwap"));
395 const OpTextureSwap& ots = reply.get_OpTextureSwap();
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();
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 }
418 default:
419 NS_RUNTIMEABORT("not reached");
420 }
421 }
423 if (sent) {
424 mNeedsComposite = false;
425 }
426 } else if (HasShadowManager()) {
427 NS_WARNING("failed to forward Layers transaction");
428 }
430 mForwarder->RemoveTexturesIfNecessary();
431 mPhase = PHASE_NONE;
433 // this may result in Layers being deleted, which results in
434 // PLayer::Send__delete__() and DeallocShmem()
435 mKeepAlive.Clear();
436 }
438 ShadowableLayer*
439 ClientLayerManager::Hold(Layer* aLayer)
440 {
441 NS_ABORT_IF_FALSE(HasShadowManager(),
442 "top-level tree, no shadow tree to remote to");
444 ShadowableLayer* shadowable = ClientLayer::ToClientLayer(aLayer);
445 NS_ABORT_IF_FALSE(shadowable, "trying to remote an unshadowable layer");
447 mKeepAlive.AppendElement(aLayer);
448 return shadowable;
449 }
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 }
459 void
460 ClientLayerManager::SetIsFirstPaint()
461 {
462 mForwarder->SetIsFirstPaint();
463 }
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 }
474 mTexturePools.AppendElement(
475 new TextureClientPool(aFormat, IntSize(gfxPrefs::LayersTileWidth(),
476 gfxPrefs::LayersTileHeight()),
477 mForwarder));
479 return mTexturePools.LastElement();
480 }
482 SimpleTextureClientPool*
483 ClientLayerManager::GetSimpleTileTexturePool(SurfaceFormat aFormat)
484 {
485 int index = (int) aFormat;
486 mSimpleTilePools.EnsureLengthAtLeast(index+1);
488 if (mSimpleTilePools[index].get() == nullptr) {
489 mSimpleTilePools[index] = new SimpleTextureClientPool(aFormat, IntSize(gfxPrefs::LayersTileWidth(),
490 gfxPrefs::LayersTileHeight()),
491 mForwarder);
492 }
494 return mSimpleTilePools[index];
495 }
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 }
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 }
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 }
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();
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;
557 return AndroidBridge::Bridge()->ProgressiveUpdateCallback(
558 aHasPendingNewThebesContent, displayPort, paintScale.scale, aDrawingCritical,
559 aCompositionBounds, aZoom);
560 }
561 #endif
563 return false;
564 }
566 ClientLayer::~ClientLayer()
567 {
568 if (HasShadow()) {
569 PLayerChild::Send__delete__(GetShadow());
570 }
571 MOZ_COUNT_DTOR(ClientLayer);
572 }
574 }
575 }