gfx/layers/client/ClientLayerManager.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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(&currentConfig);
   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 }

mercurial