gfx/layers/ipc/CompositorParent.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

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 /* vim: set sw=2 ts=2 et 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/. */
     7 #include "CompositorParent.h"
     8 #include <stdio.h>                      // for fprintf, stdout
     9 #include <stdint.h>                     // for uint64_t
    10 #include <map>                          // for _Rb_tree_iterator, etc
    11 #include <utility>                      // for pair
    12 #include "LayerTransactionParent.h"     // for LayerTransactionParent
    13 #include "RenderTrace.h"                // for RenderTraceLayers
    14 #include "base/message_loop.h"          // for MessageLoop
    15 #include "base/process.h"               // for ProcessHandle
    16 #include "base/process_util.h"          // for OpenProcessHandle
    17 #include "base/task.h"                  // for CancelableTask, etc
    18 #include "base/thread.h"                // for Thread
    19 #include "base/tracked.h"               // for FROM_HERE
    20 #include "gfxContext.h"                 // for gfxContext
    21 #include "gfxPlatform.h"                // for gfxPlatform
    22 #include "gfxPrefs.h"                   // for gfxPrefs
    23 #include "ipc/ShadowLayersManager.h"    // for ShadowLayersManager
    24 #include "mozilla/AutoRestore.h"        // for AutoRestore
    25 #include "mozilla/DebugOnly.h"          // for DebugOnly
    26 #include "mozilla/gfx/2D.h"          // for DrawTarget
    27 #include "mozilla/gfx/Point.h"          // for IntSize
    28 #include "mozilla/ipc/Transport.h"      // for Transport
    29 #include "mozilla/layers/APZCTreeManager.h"  // for APZCTreeManager
    30 #include "mozilla/layers/AsyncCompositionManager.h"
    31 #include "mozilla/layers/BasicCompositor.h"  // for BasicCompositor
    32 #include "mozilla/layers/Compositor.h"  // for Compositor
    33 #include "mozilla/layers/CompositorOGL.h"  // for CompositorOGL
    34 #include "mozilla/layers/CompositorTypes.h"
    35 #include "mozilla/layers/LayerManagerComposite.h"
    36 #include "mozilla/layers/LayersTypes.h"
    37 #include "mozilla/layers/PLayerTransactionParent.h"
    38 #include "mozilla/mozalloc.h"           // for operator new, etc
    39 #include "nsCOMPtr.h"                   // for already_AddRefed
    40 #include "nsDebug.h"                    // for NS_ABORT_IF_FALSE, etc
    41 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
    42 #include "nsIWidget.h"                  // for nsIWidget
    43 #include "nsRect.h"                     // for nsIntRect
    44 #include "nsTArray.h"                   // for nsTArray
    45 #include "nsThreadUtils.h"              // for NS_IsMainThread
    46 #include "nsXULAppAPI.h"                // for XRE_GetIOMessageLoop
    47 #ifdef XP_WIN
    48 #include "mozilla/layers/CompositorD3D11.h"
    49 #include "mozilla/layers/CompositorD3D9.h"
    50 #endif
    51 #include "GeckoProfiler.h"
    52 #include "mozilla/ipc/ProtocolTypes.h"
    53 #include "mozilla/unused.h"
    55 using namespace base;
    56 using namespace mozilla;
    57 using namespace mozilla::ipc;
    58 using namespace mozilla::gfx;
    59 using namespace std;
    61 namespace mozilla {
    62 namespace layers {
    64 CompositorParent::LayerTreeState::LayerTreeState()
    65   : mParent(nullptr)
    66   , mLayerManager(nullptr)
    67   , mCrossProcessParent(nullptr)
    68 {
    69 }
    71 typedef map<uint64_t, CompositorParent::LayerTreeState> LayerTreeMap;
    72 static LayerTreeMap sIndirectLayerTrees;
    74 // FIXME/bug 774386: we're assuming that there's only one
    75 // CompositorParent, but that's not always true.  This assumption only
    76 // affects CrossProcessCompositorParent below.
    77 static Thread* sCompositorThread = nullptr;
    78 // manual reference count of the compositor thread.
    79 static int sCompositorThreadRefCount = 0;
    80 static MessageLoop* sMainLoop = nullptr;
    81 // When ContentParent::StartUp() is called, we use the Thread global.
    82 // When StartUpWithExistingThread() is used, we have to use the two
    83 // duplicated globals, because there's no API to make a Thread from an
    84 // existing thread.
    85 static PlatformThreadId sCompositorThreadID = 0;
    86 static MessageLoop* sCompositorLoop = nullptr;
    88 // See ImageBridgeChild.cpp
    89 void ReleaseImageBridgeParentSingleton();
    91 static void DeferredDeleteCompositorParent(CompositorParent* aNowReadyToDie)
    92 {
    93   aNowReadyToDie->Release();
    94 }
    96 static void DeleteCompositorThread()
    97 {
    98   if (NS_IsMainThread()){
    99     ReleaseImageBridgeParentSingleton();
   100     delete sCompositorThread;
   101     sCompositorThread = nullptr;
   102     sCompositorLoop = nullptr;
   103     sCompositorThreadID = 0;
   104   } else {
   105     sMainLoop->PostTask(FROM_HERE, NewRunnableFunction(&DeleteCompositorThread));
   106   }
   107 }
   109 static void ReleaseCompositorThread()
   110 {
   111   if(--sCompositorThreadRefCount == 0) {
   112     DeleteCompositorThread();
   113   }
   114 }
   116 void
   117 CompositorParent::StartUpWithExistingThread(MessageLoop* aMsgLoop,
   118                                             PlatformThreadId aThreadID)
   119 {
   120   MOZ_ASSERT(!sCompositorThread);
   121   CreateCompositorMap();
   122   sCompositorLoop = aMsgLoop;
   123   sCompositorThreadID = aThreadID;
   124   sMainLoop = MessageLoop::current();
   125   sCompositorThreadRefCount = 1;
   126 }
   128 void CompositorParent::StartUp()
   129 {
   130   // Check if compositor started already with StartUpWithExistingThread
   131   if (sCompositorThreadID) {
   132     return;
   133   }
   134   MOZ_ASSERT(!sCompositorLoop);
   135   CreateCompositorMap();
   136   CreateThread();
   137   sMainLoop = MessageLoop::current();
   138 }
   140 void CompositorParent::ShutDown()
   141 {
   142   DestroyThread();
   143   DestroyCompositorMap();
   144 }
   146 bool CompositorParent::CreateThread()
   147 {
   148   NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
   149   if (sCompositorThread || sCompositorLoop) {
   150     return true;
   151   }
   152   sCompositorThreadRefCount = 1;
   153   sCompositorThread = new Thread("Compositor");
   155   Thread::Options options;
   156   /* Timeout values are powers-of-two to enable us get better data.
   157      128ms is chosen for transient hangs because 8Hz should be the minimally
   158      acceptable goal for Compositor responsiveness (normal goal is 60Hz). */
   159   options.transient_hang_timeout = 128; // milliseconds
   160   /* 8192ms is chosen for permanent hangs because it's several seconds longer
   161      than the default hang timeout on major platforms (about 5 seconds). */
   162   options.permanent_hang_timeout = 8192; // milliseconds
   164   if (!sCompositorThread->StartWithOptions(options)) {
   165     delete sCompositorThread;
   166     sCompositorThread = nullptr;
   167     return false;
   168   }
   169   return true;
   170 }
   172 void CompositorParent::DestroyThread()
   173 {
   174   NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
   175   ReleaseCompositorThread();
   176 }
   178 MessageLoop* CompositorParent::CompositorLoop()
   179 {
   180   return sCompositorThread ? sCompositorThread->message_loop() : sCompositorLoop;
   181 }
   183 CompositorParent::CompositorParent(nsIWidget* aWidget,
   184                                    bool aUseExternalSurfaceSize,
   185                                    int aSurfaceWidth, int aSurfaceHeight)
   186   : mWidget(aWidget)
   187   , mCurrentCompositeTask(nullptr)
   188   , mIsTesting(false)
   189   , mPaused(false)
   190   , mUseExternalSurfaceSize(aUseExternalSurfaceSize)
   191   , mEGLSurfaceSize(aSurfaceWidth, aSurfaceHeight)
   192   , mPauseCompositionMonitor("PauseCompositionMonitor")
   193   , mResumeCompositionMonitor("ResumeCompositionMonitor")
   194   , mOverrideComposeReadiness(false)
   195   , mForceCompositionTask(nullptr)
   196   , mWantDidCompositeEvent(false)
   197 {
   198   NS_ABORT_IF_FALSE(sCompositorThread != nullptr || sCompositorThreadID,
   199                     "The compositor thread must be Initialized before instanciating a COmpositorParent.");
   200   MOZ_COUNT_CTOR(CompositorParent);
   201   mCompositorID = 0;
   202   // FIXME: This holds on the the fact that right now the only thing that
   203   // can destroy this instance is initialized on the compositor thread after
   204   // this task has been processed.
   205   CompositorLoop()->PostTask(FROM_HERE, NewRunnableFunction(&AddCompositor,
   206                                                           this, &mCompositorID));
   208   mRootLayerTreeID = AllocateLayerTreeId();
   209   sIndirectLayerTrees[mRootLayerTreeID].mParent = this;
   211   mApzcTreeManager = new APZCTreeManager();
   212   ++sCompositorThreadRefCount;
   213 }
   215 PlatformThreadId
   216 CompositorParent::CompositorThreadID()
   217 {
   218   return sCompositorThread ? sCompositorThread->thread_id() : sCompositorThreadID;
   219 }
   221 bool
   222 CompositorParent::IsInCompositorThread()
   223 {
   224   return CompositorThreadID() == PlatformThread::CurrentId();
   225 }
   227 uint64_t
   228 CompositorParent::RootLayerTreeId()
   229 {
   230   return mRootLayerTreeID;
   231 }
   233 CompositorParent::~CompositorParent()
   234 {
   235   MOZ_COUNT_DTOR(CompositorParent);
   237   ReleaseCompositorThread();
   238 }
   240 void
   241 CompositorParent::Destroy()
   242 {
   243   NS_ABORT_IF_FALSE(ManagedPLayerTransactionParent().Length() == 0,
   244                     "CompositorParent destroyed before managed PLayerTransactionParent");
   246   // Ensure that the layer manager is destructed on the compositor thread.
   247   mLayerManager = nullptr;
   248   mCompositor = nullptr;
   249   mCompositionManager = nullptr;
   250   mApzcTreeManager->ClearTree();
   251   mApzcTreeManager = nullptr;
   252   sIndirectLayerTrees.erase(mRootLayerTreeID);
   253 }
   255 void
   256 CompositorParent::ForceIsFirstPaint()
   257 {
   258   mCompositionManager->ForceIsFirstPaint();
   259 }
   261 bool
   262 CompositorParent::RecvWillStop()
   263 {
   264   mPaused = true;
   265   RemoveCompositor(mCompositorID);
   267   // Ensure that the layer manager is destroyed before CompositorChild.
   268   if (mLayerManager) {
   269     for (LayerTreeMap::iterator it = sIndirectLayerTrees.begin();
   270          it != sIndirectLayerTrees.end(); it++)
   271     {
   272       LayerTreeState* lts = &it->second;
   273       if (lts->mParent == this) {
   274         mLayerManager->ClearCachedResources(lts->mRoot);
   275         lts->mLayerManager = nullptr;
   276       }
   277     }
   278     mLayerManager->Destroy();
   279     mLayerManager = nullptr;
   280     mCompositor = nullptr;
   281     mCompositionManager = nullptr;
   282   }
   284   return true;
   285 }
   287 bool
   288 CompositorParent::RecvStop()
   289 {
   290   Destroy();
   291   // There are chances that the ref count reaches zero on the main thread shortly
   292   // after this function returns while some ipdl code still needs to run on
   293   // this thread.
   294   // We must keep the compositor parent alive untill the code handling message
   295   // reception is finished on this thread.
   296   this->AddRef(); // Corresponds to DeferredDeleteCompositorParent's Release
   297   CompositorLoop()->PostTask(FROM_HERE,
   298                            NewRunnableFunction(&DeferredDeleteCompositorParent,
   299                                                this));
   300   return true;
   301 }
   303 bool
   304 CompositorParent::RecvPause()
   305 {
   306   PauseComposition();
   307   return true;
   308 }
   310 bool
   311 CompositorParent::RecvResume()
   312 {
   313   ResumeComposition();
   314   return true;
   315 }
   317 bool
   318 CompositorParent::RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
   319                                    SurfaceDescriptor* aOutSnapshot)
   320 {
   321   RefPtr<DrawTarget> target = GetDrawTargetForDescriptor(aInSnapshot, gfx::BackendType::CAIRO);
   322   ForceComposeToTarget(target);
   323   *aOutSnapshot = aInSnapshot;
   324   return true;
   325 }
   327 bool
   328 CompositorParent::RecvFlushRendering()
   329 {
   330   // If we're waiting to do a composite, then cancel it
   331   // and do it immediately instead.
   332   if (mCurrentCompositeTask) {
   333     CancelCurrentCompositeTask();
   334     ForceComposeToTarget(nullptr);
   335   }
   336   return true;
   337 }
   339 bool
   340 CompositorParent::RecvNotifyRegionInvalidated(const nsIntRegion& aRegion)
   341 {
   342   if (mLayerManager) {
   343     mLayerManager->AddInvalidRegion(aRegion);
   344   }
   345   return true;
   346 }
   348 bool
   349 CompositorParent::RecvStartFrameTimeRecording(const int32_t& aBufferSize, uint32_t* aOutStartIndex)
   350 {
   351   if (mLayerManager) {
   352     *aOutStartIndex = mLayerManager->StartFrameTimeRecording(aBufferSize);
   353   } else {
   354     *aOutStartIndex = 0;
   355   }
   356   return true;
   357 }
   359 bool
   360 CompositorParent::RecvStopFrameTimeRecording(const uint32_t& aStartIndex,
   361                                              InfallibleTArray<float>* intervals)
   362 {
   363   if (mLayerManager) {
   364     mLayerManager->StopFrameTimeRecording(aStartIndex, *intervals);
   365   }
   366   return true;
   367 }
   369 void
   370 CompositorParent::ActorDestroy(ActorDestroyReason why)
   371 {
   372   CancelCurrentCompositeTask();
   373   if (mForceCompositionTask) {
   374     mForceCompositionTask->Cancel();
   375     mForceCompositionTask = nullptr;
   376   }
   377   mPaused = true;
   378   RemoveCompositor(mCompositorID);
   380   if (mLayerManager) {
   381     mLayerManager->Destroy();
   382     mLayerManager = nullptr;
   383     sIndirectLayerTrees[mRootLayerTreeID].mLayerManager = nullptr;
   384     mCompositionManager = nullptr;
   385     mCompositor = nullptr;
   386   }
   387 }
   390 void
   391 CompositorParent::ScheduleRenderOnCompositorThread()
   392 {
   393   CancelableTask *renderTask = NewRunnableMethod(this, &CompositorParent::ScheduleComposition);
   394   CompositorLoop()->PostTask(FROM_HERE, renderTask);
   395 }
   397 void
   398 CompositorParent::PauseComposition()
   399 {
   400   NS_ABORT_IF_FALSE(CompositorThreadID() == PlatformThread::CurrentId(),
   401                     "PauseComposition() can only be called on the compositor thread");
   403   MonitorAutoLock lock(mPauseCompositionMonitor);
   405   if (!mPaused) {
   406     mPaused = true;
   408     mCompositor->Pause();
   409   }
   411   // if anyone's waiting to make sure that composition really got paused, tell them
   412   lock.NotifyAll();
   413 }
   415 void
   416 CompositorParent::ResumeComposition()
   417 {
   418   NS_ABORT_IF_FALSE(CompositorThreadID() == PlatformThread::CurrentId(),
   419                     "ResumeComposition() can only be called on the compositor thread");
   421   MonitorAutoLock lock(mResumeCompositionMonitor);
   423   if (!mCompositor->Resume()) {
   424 #ifdef MOZ_WIDGET_ANDROID
   425     // We can't get a surface. This could be because the activity changed between
   426     // the time resume was scheduled and now.
   427     __android_log_print(ANDROID_LOG_INFO, "CompositorParent", "Unable to renew compositor surface; remaining in paused state");
   428 #endif
   429     lock.NotifyAll();
   430     return;
   431   }
   433   mPaused = false;
   435   Composite();
   437   // if anyone's waiting to make sure that composition really got resumed, tell them
   438   lock.NotifyAll();
   439 }
   441 void
   442 CompositorParent::ForceComposition()
   443 {
   444   // Cancel the orientation changed state to force composition
   445   mForceCompositionTask = nullptr;
   446   ScheduleRenderOnCompositorThread();
   447 }
   449 void
   450 CompositorParent::CancelCurrentCompositeTask()
   451 {
   452   if (mCurrentCompositeTask) {
   453     mCurrentCompositeTask->Cancel();
   454     mCurrentCompositeTask = nullptr;
   455   }
   456 }
   458 void
   459 CompositorParent::SetEGLSurfaceSize(int width, int height)
   460 {
   461   NS_ASSERTION(mUseExternalSurfaceSize, "Compositor created without UseExternalSurfaceSize provided");
   462   mEGLSurfaceSize.SizeTo(width, height);
   463   if (mCompositor) {
   464     mCompositor->SetDestinationSurfaceSize(gfx::IntSize(mEGLSurfaceSize.width, mEGLSurfaceSize.height));
   465   }
   466 }
   468 void
   469 CompositorParent::ResumeCompositionAndResize(int width, int height)
   470 {
   471   SetEGLSurfaceSize(width, height);
   472   ResumeComposition();
   473 }
   475 /*
   476  * This will execute a pause synchronously, waiting to make sure that the compositor
   477  * really is paused.
   478  */
   479 void
   480 CompositorParent::SchedulePauseOnCompositorThread()
   481 {
   482   MonitorAutoLock lock(mPauseCompositionMonitor);
   484   CancelableTask *pauseTask = NewRunnableMethod(this,
   485                                                 &CompositorParent::PauseComposition);
   486   CompositorLoop()->PostTask(FROM_HERE, pauseTask);
   488   // Wait until the pause has actually been processed by the compositor thread
   489   lock.Wait();
   490 }
   492 bool
   493 CompositorParent::ScheduleResumeOnCompositorThread(int width, int height)
   494 {
   495   MonitorAutoLock lock(mResumeCompositionMonitor);
   497   CancelableTask *resumeTask =
   498     NewRunnableMethod(this, &CompositorParent::ResumeCompositionAndResize, width, height);
   499   CompositorLoop()->PostTask(FROM_HERE, resumeTask);
   501   // Wait until the resume has actually been processed by the compositor thread
   502   lock.Wait();
   504   return !mPaused;
   505 }
   507 void
   508 CompositorParent::ScheduleTask(CancelableTask* task, int time)
   509 {
   510   if (time == 0) {
   511     MessageLoop::current()->PostTask(FROM_HERE, task);
   512   } else {
   513     MessageLoop::current()->PostDelayedTask(FROM_HERE, task, time);
   514   }
   515 }
   517 void
   518 CompositorParent::NotifyShadowTreeTransaction(uint64_t aId, bool aIsFirstPaint, bool aScheduleComposite)
   519 {
   520   if (mApzcTreeManager &&
   521       mLayerManager &&
   522       mLayerManager->GetRoot()) {
   523     AutoResolveRefLayers resolve(mCompositionManager);
   524     mApzcTreeManager->UpdatePanZoomControllerTree(this, mLayerManager->GetRoot(), aIsFirstPaint, aId);
   526     mLayerManager->NotifyShadowTreeTransaction();
   527   }
   528   if (aScheduleComposite) {
   529     ScheduleComposition();
   530   }
   532   mWantDidCompositeEvent = true;
   533 }
   535 // Used when layout.frame_rate is -1. Needs to be kept in sync with
   536 // DEFAULT_FRAME_RATE in nsRefreshDriver.cpp.
   537 static const int32_t kDefaultFrameRate = 60;
   539 static int32_t
   540 CalculateCompositionFrameRate()
   541 {
   542   int32_t compositionFrameRatePref = gfxPrefs::LayersCompositionFrameRate();
   543   if (compositionFrameRatePref < 0) {
   544     // Use the same frame rate for composition as for layout.
   545     int32_t layoutFrameRatePref = gfxPrefs::LayoutFrameRate();
   546     if (layoutFrameRatePref < 0) {
   547       // TODO: The main thread frame scheduling code consults the actual
   548       // monitor refresh rate in this case. We should do the same.
   549       return kDefaultFrameRate;
   550     }
   551     return layoutFrameRatePref;
   552   }
   553   return compositionFrameRatePref;
   554 }
   556 void
   557 CompositorParent::ScheduleComposition()
   558 {
   559   if (mCurrentCompositeTask || mPaused) {
   560     return;
   561   }
   563   bool initialComposition = mLastCompose.IsNull();
   564   TimeDuration delta;
   565   if (!initialComposition)
   566     delta = TimeStamp::Now() - mLastCompose;
   568   int32_t rate = CalculateCompositionFrameRate();
   570   // If rate == 0 (ASAP mode), minFrameDelta must be 0 so there's no delay.
   571   TimeDuration minFrameDelta = TimeDuration::FromMilliseconds(
   572     rate == 0 ? 0.0 : std::max(0.0, 1000.0 / rate));
   575   mCurrentCompositeTask = NewRunnableMethod(this, &CompositorParent::Composite);
   577   if (!initialComposition && delta < minFrameDelta) {
   578     TimeDuration delay = minFrameDelta - delta;
   579 #ifdef COMPOSITOR_PERFORMANCE_WARNING
   580     mExpectedComposeStartTime = TimeStamp::Now() + delay;
   581 #endif
   582     ScheduleTask(mCurrentCompositeTask, delay.ToMilliseconds());
   583   } else {
   584 #ifdef COMPOSITOR_PERFORMANCE_WARNING
   585     mExpectedComposeStartTime = TimeStamp::Now();
   586 #endif
   587     ScheduleTask(mCurrentCompositeTask, 0);
   588   }
   589 }
   591 void
   592 CompositorParent::Composite()
   593 {
   594   CompositeToTarget(nullptr);
   595 }
   597 void
   598 CompositorParent::CompositeToTarget(DrawTarget* aTarget)
   599 {
   600   profiler_tracing("Paint", "Composite", TRACING_INTERVAL_START);
   601   PROFILER_LABEL("CompositorParent", "Composite");
   602   NS_ABORT_IF_FALSE(CompositorThreadID() == PlatformThread::CurrentId(),
   603                     "Composite can only be called on the compositor thread");
   605 #ifdef COMPOSITOR_PERFORMANCE_WARNING
   606   TimeDuration scheduleDelta = TimeStamp::Now() - mExpectedComposeStartTime;
   607   if (scheduleDelta > TimeDuration::FromMilliseconds(2) ||
   608       scheduleDelta < TimeDuration::FromMilliseconds(-2)) {
   609     printf_stderr("Compositor: Compose starting off schedule by %4.1f ms\n",
   610                   scheduleDelta.ToMilliseconds());
   611   }
   612 #endif
   614   if (mCurrentCompositeTask) {
   615     mCurrentCompositeTask->Cancel();
   616     mCurrentCompositeTask = nullptr;
   617   }
   619   mLastCompose = TimeStamp::Now();
   621   if (!CanComposite()) {
   622     return;
   623   }
   625   AutoResolveRefLayers resolve(mCompositionManager);
   627   if (aTarget) {
   628     mLayerManager->BeginTransactionWithDrawTarget(aTarget);
   629   } else {
   630     mLayerManager->BeginTransaction();
   631   }
   633   if (mForceCompositionTask && !mOverrideComposeReadiness) {
   634     if (mCompositionManager->ReadyForCompose()) {
   635       mForceCompositionTask->Cancel();
   636       mForceCompositionTask = nullptr;
   637     } else {
   638       return;
   639     }
   640   }
   642   TimeStamp time = mIsTesting ? mTestTime : mLastCompose;
   643   bool requestNextFrame = mCompositionManager->TransformShadowTree(time);
   644   if (requestNextFrame) {
   645     ScheduleComposition();
   646   }
   648   RenderTraceLayers(mLayerManager->GetRoot(), "0000");
   650   mCompositionManager->ComputeRotation();
   652 #ifdef MOZ_DUMP_PAINTING
   653   static bool gDumpCompositorTree = false;
   654   if (gDumpCompositorTree) {
   655     printf_stderr("Painting --- compositing layer tree:\n");
   656     mLayerManager->Dump();
   657   }
   658 #endif
   659   mLayerManager->SetDebugOverlayWantsNextFrame(false);
   660   mLayerManager->EndEmptyTransaction();
   662   if (!aTarget && mWantDidCompositeEvent) {
   663     DidComposite();
   664     mWantDidCompositeEvent = false;
   665   }
   667   if (mLayerManager->DebugOverlayWantsNextFrame()) {
   668     ScheduleComposition();
   669   }
   671 #ifdef COMPOSITOR_PERFORMANCE_WARNING
   672   TimeDuration executionTime = TimeStamp::Now() - mLastCompose;
   673   TimeDuration frameBudget = TimeDuration::FromMilliseconds(15);
   674   int32_t frameRate = CalculateCompositionFrameRate();
   675   if (frameRate > 0) {
   676     frameBudget = TimeDuration::FromSeconds(1.0 / frameRate);
   677   }
   678   if (executionTime > frameBudget) {
   679     printf_stderr("Compositor: Composite execution took %4.1f ms\n",
   680                   executionTime.ToMilliseconds());
   681   }
   682 #endif
   684   // 0 -> Full-tilt composite
   685   if (gfxPrefs::LayersCompositionFrameRate() == 0
   686     || mLayerManager->GetCompositor()->GetDiagnosticTypes() & DIAGNOSTIC_FLASH_BORDERS) {
   687     // Special full-tilt composite mode for performance testing
   688     ScheduleComposition();
   689   }
   691   profiler_tracing("Paint", "Composite", TRACING_INTERVAL_END);
   692 }
   694 void
   695 CompositorParent::DidComposite()
   696 {
   697   unused << SendDidComposite(0);
   699   for (LayerTreeMap::iterator it = sIndirectLayerTrees.begin();
   700        it != sIndirectLayerTrees.end(); it++) {
   701     LayerTreeState* lts = &it->second;
   702     if (lts->mParent == this && lts->mCrossProcessParent) {
   703       unused << lts->mCrossProcessParent->SendDidComposite(it->first);
   704     }
   705   }
   706 }
   708 void
   709 CompositorParent::ForceComposeToTarget(DrawTarget* aTarget)
   710 {
   711   PROFILER_LABEL("CompositorParent", "ForceComposeToTarget");
   712   AutoRestore<bool> override(mOverrideComposeReadiness);
   713   mOverrideComposeReadiness = true;
   715   CompositeToTarget(aTarget);
   716 }
   718 bool
   719 CompositorParent::CanComposite()
   720 {
   721   return !(mPaused || !mLayerManager || !mLayerManager->GetRoot());
   722 }
   724 // Go down the composite layer tree, setting properties to match their
   725 // content-side counterparts.
   726 static void
   727 SetShadowProperties(Layer* aLayer)
   728 {
   729   // FIXME: Bug 717688 -- Do these updates in LayerTransactionParent::RecvUpdate.
   730   LayerComposite* layerComposite = aLayer->AsLayerComposite();
   731   // Set the layerComposite's base transform to the layer's base transform.
   732   layerComposite->SetShadowTransform(aLayer->GetBaseTransform());
   733   layerComposite->SetShadowTransformSetByAnimation(false);
   734   layerComposite->SetShadowVisibleRegion(aLayer->GetVisibleRegion());
   735   layerComposite->SetShadowClipRect(aLayer->GetClipRect());
   736   layerComposite->SetShadowOpacity(aLayer->GetOpacity());
   738   for (Layer* child = aLayer->GetFirstChild();
   739       child; child = child->GetNextSibling()) {
   740     SetShadowProperties(child);
   741   }
   742 }
   744 void
   745 CompositorParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
   746                                       const TargetConfig& aTargetConfig,
   747                                       bool aIsFirstPaint,
   748                                       bool aScheduleComposite)
   749 {
   750   if (!aIsFirstPaint &&
   751       !mCompositionManager->IsFirstPaint() &&
   752       mCompositionManager->RequiresReorientation(aTargetConfig.orientation())) {
   753     if (mForceCompositionTask != nullptr) {
   754       mForceCompositionTask->Cancel();
   755     }
   756     mForceCompositionTask = NewRunnableMethod(this, &CompositorParent::ForceComposition);
   757     ScheduleTask(mForceCompositionTask, gfxPrefs::OrientationSyncMillis());
   758   }
   760   // Instruct the LayerManager to update its render bounds now. Since all the orientation
   761   // change, dimension change would be done at the stage, update the size here is free of
   762   // race condition.
   763   mLayerManager->UpdateRenderBounds(aTargetConfig.clientBounds());
   764   mLayerManager->SetRegionToClear(aTargetConfig.clearRegion());
   766   mCompositionManager->Updated(aIsFirstPaint, aTargetConfig);
   767   Layer* root = aLayerTree->GetRoot();
   768   mLayerManager->SetRoot(root);
   770   if (mApzcTreeManager) {
   771     AutoResolveRefLayers resolve(mCompositionManager);
   772     mApzcTreeManager->UpdatePanZoomControllerTree(this, root, aIsFirstPaint, mRootLayerTreeID);
   773   }
   775   if (root) {
   776     SetShadowProperties(root);
   777   }
   778   if (aScheduleComposite) {
   779     ScheduleComposition();
   780     // When testing we synchronously update the shadow tree with the animated
   781     // values to avoid race conditions when calling GetAnimationTransform etc.
   782     // (since the above SetShadowProperties will remove animation effects).
   783     // However, we only do this update when a composite operation is already
   784     // scheduled in order to better match the behavior under regular sampling
   785     // conditions.
   786     if (mIsTesting && root && mCurrentCompositeTask) {
   787       AutoResolveRefLayers resolve(mCompositionManager);
   788       bool requestNextFrame =
   789         mCompositionManager->TransformShadowTree(mTestTime);
   790       if (!requestNextFrame) {
   791         CancelCurrentCompositeTask();
   792       }
   793     }
   794   }
   795   mLayerManager->NotifyShadowTreeTransaction();
   796   mWantDidCompositeEvent = true;
   797 }
   799 void
   800 CompositorParent::ForceComposite(LayerTransactionParent* aLayerTree)
   801 {
   802   ScheduleComposition();
   803 }
   805 bool
   806 CompositorParent::SetTestSampleTime(LayerTransactionParent* aLayerTree,
   807                                     const TimeStamp& aTime)
   808 {
   809   if (aTime.IsNull()) {
   810     return false;
   811   }
   813   mIsTesting = true;
   814   mTestTime = aTime;
   816   // Update but only if we were already scheduled to animate
   817   if (mCompositionManager && mCurrentCompositeTask) {
   818     AutoResolveRefLayers resolve(mCompositionManager);
   819     bool requestNextFrame = mCompositionManager->TransformShadowTree(aTime);
   820     if (!requestNextFrame) {
   821       CancelCurrentCompositeTask();
   822     }
   823   }
   825   return true;
   826 }
   828 void
   829 CompositorParent::LeaveTestMode(LayerTransactionParent* aLayerTree)
   830 {
   831   mIsTesting = false;
   832 }
   834 void
   835 CompositorParent::InitializeLayerManager(const nsTArray<LayersBackend>& aBackendHints)
   836 {
   837   NS_ASSERTION(!mLayerManager, "Already initialised mLayerManager");
   838   NS_ASSERTION(!mCompositor,   "Already initialised mCompositor");
   840   for (size_t i = 0; i < aBackendHints.Length(); ++i) {
   841     RefPtr<Compositor> compositor;
   842     if (aBackendHints[i] == LayersBackend::LAYERS_OPENGL) {
   843       compositor = new CompositorOGL(mWidget,
   844                                      mEGLSurfaceSize.width,
   845                                      mEGLSurfaceSize.height,
   846                                      mUseExternalSurfaceSize);
   847     } else if (aBackendHints[i] == LayersBackend::LAYERS_BASIC) {
   848       compositor = new BasicCompositor(mWidget);
   849 #ifdef XP_WIN
   850     } else if (aBackendHints[i] == LayersBackend::LAYERS_D3D11) {
   851       compositor = new CompositorD3D11(mWidget);
   852     } else if (aBackendHints[i] == LayersBackend::LAYERS_D3D9) {
   853       compositor = new CompositorD3D9(this, mWidget);
   854 #endif
   855     }
   857     if (!compositor) {
   858       // We passed a backend hint for which we can't create a compositor.
   859       // For example, we sometime pass LayersBackend::LAYERS_NONE as filler in aBackendHints.
   860       continue;
   861     }
   863     compositor->SetCompositorID(mCompositorID);
   864     RefPtr<LayerManagerComposite> layerManager = new LayerManagerComposite(compositor);
   866     if (layerManager->Initialize()) {
   867       mLayerManager = layerManager;
   868       MOZ_ASSERT(compositor);
   869       mCompositor = compositor;
   870       sIndirectLayerTrees[mRootLayerTreeID].mLayerManager = layerManager;
   871       return;
   872     }
   873   }
   874 }
   876 PLayerTransactionParent*
   877 CompositorParent::AllocPLayerTransactionParent(const nsTArray<LayersBackend>& aBackendHints,
   878                                                const uint64_t& aId,
   879                                                TextureFactoryIdentifier* aTextureFactoryIdentifier,
   880                                                bool *aSuccess)
   881 {
   882   MOZ_ASSERT(aId == 0);
   884   // mWidget doesn't belong to the compositor thread, so it should be set to
   885   // nullptr before returning from this method, to avoid accessing it elsewhere.
   886   nsIntRect rect;
   887   mWidget->GetClientBounds(rect);
   888   InitializeLayerManager(aBackendHints);
   889   mWidget = nullptr;
   891   if (!mLayerManager) {
   892     NS_WARNING("Failed to initialise Compositor");
   893     *aSuccess = false;
   894     LayerTransactionParent* p = new LayerTransactionParent(nullptr, this, 0);
   895     p->AddIPDLReference();
   896     return p;
   897   }
   899   mCompositionManager = new AsyncCompositionManager(mLayerManager);
   900   *aSuccess = true;
   902   *aTextureFactoryIdentifier = mCompositor->GetTextureFactoryIdentifier();
   903   LayerTransactionParent* p = new LayerTransactionParent(mLayerManager, this, 0);
   904   p->AddIPDLReference();
   905   return p;
   906 }
   908 bool
   909 CompositorParent::DeallocPLayerTransactionParent(PLayerTransactionParent* actor)
   910 {
   911   static_cast<LayerTransactionParent*>(actor)->ReleaseIPDLReference();
   912   return true;
   913 }
   916 typedef map<uint64_t,CompositorParent*> CompositorMap;
   917 static CompositorMap* sCompositorMap;
   919 void CompositorParent::CreateCompositorMap()
   920 {
   921   if (sCompositorMap == nullptr) {
   922     sCompositorMap = new CompositorMap;
   923   }
   924 }
   926 void CompositorParent::DestroyCompositorMap()
   927 {
   928   if (sCompositorMap != nullptr) {
   929     NS_ASSERTION(sCompositorMap->empty(),
   930                  "The Compositor map should be empty when destroyed>");
   931     delete sCompositorMap;
   932     sCompositorMap = nullptr;
   933   }
   934 }
   936 CompositorParent* CompositorParent::GetCompositor(uint64_t id)
   937 {
   938   CompositorMap::iterator it = sCompositorMap->find(id);
   939   return it != sCompositorMap->end() ? it->second : nullptr;
   940 }
   942 void CompositorParent::AddCompositor(CompositorParent* compositor, uint64_t* outID)
   943 {
   944   static uint64_t sNextID = 1;
   946   ++sNextID;
   947   (*sCompositorMap)[sNextID] = compositor;
   948   *outID = sNextID;
   949 }
   951 CompositorParent* CompositorParent::RemoveCompositor(uint64_t id)
   952 {
   953   CompositorMap::iterator it = sCompositorMap->find(id);
   954   if (it == sCompositorMap->end()) {
   955     return nullptr;
   956   }
   957   CompositorParent *retval = it->second;
   958   sCompositorMap->erase(it);
   959   return retval;
   960 }
   962 bool
   963 CompositorParent::RecvNotifyChildCreated(const uint64_t& child)
   964 {
   965   NotifyChildCreated(child);
   966   return true;
   967 }
   969 void
   970 CompositorParent::NotifyChildCreated(uint64_t aChild)
   971 {
   972   sIndirectLayerTrees[aChild].mParent = this;
   973   sIndirectLayerTrees[aChild].mLayerManager = mLayerManager;
   974 }
   976 /*static*/ uint64_t
   977 CompositorParent::AllocateLayerTreeId()
   978 {
   979   MOZ_ASSERT(CompositorLoop());
   980   MOZ_ASSERT(NS_IsMainThread());
   981   static uint64_t ids = 0;
   982   return ++ids;
   983 }
   985 static void
   986 EraseLayerState(uint64_t aId)
   987 {
   988   sIndirectLayerTrees.erase(aId);
   989 }
   991 /*static*/ void
   992 CompositorParent::DeallocateLayerTreeId(uint64_t aId)
   993 {
   994   MOZ_ASSERT(NS_IsMainThread());
   995   CompositorLoop()->PostTask(FROM_HERE,
   996                              NewRunnableFunction(&EraseLayerState, aId));
   997 }
   999 static void
  1000 UpdateControllerForLayersId(uint64_t aLayersId,
  1001                             GeckoContentController* aController)
  1003   // Adopt ref given to us by SetControllerForLayerTree()
  1004   sIndirectLayerTrees[aLayersId].mController =
  1005     already_AddRefed<GeckoContentController>(aController);
  1008 ScopedLayerTreeRegistration::ScopedLayerTreeRegistration(uint64_t aLayersId,
  1009                                                          Layer* aRoot,
  1010                                                          GeckoContentController* aController)
  1011     : mLayersId(aLayersId)
  1013   sIndirectLayerTrees[aLayersId].mRoot = aRoot;
  1014   sIndirectLayerTrees[aLayersId].mController = aController;
  1017 ScopedLayerTreeRegistration::~ScopedLayerTreeRegistration()
  1019   sIndirectLayerTrees.erase(mLayersId);
  1022 /*static*/ void
  1023 CompositorParent::SetControllerForLayerTree(uint64_t aLayersId,
  1024                                             GeckoContentController* aController)
  1026   // This ref is adopted by UpdateControllerForLayersId().
  1027   aController->AddRef();
  1028   CompositorLoop()->PostTask(FROM_HERE,
  1029                              NewRunnableFunction(&UpdateControllerForLayersId,
  1030                                                  aLayersId,
  1031                                                  aController));
  1034 /*static*/ APZCTreeManager*
  1035 CompositorParent::GetAPZCTreeManager(uint64_t aLayersId)
  1037   const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(aLayersId);
  1038   if (state && state->mParent) {
  1039     return state->mParent->mApzcTreeManager;
  1041   return nullptr;
  1044 float
  1045 CompositorParent::ComputeRenderIntegrity()
  1047   if (mLayerManager) {
  1048     return mLayerManager->ComputeRenderIntegrity();
  1051   return 1.0f;
  1055 /**
  1056  * This class handles layer updates pushed directly from child
  1057  * processes to the compositor thread.  It's associated with a
  1058  * CompositorParent on the compositor thread.  While it uses the
  1059  * PCompositor protocol to manage these updates, it doesn't actually
  1060  * drive compositing itself.  For that it hands off work to the
  1061  * CompositorParent it's associated with.
  1062  */
  1063 class CrossProcessCompositorParent MOZ_FINAL : public PCompositorParent,
  1064                                                public ShadowLayersManager
  1066   friend class CompositorParent;
  1068   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CrossProcessCompositorParent)
  1069 public:
  1070   CrossProcessCompositorParent(Transport* aTransport)
  1071     : mTransport(aTransport)
  1072   {}
  1074   // IToplevelProtocol::CloneToplevel()
  1075   virtual IToplevelProtocol*
  1076   CloneToplevel(const InfallibleTArray<mozilla::ipc::ProtocolFdMapping>& aFds,
  1077                 base::ProcessHandle aPeerProcess,
  1078                 mozilla::ipc::ProtocolCloneContext* aCtx) MOZ_OVERRIDE;
  1080   virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
  1082   // FIXME/bug 774388: work out what shutdown protocol we need.
  1083   virtual bool RecvWillStop() MOZ_OVERRIDE { return true; }
  1084   virtual bool RecvStop() MOZ_OVERRIDE { return true; }
  1085   virtual bool RecvPause() MOZ_OVERRIDE { return true; }
  1086   virtual bool RecvResume() MOZ_OVERRIDE { return true; }
  1087   virtual bool RecvNotifyChildCreated(const uint64_t& child) MOZ_OVERRIDE;
  1088   virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
  1089                                 SurfaceDescriptor* aOutSnapshot)
  1090   { return true; }
  1091   virtual bool RecvFlushRendering() MOZ_OVERRIDE { return true; }
  1092   virtual bool RecvNotifyRegionInvalidated(const nsIntRegion& aRegion) { return true; }
  1093   virtual bool RecvStartFrameTimeRecording(const int32_t& aBufferSize, uint32_t* aOutStartIndex) MOZ_OVERRIDE { return true; }
  1094   virtual bool RecvStopFrameTimeRecording(const uint32_t& aStartIndex, InfallibleTArray<float>* intervals) MOZ_OVERRIDE  { return true; }
  1096   virtual PLayerTransactionParent*
  1097     AllocPLayerTransactionParent(const nsTArray<LayersBackend>& aBackendHints,
  1098                                  const uint64_t& aId,
  1099                                  TextureFactoryIdentifier* aTextureFactoryIdentifier,
  1100                                  bool *aSuccess) MOZ_OVERRIDE;
  1102   virtual bool DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers) MOZ_OVERRIDE;
  1104   virtual void ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
  1105                                    const TargetConfig& aTargetConfig,
  1106                                    bool aIsFirstPaint,
  1107                                    bool aScheduleComposite) MOZ_OVERRIDE;
  1108   virtual void ForceComposite(LayerTransactionParent* aLayerTree) MOZ_OVERRIDE;
  1109   virtual bool SetTestSampleTime(LayerTransactionParent* aLayerTree,
  1110                                  const TimeStamp& aTime) MOZ_OVERRIDE;
  1111   virtual void LeaveTestMode(LayerTransactionParent* aLayerTree) MOZ_OVERRIDE;
  1113   virtual AsyncCompositionManager* GetCompositionManager(LayerTransactionParent* aParent) MOZ_OVERRIDE;
  1115 private:
  1116   // Private destructor, to discourage deletion outside of Release():
  1117   virtual ~CrossProcessCompositorParent();
  1119   void DeferredDestroy();
  1121   // There can be many CPCPs, and IPDL-generated code doesn't hold a
  1122   // reference to top-level actors.  So we hold a reference to
  1123   // ourself.  This is released (deferred) in ActorDestroy().
  1124   nsRefPtr<CrossProcessCompositorParent> mSelfRef;
  1125   Transport* mTransport;
  1126 };
  1128 static void
  1129 OpenCompositor(CrossProcessCompositorParent* aCompositor,
  1130                Transport* aTransport, ProcessHandle aHandle,
  1131                MessageLoop* aIOLoop)
  1133   DebugOnly<bool> ok = aCompositor->Open(aTransport, aHandle, aIOLoop);
  1134   MOZ_ASSERT(ok);
  1137 /*static*/ PCompositorParent*
  1138 CompositorParent::Create(Transport* aTransport, ProcessId aOtherProcess)
  1140   nsRefPtr<CrossProcessCompositorParent> cpcp =
  1141     new CrossProcessCompositorParent(aTransport);
  1142   ProcessHandle handle;
  1143   if (!base::OpenProcessHandle(aOtherProcess, &handle)) {
  1144     // XXX need to kill |aOtherProcess|, it's boned
  1145     return nullptr;
  1147   cpcp->mSelfRef = cpcp;
  1148   CompositorLoop()->PostTask(
  1149     FROM_HERE,
  1150     NewRunnableFunction(OpenCompositor, cpcp.get(),
  1151                         aTransport, handle, XRE_GetIOMessageLoop()));
  1152   // The return value is just compared to null for success checking,
  1153   // we're not sharing a ref.
  1154   return cpcp.get();
  1157 IToplevelProtocol*
  1158 CompositorParent::CloneToplevel(const InfallibleTArray<mozilla::ipc::ProtocolFdMapping>& aFds,
  1159                                 base::ProcessHandle aPeerProcess,
  1160                                 mozilla::ipc::ProtocolCloneContext* aCtx)
  1162   for (unsigned int i = 0; i < aFds.Length(); i++) {
  1163     if (aFds[i].protocolId() == (unsigned)GetProtocolId()) {
  1164       Transport* transport = OpenDescriptor(aFds[i].fd(),
  1165                                             Transport::MODE_SERVER);
  1166       PCompositorParent* compositor = Create(transport, base::GetProcId(aPeerProcess));
  1167       compositor->CloneManagees(this, aCtx);
  1168       compositor->IToplevelProtocol::SetTransport(transport);
  1169       return compositor;
  1172   return nullptr;
  1175 static void
  1176 UpdateIndirectTree(uint64_t aId, Layer* aRoot, const TargetConfig& aTargetConfig)
  1178   sIndirectLayerTrees[aId].mRoot = aRoot;
  1179   sIndirectLayerTrees[aId].mTargetConfig = aTargetConfig;
  1182 /* static */ const CompositorParent::LayerTreeState*
  1183 CompositorParent::GetIndirectShadowTree(uint64_t aId)
  1185   LayerTreeMap::const_iterator cit = sIndirectLayerTrees.find(aId);
  1186   if (sIndirectLayerTrees.end() == cit) {
  1187     return nullptr;
  1189   return &cit->second;
  1192 static void
  1193 RemoveIndirectTree(uint64_t aId)
  1195   sIndirectLayerTrees.erase(aId);
  1198 void
  1199 CrossProcessCompositorParent::ActorDestroy(ActorDestroyReason aWhy)
  1201   MessageLoop::current()->PostTask(
  1202     FROM_HERE,
  1203     NewRunnableMethod(this, &CrossProcessCompositorParent::DeferredDestroy));
  1206 PLayerTransactionParent*
  1207 CrossProcessCompositorParent::AllocPLayerTransactionParent(const nsTArray<LayersBackend>&,
  1208                                                            const uint64_t& aId,
  1209                                                            TextureFactoryIdentifier* aTextureFactoryIdentifier,
  1210                                                            bool *aSuccess)
  1212   MOZ_ASSERT(aId != 0);
  1214   if (sIndirectLayerTrees[aId].mLayerManager) {
  1215     sIndirectLayerTrees[aId].mCrossProcessParent = this;
  1216     LayerManagerComposite* lm = sIndirectLayerTrees[aId].mLayerManager;
  1217     *aTextureFactoryIdentifier = lm->GetCompositor()->GetTextureFactoryIdentifier();
  1218     *aSuccess = true;
  1219     LayerTransactionParent* p = new LayerTransactionParent(lm, this, aId);
  1220     p->AddIPDLReference();
  1221     return p;
  1224   NS_WARNING("Created child without a matching parent?");
  1225   // XXX: should be false, but that causes us to fail some tests on Mac w/ OMTC.
  1226   // Bug 900745. change *aSuccess to false to see test failures.
  1227   *aSuccess = true;
  1228   LayerTransactionParent* p = new LayerTransactionParent(nullptr, this, aId);
  1229   p->AddIPDLReference();
  1230   return p;
  1233 bool
  1234 CrossProcessCompositorParent::DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers)
  1236   LayerTransactionParent* slp = static_cast<LayerTransactionParent*>(aLayers);
  1237   RemoveIndirectTree(slp->GetId());
  1238   static_cast<LayerTransactionParent*>(aLayers)->ReleaseIPDLReference();
  1239   return true;
  1242 bool
  1243 CrossProcessCompositorParent::RecvNotifyChildCreated(const uint64_t& child)
  1245   sIndirectLayerTrees[child].mParent->NotifyChildCreated(child);
  1246   return true;
  1249 void
  1250 CrossProcessCompositorParent::ShadowLayersUpdated(
  1251   LayerTransactionParent* aLayerTree,
  1252   const TargetConfig& aTargetConfig,
  1253   bool aIsFirstPaint,
  1254   bool aScheduleComposite)
  1256   uint64_t id = aLayerTree->GetId();
  1257   MOZ_ASSERT(id != 0);
  1258   Layer* shadowRoot = aLayerTree->GetRoot();
  1259   if (shadowRoot) {
  1260     SetShadowProperties(shadowRoot);
  1262   UpdateIndirectTree(id, shadowRoot, aTargetConfig);
  1264   sIndirectLayerTrees[id].mParent->NotifyShadowTreeTransaction(id, aIsFirstPaint, aScheduleComposite);
  1267 void
  1268 CrossProcessCompositorParent::ForceComposite(LayerTransactionParent* aLayerTree)
  1270   uint64_t id = aLayerTree->GetId();
  1271   MOZ_ASSERT(id != 0);
  1272   sIndirectLayerTrees[id].mParent->ForceComposite(aLayerTree);
  1275 bool
  1276 CrossProcessCompositorParent::SetTestSampleTime(
  1277   LayerTransactionParent* aLayerTree, const TimeStamp& aTime)
  1279   uint64_t id = aLayerTree->GetId();
  1280   MOZ_ASSERT(id != 0);
  1281   return sIndirectLayerTrees[id].mParent->SetTestSampleTime(aLayerTree, aTime);
  1284 void
  1285 CrossProcessCompositorParent::LeaveTestMode(LayerTransactionParent* aLayerTree)
  1287   uint64_t id = aLayerTree->GetId();
  1288   MOZ_ASSERT(id != 0);
  1289   sIndirectLayerTrees[id].mParent->LeaveTestMode(aLayerTree);
  1292 AsyncCompositionManager*
  1293 CrossProcessCompositorParent::GetCompositionManager(LayerTransactionParent* aLayerTree)
  1295   uint64_t id = aLayerTree->GetId();
  1296   return sIndirectLayerTrees[id].mParent->GetCompositionManager(aLayerTree);
  1299 void
  1300 CrossProcessCompositorParent::DeferredDestroy()
  1302   CrossProcessCompositorParent* self;
  1303   mSelfRef.forget(&self);
  1305   nsCOMPtr<nsIRunnable> runnable =
  1306     NS_NewNonOwningRunnableMethod(self, &CrossProcessCompositorParent::Release);
  1307   MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(runnable)));
  1310 CrossProcessCompositorParent::~CrossProcessCompositorParent()
  1312   XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
  1313                                    new DeleteTask<Transport>(mTransport));
  1316 IToplevelProtocol*
  1317 CrossProcessCompositorParent::CloneToplevel(const InfallibleTArray<mozilla::ipc::ProtocolFdMapping>& aFds,
  1318                                             base::ProcessHandle aPeerProcess,
  1319                                             mozilla::ipc::ProtocolCloneContext* aCtx)
  1321   for (unsigned int i = 0; i < aFds.Length(); i++) {
  1322     if (aFds[i].protocolId() == (unsigned)GetProtocolId()) {
  1323       Transport* transport = OpenDescriptor(aFds[i].fd(),
  1324                                             Transport::MODE_SERVER);
  1325       PCompositorParent* compositor =
  1326         CompositorParent::Create(transport, base::GetProcId(aPeerProcess));
  1327       compositor->CloneManagees(this, aCtx);
  1328       compositor->IToplevelProtocol::SetTransport(transport);
  1329       return compositor;
  1332   return nullptr;
  1335 } // namespace layers
  1336 } // namespace mozilla

mercurial