void CompositorParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree, const uint64_t& aTransactionId, const TargetConfig& aTargetConfig, bool aIsFirstPaint, bool aScheduleComposite, uint32_t aPaintSequenceNumber) { ScheduleRotationOnCompositorThread(aTargetConfig, aIsFirstPaint); // Instruct the LayerManager to update its render bounds now. Since all the orientation // change, dimension change would be done at the stage, update the size here is free of // race condition. mLayerManager->UpdateRenderBounds(aTargetConfig.clientBounds()); mLayerManager->SetRegionToClear(aTargetConfig.clearRegion()); mCompositionManager->Updated(aIsFirstPaint, aTargetConfig); Layer* root = aLayerTree->GetRoot(); mLayerManager->SetRoot(root); if (mApzcTreeManager) { AutoResolveRefLayers resolve(mCompositionManager); mApzcTreeManager->UpdatePanZoomControllerTree(this, root, aIsFirstPaint, mRootLayerTreeID, aPaintSequenceNumber); } MOZ_ASSERT(aTransactionId > mPendingTransaction); mPendingTransaction = aTransactionId; if (root) { SetShadowProperties(root); } if (aScheduleComposite) { ScheduleComposition(); if (mPaused) { DidComposite(); } // When testing we synchronously update the shadow tree with the animated // values to avoid race conditions when calling GetAnimationTransform etc. // (since the above SetShadowProperties will remove animation effects). // However, we only do this update when a composite operation is already // scheduled in order to better match the behavior under regular sampling // conditions. if (mIsTesting && root && mCurrentCompositeTask) { AutoResolveRefLayers resolve(mCompositionManager); bool requestNextFrame = mCompositionManager->TransformShadowTree(mTestTime); if (!requestNextFrame) { CancelCurrentCompositeTask(); // Pretend we composited in case someone is wating for this event. DidComposite(); } } } mLayerManager->NotifyShadowTreeTransaction(); }
void CompositorParent::PauseComposition() { MOZ_ASSERT(IsInCompositorThread(), "PauseComposition() can only be called on the compositor thread"); MonitorAutoLock lock(mPauseCompositionMonitor); if (!mPaused) { mPaused = true; mCompositor->Pause(); DidComposite(); } // if anyone's waiting to make sure that composition really got paused, tell them lock.NotifyAll(); }
ClientLayerManager::~ClientLayerManager() { if (mTransactionIdAllocator) { DidComposite(mLatestTransactionId); } mMemoryPressureObserver->Destroy(); ClearCachedResources(); // Stop receiveing AsyncParentMessage at Forwarder. // After the call, the message is directly handled by LayerTransactionChild. // Basically this function should be called in ShadowLayerForwarder's // destructor. But when the destructor is triggered by // CompositorChild::Destroy(), the destructor can not handle it correctly. // See Bug 1000525. mForwarder->StopReceiveAsyncParentMessge(); mRoot = nullptr; MOZ_COUNT_DTOR(ClientLayerManager); }
bool CompositorParent::SetTestSampleTime(LayerTransactionParent* aLayerTree, const TimeStamp& aTime) { if (aTime.IsNull()) { return false; } mIsTesting = true; mTestTime = aTime; // Update but only if we were already scheduled to animate if (mCompositionManager && mCurrentCompositeTask) { AutoResolveRefLayers resolve(mCompositionManager); bool requestNextFrame = mCompositionManager->TransformShadowTree(aTime); if (!requestNextFrame) { CancelCurrentCompositeTask(); // Pretend we composited in case someone is wating for this event. DidComposite(); } } return true; }
void CompositorParent::CompositeToTarget(DrawTarget* aTarget, const nsIntRect* aRect) { profiler_tracing("Paint", "Composite", TRACING_INTERVAL_START); PROFILER_LABEL("CompositorParent", "Composite", js::ProfileEntry::Category::GRAPHICS); MOZ_ASSERT(IsInCompositorThread(), "Composite can only be called on the compositor thread"); #ifdef COMPOSITOR_PERFORMANCE_WARNING TimeDuration scheduleDelta = TimeStamp::Now() - mExpectedComposeStartTime; if (scheduleDelta > TimeDuration::FromMilliseconds(2) || scheduleDelta < TimeDuration::FromMilliseconds(-2)) { printf_stderr("Compositor: Compose starting off schedule by %4.1f ms\n", scheduleDelta.ToMilliseconds()); } #endif mLastCompose = TimeStamp::Now(); if (!CanComposite()) { DidComposite(); return; } AutoResolveRefLayers resolve(mCompositionManager); if (aTarget) { mLayerManager->BeginTransactionWithDrawTarget(aTarget, *aRect); } else { mLayerManager->BeginTransaction(); } if (mForceCompositionTask && !mOverrideComposeReadiness) { if (mCompositionManager->ReadyForCompose()) { mForceCompositionTask->Cancel(); mForceCompositionTask = nullptr; } else { return; } } TimeStamp time = mIsTesting ? mTestTime : mLastCompose; bool requestNextFrame = mCompositionManager->TransformShadowTree(time); if (requestNextFrame) { ScheduleComposition(); } RenderTraceLayers(mLayerManager->GetRoot(), "0000"); mCompositionManager->ComputeRotation(); #ifdef MOZ_DUMP_PAINTING static bool gDumpCompositorTree = false; if (gDumpCompositorTree) { printf_stderr("Painting --- compositing layer tree:\n"); mLayerManager->Dump(); } #endif mLayerManager->SetDebugOverlayWantsNextFrame(false); mLayerManager->EndEmptyTransaction(); if (!aTarget) { DidComposite(); } if (mLayerManager->DebugOverlayWantsNextFrame()) { ScheduleComposition(); } #ifdef COMPOSITOR_PERFORMANCE_WARNING TimeDuration executionTime = TimeStamp::Now() - mLastCompose; TimeDuration frameBudget = TimeDuration::FromMilliseconds(15); int32_t frameRate = CalculateCompositionFrameRate(); if (frameRate > 0) { frameBudget = TimeDuration::FromSeconds(1.0 / frameRate); } if (executionTime > frameBudget) { printf_stderr("Compositor: Composite execution took %4.1f ms\n", executionTime.ToMilliseconds()); } #endif // 0 -> Full-tilt composite if (gfxPrefs::LayersCompositionFrameRate() == 0 || mLayerManager->GetCompositor()->GetDiagnosticTypes() & DiagnosticTypes::FLASH_BORDERS) { // Special full-tilt composite mode for performance testing ScheduleComposition(); } profiler_tracing("Paint", "Composite", TRACING_INTERVAL_END); }