Bug 1324591 - Report janked animations to the main-thread and update them on the main-thread. r=botond,boris

The machinery to report janked animations is;

1) Store the partial pre-rendered animation id and the Animation object in a
   hashtable in LayerManager
2) Store the animation id in the Animation object as well
3) When we detect jank, we send the animation id to the main-thread via an IPC
   call
4) Find the Animation object with the id in the hashtable and update the
   Animaiton
5) Whenever the partial pre-rendered Animation stop running on the compositor
   i.e. the Animation finished normally, the Animation's target element is
   changed, etc. etc., remove the Animation from the hashtable

Depends on D75731

Differential Revision: https://phabricator.services.mozilla.com/D75732
This commit is contained in:
Hiroyuki Ikezoe
2020-07-05 11:45:01 +00:00
parent 2e32e24613
commit 98c4bd8d3f
19 changed files with 220 additions and 27 deletions

View File

@@ -183,6 +183,11 @@ void Animation::SetEffectNoUpdate(AnimationEffect* aEffect) {
// Break links with the old effect and then drop it.
RefPtr<AnimationEffect> oldEffect = mEffect;
mEffect = nullptr;
if (IsPartialPrerendered()) {
if (KeyframeEffect* oldKeyframeEffect = oldEffect->AsKeyframeEffect()) {
oldKeyframeEffect->ResetPartialPrerendered();
}
}
oldEffect->SetAnimation(nullptr);
// The following will not do any notification because mEffect is null.

View File

@@ -421,6 +421,30 @@ class Animation : public DOMEventTargetHelper,
int32_t& CachedChildIndexRef() { return mCachedChildIndex; }
void SetPartialPrerendered(uint64_t aIdOnCompositor) {
mIdOnCompositor = aIdOnCompositor;
mIsPartialPrerendered = true;
}
bool IsPartialPrerendered() const { return mIsPartialPrerendered; }
uint64_t IdOnCompositor() const { return mIdOnCompositor; }
/**
* Needs to be called when the pre-rendered animation is going to no longer
* run on the compositor.
*/
void ResetPartialPrerendered() {
MOZ_ASSERT(mIsPartialPrerendered);
mIsPartialPrerendered = false;
mIdOnCompositor = 0;
}
/**
* Called via NotifyJankedAnimations IPC call from the compositor to update
* pre-rendered area on the main-thread.
*/
void UpdatePartialPrerendered() {
ResetPartialPrerendered();
PostUpdate();
}
protected:
void SilentlySetCurrentTime(const TimeDuration& aNewCurrentTime);
void CancelNoUpdate();
@@ -618,6 +642,11 @@ class Animation : public DOMEventTargetHelper,
RefPtr<MicroTaskRunnable> mFinishNotificationTask;
nsString mId;
private:
// The id for this animaiton on the compositor.
uint64_t mIdOnCompositor = 0;
bool mIsPartialPrerendered = false;
};
} // namespace dom

View File

@@ -684,6 +684,8 @@ void KeyframeEffect::SetIsRunningOnCompositor(nsCSSPropertyID aProperty,
// on the compositor we don't need a message.
if (aIsRunning) {
property.mPerformanceWarning.reset();
} else if (mAnimation && mAnimation->IsPartialPrerendered()) {
ResetPartialPrerendered();
}
return;
}
@@ -707,12 +709,39 @@ void KeyframeEffect::SetIsRunningOnCompositor(
}
}
}
if (!aIsRunning && mAnimation && mAnimation->IsPartialPrerendered()) {
ResetPartialPrerendered();
}
}
void KeyframeEffect::ResetIsRunningOnCompositor() {
for (AnimationProperty& property : mProperties) {
property.mIsRunningOnCompositor = false;
}
if (mAnimation && mAnimation->IsPartialPrerendered()) {
ResetPartialPrerendered();
}
}
void KeyframeEffect::ResetPartialPrerendered() {
MOZ_ASSERT(mAnimation && mAnimation->IsPartialPrerendered());
nsIFrame* frame = GetPrimaryFrame();
if (!frame) {
return;
}
nsIWidget* widget = frame->GetNearestWidget();
if (!widget) {
return;
}
if (layers::LayerManager* layerManager = widget->GetLayerManager()) {
layerManager->RemovePartialPrerenderedAnimation(
mAnimation->IdOnCompositor(), mAnimation);
}
}
static bool IsSupportedPseudoForWebAnimation(PseudoStyleType aType) {

View File

@@ -274,6 +274,8 @@ class KeyframeEffect : public AnimationEffect {
bool aIsRunning);
void ResetIsRunningOnCompositor();
void ResetPartialPrerendered();
// Returns true if this effect, applied to |aFrame|, contains properties
// that mean we shouldn't run transform compositor animations on this element.
//

View File

@@ -3105,6 +3105,14 @@ BrowserChild::OnHideTooltip() {
return NS_OK;
}
void BrowserChild::NotifyJankedAnimations(
const nsTArray<uint64_t>& aJankedAnimations) {
MOZ_ASSERT(mPuppetWidget);
RefPtr<LayerManager> lm = mPuppetWidget->GetLayerManager();
MOZ_ASSERT(lm);
lm->UpdatePartialPrerenderedAnimations(aJankedAnimations);
}
mozilla::ipc::IPCResult BrowserChild::RecvRequestNotifyAfterRemotePaint() {
// Get the CompositorBridgeChild instance for this content thread.
CompositorBridgeChild* compositor = CompositorBridgeChild::Get();

View File

@@ -509,6 +509,8 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
void ReinitRendering();
void ReinitRenderingForDeviceReset();
void NotifyJankedAnimations(const nsTArray<uint64_t>& aJankedAnimations);
static inline BrowserChild* GetFrom(nsIDOMWindow* aWindow) {
nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(aWindow);
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(webNav);

View File

@@ -597,7 +597,7 @@ bool AnimationInfo::AddAnimationsForProperty(
nsIFrame* aFrame, const EffectSet* aEffects,
const nsTArray<RefPtr<dom::Animation>>& aCompositorAnimations,
const Maybe<TransformData>& aTransformData, nsCSSPropertyID aProperty,
Send aSendFlag) {
Send aSendFlag, LayerManager* aLayerManager) {
bool addedAny = false;
// Add from first to last (since last overrides)
for (dom::Animation* anim : aCompositorAnimations) {
@@ -643,6 +643,11 @@ bool AnimationInfo::AddAnimationsForProperty(
AddAnimationForProperty(aFrame, *property, anim, aTransformData, aSendFlag);
keyframeEffect->SetIsRunningOnCompositor(aProperty, true);
addedAny = true;
if (aTransformData && aTransformData->partialPrerenderData() &&
aLayerManager) {
aLayerManager->AddPartialPrerenderedAnimation(GetCompositorAnimationsId(),
anim);
}
}
return addedAny;
}
@@ -871,9 +876,11 @@ void AnimationInfo::AddNonAnimatingTransformLikePropertiesStyles(
}
}
void AnimationInfo::AddAnimationsForDisplayItem(
nsIFrame* aFrame, nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem,
DisplayItemType aType, layers::LayersBackend aLayersBackend) {
void AnimationInfo::AddAnimationsForDisplayItem(nsIFrame* aFrame,
nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem,
DisplayItemType aType,
LayerManager* aLayerManager) {
Send sendFlag = !aBuilder ? Send::NextTransaction : Send::Immediate;
if (sendFlag == Send::NextTransaction) {
ClearAnimationsForNextTransaction();
@@ -918,7 +925,7 @@ void AnimationInfo::AddAnimationsForDisplayItem(
compositorAnimations =
GroupAnimationsByProperty(matchedAnimations, propertySet);
Maybe<TransformData> transformData =
CreateAnimationData(aFrame, aItem, aType, aLayersBackend,
CreateAnimationData(aFrame, aItem, aType, aLayerManager->GetBackendType(),
compositorAnimations.has(eCSSProperty_offset_path) ||
!aFrame->StyleDisplay()->mOffsetPath.IsNone()
? AnimationDataType::WithMotionPath
@@ -938,9 +945,9 @@ void AnimationInfo::AddAnimationsForDisplayItem(
// structure, 2) AddAnimationsForProperty() marks these animations as
// running on the composiror, so CanThrottle() returns true for them, and
// we avoid running these animations on the main thread.
bool added =
AddAnimationsForProperty(aFrame, effects, iter.get().value(),
transformData, iter.get().key(), sendFlag);
bool added = AddAnimationsForProperty(aFrame, effects, iter.get().value(),
transformData, iter.get().key(),
sendFlag, aLayerManager);
if (added && transformData) {
// Only copy TransformLikeMetaData in the first animation property.
transformData.reset();

View File

@@ -42,7 +42,6 @@ class Layer;
class LayerManager;
struct CompositorAnimationData;
struct PropertyAnimationGroup;
enum class LayersBackend : int8_t;
class AnimationInfo final {
typedef nsTArray<Animation> AnimationArray;
@@ -120,7 +119,7 @@ class AnimationInfo final {
void AddAnimationsForDisplayItem(nsIFrame* aFrame,
nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem, DisplayItemType aType,
LayersBackend aLayersBackend);
LayerManager* aLayerManager);
private:
enum class Send {
@@ -137,7 +136,7 @@ class AnimationInfo final {
nsIFrame* aFrame, const EffectSet* aEffects,
const nsTArray<RefPtr<dom::Animation>>& aCompositorAnimations,
const Maybe<TransformData>& aTransformData, nsCSSPropertyID aProperty,
Send aSendFlag);
Send aSendFlag, LayerManager* aLayerManager);
void AddNonAnimatingTransformLikePropertiesStyles(
const nsCSSPropertyIDSet& aNonAnimatingProperties, nsIFrame* aFrame,

View File

@@ -467,6 +467,8 @@ bool CompositorAnimationStorage::SampleAnimations(
}
});
std::unordered_map<LayersId, nsTArray<uint64_t>, LayersId::HashFn> janked;
ForEachNode<ForwardIterator>(aRoot, [&](Layer* layer) {
auto& propertyAnimationGroups = layer->GetPropertyAnimationGroups();
if (propertyAnimationGroups.IsEmpty()) {
@@ -519,8 +521,8 @@ bool CompositorAnimationStorage::SampleAnimations(
for (PropertyAnimationGroup& group : propertyAnimationGroups) {
group.ResetLastCompositionValues();
}
// TODO: Report this jank to the main thread and update the animations
// on the main thread.
janked[layer->GetAnimationLayersId()].AppendElement(
layer->GetCompositorAnimationsId());
}
break;
case AnimationHelper::SampleResult::Skipped:
@@ -603,6 +605,10 @@ bool CompositorAnimationStorage::SampleAnimations(
}
});
if (!janked.empty()) {
aCompositorBridge->NotifyJankedAnimations(janked);
}
return isAnimating;
}

View File

@@ -24,6 +24,7 @@
#include "mozilla/StaticPrefs_layers.h"
#include "mozilla/Telemetry.h" // for Accumulate
#include "mozilla/ToString.h"
#include "mozilla/dom/Animation.h" // for dom::Animation
#include "mozilla/gfx/2D.h" // for DrawTarget
#include "mozilla/gfx/BaseSize.h" // for BaseSize
#include "mozilla/gfx/Matrix.h" // for Matrix4x4
@@ -167,6 +168,37 @@ void LayerManager::PayloadPresented() {
RecordCompositionPayloadsPresented(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<dom::Animation> animation;
if (mPartialPrerenderedAnimations.Remove(aCompositorAnimationId,
getter_AddRefs(animation))) {
MOZ_ASSERT(aAnimation == animation.get());
}
#else
mPartialPrerenderedAnimations.Remove(aCompositorAnimationId);
#endif
aAnimation->ResetPartialPrerendered();
}
void LayerManager::UpdatePartialPrerenderedAnimations(
const nsTArray<uint64_t>& aJankedAnimations) {
for (uint64_t id : aJankedAnimations) {
RefPtr<dom::Animation> animation;
if (mPartialPrerenderedAnimations.Remove(id, getter_AddRefs(animation))) {
animation->UpdatePartialPrerendered();
}
}
}
//--------------------------------------------------
// Layer

View File

@@ -28,6 +28,7 @@
#include "mozilla/RefPtr.h" // for already_AddRefed
#include "mozilla/TimeStamp.h" // for TimeStamp, TimeDuration
#include "mozilla/UniquePtr.h" // for UniquePtr
#include "mozilla/dom/Animation.h" // for dom::Animation
#include "mozilla/gfx/BaseMargin.h" // for BaseMargin
#include "mozilla/gfx/BasePoint.h" // for BasePoint
#include "mozilla/gfx/Point.h" // for IntSize
@@ -46,6 +47,7 @@
#include "nsDebug.h" // for NS_ASSERTION
#include "nsISupportsImpl.h" // for Layer::Release, etc
#include "nsRect.h" // for mozilla::gfx::IntRect
#include "nsRefPtrHashtable.h" // for nsRefPtrHashtable
#include "nsRegion.h" // for nsIntRegion
#include "nsString.h" // for nsCString
#include "nsTArray.h" // for nsTArray
@@ -256,6 +258,7 @@ class LayerManager : public FrameRecorder {
mDestroyed = true;
mUserData.Destroy();
mRoot = nullptr;
mPartialPrerenderedAnimations.Clear();
}
bool IsDestroyed() { return mDestroyed; }
@@ -753,6 +756,13 @@ class LayerManager : public FrameRecorder {
void SetContainsSVG(bool aContainsSVG) { mContainsSVG = aContainsSVG; }
void AddPartialPrerenderedAnimation(uint64_t aCompositorAnimationId,
dom::Animation* aAnimation);
void RemovePartialPrerenderedAnimation(uint64_t aCompositorAnimationId,
dom::Animation* aAnimation);
void UpdatePartialPrerenderedAnimations(
const nsTArray<uint64_t>& aJankedAnimations);
protected:
RefPtr<Layer> mRoot;
gfx::UserData mUserData;
@@ -790,6 +800,12 @@ class LayerManager : public FrameRecorder {
// IMPORTANT: Clients should take care to clear this or risk it slowly
// growing out of control.
nsTArray<CompositionPayload> mPayload;
// Transform animations which are not fully pre-rendered because it's on a
// large frame. We need to update the pre-rendered area once after we tried
// to composite area which is outside of the pre-rendered area on the
// compositor.
nsRefPtrHashtable<nsUint64HashKey, dom::Animation>
mPartialPrerenderedAnimations;
public:
/*
@@ -816,7 +832,7 @@ class LayerManager : public FrameRecorder {
class Layer {
NS_INLINE_DECL_REFCOUNTING(Layer)
typedef nsTArray<Animation> AnimationArray;
using AnimationArray = nsTArray<layers::Animation>;
public:
// Keep these in alphabetical order

View File

@@ -847,6 +847,21 @@ mozilla::ipc::IPCResult CompositorBridgeChild::RecvCompositorOptionsChanged(
return IPC_OK();
}
mozilla::ipc::IPCResult CompositorBridgeChild::RecvNotifyJankedAnimations(
const LayersId& aLayersId, nsTArray<uint64_t>&& aJankedAnimations) {
if (mLayerManager) {
MOZ_ASSERT(!aLayersId.IsValid());
mLayerManager->UpdatePartialPrerenderedAnimations(aJankedAnimations);
} else if (aLayersId.IsValid()) {
RefPtr<dom::BrowserChild> child = dom::BrowserChild::GetFrom(aLayersId);
if (child) {
child->NotifyJankedAnimations(aJankedAnimations);
}
}
return IPC_OK();
}
void CompositorBridgeChild::HoldUntilCompositableRefReleasedIfNecessary(
TextureClient* aClient) {
if (!aClient) {

View File

@@ -111,6 +111,9 @@ class CompositorBridgeChild final : public PCompositorBridgeChild,
mozilla::ipc::IPCResult RecvHideAllPlugins(const uintptr_t& aParentWidget);
mozilla::ipc::IPCResult RecvNotifyJankedAnimations(
const LayersId& aLayersId, nsTArray<uint64_t>&& aJankedAnimations);
PTextureChild* AllocPTextureChild(
const SurfaceDescriptor& aSharedData, const ReadLockDescriptor& aReadLock,
const LayersBackend& aLayersBackend, const TextureFlags& aFlags,

View File

@@ -1375,6 +1375,33 @@ CompositorAnimationStorage* CompositorBridgeParent::GetAnimationStorage() {
return mAnimationStorage;
}
void CompositorBridgeParent::NotifyJankedAnimations(
const JankedAnimations& aJankedAnimations) {
MOZ_ASSERT(!aJankedAnimations.empty());
if (StaticPrefs::layout_animation_prerender_partial_jank()) {
return;
}
for (const auto& entry : aJankedAnimations) {
const LayersId& layersId = entry.first;
const nsTArray<uint64_t>& animations = entry.second;
if (layersId == mRootLayerTreeID) {
if (mLayerManager) {
Unused << SendNotifyJankedAnimations(LayersId{0}, animations);
}
// It unlikely happens multiple processes have janked animations at same
// time, so it should be fine with enumerating sIndirectLayerTrees every
// time.
} else if (const LayerTreeState* state = GetIndirectShadowTree(layersId)) {
if (ContentCompositorBridgeParent* cpcp =
state->mContentCompositorBridgeParent) {
Unused << cpcp->SendNotifyJankedAnimations(layersId, animations);
}
}
}
}
mozilla::ipc::IPCResult CompositorBridgeParent::RecvGetFrameUniformity(
FrameUniformityData* aOutData) {
mCompositionManager->GetFrameUniformity(aOutData);

View File

@@ -408,6 +408,9 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
void ApplyAsyncProperties(LayerTransactionParent* aLayerTree,
TransformsToSkip aSkip) override;
CompositorAnimationStorage* GetAnimationStorage();
using JankedAnimations =
std::unordered_map<LayersId, nsTArray<uint64_t>, LayersId::HashFn>;
void NotifyJankedAnimations(const JankedAnimations& aJankedAnimations);
void SetTestAsyncScrollOffset(const LayersId& aLayersId,
const ScrollableLayerGuid::ViewID& aScrollId,
const CSSPoint& aPoint) override;

View File

@@ -161,6 +161,8 @@ child:
async CompositorOptionsChanged(LayersId id, CompositorOptions newOptions);
async NotifyJankedAnimations(LayersId id, uint64_t[] aJankedAnimations);
parent:
async __delete__();

View File

@@ -229,7 +229,7 @@ static uint64_t AddAnimationsForWebRender(
AnimationInfo& animationInfo = animationData->GetAnimationInfo();
animationInfo.AddAnimationsForDisplayItem(aItem->Frame(), aDisplayListBuilder,
aItem, aItem->GetType(),
layers::LayersBackend::LAYERS_WR);
aManager->LayerManager());
animationInfo.StartPendingAnimations(
aManager->LayerManager()->GetAnimationReadyTime());
@@ -321,8 +321,8 @@ void nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(
}
AnimationInfo& animationInfo = aLayer->GetAnimationInfo();
animationInfo.AddAnimationsForDisplayItem(
aFrame, aBuilder, aItem, aType, layers::LayersBackend::LAYERS_CLIENT);
animationInfo.AddAnimationsForDisplayItem(aFrame, aBuilder, aItem, aType,
aLayer->Manager());
animationInfo.TransferMutatedFlagToLayer(aLayer);
}

View File

@@ -156,20 +156,20 @@ test-pref(layout.css.zoom-transform-hack.enabled,false) != zoom-hack-1.html zoom
test-pref(layout.css.zoom-transform-hack.enabled,true) == zoom-hack-2.html zoom-hack-ref.html
== transform-anon-block-1.html transform-anon-block-1-ref.html
test-pref(layout.animation.prerender.partial,true) == partial-prerender-expansion-translate.html partial-prerender-expansion-ref.html
test-pref(layout.animation.prerender.partial,true) == partial-prerender-translate-1.html about:blank
skip-if(webrender) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-2.html partial-prerender-translate-2-ref.html # bug 1638152 for WebRender
fails test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-3.html partial-prerender-translate-3-ref.html # bug 1642575
test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) == partial-prerender-expansion-translate.html partial-prerender-expansion-ref.html
test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) == partial-prerender-translate-1.html about:blank
skip-if(webrender) test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-2.html partial-prerender-translate-2-ref.html # bug 1638152 for WebRender
fails test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-3.html partial-prerender-translate-3-ref.html # bug 1642575
# This reftest doesn't fail on WebRender, this reftest fails only if there is a jank mechanism and the mechanism doesn't properly handle ancestor's transform values
test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-4.html partial-prerender-expansion-ref.html
test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-4.html partial-prerender-expansion-ref.html
# This reftest doesn't fail on WebRender, this reftest fails only if there is a jank mechanism and the mechanism does inproperly handle position:fixed scroll target
test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-5.html partial-prerender-translate-5-ref.html
fails-if(webrender) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-6.html partial-prerender-translate-6-ref.html # bug 1638152 for WebRender
fail-if(webrender) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-7.html partial-prerender-translate-2-ref.html # bug 1638152 for WebRender
test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-5.html partial-prerender-translate-5-ref.html
fails-if(webrender) test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-6.html partial-prerender-translate-6-ref.html # bug 1638152 for WebRender
fails-if(webrender) test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-7.html partial-prerender-translate-2-ref.html # bug 1638152 for WebRender
# This reftest doesn't fail on WebRender, this reftest fails only if there is a jank mechanism and the mechanism doesn't properly clip transform in iframes.
test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-8.html partial-prerender-translate-8-ref.html
test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-8.html partial-prerender-translate-8-ref.html
# This reftest doesn't fail on WebRender, this reftest fails only if there is a jank mechanism and the mechanism does inproperly handle position:fixed scroll target
test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-9.html partial-prerender-translate-5-ref.html
test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-9.html partial-prerender-translate-5-ref.html
# This reftest heavily depends on layout.animation.prerender.viewport-ratio-limit
# and reftest viewport size (800, 1000).
skip-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)||Android) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-expansion-rotate.html partial-prerender-expansion-ref.html

View File

@@ -5601,6 +5601,14 @@
value: 4096
mirror: always
# Test-only pref, if this is true, partial pre-rendered transform animations
# get stuck when it reaches to the pre-rendered boundaries and the pre-render
# region is never updated.
- name: layout.animation.prerender.partial.jank
type: RelaxedAtomicBool
value: false
mirror: always
# Whether Constructable Stylesheets are enabled in script.
- name: layout.css.constructable-stylesheets.enabled
type: bool