Backed out 9 changesets (bug 1324591) for linux build bustages on central on nsDisplayList.h.

Backed out changeset 75966ee1fe65 (bug 1324591)
Backed out changeset d6a01c6bc40e (bug 1324591)
Backed out changeset fef36ff2ea3d (bug 1324591)
Backed out changeset 4a4ae4bd95d1 (bug 1324591)
Backed out changeset 732804c83add (bug 1324591)
Backed out changeset 84657a3522fb (bug 1324591)
Backed out changeset e6c74ba41007 (bug 1324591)
Backed out changeset 8e6d4e9f5aa0 (bug 1324591)
Backed out changeset 6bc284863aff (bug 1324591)
This commit is contained in:
Brindusan Cristian 2020-07-05 13:45:35 +03:00
Родитель 4215f9a916
Коммит 7f75410fd7
53 изменённых файлов: 88 добавлений и 1485 удалений

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

@ -183,11 +183,6 @@ 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,30 +421,6 @@ 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();
@ -642,11 +618,6 @@ 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,8 +684,6 @@ 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;
}
@ -709,39 +707,12 @@ 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,8 +274,6 @@ 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.
//

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

@ -1,6 +1,5 @@
<!doctype html>
<head>
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<meta charset=utf-8>
<title>Tests restyles caused by animations</title>
<script>
@ -1955,28 +1954,6 @@ waitForAllPaints(() => {
await ensureElementRemoval(div);
});
add_task(async function partial_prerendered_transform_animations() {
await SpecialPowers.pushPrefEnv({
set: [['layout.animation.prerender.partial', true]] });
const div = addDiv(null, { style: 'width: 10000px; height: 10000px;' });
const animation = div.animate(
// Use the same value both for `from` and `to` to avoid jank on the
// compositor.
{ transform: ['rotate(0deg)', 'rotate(0deg)'] },
100 * MS_PER_SEC
);
await waitForAnimationReadyToRestyle(animation);
const markers = await observeStyling(5);
is(markers.length, 0,
'Transform animation with partial pre-rendered should never cause ' +
'restyles');
await ensureElementRemoval(div);
});
add_task(async function restyling_on_create_animation() {
const div = addDiv();
const docShell = getDocShellForObservingRestylesForWindow(window);

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

@ -2615,9 +2615,13 @@ nsDOMWindowUtils::ZoomToFocusedInput() {
// Note that we only do this if the frame belongs to `presShell` (that is,
// we still zoom in fixed elements in subdocuments, as they're not fixed to
// the root content document).
if (frame->PresShell() == presShell &&
nsLayoutUtils::IsInPositionFixedSubtree(frame)) {
return true;
if (frame->PresShell() == presShell) {
for (; frame; frame = frame->GetParent()) {
if (frame->StyleDisplay()->mPosition == StylePositionProperty::Fixed &&
nsLayoutUtils::IsReallyFixedPos(frame)) {
return true;
}
}
}
return false;
}();

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

@ -3105,14 +3105,6 @@ 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,8 +509,6 @@ 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);

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

@ -5,13 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "AnimationHelper.h"
#include "gfx2DGlue.h" // for ThebesRect
#include "gfxLineSegment.h" // for gfxLineSegment
#include "gfxPoint.h" // for gfxPoint
#include "gfxQuad.h" // for gfxQuad
#include "gfxRect.h" // for gfxRect
#include "gfxUtils.h" // for gfxUtils::TransformToQuad
#include "mozilla/ComputedTimingFunction.h" // for ComputedTimingFunction
#include "mozilla/ComputedTimingFunction.h" // for ComputedTimingFunction
#include "mozilla/dom/AnimationEffectBinding.h" // for dom::FillMode
#include "mozilla/dom/KeyframeEffectBinding.h" // for dom::IterationComposite
#include "mozilla/dom/KeyframeEffect.h" // for dom::KeyFrameEffectReadOnly
@ -321,9 +315,8 @@ static bool HasTransformLikeAnimations(const AnimationArray& aAnimations) {
#endif
AnimationStorageData AnimationHelper::ExtractAnimations(
const LayersId& aLayersId, const AnimationArray& aAnimations) {
const AnimationArray& aAnimations) {
AnimationStorageData storageData;
storageData.mLayersId = aLayersId;
nsCSSPropertyID prevID = eCSSProperty_UNKNOWN;
PropertyAnimationGroup* currData = nullptr;
@ -553,136 +546,5 @@ gfx::Matrix4x4 AnimationHelper::ServoAnimationValueToMatrix4x4(
props, refBox, aTransformData.appUnitsPerDevPixel());
}
static uint8_t CollectOverflowedSideLines(const gfxQuad& aPrerenderedQuad,
SideBits aOverflowSides,
gfxLineSegment sideLines[4]) {
uint8_t count = 0;
if (aOverflowSides & SideBits::eTop) {
sideLines[count] = gfxLineSegment(aPrerenderedQuad.mPoints[0],
aPrerenderedQuad.mPoints[1]);
count++;
}
if (aOverflowSides & SideBits::eRight) {
sideLines[count] = gfxLineSegment(aPrerenderedQuad.mPoints[1],
aPrerenderedQuad.mPoints[2]);
count++;
}
if (aOverflowSides & SideBits::eBottom) {
sideLines[count] = gfxLineSegment(aPrerenderedQuad.mPoints[2],
aPrerenderedQuad.mPoints[3]);
count++;
}
if (aOverflowSides & SideBits::eLeft) {
sideLines[count] = gfxLineSegment(aPrerenderedQuad.mPoints[3],
aPrerenderedQuad.mPoints[0]);
count++;
}
return count;
}
enum RegionBits : uint8_t {
Inside = 0,
Left = (1 << 0),
Right = (1 << 1),
Bottom = (1 << 2),
Top = (1 << 3),
};
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(RegionBits);
static RegionBits GetRegionBitsForPoint(double aX, double aY,
const gfxRect& aClip) {
RegionBits result = RegionBits::Inside;
if (aX < aClip.X()) {
result |= RegionBits::Left;
} else if (aX > aClip.XMost()) {
result |= RegionBits::Right;
}
if (aY < aClip.Y()) {
result |= RegionBits::Bottom;
} else if (aY > aClip.YMost()) {
result |= RegionBits::Top;
}
return result;
};
// https://en.wikipedia.org/wiki/Cohen%E2%80%93Sutherland_algorithm
static bool LineSegmentIntersectsClip(double aX0, double aY0, double aX1,
double aY1, const gfxRect& aClip) {
RegionBits b0 = GetRegionBitsForPoint(aX0, aY0, aClip);
RegionBits b1 = GetRegionBitsForPoint(aX1, aY1, aClip);
while (true) {
if (!(b0 | b1)) {
// Completely inside.
return true;
}
if (b0 & b1) {
// Completely outside.
return false;
}
double x, y;
// Choose an outside point.
RegionBits outsidePointBits = b1 > b0 ? b1 : b0;
if (outsidePointBits & RegionBits::Top) {
x = aX0 + (aX1 - aX0) * (aClip.YMost() - aY0) / (aY1 - aY0);
y = aClip.YMost();
} else if (outsidePointBits & RegionBits::Bottom) {
x = aX0 + (aX1 - aX0) * (aClip.Y() - aY0) / (aY1 - aY0);
y = aClip.Y();
} else if (outsidePointBits & RegionBits::Right) {
y = aY0 + (aY1 - aY0) * (aClip.XMost() - aX0) / (aX1 - aX0);
x = aClip.XMost();
} else if (outsidePointBits & RegionBits::Left) {
y = aY0 + (aY1 - aY0) * (aClip.X() - aX0) / (aX1 - aX0);
x = aClip.X();
}
if (outsidePointBits == b0) {
aX0 = x;
aY0 = y;
b0 = GetRegionBitsForPoint(aX0, aY0, aClip);
} else {
aX1 = x;
aY1 = y;
b1 = GetRegionBitsForPoint(aX1, aY1, aClip);
}
}
MOZ_ASSERT_UNREACHABLE();
return false;
}
// static
bool AnimationHelper::ShouldBeJank(const LayoutDeviceIntRect& aPrerenderedRect,
SideBits aOverflowSides,
const gfx::Matrix4x4& aTransform,
const ParentLayerRect& aClipRect) {
if (aClipRect.IsEmpty()) {
return false;
}
gfxQuad prerenderedQuad = gfxUtils::TransformToQuad(
ThebesRect(aPrerenderedRect.ToUnknownRect()), aTransform);
gfxLineSegment sideLines[4];
uint8_t overflowSideCount =
CollectOverflowedSideLines(prerenderedQuad, aOverflowSides, sideLines);
gfxRect clipRect = ThebesRect(aClipRect.ToUnknownRect());
for (uint8_t j = 0; j < overflowSideCount; j++) {
if (LineSegmentIntersectsClip(sideLines[j].mStart.x, sideLines[j].mStart.y,
sideLines[j].mEnd.x, sideLines[j].mEnd.y,
clipRect)) {
return true;
}
}
return false;
}
} // namespace layers
} // namespace mozilla

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

@ -14,7 +14,6 @@
#include "mozilla/webrender/WebRenderTypes.h" // for RenderRoot
#include "mozilla/TimeStamp.h" // for TimeStamp
#include "mozilla/TimingParams.h"
#include "mozilla/Types.h" // for SideBits
#include "mozilla/Variant.h"
#include "X11UndefineNone.h"
#include <unordered_map>
@ -116,7 +115,7 @@ class AnimationHelper {
* IPC boundary into something we can readily use for sampling.
*/
static AnimationStorageData ExtractAnimations(
const LayersId& aLayersId, const AnimationArray& aAnimations);
const AnimationArray& aAnimations);
/**
* Get a unique id to represent the compositor animation between child
@ -135,16 +134,6 @@ class AnimationHelper {
static gfx::Matrix4x4 ServoAnimationValueToMatrix4x4(
const nsTArray<RefPtr<RawServoAnimationValue>>& aValue,
const TransformData& aTransformData, gfx::Path* aCachedMotionPath);
/**
* Returns true if |aPrerenderedRect| transformed by |aTransform| were
* composited in |aClipRect| there appears area which wasn't pre-rendered
* on the main-thread. I.e. checkerboarding.
*/
static bool ShouldBeJank(const LayoutDeviceIntRect& aPrerenderedRect,
SideBits aOverflowedSides,
const gfx::Matrix4x4& aTransform,
const ParentLayerRect& aClipRect);
};
} // namespace layers

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

@ -81,12 +81,11 @@ void AnimationInfo::ClearAnimationsForNextTransaction() {
}
void AnimationInfo::SetCompositorAnimations(
const LayersId& aLayersId,
const CompositorAnimations& aCompositorAnimations) {
mCompositorAnimationsId = aCompositorAnimations.id();
mStorageData = AnimationHelper::ExtractAnimations(
aLayersId, aCompositorAnimations.animations());
mStorageData =
AnimationHelper::ExtractAnimations(aCompositorAnimations.animations());
}
bool AnimationInfo::StartPendingAnimations(const TimeStamp& aReadyTime) {
@ -597,7 +596,7 @@ bool AnimationInfo::AddAnimationsForProperty(
nsIFrame* aFrame, const EffectSet* aEffects,
const nsTArray<RefPtr<dom::Animation>>& aCompositorAnimations,
const Maybe<TransformData>& aTransformData, nsCSSPropertyID aProperty,
Send aSendFlag, LayerManager* aLayerManager) {
Send aSendFlag) {
bool addedAny = false;
// Add from first to last (since last overrides)
for (dom::Animation* anim : aCompositorAnimations) {
@ -643,94 +642,10 @@ 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;
}
// Returns which pre-rendered area's sides are overflowed from the pre-rendered
// rect.
//
// We don't need to make jank animations when we are going to composite the
// area where there is no overflowed area even if it's outside of the
// pre-rendered area.
static SideBits GetOverflowedSides(const nsRect& aOverflow,
const nsRect& aPartialPrerenderArea) {
SideBits sides = SideBits::eNone;
if (aOverflow.X() < aPartialPrerenderArea.X()) {
sides |= SideBits::eLeft;
}
if (aOverflow.Y() < aPartialPrerenderArea.Y()) {
sides |= SideBits::eTop;
}
if (aOverflow.XMost() > aPartialPrerenderArea.XMost()) {
sides |= SideBits::eRight;
}
if (aOverflow.YMost() > aPartialPrerenderArea.YMost()) {
sides |= SideBits::eBottom;
}
return sides;
}
static ParentLayerRect GetClipRectForPartialPrerender(
const nsIFrame* aFrame, int32_t aDevPixelsToAppUnits) {
nsIScrollableFrame* scrollFrame = nsLayoutUtils::GetNearestScrollableFrame(
aFrame->GetParent(), nsLayoutUtils::SCROLLABLE_SAME_DOC |
nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN);
if (!scrollFrame) {
// If there is no suitable scrollable frame in the same document, use the
// root one.
scrollFrame = aFrame->PresShell()->GetRootScrollFrameAsScrollable();
}
MOZ_ASSERT(scrollFrame);
// We don't necessarily use nsLayoutUtils::CalculateCompositionSizeForFrame
// since this is a case where we don't use APZ at all.
return LayoutDeviceRect::FromAppUnits(scrollFrame->GetScrollPortRect(),
aDevPixelsToAppUnits) *
LayoutDeviceToLayerScale2D() * LayerToParentLayerScale();
}
static PartialPrerenderData GetPartialPrerenderData(
const nsIFrame* aFrame, const nsDisplayItem* aItem) {
const nsRect& partialPrerenderedRect = aItem->GetUntransformedPaintRect();
nsRect overflow = aFrame->GetVisualOverflowRectRelativeToSelf();
ScrollableLayerGuid::ViewID scrollId = ScrollableLayerGuid::NULL_SCROLL_ID;
if (nsLayoutUtils::AsyncPanZoomEnabled(const_cast<nsIFrame*>(aFrame))) {
const bool isInPositionFixed =
nsLayoutUtils::IsInPositionFixedSubtree(aFrame);
const ActiveScrolledRoot* asr = aItem->GetActiveScrolledRoot();
const nsIFrame* asrScrollableFrame =
asr ? do_QueryFrame(asr->mScrollableFrame) : nullptr;
if (!isInPositionFixed && asr &&
aFrame->PresContext() == asrScrollableFrame->PresContext()) {
scrollId = asr->GetViewId();
} else {
// Use the root scroll id in the same document if the target frame is in
// position:fixed subtree or there is no ASR or the ASR is in a different
// ancestor document.
scrollId =
nsLayoutUtils::ScrollIdForRootScrollFrame(aFrame->PresContext());
}
}
int32_t devPixelsToAppUnits = aFrame->PresContext()->AppUnitsPerDevPixel();
ParentLayerRect clipRect =
GetClipRectForPartialPrerender(aFrame, devPixelsToAppUnits);
return PartialPrerenderData{
LayoutDeviceIntRect::FromAppUnitsToInside(partialPrerenderedRect,
devPixelsToAppUnits),
GetOverflowedSides(overflow, partialPrerenderedRect), scrollId, clipRect};
}
enum class AnimationDataType {
WithMotionPath,
WithoutMotionPath,
@ -791,14 +706,9 @@ static Maybe<TransformData> CreateAnimationData(
motionPathOrigin, anchorAdjustment, RayReferenceData(aFrame)));
}
Maybe<PartialPrerenderData> partialPrerenderData;
if (aItem && static_cast<nsDisplayTransform*>(aItem)->IsPartialPrerender()) {
partialPrerenderData = Some(GetPartialPrerenderData(aFrame, aItem));
}
return Some(TransformData(
origin, offsetToTransformOrigin, bounds, devPixelsToAppUnits, scaleX,
scaleY, hasPerspectiveParent, motionPathData, partialPrerenderData));
return Some(TransformData(origin, offsetToTransformOrigin, bounds,
devPixelsToAppUnits, scaleX, scaleY,
hasPerspectiveParent, motionPathData));
}
void AnimationInfo::AddNonAnimatingTransformLikePropertiesStyles(
@ -876,11 +786,9 @@ void AnimationInfo::AddNonAnimatingTransformLikePropertiesStyles(
}
}
void AnimationInfo::AddAnimationsForDisplayItem(nsIFrame* aFrame,
nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem,
DisplayItemType aType,
LayerManager* aLayerManager) {
void AnimationInfo::AddAnimationsForDisplayItem(
nsIFrame* aFrame, nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem,
DisplayItemType aType, layers::LayersBackend aLayersBackend) {
Send sendFlag = !aBuilder ? Send::NextTransaction : Send::Immediate;
if (sendFlag == Send::NextTransaction) {
ClearAnimationsForNextTransaction();
@ -925,7 +833,7 @@ void AnimationInfo::AddAnimationsForDisplayItem(nsIFrame* aFrame,
compositorAnimations =
GroupAnimationsByProperty(matchedAnimations, propertySet);
Maybe<TransformData> transformData =
CreateAnimationData(aFrame, aItem, aType, aLayerManager->GetBackendType(),
CreateAnimationData(aFrame, aItem, aType, aLayersBackend,
compositorAnimations.has(eCSSProperty_offset_path) ||
!aFrame->StyleDisplay()->mOffsetPath.IsNone()
? AnimationDataType::WithMotionPath
@ -945,9 +853,9 @@ void AnimationInfo::AddAnimationsForDisplayItem(nsIFrame* aFrame,
// 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, aLayerManager);
bool added =
AddAnimationsForProperty(aFrame, effects, iter.get().value(),
transformData, iter.get().key(), sendFlag);
if (added && transformData) {
// Only copy TransformLikeMetaData in the first animation property.
transformData.reset();

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

@ -42,6 +42,7 @@ class Layer;
class LayerManager;
struct CompositorAnimationData;
struct PropertyAnimationGroup;
enum class LayersBackend : int8_t;
class AnimationInfo final {
typedef nsTArray<Animation> AnimationArray;
@ -76,7 +77,6 @@ class AnimationInfo final {
void ClearAnimations();
void ClearAnimationsForNextTransaction();
void SetCompositorAnimations(
const LayersId& aLayersId,
const CompositorAnimations& aCompositorAnimations);
bool StartPendingAnimations(const TimeStamp& aReadyTime);
void TransferMutatedFlagToLayer(Layer* aLayer);
@ -91,7 +91,6 @@ class AnimationInfo final {
const Maybe<TransformData>& GetTransformData() const {
return mStorageData.mTransformData;
}
const LayersId& GetLayersId() const { return mStorageData.mLayersId; }
bool ApplyPendingUpdatesForThisTransaction();
bool HasTransformAnimation() const;
@ -119,7 +118,7 @@ class AnimationInfo final {
void AddAnimationsForDisplayItem(nsIFrame* aFrame,
nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem, DisplayItemType aType,
LayerManager* aLayerManager);
LayersBackend aLayersBackend);
private:
enum class Send {
@ -136,7 +135,7 @@ class AnimationInfo final {
nsIFrame* aFrame, const EffectSet* aEffects,
const nsTArray<RefPtr<dom::Animation>>& aCompositorAnimations,
const Maybe<TransformData>& aTransformData, nsCSSPropertyID aProperty,
Send aSendFlag, LayerManager* aLayerManager);
Send aSendFlag);
void AddNonAnimatingTransformLikePropertiesStyles(
const nsCSSPropertyIDSet& aNonAnimatingProperties, nsIFrame* aFrame,

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

@ -10,7 +10,6 @@
#include "mozilla/dom/Nullable.h"
#include "mozilla/ComputedTimingFunction.h" // for ComputedTimingFunction
#include "mozilla/layers/LayersMessages.h" // for TransformData, etc
#include "mozilla/layers/LayersTypes.h" // for LayersId
#include "mozilla/TimeStamp.h" // for TimeStamp
#include "mozilla/TimingParams.h"
#include "X11UndefineNone.h"
@ -53,13 +52,6 @@ struct PropertyAnimation {
float mPlaybackRate;
dom::IterationCompositeOperation mIterationComposite;
bool mIsNotPlaying;
void ResetLastCompositionValues() {
mCurrentIterationOnLastCompose = 0;
mSegmentIndexOnLastCompose = 0;
mProgressOnLastCompose.SetNull();
mPortionInSegmentOnLastCompose.SetNull();
}
};
struct PropertyAnimationGroup {
@ -73,11 +65,6 @@ struct PropertyAnimationGroup {
mAnimations.Clear();
mBaseStyle = nullptr;
}
void ResetLastCompositionValues() {
for (PropertyAnimation& animation : mAnimations) {
animation.ResetLastCompositionValues();
}
}
};
struct AnimationStorageData {
@ -88,9 +75,6 @@ struct AnimationStorageData {
Maybe<TransformData> mTransformData;
// For motion path. We cached the gfx path for optimization.
RefPtr<gfx::Path> mCachedMotionPath;
// This is used to communicate with the main-thread. E.g. to tell the fact
// that this animation needs to be pre-rendered again on the main-thread, etc.
LayersId mLayersId;
AnimationStorageData() = default;
AnimationStorageData(AnimationStorageData&& aOther) = default;

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

@ -7,11 +7,8 @@
#include "CompositorAnimationStorage.h"
#include "AnimationHelper.h"
#include "mozilla/layers/APZSampler.h" // for APZSampler
#include "mozilla/layers/CompositorBridgeParent.h" // for CompositorBridgeParent
#include "mozilla/layers/CompositorThread.h" // for CompositorThreadHolder
#include "mozilla/layers/LayerManagerComposite.h" // for LayerComposite, etc
#include "mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper
#include "mozilla/ServoStyleConsts.h"
#include "mozilla/webrender/WebRenderTypes.h" // for ToWrTransformProperty, etc
#include "nsDeviceContext.h" // for AppUnitsPerCSSPixel
@ -140,13 +137,12 @@ void CompositorAnimationStorage::SetAnimatedValue(uint64_t aId,
}
void CompositorAnimationStorage::SetAnimations(uint64_t aId,
const LayersId& aLayersId,
const AnimationArray& aValue) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
MutexAutoLock lock(mLock);
mAnimations[aId] = std::make_unique<AnimationStorageData>(
AnimationHelper::ExtractAnimations(aLayersId, aValue));
AnimationHelper::ExtractAnimations(aValue));
// If there is the last animated value, then we need to store the id to remove
// the value if the new animation doesn't produce any animated data (i.e. in
@ -289,81 +285,13 @@ static gfx::Matrix4x4 FrameTransformToTransformInDevice(
return transformInDevice;
}
static Matrix4x4 GetTransformForPartialPrerender(
Layer* aLayer, const LayersId aLayersId,
const ScrollableLayerGuid::ViewID& aScrollId,
const RefPtr<APZSampler>& aSampler) {
MOZ_ASSERT(aLayer);
ParentLayerPoint translationByApz;
Matrix4x4 transform;
for (Layer* layer = aLayer; layer; layer = layer->GetParent()) {
if (layer->AsRefLayer()) {
MOZ_ASSERT(layer->AsRefLayer()->GetReferentId() == aLayersId);
break;
}
// Accumulate static transforms.
if (layer != aLayer) {
Matrix4x4 baseTransform = layer->GetBaseTransform();
if (ContainerLayer* container = layer->AsContainerLayer()) {
baseTransform.PostScale(container->GetPreXScale(),
container->GetPreYScale(), 1);
}
transform *= baseTransform;
}
if (!layer->GetIsStickyPosition() && !layer->GetIsFixedPosition()) {
bool hasSameScrollId = false;
for (uint32_t i = 0; i < layer->GetScrollMetadataCount(); i++) {
// Factor APZ translation if there exists.
if (aSampler) {
LayerMetricsWrapper wrapper = LayerMetricsWrapper(layer, i);
AsyncTransform asyncTransform =
aSampler->GetCurrentAsyncTransform(wrapper, LayoutAndVisual);
translationByApz += asyncTransform.mTranslation;
}
if (layer->GetFrameMetrics(i).GetScrollId() == aScrollId) {
hasSameScrollId = true;
}
}
if (hasSameScrollId) {
break;
}
} else {
// Bug 1642547: Fix for position:sticky layers.
}
}
transform.PostTranslate(translationByApz.ToUnknownPoint());
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,
void CompositorAnimationStorage::ApplyAnimatedValue(
Layer* aLayer, nsCSSPropertyID aProperty, AnimatedValue* aPreviousValue,
const nsTArray<RefPtr<RawServoAnimationValue>>& aValues) {
mLock.AssertCurrentThreadOwns();
MOZ_ASSERT(!aValues.IsEmpty());
bool janked = false;
HostLayer* layerCompositor = aLayer->AsHostLayer();
switch (aProperty) {
case eCSSProperty_background_color: {
@ -410,31 +338,6 @@ bool CompositorAnimationStorage::ApplyAnimatedValue(
gfx::Matrix4x4 transform = FrameTransformToTransformInDevice(
frameTransform, aLayer, transformData);
if (const Maybe<PartialPrerenderData>& partialPrerenderData =
transformData.partialPrerenderData()) {
Matrix4x4 transformInClip = GetTransformForPartialPrerender(
aLayer, aLayer->GetAnimationLayersId(),
partialPrerenderData->scrollId(),
aCompositorBridge->GetAPZSampler());
transformInClip = transform * transformInClip;
ParentLayerRect clipRect = GetClipRectForPartialPrerender(
aLayer->GetAnimationLayersId(), *partialPrerenderData,
aCompositorBridge->GetAPZSampler());
if (AnimationHelper::ShouldBeJank(
partialPrerenderData->rect(),
partialPrerenderData->overflowedSides(), transformInClip,
clipRect)) {
// It's possible that we don't have the previous value and we don't
// either have enough area to composite in the first composition,
// e.g. a translate animation with a step timing function. In such
// cases we use the base transform value which was calculated on the
// main-thread as a fallback value.
transform = aPreviousValue
? aPreviousValue->Transform().mTransformInDevSpace
: aLayer->GetBaseTransform();
janked = true;
}
}
layerCompositor->SetShadowBaseTransform(transform);
layerCompositor->SetShadowTransformSetByAnimation(true);
@ -449,12 +352,11 @@ bool CompositorAnimationStorage::ApplyAnimatedValue(
default:
MOZ_ASSERT_UNREACHABLE("Unhandled animated property");
}
return !janked;
}
bool CompositorAnimationStorage::SampleAnimations(
Layer* aRoot, CompositorBridgeParent* aCompositorBridge,
TimeStamp aPreviousFrameTime, TimeStamp aCurrentFrameTime) {
bool CompositorAnimationStorage::SampleAnimations(Layer* aRoot,
TimeStamp aPreviousFrameTime,
TimeStamp aCurrentFrameTime) {
MutexAutoLock lock(mLock);
bool isAnimating = false;
@ -467,8 +369,6 @@ 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()) {
@ -493,37 +393,8 @@ bool CompositorAnimationStorage::SampleAnimations(
// We assume all transform like properties (on the same frame) live in
// a single same layer, so using the transform data of the last element
// should be fine.
if (!ApplyAnimatedValue(aCompositorBridge, layer,
lastPropertyAnimationGroup.mProperty,
previousValue, animationValues)) {
// Reset the last composition values in cases of jank so that we will
// never mis-compare in a sanity check in the case of
// SampleResult::Skipped below in this function.
//
// An example;
// a translateX(0px) -> translateX(100px) animation with step(2,start)
// and if the animation janked at translateX(50px) and in a later
// frame if the calculated transform value is going to be still
// translateX(50px) (i.e. at the same timing portion calculated by the
// step timing function), we skip sampling. That's correct ideally.
// But we have an assertion to do a sanity check for the skip sampling
// case that the check compares the calculated value translateX(50px)
// with the previous composited value. In this case the previous
// composited value is translateX(0px).
//
// NOTE: Ideally we shouldn't update the last composition values when
// we met janks, but it's quite hard to tell whether the jank will
// happen or not when we calculate each transform like properties'
// value (i.e. when we set the last composition value) since janks are
// caused by a result of the combinations of all transform like
// properties (e.g. `transform: translateX(50px)` and
// `translate: -50px` results `translateX(0px)`.
for (PropertyAnimationGroup& group : propertyAnimationGroups) {
group.ResetLastCompositionValues();
}
janked[layer->GetAnimationLayersId()].AppendElement(
layer->GetCompositorAnimationsId());
}
ApplyAnimatedValue(layer, lastPropertyAnimationGroup.mProperty,
previousValue, animationValues);
break;
case AnimationHelper::SampleResult::Skipped:
switch (lastPropertyAnimationGroup.mProperty) {
@ -605,10 +476,6 @@ bool CompositorAnimationStorage::SampleAnimations(
}
});
if (!janked.empty()) {
aCompositorBridge->NotifyJankedAnimations(janked);
}
return isAnimating;
}

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

@ -18,7 +18,6 @@ namespace mozilla {
namespace layers {
class Animation;
class Layers;
class CompositorBridgeParent;
typedef nsTArray<layers::Animation> AnimationArray;
@ -123,8 +122,7 @@ class CompositorAnimationStorage final {
/**
* Set the animations based on the unique id
*/
void SetAnimations(uint64_t aId, const LayersId& aLayersId,
const AnimationArray& aAnimations);
void SetAnimations(uint64_t aId, const AnimationArray& aAnimations);
/**
* Sample animation based the given timestamps and store them in this
@ -146,8 +144,7 @@ class CompositorAnimationStorage final {
*
* Note: This is called only by non WebRender.
*/
bool SampleAnimations(Layer* aRoot, CompositorBridgeParent* aCompositorBridge,
TimeStamp aPreviousFrameTime,
bool SampleAnimations(Layer* aRoot, TimeStamp aPreviousFrameTime,
TimeStamp aCurrentFrameTime);
bool HasAnimations() const;
@ -189,9 +186,8 @@ class CompositorAnimationStorage final {
void SetAnimatedValue(uint64_t aId, AnimatedValue* aPreviousValue,
nscolor aColor);
bool ApplyAnimatedValue(
CompositorBridgeParent* aCompositorBridge, Layer* aLayer,
nsCSSPropertyID aProperty, AnimatedValue* aPreviousValue,
void ApplyAnimatedValue(
Layer* aLayer, nsCSSPropertyID aProperty, AnimatedValue* aPreviousValue,
const nsTArray<RefPtr<RawServoAnimationValue>>& aValues);
void Clear();

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

@ -24,7 +24,6 @@
#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
@ -168,37 +167,6 @@ 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
@ -219,13 +187,12 @@ Layer::Layer(LayerManager* aManager, void* aImplData)
Layer::~Layer() = default;
void Layer::SetCompositorAnimations(
const LayersId& aLayersId,
const CompositorAnimations& aCompositorAnimations) {
MOZ_LAYERS_LOG_IF_SHADOWABLE(
this, ("Layer::Mutated(%p) SetCompositorAnimations with id=%" PRIu64,
this, mAnimationInfo.GetCompositorAnimationsId()));
mAnimationInfo.SetCompositorAnimations(aLayersId, aCompositorAnimations);
mAnimationInfo.SetCompositorAnimations(aCompositorAnimations);
Mutated();
}

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

@ -28,7 +28,6 @@
#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
@ -47,7 +46,6 @@
#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
@ -258,7 +256,6 @@ class LayerManager : public FrameRecorder {
mDestroyed = true;
mUserData.Destroy();
mRoot = nullptr;
mPartialPrerenderedAnimations.Clear();
}
bool IsDestroyed() { return mDestroyed; }
@ -756,13 +753,6 @@ 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;
@ -800,12 +790,6 @@ 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:
/*
@ -832,7 +816,7 @@ class LayerManager : public FrameRecorder {
class Layer {
NS_INLINE_DECL_REFCOUNTING(Layer)
using AnimationArray = nsTArray<layers::Animation>;
typedef nsTArray<Animation> AnimationArray;
public:
// Keep these in alphabetical order
@ -1270,7 +1254,6 @@ class Layer {
// This is only called when the layer tree is updated. Do not call this from
// layout code. To add an animation to this layer, use AddAnimation.
void SetCompositorAnimations(
const LayersId& aLayersId,
const CompositorAnimations& aCompositorAnimations);
// Go through all animations in this layer and its children and, for
// any animations with a null start time, update their start time such
@ -1369,7 +1352,7 @@ class Layer {
bool HasScrollableFrameMetrics() const;
bool IsScrollableWithoutContent() const;
const EventRegions& GetEventRegions() const { return mEventRegions; }
ContainerLayer* GetParent() const { return mParent; }
ContainerLayer* GetParent() { return mParent; }
Layer* GetNextSibling() {
if (mNextSibling) {
mNextSibling->CheckCanary();
@ -1485,9 +1468,6 @@ class Layer {
const Maybe<TransformData>& GetTransformData() const {
return mAnimationInfo.GetTransformData();
}
const LayersId& GetAnimationLayersId() const {
return mAnimationInfo.GetLayersId();
}
Maybe<uint64_t> GetAnimationGeneration() const {
return mAnimationInfo.GetAnimationGeneration();

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

@ -98,14 +98,6 @@ class APZSampler {
void MarkAsyncTransformAppliedToContent(const LayerMetricsWrapper& aLayer);
bool HasUnusedAsyncTransform(const LayerMetricsWrapper& aLayer);
/**
* Returns the composition bounds of the APZC correspoinding to the pair of
* |aLayersId| and |aScrollId|.
*/
ParentLayerRect GetCompositionBounds(
const LayersId& aLayersId,
const ScrollableLayerGuid::ViewID& aScrollId) const;
ScrollableLayerGuid GetGuid(const LayerMetricsWrapper& aLayer);
ScreenMargin GetGeckoFixedLayerMargins() const;

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

@ -212,28 +212,6 @@ ScreenMargin APZSampler::GetGeckoFixedLayerMargins() const {
return mApz->GetGeckoFixedLayerMargins();
}
ParentLayerRect APZSampler::GetCompositionBounds(
const LayersId& aLayersId,
const ScrollableLayerGuid::ViewID& aScrollId) const {
// This function can get called on the compositor in case of non WebRender
// get called on the sampler thread in case of WebRender.
AssertOnSamplerThread();
RefPtr<AsyncPanZoomController> apzc =
mApz->GetTargetAPZC(aLayersId, aScrollId);
if (!apzc) {
// On WebRender 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 one, i.e. queue mCompositorAnimationsToDelete in
// WebRenderBridgeParent and then remove them in
// WebRenderBridgeParent::RemoveEpochDataPriorTo.
return ParentLayerRect();
}
return apzc->GetCompositionBounds();
}
void APZSampler::AssertOnSamplerThread() const {
if (APZThreadUtils::GetThreadAssertionsEnabled()) {
MOZ_ASSERT(IsSamplerThread());

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

@ -560,8 +560,8 @@ bool AsyncCompositionManager::SampleAnimations(Layer* aLayer,
mCompositorBridge->GetAnimationStorage();
MOZ_ASSERT(storage);
return storage->SampleAnimations(aLayer, mCompositorBridge,
mPreviousFrameTimeStamp, aCurrentFrameTime);
return storage->SampleAnimations(aLayer, mPreviousFrameTimeStamp,
aCurrentFrameTime);
}
void AsyncCompositionManager::RecordShadowTransforms(Layer* aLayer) {

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

@ -847,21 +847,6 @@ 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,9 +111,6 @@ 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,33 +1375,6 @@ 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,9 +408,6 @@ 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;

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

@ -524,7 +524,7 @@ bool LayerTransactionParent::SetLayerAttributes(
} else {
layer->SetMaskLayer(nullptr);
}
layer->SetCompositorAnimations(mId, common.compositorAnimations());
layer->SetCompositorAnimations(common.compositorAnimations());
// Clean up the Animations by id in the CompositorAnimationStorage
// if there are no active animations on the layer
if (mAnimStorage && layer->GetCompositorAnimationsId() &&

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

@ -20,7 +20,6 @@ using struct mozilla::gfx::Point from "mozilla/gfx/Point.h";
using struct mozilla::gfx::Point3D from "mozilla/gfx/Point.h";
using mozilla::gfx::IntPoint from "mozilla/gfx/Point.h";
using class mozilla::gfx::Matrix4x4 from "mozilla/gfx/Matrix.h";
using class mozilla::SideBits from "mozilla/gfx/Types.h";
using nscolor from "nsColor.h";
using nscoord from "nsCoord.h";
using struct nsRect from "nsRect.h";
@ -39,10 +38,8 @@ using mozilla::LayerCoord from "Units.h";
using mozilla::LayerSize from "Units.h";
using mozilla::LayerRect from "Units.h";
using mozilla::LayerIntSize from "Units.h";
using mozilla::LayerIntRect from "Units.h";
using mozilla::LayerIntRegion from "Units.h";
using mozilla::ParentLayerIntRect from "Units.h";
using mozilla::ParentLayerRect from "Units.h";
using mozilla::LayoutDeviceIntRect from "Units.h";
using mozilla::layers::ScaleMode from "mozilla/layers/LayersTypes.h";
using mozilla::layers::EventRegions from "mozilla/layers/LayersTypes.h";
@ -156,17 +153,6 @@ struct MotionPathData {
RayReferenceData rayReferenceData;
};
struct PartialPrerenderData {
LayoutDeviceIntRect rect;
SideBits overflowedSides;
// the scroll id of the nearest scrollable frame of this partial prerender
// data.
ViewID scrollId;
// The clip rectangle of the nearest scrollable frame.
// NOTE: This should be used only for fallback cases where APZ is not enabled.
ParentLayerRect clipRect;
};
// Transforms need extra information to correctly convert the list of transform
// functions to a Matrix4x4 that can be applied directly to the layer.
struct TransformData {
@ -182,7 +168,6 @@ struct TransformData {
// True if the parent has perspective transform
bool hasPerspectiveParent;
MotionPathData? motionPathData;
PartialPrerenderData? partialPrerenderData;
};
struct Animation {

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

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

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

@ -154,12 +154,11 @@ void OMTASampler::SampleForTesting(const Maybe<TimeStamp>& aTestingSampleTime) {
}
void OMTASampler::SetAnimations(
uint64_t aId, const LayersId& aLayersId,
const nsTArray<layers::Animation>& aAnimations) {
uint64_t aId, const nsTArray<layers::Animation>& aAnimations) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
MutexAutoLock lock(mStorageLock);
mAnimStorage->SetAnimations(aId, aLayersId, aAnimations);
mAnimStorage->SetAnimations(aId, aAnimations);
}
bool OMTASampler::HasAnimations() const {

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

@ -66,7 +66,7 @@ class OMTASampler final {
*/
void SetSampleTime(const TimeStamp& aSampleTime);
void ResetPreviousSampleTime();
void SetAnimations(uint64_t aId, const LayersId& aLayersId,
void SetAnimations(uint64_t aId,
const nsTArray<layers::Animation>& aAnimations);
bool HasAnimations() const;

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

@ -1387,7 +1387,7 @@ bool WebRenderBridgeParent::ProcessWebRenderParentCommands(
}
if (data.animations().Length()) {
if (RefPtr<OMTASampler> sampler = GetOMTASampler()) {
sampler->SetAnimations(data.id(), GetLayersId(), data.animations());
sampler->SetAnimations(data.id(), data.animations());
const auto activeAnim = mActiveAnimations.find(data.id());
if (activeAnim == mActiveAnimations.end()) {
mActiveAnimations.emplace(data.id(), mWrEpoch);

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

@ -10,7 +10,6 @@
#include "gfxPoint.h"
struct gfxLineSegment {
gfxLineSegment() : mStart(gfxPoint()), mEnd(gfxPoint()) {}
gfxLineSegment(const gfxPoint& aStart, const gfxPoint& aEnd)
: mStart(aStart), mEnd(aEnd) {}

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

@ -174,8 +174,14 @@ void AccessibleCaret::EnsureApzAware() {
}
bool AccessibleCaret::IsInPositionFixedSubtree() const {
return nsLayoutUtils::IsInPositionFixedSubtree(
mImaginaryCaretReferenceFrame.GetFrame());
for (nsIFrame* f = mImaginaryCaretReferenceFrame.GetFrame(); f;
f = f->GetParent()) {
if (f->StyleDisplay()->mPosition == StylePositionProperty::Fixed &&
nsLayoutUtils::IsReallyFixedPos(f)) {
return true;
}
}
return false;
}
void AccessibleCaret::InjectCaretElement(Document* aDocument) {

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

@ -7653,17 +7653,6 @@ bool nsLayoutUtils::MayBeReallyFixedPos(const nsIFrame* aFrame) {
parentType == LayoutFrameType::PageContent;
}
/* static */
bool nsLayoutUtils::IsInPositionFixedSubtree(const nsIFrame* aFrame) {
for (const nsIFrame* f = aFrame; f; f = f->GetParent()) {
if (f->StyleDisplay()->mPosition == StylePositionProperty::Fixed &&
nsLayoutUtils::IsReallyFixedPos(f)) {
return true;
}
}
return false;
}
nsLayoutUtils::SurfaceFromElementResult
nsLayoutUtils::SurfaceFromOffscreenCanvas(OffscreenCanvas* aOffscreenCanvas,
uint32_t aSurfaceFlags,

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

@ -2186,11 +2186,6 @@ class nsLayoutUtils {
*/
static bool MayBeReallyFixedPos(const nsIFrame* aFrame);
/**
* Returns true if |aFrame| is inside position:fixed subtree.
*/
static bool IsInPositionFixedSubtree(const nsIFrame* aFrame);
/**
* Obtain a SourceSurface from the given DOM element, if possible.
* This obtains the most natural surface from the element; that

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

@ -3260,15 +3260,17 @@ void nsIFrame::BuildDisplayListForStackingContext(
aBuilder->SetContainsBackdropFilter(false);
nsRect visibleRectOutsideTransform = visibleRect;
nsDisplayTransform::PrerenderInfo prerenderInfo;
bool allowAsyncAnimation = false;
bool inTransform = aBuilder->IsInTransform();
if (isTransformed) {
prerenderInfo = nsDisplayTransform::ShouldPrerenderTransformedContent(
aBuilder, this, &dirtyRect);
nsDisplayTransform::PrerenderInfo decision =
nsDisplayTransform::ShouldPrerenderTransformedContent(aBuilder, this,
&dirtyRect);
switch (prerenderInfo.mDecision) {
switch (decision.mDecision) {
case nsDisplayTransform::PrerenderDecision::Full:
case nsDisplayTransform::PrerenderDecision::Partial:
allowAsyncAnimation = true;
visibleRect = dirtyRect;
break;
case nsDisplayTransform::PrerenderDecision::No: {
@ -3276,7 +3278,7 @@ void nsIFrame::BuildDisplayListForStackingContext(
// then we want disable async animations for the rest of the preserve-3d
// (especially ancestors).
if ((extend3DContext || combines3DTransformWithAncestors) &&
prerenderInfo.mHasAnimations) {
decision.mHasAnimations) {
aBuilder->SavePreserves3DAllowAsyncAnimation(false);
}
@ -3766,15 +3768,14 @@ void nsIFrame::BuildDisplayListForStackingContext(
// Alternatively we could not block animations for later siblings, and only
// block them for ancestors of a blocked one.
if ((extend3DContext || combines3DTransformWithAncestors) &&
prerenderInfo.CanUseAsyncAnimations() &&
!aBuilder->GetPreserves3DAllowAsyncAnimation()) {
allowAsyncAnimation) {
// aBuilder->GetPreserves3DAllowAsyncAnimation() means the inner or
// previous silbing frames are allowed/disallowed for async animations.
prerenderInfo.mDecision = nsDisplayTransform::PrerenderDecision::No;
allowAsyncAnimation = aBuilder->GetPreserves3DAllowAsyncAnimation();
}
nsDisplayTransform* transformItem = MakeDisplayItem<nsDisplayTransform>(
aBuilder, this, &resultList, visibleRect, prerenderInfo.mDecision);
aBuilder, this, &resultList, visibleRect, allowAsyncAnimation);
if (transformItem) {
resultList.AppendToTop(transformItem);
ct.TrackContainer(transformItem);

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

@ -229,7 +229,7 @@ static uint64_t AddAnimationsForWebRender(
AnimationInfo& animationInfo = animationData->GetAnimationInfo();
animationInfo.AddAnimationsForDisplayItem(aItem->Frame(), aDisplayListBuilder,
aItem, aItem->GetType(),
aManager->LayerManager());
layers::LayersBackend::LAYERS_WR);
animationInfo.StartPendingAnimations(
aManager->LayerManager()->GetAnimationReadyTime());
@ -321,8 +321,8 @@ void nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(
}
AnimationInfo& animationInfo = aLayer->GetAnimationInfo();
animationInfo.AddAnimationsForDisplayItem(aFrame, aBuilder, aItem, aType,
aLayer->Manager());
animationInfo.AddAnimationsForDisplayItem(
aFrame, aBuilder, aItem, aType, layers::LayersBackend::LAYERS_CLIENT);
animationInfo.TransferMutatedFlagToLayer(aLayer);
}
@ -7287,8 +7287,8 @@ nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder,
mAnimatedGeometryRootForChildren(mAnimatedGeometryRoot),
mAnimatedGeometryRootForScrollMetadata(mAnimatedGeometryRoot),
mChildrenBuildingRect(aChildrenBuildingRect),
mPrerenderDecision(PrerenderDecision::No),
mIsTransformSeparator(true) {
mIsTransformSeparator(true),
mAllowAsyncAnimation(false) {
MOZ_COUNT_CTOR(nsDisplayTransform);
MOZ_ASSERT(aFrame, "Must have a frame!");
Init(aBuilder, aList);
@ -7297,14 +7297,14 @@ nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder,
nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList,
const nsRect& aChildrenBuildingRect,
PrerenderDecision aPrerenderDecision)
bool aAllowAsyncAnimation)
: nsDisplayHitTestInfoBase(aBuilder, aFrame),
mTransformGetter(nullptr),
mAnimatedGeometryRootForChildren(mAnimatedGeometryRoot),
mAnimatedGeometryRootForScrollMetadata(mAnimatedGeometryRoot),
mChildrenBuildingRect(aChildrenBuildingRect),
mPrerenderDecision(aPrerenderDecision),
mIsTransformSeparator(false) {
mIsTransformSeparator(false),
mAllowAsyncAnimation(aAllowAsyncAnimation) {
MOZ_COUNT_CTOR(nsDisplayTransform);
MOZ_ASSERT(aFrame, "Must have a frame!");
SetReferenceFrameToAncestor(aBuilder);
@ -7320,8 +7320,8 @@ nsDisplayTransform::nsDisplayTransform(
mAnimatedGeometryRootForChildren(mAnimatedGeometryRoot),
mAnimatedGeometryRootForScrollMetadata(mAnimatedGeometryRoot),
mChildrenBuildingRect(aChildrenBuildingRect),
mPrerenderDecision(PrerenderDecision::No),
mIsTransformSeparator(false) {
mIsTransformSeparator(false),
mAllowAsyncAnimation(false) {
MOZ_COUNT_CTOR(nsDisplayTransform);
MOZ_ASSERT(aFrame, "Must have a frame!");
Init(aBuilder, aList);
@ -7640,7 +7640,7 @@ bool nsDisplayOpacity::CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) {
}
bool nsDisplayTransform::CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) {
return mPrerenderDecision != PrerenderDecision::No;
return mAllowAsyncAnimation;
}
bool nsDisplayBackgroundColor::CanUseAsyncAnimations(
@ -7648,22 +7648,6 @@ bool nsDisplayBackgroundColor::CanUseAsyncAnimations(
return StaticPrefs::gfx_omta_background_color();
}
static bool IsInStickyPositionedSubtree(const nsIFrame* aFrame) {
for (const nsIFrame* frame = aFrame; frame;
frame = nsLayoutUtils::GetCrossDocParentFrame(frame)) {
if (frame->IsStickyPositioned()) {
return true;
}
}
return false;
}
static bool ShouldUsePartialPrerender(const nsIFrame* aFrame) {
return StaticPrefs::layout_animation_prerender_partial() &&
// Bug 1642547: Support partial prerender for position:sticky elements.
!IsInStickyPositionedSubtree(aFrame);
}
/* static */
auto nsDisplayTransform::ShouldPrerenderTransformedContent(
nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsRect* aDirtyRect)
@ -7785,7 +7769,7 @@ auto nsDisplayTransform::ShouldPrerenderTransformedContent(
return result;
}
if (ShouldUsePartialPrerender(aFrame)) {
if (StaticPrefs::layout_animation_prerender_partial()) {
*aDirtyRect = nsLayoutUtils::ComputePartialPrerenderArea(
aFrame, untransformedDirtyRect, overflow, maxSize);
result.mDecision = PrerenderDecision::Partial;
@ -8069,7 +8053,7 @@ already_AddRefed<Layer> nsDisplayTransform::BuildLayer(
~Layer::CONTENT_EXTEND_3D_CONTEXT);
}
if (CanUseAsyncAnimations(aBuilder)) {
if (mAllowAsyncAnimation) {
mFrame->SetProperty(nsIFrame::RefusedAsyncAnimationProperty(), false);
}
@ -8079,7 +8063,7 @@ already_AddRefed<Layer> nsDisplayTransform::BuildLayer(
container, aBuilder, this, mFrame, GetType());
}
if (CanUseAsyncAnimations(aBuilder) && MayBeAnimated(aBuilder)) {
if (mAllowAsyncAnimation && MayBeAnimated(aBuilder)) {
// Only allow async updates to the transform if we're an animated layer,
// since that's what triggers us to set the correct AGR in the constructor
// and makes sure FrameLayerBuilder won't compute occlusions for this layer.
@ -8556,19 +8540,7 @@ void nsDisplayTransform::WriteDebugInfo(std::stringstream& aStream) {
aStream << " combines-3d-with-ancestors";
}
aStream << " prerender(";
switch (mPrerenderDecision) {
case PrerenderDecision::No:
aStream << "no";
break;
case PrerenderDecision::Partial:
aStream << "partial";
break;
case PrerenderDecision::Full:
aStream << "full";
break;
}
aStream << ")";
aStream << " allowAsync(" << (mAllowAsyncAnimation ? "true" : "false") << ")";
aStream << " childrenBuildingRect" << mChildrenBuildingRect;
}

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

@ -6727,7 +6727,7 @@ class nsDisplayTransform : public nsDisplayHitTestInfoBase {
using TransformReferenceBox = nsStyleTransformMatrix::TransformReferenceBox;
public:
enum class PrerenderDecision : uint8_t { No, Full, Partial };
enum class PrerenderDecision { No, Full, Partial };
/**
* Returns a matrix (in pixels) for the current frame. The matrix should be
@ -6747,7 +6747,7 @@ class nsDisplayTransform : public nsDisplayHitTestInfoBase {
nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList, const nsRect& aChildrenBuildingRect,
PrerenderDecision aPrerenderDecision);
bool aAllowAsyncAnimation);
nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList, const nsRect& aChildrenBuildingRect,
@ -7006,9 +7006,6 @@ class nsDisplayTransform : public nsDisplayHitTestInfoBase {
float aAppUnitsPerPixel);
struct PrerenderInfo {
bool CanUseAsyncAnimations() const {
return mDecision != PrerenderDecision::No && mHasAnimations;
}
PrerenderDecision mDecision = PrerenderDecision::No;
bool mHasAnimations = true;
};
@ -7055,10 +7052,6 @@ class nsDisplayTransform : public nsDisplayHitTestInfoBase {
return mFrame->Extend3DContext() || Combines3DTransformWithAncestors();
}
bool IsPartialPrerender() const {
return mPrerenderDecision == PrerenderDecision::Partial;
}
void AddSizeOfExcludingThis(nsWindowSizes&) const override;
private:
@ -7089,7 +7082,6 @@ class nsDisplayTransform : public nsDisplayHitTestInfoBase {
nsRect mChildBounds;
// The transformed bounds of this display item.
nsRect mBounds;
PrerenderDecision mPrerenderDecision : 2;
// This item is a separator between 3D rendering contexts, and
// mTransform have been presetted by the constructor.
// This also forces us not to extend the 3D context. Since we don't create a
@ -7097,9 +7089,11 @@ class nsDisplayTransform : public nsDisplayHitTestInfoBase {
// context, the transform items of a child preserves3d context may extend the
// parent context unintendedly if the root of the child preserves3d context
// doesn't create a transform item.
bool mIsTransformSeparator : 1;
bool mIsTransformSeparator;
// True if async animation of the transform is allowed.
bool mAllowAsyncAnimation;
// True if this nsDisplayTransform should get flattened
bool mShouldFlatten : 1;
bool mShouldFlatten;
};
/* A display item that applies a perspective transformation to a single

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

@ -1,57 +0,0 @@
<!DOCTYPE html>
<html class="reftest-wait reftest-no-flush">
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<!--
A test for a partial pre-rendered transform animation moves to a place where
the whole area of the transform animation is out of the viewport.
If we mis-recognize it as a jank, the last visible composited area will
remain.
-->
<style>
html {
overflow: hidden;
}
body {
margin: 0px;
padding: 0px;
}
@keyframes anim {
/* translate to a position the element is completely outside of the */
/* viewport */
to { transform: translateX(-300vw); }
}
#target {
width: 200vw;
height: 200vh;
position: absolute;
/* Some part of this element needs to be visible initially so that */
/* a display item for this element is generated, thus the transform */
/* animation runs on the compositor. */
transform: translateX(-110vw);
}
</style>
<div id="target">
<!--
Put an SVG element so that the transform display item has a blob on
WebRender which means this test properly fails without the proper fix.
-->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<rect fill="green" width="16" height="16"></rect>
</svg>
</div>
<script>
document.addEventListener("MozReftestInvalidate", () => {
target.style.animation = "anim 100s 1s step-start";
target.addEventListener("animationstart", () => {
// animtionstart event is fired just before requestAnimationFrame callbacks,
// so we need to wait two rAF to make sure the initial animation value is
// composited on the compositor.
requestAnimationFrame(() => {
requestAnimationFrame(() => {
document.documentElement.classList.remove("reftest-wait");
});
});
});
}, { once: true });
</script>
</html>

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

@ -1,29 +0,0 @@
<!DOCTYPE html>
<html>
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<style>
html {
overflow: hidden;
}
body {
margin: 0px;
padding: 0px;
}
#target {
width: 2000px;
height: 2000px;
position: absolute;
transform: translateX(-325px);
}
</style>
<div id="target">
<!--
Put an SVG element so that the transform display item has a blob on
WebRender which means this test properly fails without the proper fix.
-->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<rect fill="green" x="0" width="1125" height="2000"></rect>
<rect fill="red" x="1125" width="875" height="2000"></rect>
</svg>
</div>
</html>

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

@ -1,56 +0,0 @@
<!DOCTYPE html>
<html class="reftest-wait reftest-no-flush">
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<!--
A test for a partial pre-rendered transform animation moves to a place where
jank happens.
-->
<style>
html {
overflow: hidden;
}
body {
margin: 0px;
padding: 0px;
}
@keyframes anim {
/* The reftest window size is (800x1000), which means the partial prerender */
/* area is (1125x1125). Thus -325px(= 800 - 1125) is the boundary where */
/* jank happens, so we choose a value close to -325px so that within a next */
/* couple of frames jank should happen. */
0% { transform: translateX(-324px); }
100% { transform: translateX(-2000px); }
}
#target {
width: 2000px;
height: 2000px;
position: absolute;
transform: translateX(0px);
}
</style>
<div id="target">
<!--
Put an SVG element so that the transform display item has a blob on
WebRender which means this test properly fails without the proper fix.
-->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2000 2000">
<!-- green on the pre-render area -->
<rect fill="green" x="0" width="1125" height="2000"></rect>
<rect fill="red" x="1125" width="875" height="2000"></rect>
</svg>
</div>
<script>
document.addEventListener("MozReftestInvalidate", () => {
// A shorter animation-duration than we normally use (100s) because if we used
// the longer duration it may NOT fail this test even if any jank happens.
target.style.animation = "anim 10s 1s";
target.addEventListener("animationstart", () => {
// Wait a second to make sure the animation gets stucked (i.e. jank) at the
// boundary (325px).
setTimeout(() => {
document.documentElement.classList.remove("reftest-wait");
}, 1000);
});
}, { once: true });
</script>
</html>

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

@ -1,20 +0,0 @@
<!DOCTYPE html>
<html>
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<style>
html {
overflow: hidden;
}
body {
margin: 0px;
padding: 0px;
}
#target {
background-color: green;
width: 50vw;
height: 100vh;
position: absolute;
}
</style>
<div id="target"></div>
</html>

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

@ -1,54 +0,0 @@
<!DOCTYPE html>
<html class="reftest-wait reftest-no-flush">
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<!--
A test for a partial pre-rendered transform animation moves to a place where
the partial pre-rendered area is completely out of the viewport but still
there remains some amount of area of the entire transform element.
If we mis-recognize it as NOT a jank, checkerboading will happen.
-->
<style>
html {
overflow: hidden;
}
body {
margin: 0px;
padding: 0px;
}
@keyframes anim {
/* translate to a position the partial pre-rendered area is outside of the */
/* viewport but still there should remain visible area. */
to { transform: translateX(-150vw); }
}
#target {
width: 200vw;
height: 200vh;
position: absolute;
transform: translateX(0vw);
}
</style>
<div id="target">
<!--
Put an SVG element so that the transform display item has a blob on
WebRender which means this test properly fails without the proper fix.
-->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<rect fill="green" width="16" height="16"></rect>
</svg>
</div>
<script>
document.addEventListener("MozReftestInvalidate", () => {
target.style.animation = "anim 100s 1s step-start";
target.addEventListener("animationstart", () => {
// animtionstart event is fired just before requestAnimationFrame callbacks,
// so we need to wait two rAF to make sure the initial animation value is
// composited on the compositor.
requestAnimationFrame(() => {
requestAnimationFrame(() => {
document.documentElement.classList.remove("reftest-wait");
});
});
});
}, { once: true });
</script>
</html>

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

@ -1,56 +0,0 @@
<!DOCTYPE html>
<html class="reftest-wait reftest-no-flush">
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<!--
A test that a partial pre-rendered transform animation is transformed by an
ancestor transform value.
If we don't factor the ancestor's transform, we mis-recognize janks, which
means janked at the initial translateX(0vw) position, thus white blank area
will appears.
-->
<style>
html {
overflow: hidden;
}
body {
margin: 0px;
padding: 0px;
}
@keyframes anim {
/* translate to a position where the left edge of partial pre-rendered on */
/* the left edge of the viewport. */
to { transform: translateX(-50vw); }
}
#target {
width: 300vw;
height: 300vh;
transform: translateX(0vw);
}
</style>
<div style="transform: translateX(50vw);">
<div id="target">
<!--
Put an SVG element so that the transform display item has a blob on
WebRender which means this test properly fails without the proper fix.
-->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<rect fill="green" width="16" height="16"></rect>
</svg>
</div>
</div>
<script>
document.addEventListener("MozReftestInvalidate", () => {
target.style.animation = "anim 100s 1s step-start";
target.addEventListener("animationstart", () => {
// animtionstart event is fired just before requestAnimationFrame callbacks,
// so we need to wait two rAF to make sure the initial animation value is
// composited on the compositor.
requestAnimationFrame(() => {
requestAnimationFrame(() => {
document.documentElement.classList.remove("reftest-wait");
});
});
});
}, { once: true });
</script>
</html>

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

@ -1,35 +0,0 @@
<!DOCTYPE html>
<html reftest-async-scroll
reftest-displayport-x="0" reftest-displayport-y="0"
reftest-displayport-w="800" reftest-displayport-h="2000"
reftest-async-scroll-x="0" reftest-async-scroll-y="1000">
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<style>
html {
overflow-x: hidden;
}
body {
margin: 0px;
padding: 0px;
}
#target {
width: 800px;
height: 1600px;
transform: translateY(-500px);
}
</style>
<div style="width: 800px; height: 2000px"><!-- spacer --></div>
<div style="position: fixed; top: 400px">
<div id="target">
<!--
Put an SVG element so that the transform display item has a blob on
WebRender which means this test properly fails without the proper fix.
-->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 1600">
<rect fill="green" y="0" width="800" height="1000"></rect>
<rect fill="blue" y="1000" width="800" height="125"></rect>
<rect fill="red" y="1125" width="800" height="875"></rect>
</svg>
</div>
</div>
</html>

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

@ -1,58 +0,0 @@
<!DOCTYPE html>
<html class="reftest-wait reftest-no-flush"
reftest-async-scroll
reftest-displayport-x="0" reftest-displayport-y="0"
reftest-displayport-w="800" reftest-displayport-h="2000"
reftest-async-scroll-x="0" reftest-async-scroll-y="1000">
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<!--
A test that a partial pre-rendered transform animation is in a position:fixed
layer.
-->
<style>
html {
overflow-x: hidden;
}
body {
margin: 0px;
padding: 0px;
}
@keyframes anim {
to { transform: translateY(-500px); }
}
#target {
width: 800px;
height: 1600px;
transform: translateY(-400px);
}
</style>
<div style="width: 800px; height: 2000px"><!-- spacer --></div>
<div style="position: fixed; top: 400px">
<div id="target">
<!--
Put an SVG element so that the transform display item has a blob on
WebRender which means this test properly fails without the proper fix.
-->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 1600">
<rect fill="green" y="0" width="800" height="1000"></rect>
<rect fill="blue" y="1000" width="800" height="125"></rect>
<rect fill="red" y="1125" width="800" height="875"></rect>
</svg>
</div>
</div>
<script>
document.addEventListener("MozReftestInvalidate", () => {
target.style.animation = "anim 100s 1s step-start";
target.addEventListener("animationstart", () => {
// animtionstart event is fired just before requestAnimationFrame callbacks,
// so we need to wait two rAF to make sure the initial animation value is
// composited on the compositor.
requestAnimationFrame(() => {
requestAnimationFrame(() => {
document.documentElement.classList.remove("reftest-wait");
});
});
});
}, { once: true });
</script>
</html>

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

@ -1,29 +0,0 @@
<!DOCTYPE html>
<html>
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<style>
html {
overflow: hidden;
}
body {
margin: 0px;
padding: 0px;
}
#target {
width: 1600px;
height: 900px;
position: absolute;
transform: translateX(-325px);
}
</style>
<div id="target">
<!--
Put an SVG element so that the transform display item has a blob on
WebRender which means this test properly fails without the proper fix.
-->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 900">
<rect fill="green" x="0" width="1125" height="900"></rect>
<rect fill="red" x="1125" width="875" height="900"></rect>
</svg>
</div>
</html>

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

@ -1,54 +0,0 @@
<!DOCTYPE html>
<html class="reftest-wait reftest-no-flush">
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<style>
html {
overflow: hidden;
}
body {
margin: 0px;
padding: 0px;
}
@keyframes anim {
/* The reftest window size is (800x1000), which means the partial prerender */
/* area is (1125x900). Thus -325px(= 800 - 1125) is the boundary where jank */
/* happens, so we choose a value close to -325px so that within a next */
/* couple of frames jank should happen. */
0% { transform: translateX(-324px); }
100% { transform: translateX(-2000px); }
}
#target {
width: 1600px;
/* Use a smallar value than the reftest window height to avoid bloating up */
/* svg inside this element beyond the window height */
height: 900px;
position: absolute;
transform: translateX(0px);
}
</style>
<div id="target">
<!--
Put an SVG element so that the transform display item has a blob on
WebRender which means this test properly fails without the proper fix.
-->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 900">
<!-- green on the pre-render area -->
<rect fill="green" x="0" width="1125" height="900"></rect>
<rect fill="red" x="1125" width="875" height="900"></rect>
</svg>
</div>
<script>
document.addEventListener("MozReftestInvalidate", () => {
// A shorter animation-duration than we normally use (100s) because if we used
// the longer duration it may NOT fail this test even if any jank happens.
target.style.animation = "anim 10s 1s";
target.addEventListener("animationstart", () => {
// Wait a second to make sure the animation gets stucked (i.e. jank) at the
// boundary (325px).
setTimeout(() => {
document.documentElement.classList.remove("reftest-wait");
}, 1000);
});
}, { once: true });
</script>
</html>

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

@ -1,53 +0,0 @@
<!DOCTYPE html>
<html class="reftest-wait reftest-no-flush">
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<!--
Another variant of partial-prerender-translate-2.html, but the transform
animation is scaled by the parent element.
-->
<style>
html {
overflow: hidden;
}
body {
margin: 0px;
padding: 0px;
}
@keyframes anim {
/* translate to a position where the left edge of partial pre-rendered on */
/* the left edge of the viewport. */
0% { transform: translateX(-649px); }
100% { transform: translateX(-2000px); }
}
#target {
width: 4000px;
height: 2000px;
position: absolute;
transform: translateX(0);
}
</style>
<div style="transform: scale(0.5); transform-origin: 0 0">
<div id="target">
<!--
Put an SVG element so that the transform display item has a blob on
WebRender which means this test properly fails without the proper fix.
-->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 4000 2000">
<rect fill="green" x="0" width="2250" height="2000"></rect>
<rect fill="red" x="2250" width="1750" height="2000"></rect>
</svg>
</div>
</div>
<script>
document.addEventListener("MozReftestInvalidate", () => {
target.style.animation = "anim 10s 1s";
target.addEventListener("animationstart", () => {
// Wait a second to make sure the animation gets stucked (i.e. jank) at the
// boundary (650px).
setTimeout(() => {
document.documentElement.classList.remove("reftest-wait");
}, 1000);
});
}, { once: true });
</script>
</html>

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

@ -1,44 +0,0 @@
<!DOCTYPE html>
<html>
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<!--
A variant test of partial-prerender-translate-5.html but in this test the
position:fixed element is inside an iframe.
-->
<style>
html {
overflow: hidden;
}
body {
margin: 0px;
padding: 0px;
}
</style>
<iframe style="width:400px; height:1000px; border: 0"
srcdoc="<!DOCTYPE HTML>
<html>
<style>
html {
overflow-x: hidden;
scrollbar-width: none;
}
html, body {
margin: 0;
padding: 0;
}
#target {
width: 1600px;
height: 1000px;
transform: translateX(-725px);
}
</style>
<div id='target'>
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1600 1000'>
<rect fill='green' x='0' width='800' height='1000'></rect>
<rect fill='blue' x='800' width='325' height='1000'></rect>
<rect fill='red' x='1125' width='675' height='1000'></rect>
</svg>
</div>
</html>">
</iframe>
</html>

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

@ -1,73 +0,0 @@
<!DOCTYPE html>
<html class="reftest-wait reftest-no-flush">
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<!--
A test for a partial pre-rendered transform in an iframe, if the clip
rectangle of the transform animation were wrong, e.g. (800, 1000), the
transform animation janks at the initial position.
-->
<style>
html {
overflow: hidden;
}
body {
margin: 0px;
padding: 0px;
}
</style>
<!-- a half width of the view port -->
<iframe style="width:400px; height:1000px; border: 0"
srcdoc="<!DOCTYPE HTML>
<html>
<style>
html {
overflow: hidden;
scrollbar-width: none;
}
html, body {
margin: 0;
padding: 0;
}
@keyframes anim {
/* the partial prerender area is (1125, 1000), thus */
/* translateX(-725px) is the position where the right edge */
/* of the partial prerender is positioned at the right edge */
/* of the clip rect (400, 1000). */
to { transform: translateX(-725px); }
}
#target {
width: 1600px;
height: 1000px;
transform: translateX(0px);
}
</style>
<div id='target'>
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1600 1000'>
<rect fill='green' x='0' width='800' height='1000'></rect>
<rect fill='blue' x='800' width='325' height='1000'></rect>
<rect fill='red' x='1125' width='675' height='1000'></rect>
</svg>
</div>
<script>
window.addEventListener('message', () => {
if (event.data == 'start') {
target.style.animation = 'anim 100s 1s step-start';
target.addEventListener('animationstart', () => {
parent.postMessage('animationstart', '*');
});
}
});
</script></html>">
</iframe>
<script>
document.addEventListener("MozReftestInvalidate", () => {
document.querySelector("iframe").contentWindow.postMessage("start", "*");
}, { once: true });
window.addEventListener("message", event => {
if (event.data == "animationstart") {
document.documentElement.classList.remove('reftest-wait');
}
});
</script>
</html>

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

@ -1,76 +0,0 @@
<!DOCTYPE html>
<html reftest-async-scroll class="reftest-wait reftest-no-flush">
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<!--
A variant test of partial-prerender-translate-5.html but in this test the
position:fixed element is inside an iframe.
-->
<style>
html {
overflow: hidden;
}
body {
margin: 0px;
padding: 0px;
}
</style>
<iframe style="width:800px; height:1000px; border: 0"
srcdoc="<!DOCTYPE HTML>
<html reftest-displayport-x='0' reftest-displayport-y='0'
reftest-displayport-w='800' reftest-displayport-h='2000'
reftest-async-scroll-x='0' reftest-async-scroll-y='1000'>
<style>
html {
overflow-x: hidden;
}
html, body {
margin: 0;
padding: 0;
}
@keyframes anim {
to { transform: translateY(-500px); }
}
#target {
width: 800px;
height: 1600px;
transform: translateY(-400px);
}
</style>
<div style='width: 800px; height: 2000px'><!-- spacer --></div>
<div style='position: fixed; top: 400px'>
<div id='target'>
<!--
Put an SVG element so that the transform display item has
a blob on WebRender which means this test properly fails
without the proper fix.
-->
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 800 1600'>
<rect fill='green' y='0' width='800' height='1000'></rect>
<rect fill='blue' y='1000' width='800' height='125'></rect>
<rect fill='red' y='1125' width='800' height='875'></rect>
</svg>
</div>
</div>
<script>
window.addEventListener('message', () => {
if (event.data == 'start') {
target.style.animation = 'anim 100s 1s step-start';
target.addEventListener('animationstart', () => {
parent.postMessage('animationstart', '*');
});
}
});
</script></html>">
</iframe>
<script>
document.addEventListener("MozReftestInvalidate", () => {
document.querySelector("iframe").contentWindow.postMessage("start", "*");
}, { once: true });
window.addEventListener("message", event => {
if (event.data == "animationstart") {
document.documentElement.classList.remove('reftest-wait');
}
});
</script>
</html>

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

@ -156,20 +156,7 @@ 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.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.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
# 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
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
test-pref(layout.animation.prerender.partial,true) == partial-prerender-expansion-translate.html partial-prerender-expansion-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,14 +5601,6 @@
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