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
Родитель 85030f4af6
Коммит 4205879729
19 изменённых файлов: 220 добавлений и 27 удалений

Просмотреть файл

@ -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.

Просмотреть файл

@ -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

Просмотреть файл

@ -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) {

Просмотреть файл

@ -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.
//

Просмотреть файл

@ -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();

Просмотреть файл

@ -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);

Просмотреть файл

@ -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();

Просмотреть файл

@ -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,

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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) {

Просмотреть файл

@ -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,

Просмотреть файл

@ -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);

Просмотреть файл

@ -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;

Просмотреть файл

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

Просмотреть файл

@ -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);
}

Просмотреть файл

@ -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

Просмотреть файл

@ -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