/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/layers/LayerManager.h" #include // for uint64_t, uint8_t #include // for abort #include // for copy, copy_backward #include // for move, forward #include "FrameMetrics.h" // for FrameMetrics #include "ImageContainer.h" // for ImageContainer, ImageContainer::Mode #include "LayerUserData.h" // for LayerUserData #include "Layers.h" // for RecordCompositionPayloadsPresented, Layer #include "TreeTraversal.h" // for ForwardIterator, BreadthFirstSearch #include "gfxPlatform.h" // for gfxPlatform #include "mozilla/AlreadyAddRefed.h" // for already_AddRefed #include "mozilla/ArrayIterator.h" // for ArrayIterator #include "mozilla/Assertions.h" // for AssertionConditionType, MOZ_ASSERT, MOZ_ASSERT_HELPER1 #include "mozilla/EffectSet.h" // for EffectSet #include "mozilla/Logging.h" // for LazyLogModule, LogModule (ptr only) #include "mozilla/RefPtr.h" // for RefPtr, getter_AddRefs, RefPtrGetterAddRefs #include "mozilla/StaticPrefs_layers.h" // for layers_componentalpha_enabled_AtStartup_DoNotUseDirectly #include "mozilla/UniquePtr.h" // for UniquePtr #include "mozilla/dom/Animation.h" // for Animation #include "mozilla/dom/AnimationEffect.h" // for AnimationEffect #include "mozilla/gfx/Point.h" // for IntSize #include "mozilla/gfx/Types.h" // for SurfaceFormat, gfx #include "mozilla/gfx/UserData.h" // for UserData, UserDataKey (ptr only) #include "mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper #include "mozilla/layers/LayersTypes.h" // for CompositionPayload #include "mozilla/layers/PersistentBufferProvider.h" // for PersistentBufferProviderBasic, PersistentBufferProvider (ptr only) #include "mozilla/layers/ScrollableLayerGuid.h" // for ScrollableLayerGuid, ScrollableLayerGuid::NULL_SCROLL_ID, ScrollableLayerGu... #include "nsHashKeys.h" // for nsUint64HashKey #include "nsRefPtrHashtable.h" // for nsRefPtrHashtable #include "nsTArray.h" // for nsTArray uint8_t gLayerManagerLayerBuilder; // Undo the damage done by mozzconf.h #undef compress #include "mozilla/Compression.h" namespace mozilla { namespace layers { using namespace mozilla::gfx; using namespace mozilla::Compression; //-------------------------------------------------- // LayerManager LayerManager::LayerManager() : mDestroyed(false), mSnapEffectiveTransforms(true), mId(0), mInTransaction(false), mContainsSVG(false), mPaintedPixelCount(0) {} LayerManager::~LayerManager() = default; void LayerManager::Destroy() { mDestroyed = true; mUserData.Destroy(); mRoot = nullptr; mPartialPrerenderedAnimations.Clear(); } /* static */ mozilla::LogModule* LayerManager::GetLog() { static LazyLogModule sLog("Layers"); return sLog; } ScrollableLayerGuid::ViewID LayerManager::GetRootScrollableLayerId() { if (!mRoot) { return ScrollableLayerGuid::NULL_SCROLL_ID; } LayerMetricsWrapper layerMetricsRoot = LayerMetricsWrapper(mRoot); LayerMetricsWrapper rootScrollableLayerMetrics = BreadthFirstSearch( layerMetricsRoot, [](LayerMetricsWrapper aLayerMetrics) { return aLayerMetrics.Metrics().IsScrollable(); }); return rootScrollableLayerMetrics.IsValid() ? rootScrollableLayerMetrics.Metrics().GetScrollId() : ScrollableLayerGuid::NULL_SCROLL_ID; } LayerMetricsWrapper LayerManager::GetRootContentLayer() { if (!mRoot) { return LayerMetricsWrapper(); } LayerMetricsWrapper root(mRoot); return BreadthFirstSearch( root, [](LayerMetricsWrapper aLayerMetrics) { return aLayerMetrics.Metrics().IsRootContent(); }); } already_AddRefed LayerManager::CreateOptimalDrawTarget( const gfx::IntSize& aSize, SurfaceFormat aFormat) { return gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(aSize, aFormat); } already_AddRefed LayerManager::CreateOptimalMaskDrawTarget( const gfx::IntSize& aSize) { return CreateOptimalDrawTarget(aSize, SurfaceFormat::A8); } already_AddRefed LayerManager::CreateDrawTarget( const IntSize& aSize, SurfaceFormat aFormat) { return gfxPlatform::GetPlatform()->CreateOffscreenCanvasDrawTarget(aSize, aFormat); } already_AddRefed LayerManager::CreatePersistentBufferProvider( const mozilla::gfx::IntSize& aSize, mozilla::gfx::SurfaceFormat aFormat) { RefPtr bufferProvider = PersistentBufferProviderBasic::Create( aSize, aFormat, gfxPlatform::GetPlatform()->GetPreferredCanvasBackend()); if (!bufferProvider) { bufferProvider = PersistentBufferProviderBasic::Create( aSize, aFormat, gfxPlatform::GetPlatform()->GetFallbackCanvasBackend()); } return bufferProvider.forget(); } already_AddRefed LayerManager::CreateImageContainer( ImageContainer::Mode flag) { RefPtr container = new ImageContainer(flag); return container.forget(); } bool LayerManager::LayersComponentAlphaEnabled() { // If MOZ_GFX_OPTIMIZE_MOBILE is defined, we force component alpha off // and ignore the preference. #ifdef MOZ_GFX_OPTIMIZE_MOBILE return false; #else return StaticPrefs:: layers_componentalpha_enabled_AtStartup_DoNotUseDirectly(); #endif } bool LayerManager::AreComponentAlphaLayersEnabled() { return LayerManager::LayersComponentAlphaEnabled(); } /*static*/ void LayerManager::LayerUserDataDestroy(void* data) { delete static_cast(data); } UniquePtr LayerManager::RemoveUserData(void* aKey) { UniquePtr d(static_cast( mUserData.Remove(static_cast(aKey)))); return d; } void LayerManager::PayloadPresented(const TimeStamp& aTimeStamp) { RecordCompositionPayloadsPresented(aTimeStamp, mPayload); } void LayerManager::AddPartialPrerenderedAnimation( uint64_t aCompositorAnimationId, dom::Animation* aAnimation) { mPartialPrerenderedAnimations.Put(aCompositorAnimationId, RefPtr{aAnimation}); aAnimation->SetPartialPrerendered(aCompositorAnimationId); } void LayerManager::RemovePartialPrerenderedAnimation( uint64_t aCompositorAnimationId, dom::Animation* aAnimation) { MOZ_ASSERT(aAnimation); #ifdef DEBUG RefPtr animation; if (mPartialPrerenderedAnimations.Remove(aCompositorAnimationId, getter_AddRefs(animation)) && // It may be possible that either animation's effect has already been // nulled out via Animation::SetEffect() so ignore such cases. aAnimation->GetEffect() && aAnimation->GetEffect()->AsKeyframeEffect() && animation->GetEffect() && animation->GetEffect()->AsKeyframeEffect()) { MOZ_ASSERT(EffectSet::GetEffectSetForEffect( aAnimation->GetEffect()->AsKeyframeEffect()) == EffectSet::GetEffectSetForEffect( animation->GetEffect()->AsKeyframeEffect())); } #else mPartialPrerenderedAnimations.Remove(aCompositorAnimationId); #endif aAnimation->ResetPartialPrerendered(); } void LayerManager::UpdatePartialPrerenderedAnimations( const nsTArray& aJankedAnimations) { for (uint64_t id : aJankedAnimations) { RefPtr animation; if (mPartialPrerenderedAnimations.Remove(id, getter_AddRefs(animation))) { animation->UpdatePartialPrerendered(); } } } } // namespace layers } // namespace mozilla