зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1638152 - Jank partial prerender transform animations and report the janked animations to the main-thread in each process on WebRender. r=botond,kats
Differential Revision: https://phabricator.services.mozilla.com/D83202
This commit is contained in:
Родитель
c746275523
Коммит
ba018e2355
|
@ -13,6 +13,7 @@
|
|||
#include "mozilla/layers/CompositorThread.h" // for CompositorThreadHolder
|
||||
#include "mozilla/layers/LayerManagerComposite.h" // for LayerComposite, etc
|
||||
#include "mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper
|
||||
#include "mozilla/layers/OMTAController.h" // for OMTAController
|
||||
#include "mozilla/ServoStyleConsts.h"
|
||||
#include "mozilla/webrender/WebRenderTypes.h" // for ToWrTransformProperty, etc
|
||||
#include "nsDeviceContext.h" // for AppUnitsPerCSSPixel
|
||||
|
@ -174,8 +175,22 @@ void CompositorAnimationStorage::SetAnimations(uint64_t aId,
|
|||
}
|
||||
}
|
||||
|
||||
bool CompositorAnimationStorage::SampleAnimations(TimeStamp aPreviousFrameTime,
|
||||
TimeStamp aCurrentFrameTime) {
|
||||
// Returns clip rect in the scroll frame's coordinate space.
|
||||
static ParentLayerRect GetClipRectForPartialPrerender(
|
||||
const LayersId aLayersId, const PartialPrerenderData& aPartialPrerenderData,
|
||||
const RefPtr<APZSampler>& aSampler) {
|
||||
if (aSampler &&
|
||||
aPartialPrerenderData.scrollId() != ScrollableLayerGuid::NULL_SCROLL_ID) {
|
||||
return aSampler->GetCompositionBounds(aLayersId,
|
||||
aPartialPrerenderData.scrollId());
|
||||
}
|
||||
|
||||
return aPartialPrerenderData.clipRect();
|
||||
}
|
||||
|
||||
bool CompositorAnimationStorage::SampleAnimations(
|
||||
const OMTAController* aOMTAController, TimeStamp aPreviousFrameTime,
|
||||
TimeStamp aCurrentFrameTime) {
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
bool isAnimating = false;
|
||||
|
@ -186,6 +201,10 @@ bool CompositorAnimationStorage::SampleAnimations(TimeStamp aPreviousFrameTime,
|
|||
return isAnimating;
|
||||
}
|
||||
|
||||
std::unordered_map<LayersId, nsTArray<uint64_t>, LayersId::HashFn> janked;
|
||||
|
||||
RefPtr<APZSampler> apzSampler = mCompositorBridge->GetAPZSampler();
|
||||
|
||||
for (const auto& iter : mAnimations) {
|
||||
const auto& animationStorageData = iter.second;
|
||||
if (animationStorageData->mAnimation.IsEmpty()) {
|
||||
|
@ -242,6 +261,40 @@ bool CompositorAnimationStorage::SampleAnimations(TimeStamp aPreviousFrameTime,
|
|||
AnimationHelper::ServoAnimationValueToMatrix4x4(
|
||||
animationValues, transformData,
|
||||
animationStorageData->mCachedMotionPath);
|
||||
|
||||
if (const Maybe<PartialPrerenderData>& partialPrerenderData =
|
||||
transformData.partialPrerenderData()) {
|
||||
gfx::Matrix4x4 transform = frameTransform;
|
||||
transform.PostTranslate(
|
||||
partialPrerenderData->position().ToUnknownPoint());
|
||||
|
||||
gfx::Matrix4x4 transformInClip =
|
||||
partialPrerenderData->transformInClip();
|
||||
if (apzSampler && partialPrerenderData->scrollId() !=
|
||||
ScrollableLayerGuid::NULL_SCROLL_ID) {
|
||||
AsyncTransform asyncTransform =
|
||||
apzSampler->GetCurrentAsyncTransform(
|
||||
animationStorageData->mLayersId,
|
||||
partialPrerenderData->scrollId(), LayoutAndVisual);
|
||||
transformInClip.PostTranslate(
|
||||
asyncTransform.mTranslation.ToUnknownPoint());
|
||||
}
|
||||
transformInClip = transform * transformInClip;
|
||||
|
||||
ParentLayerRect clipRect =
|
||||
GetClipRectForPartialPrerender(animationStorageData->mLayersId,
|
||||
*partialPrerenderData, apzSampler);
|
||||
if (AnimationHelper::ShouldBeJank(
|
||||
partialPrerenderData->rect(),
|
||||
partialPrerenderData->overflowedSides(), transformInClip,
|
||||
clipRect)) {
|
||||
if (previousValue) {
|
||||
frameTransform = previousValue->Transform().mFrameTransform;
|
||||
}
|
||||
janked[animationStorageData->mLayersId].AppendElement(iter.first);
|
||||
}
|
||||
}
|
||||
|
||||
SetAnimatedValueForWebRender(iter.first, previousValue, frameTransform,
|
||||
transformData);
|
||||
break;
|
||||
|
@ -251,6 +304,10 @@ bool CompositorAnimationStorage::SampleAnimations(TimeStamp aPreviousFrameTime,
|
|||
}
|
||||
}
|
||||
|
||||
if (!janked.empty() && aOMTAController) {
|
||||
aOMTAController->NotifyJankedAnimations(std::move(janked));
|
||||
}
|
||||
|
||||
return isAnimating;
|
||||
}
|
||||
|
||||
|
@ -355,19 +412,6 @@ static Matrix4x4 GetTransformForPartialPrerender(
|
|||
return transform;
|
||||
}
|
||||
|
||||
// Returns clip rect in the scroll frame's coordinate space.
|
||||
static ParentLayerRect GetClipRectForPartialPrerender(
|
||||
const LayersId aLayersId, const PartialPrerenderData& aPartialPrerenderData,
|
||||
const RefPtr<APZSampler>& aSampler) {
|
||||
if (aSampler &&
|
||||
aPartialPrerenderData.scrollId() != ScrollableLayerGuid::NULL_SCROLL_ID) {
|
||||
return aSampler->GetCompositionBounds(aLayersId,
|
||||
aPartialPrerenderData.scrollId());
|
||||
}
|
||||
|
||||
return aPartialPrerenderData.clipRect();
|
||||
}
|
||||
|
||||
bool CompositorAnimationStorage::ApplyAnimatedValue(
|
||||
CompositorBridgeParent* aCompositorBridge, Layer* aLayer,
|
||||
nsCSSPropertyID aProperty, AnimatedValue* aPreviousValue,
|
||||
|
|
|
@ -18,8 +18,9 @@
|
|||
namespace mozilla {
|
||||
namespace layers {
|
||||
class Animation;
|
||||
class Layer;
|
||||
class CompositorBridgeParent;
|
||||
class Layer;
|
||||
class OMTAController;
|
||||
|
||||
typedef nsTArray<layers::Animation> AnimationArray;
|
||||
|
||||
|
@ -121,7 +122,9 @@ class CompositorAnimationStorage final {
|
|||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorAnimationStorage)
|
||||
public:
|
||||
CompositorAnimationStorage() : mLock("CompositorAnimationStorage::mLock") {}
|
||||
explicit CompositorAnimationStorage(CompositorBridgeParent* aCompositorBridge)
|
||||
: mLock("CompositorAnimationStorage::mLock"),
|
||||
mCompositorBridge(aCompositorBridge) {}
|
||||
|
||||
OMTAValue GetOMTAValue(const uint64_t& aId) const;
|
||||
|
||||
|
@ -148,7 +151,8 @@ class CompositorAnimationStorage final {
|
|||
*
|
||||
* Note: This is called only by WebRender.
|
||||
*/
|
||||
bool SampleAnimations(TimeStamp aPreviousFrameTime,
|
||||
bool SampleAnimations(const OMTAController* aOMTAController,
|
||||
TimeStamp aPreviousFrameTime,
|
||||
TimeStamp aCurrentFrameTime);
|
||||
|
||||
/**
|
||||
|
@ -168,7 +172,7 @@ class CompositorAnimationStorage final {
|
|||
void ClearById(const uint64_t& aId);
|
||||
|
||||
private:
|
||||
~CompositorAnimationStorage(){};
|
||||
~CompositorAnimationStorage() = default;
|
||||
|
||||
/**
|
||||
* Return the animated value if a given id can map to its animated value
|
||||
|
@ -220,6 +224,8 @@ class CompositorAnimationStorage final {
|
|||
AnimationsTable mAnimations;
|
||||
std::unordered_set<uint64_t> mNewAnimations;
|
||||
mutable Mutex mLock;
|
||||
// CompositorBridgeParent owns this CompositorAnimationStorage instance.
|
||||
CompositorBridgeParent* MOZ_NON_OWNING_REF mCompositorBridge;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -98,6 +98,15 @@ class APZSampler {
|
|||
void MarkAsyncTransformAppliedToContent(const LayerMetricsWrapper& aLayer);
|
||||
bool HasUnusedAsyncTransform(const LayerMetricsWrapper& aLayer);
|
||||
|
||||
/**
|
||||
* Similar to above GetCurrentAsyncTransform, but get the current transform
|
||||
* with LayersId and ViewID.
|
||||
* NOTE: This function should NOT be called on the compositor thread.
|
||||
*/
|
||||
AsyncTransform GetCurrentAsyncTransform(
|
||||
const LayersId& aLayersId, const ScrollableLayerGuid::ViewID& aScrollId,
|
||||
AsyncTransformComponents aComponents) const;
|
||||
|
||||
/**
|
||||
* Returns the composition bounds of the APZC correspoinding to the pair of
|
||||
* |aLayersId| and |aScrollId|.
|
||||
|
|
|
@ -147,6 +147,27 @@ AsyncTransform APZSampler::GetCurrentAsyncTransform(
|
|||
AsyncPanZoomController::eForCompositing, aComponents);
|
||||
}
|
||||
|
||||
AsyncTransform APZSampler::GetCurrentAsyncTransform(
|
||||
const LayersId& aLayersId, const ScrollableLayerGuid::ViewID& aScrollId,
|
||||
AsyncTransformComponents aComponents) const {
|
||||
MOZ_ASSERT(!CompositorThreadHolder::IsInCompositorThread());
|
||||
AssertOnSamplerThread();
|
||||
|
||||
RefPtr<AsyncPanZoomController> apzc =
|
||||
mApz->GetTargetAPZC(aLayersId, aScrollId);
|
||||
if (!apzc) {
|
||||
// It's possible that this function can get called even after the target
|
||||
// APZC has been already destroyed because destroying the animation which
|
||||
// triggers this function call is basically processed later than the APZC,
|
||||
// i.e. queue mCompositorAnimationsToDelete in WebRenderBridgeParent and
|
||||
// then remove in WebRenderBridgeParent::RemoveEpochDataPriorTo.
|
||||
return AsyncTransform{};
|
||||
}
|
||||
|
||||
return apzc->GetCurrentAsyncTransform(AsyncPanZoomController::eForCompositing,
|
||||
aComponents);
|
||||
}
|
||||
|
||||
Maybe<CompositionPayload> APZSampler::NotifyScrollSampling(
|
||||
const LayerMetricsWrapper& aLayer) {
|
||||
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
||||
|
|
|
@ -392,7 +392,8 @@ void CompositorBridgeParent::Initialize() {
|
|||
}
|
||||
|
||||
if (mOptions.UseWebRender()) {
|
||||
mOMTASampler = new OMTASampler(GetAnimationStorage());
|
||||
CompositorAnimationStorage* animationStorage = GetAnimationStorage();
|
||||
mOMTASampler = new OMTASampler(animationStorage, mRootLayerTreeID);
|
||||
}
|
||||
|
||||
mPaused = mOptions.InitiallyPaused();
|
||||
|
@ -1370,7 +1371,7 @@ void CompositorBridgeParent::ApplyAsyncProperties(
|
|||
|
||||
CompositorAnimationStorage* CompositorBridgeParent::GetAnimationStorage() {
|
||||
if (!mAnimationStorage) {
|
||||
mAnimationStorage = new CompositorAnimationStorage();
|
||||
mAnimationStorage = new CompositorAnimationStorage(this);
|
||||
}
|
||||
return mAnimationStorage;
|
||||
}
|
||||
|
|
|
@ -258,6 +258,7 @@ EXPORTS.mozilla.layers += [
|
|||
'wr/ClipManager.h',
|
||||
'wr/DisplayItemCache.h',
|
||||
'wr/IpcResourceUpdateQueue.h',
|
||||
'wr/OMTAController.h',
|
||||
'wr/OMTASampler.h',
|
||||
'wr/RenderRootStateManager.h',
|
||||
'wr/RenderRootTypes.h',
|
||||
|
@ -528,6 +529,7 @@ UNIFIED_SOURCES += [
|
|||
'wr/ClipManager.cpp',
|
||||
'wr/DisplayItemCache.cpp',
|
||||
'wr/IpcResourceUpdateQueue.cpp',
|
||||
'wr/OMTAController.cpp',
|
||||
'wr/OMTASampler.cpp',
|
||||
'wr/RenderRootStateManager.cpp',
|
||||
'wr/RenderRootTypes.cpp',
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/* -*- 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/OMTAController.h"
|
||||
|
||||
#include "mozilla/layers/CompositorBridgeParent.h"
|
||||
#include "mozilla/layers/CompositorThread.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
void OMTAController::NotifyJankedAnimations(
|
||||
JankedAnimations&& aJankedAnimations) const {
|
||||
if (StaticPrefs::layout_animation_prerender_partial_jank()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CompositorThread()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CompositorThread()->IsOnCurrentThread()) {
|
||||
CompositorThread()->Dispatch(NewRunnableMethod<JankedAnimations&&>(
|
||||
"layers::OMTAController::NotifyJankedAnimations", this,
|
||||
&OMTAController::NotifyJankedAnimations, std::move(aJankedAnimations)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (CompositorBridgeParent* bridge =
|
||||
CompositorBridgeParent::GetCompositorBridgeParentFromLayersId(
|
||||
mRootLayersId)) {
|
||||
bridge->NotifyJankedAnimations(aJankedAnimations);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,44 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#ifndef mozilla_layers_OMTAController_h
|
||||
#define mozilla_layers_OMTAController_h
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "mozilla/layers/LayersTypes.h" // for LayersId
|
||||
#include "nsISerialEventTarget.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsTArrayForwardDeclare.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
/**
|
||||
* This class just delegates the jank animations notification to the compositor
|
||||
* thread from the sampler thread.
|
||||
*/
|
||||
class OMTAController final {
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(OMTAController)
|
||||
|
||||
public:
|
||||
explicit OMTAController(LayersId aRootLayersId)
|
||||
: mRootLayersId(aRootLayersId) {}
|
||||
|
||||
using JankedAnimations =
|
||||
std::unordered_map<LayersId, nsTArray<uint64_t>, LayersId::HashFn>;
|
||||
void NotifyJankedAnimations(JankedAnimations&& aJankedAnimations) const;
|
||||
|
||||
private:
|
||||
~OMTAController() = default;
|
||||
|
||||
LayersId mRootLayersId;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_layers_OMTAController_h
|
|
@ -9,6 +9,7 @@
|
|||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/layers/CompositorAnimationStorage.h"
|
||||
#include "mozilla/layers/CompositorThread.h"
|
||||
#include "mozilla/layers/OMTAController.h"
|
||||
#include "mozilla/layers/SynchronousTask.h"
|
||||
#include "mozilla/layers/WebRenderBridgeParent.h"
|
||||
#include "mozilla/webrender/WebRenderAPI.h"
|
||||
|
@ -20,11 +21,14 @@ StaticMutex OMTASampler::sWindowIdLock;
|
|||
StaticAutoPtr<std::unordered_map<uint64_t, RefPtr<OMTASampler>>>
|
||||
OMTASampler::sWindowIdMap;
|
||||
|
||||
OMTASampler::OMTASampler(const RefPtr<CompositorAnimationStorage>& aAnimStorage)
|
||||
OMTASampler::OMTASampler(const RefPtr<CompositorAnimationStorage>& aAnimStorage,
|
||||
LayersId aRootLayersId)
|
||||
: mAnimStorage(aAnimStorage),
|
||||
mStorageLock("OMTASampler::mStorageLock"),
|
||||
mThreadIdLock("OMTASampler::mThreadIdLock"),
|
||||
mSampleTimeLock("OMTASampler::mSampleTimeLock") {}
|
||||
mSampleTimeLock("OMTASampler::mSampleTimeLock") {
|
||||
mController = new OMTAController(aRootLayersId);
|
||||
}
|
||||
|
||||
void OMTASampler::Destroy() {
|
||||
StaticMutexAutoLock lock(sWindowIdLock);
|
||||
|
@ -116,7 +120,7 @@ WrAnimations OMTASampler::SampleAnimations(const TimeStamp& aPreviousSampleTime,
|
|||
|
||||
MutexAutoLock lock(mStorageLock);
|
||||
|
||||
mAnimStorage->SampleAnimations(aPreviousSampleTime, aSampleTime);
|
||||
mAnimStorage->SampleAnimations(mController, aPreviousSampleTime, aSampleTime);
|
||||
|
||||
return mAnimStorage->CollectWebRenderAnimations();
|
||||
}
|
||||
|
@ -150,7 +154,7 @@ void OMTASampler::SampleForTesting(const Maybe<TimeStamp>& aTestingSampleTime) {
|
|||
}
|
||||
|
||||
MutexAutoLock storageLock(mStorageLock);
|
||||
mAnimStorage->SampleAnimations(previousSampleTime, sampleTime);
|
||||
mAnimStorage->SampleAnimations(mController, previousSampleTime, sampleTime);
|
||||
}
|
||||
|
||||
void OMTASampler::SetAnimations(
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <queue>
|
||||
|
||||
#include "base/platform_thread.h" // for PlatformThreadId
|
||||
#include "mozilla/layers/OMTAController.h" // for OMTAController
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
|
@ -42,7 +43,8 @@ class OMTASampler final {
|
|||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(OMTASampler)
|
||||
|
||||
public:
|
||||
explicit OMTASampler(const RefPtr<CompositorAnimationStorage>& aAnimStorage);
|
||||
OMTASampler(const RefPtr<CompositorAnimationStorage>& aAnimStorage,
|
||||
LayersId aRootLayersId);
|
||||
|
||||
// Whoever creates this sampler is responsible for calling Destroy() on it
|
||||
// before releasing the owning refptr.
|
||||
|
@ -110,6 +112,7 @@ class OMTASampler final {
|
|||
WrAnimations SampleAnimations(const TimeStamp& aPreviousSampleTime,
|
||||
const TimeStamp& aSampleTime);
|
||||
|
||||
RefPtr<OMTAController> mController;
|
||||
// Can only be accessed or modified while holding mStorageLock.
|
||||
RefPtr<CompositorAnimationStorage> mAnimStorage;
|
||||
mutable Mutex mStorageLock;
|
||||
|
|
|
@ -158,14 +158,14 @@ test-pref(layout.css.zoom-transform-hack.enabled,true) == zoom-hack-2.html zoom-
|
|||
== transform-anon-block-1.html transform-anon-block-1-ref.html
|
||||
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
|
||||
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
|
||||
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.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.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
|
||||
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
|
||||
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
|
||||
# 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.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
|
||||
|
|
Загрузка…
Ссылка в новой задаче