Bug 1196114 - Part 5: Store performce warning information as enum type. r=birtles

Each warning message is generated only when getPropertyState() is called.

MozReview-Commit-ID: C03ZSvPv9ff

--HG--
extra : rebase_source : 5932957f8f0b171c7b100b1c22e70513959c819e
This commit is contained in:
Hiroyuki Ikezoe 2016-03-04 17:54:25 +09:00
parent 53fd8ccffb
commit 9cacbd5b2d
8 changed files with 226 additions and 105 deletions

View File

@ -0,0 +1,72 @@
/* -*- 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 "AnimationPerformanceWarning.h"
#include "nsContentUtils.h"
namespace mozilla {
bool
AnimationPerformanceWarning::ToLocalizedString(
nsXPIDLString& aLocalizedString) const
{
const char* key = nullptr;
switch (mType) {
case Type::ContentTooLarge:
{
MOZ_ASSERT(mParams && mParams->Length() == 7,
"Parameter's length should be 7 for ContentTooLarge");
MOZ_ASSERT(mParams->Length() <= kMaxParamsForLocalization,
"Parameter's length should be less than "
"kMaxParamsForLocalization");
// We can pass an array of parameters whose length is greater than 7 to
// nsContentUtils::FormatLocalizedString because
// nsTextFormatter drops those extra parameters in the end.
nsAutoString strings[kMaxParamsForLocalization];
const char16_t* charParams[kMaxParamsForLocalization];
for (size_t i = 0, n = mParams->Length(); i < n; i++) {
strings[i].AppendInt((*mParams)[i]);
charParams[i] = strings[i].get();
}
nsresult rv = nsContentUtils::FormatLocalizedString(
nsContentUtils::eLAYOUT_PROPERTIES,
"AnimationWarningContentTooLarge",
charParams,
aLocalizedString);
return NS_SUCCEEDED(rv);
}
case Type::TransformBackfaceVisibilityHidden:
key = "AnimationWarningTransformBackfaceVisibilityHidden";
break;
case Type::TransformPreserve3D:
key = "AnimationWarningTransformPreserve3D";
break;
case Type::TransformSVG:
key = "AnimationWarningTransformSVG";
break;
case Type::TransformFrameInactive:
key = "AnimationWarningTransformFrameInactive";
break;
case Type::OpacityFrameInactive:
key = "AnimationWarningOpacityFrameInactive";
break;
case Type::WithGeometricProperties:
key = "AnimationWarningWithGeometricProperties";
break;
}
nsresult rv =
nsContentUtils::GetLocalizedString(nsContentUtils::eLAYOUT_PROPERTIES,
key, aLocalizedString);
return NS_SUCCEEDED(rv);
}
} // namespace mozilla

View File

@ -0,0 +1,74 @@
/* -*- 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_dom_AnimationPerformanceWarning_h
#define mozilla_dom_AnimationPerformanceWarning_h
#include "mozilla/InitializerList.h"
class nsXPIDLString;
namespace mozilla {
// Represents the reason why we can't run the CSS property on the compositor.
struct AnimationPerformanceWarning
{
enum class Type : uint8_t {
ContentTooLarge,
TransformBackfaceVisibilityHidden,
TransformPreserve3D,
TransformSVG,
TransformFrameInactive,
OpacityFrameInactive,
WithGeometricProperties
};
explicit AnimationPerformanceWarning(Type aType)
: mType(aType) { }
AnimationPerformanceWarning(Type aType,
std::initializer_list<int32_t> aParams)
: mType(aType)
{
// FIXME: Once std::initializer_list::size() become a constexpr function,
// we should use static_assert here.
MOZ_ASSERT(aParams.size() <= kMaxParamsForLocalization,
"The length of parameters should be less than "
"kMaxParamsForLocalization");
mParams.emplace(aParams);
}
// Maximum number of parameters passed to
// nsContentUtils::FormatLocalizedString to localize warning messages.
//
// NOTE: This constexpr can't be forward declared, so if you want to use
// this variable, please include this header file directly.
// This value is the same as the limit of nsStringBundle::FormatString.
// See the implementation of nsStringBundle::FormatString.
static MOZ_CONSTEXPR_VAR uint8_t kMaxParamsForLocalization = 10;
// Indicates why this property could not be animated on the compositor.
Type mType;
// Optional parameters that may be used for localization.
Maybe<nsTArray<int32_t>> mParams;
bool ToLocalizedString(nsXPIDLString& aLocalizedString) const;
bool operator==(const AnimationPerformanceWarning& aOther) const
{
return mType == aOther.mType &&
mParams == aOther.mParams;
}
bool operator!=(const AnimationPerformanceWarning& aOther) const
{
return !(*this == aOther);
}
};
} // namespace mozilla
#endif // mozilla_dom_AnimationPerformanceWarning_h

View File

@ -10,6 +10,7 @@
#include "mozilla/dom/Element.h"
#include "mozilla/dom/KeyframeEffect.h" // For KeyframeEffectReadOnly
#include "mozilla/AnimationUtils.h"
#include "mozilla/AnimationPerformanceWarning.h"
#include "mozilla/EffectSet.h"
#include "mozilla/InitializerList.h"
#include "mozilla/LayerAnimationInfo.h"
@ -109,14 +110,14 @@ FindAnimationsForCompositor(const nsIFrame* aFrame,
continue;
}
nsAutoString performanceWarning;
AnimationPerformanceWarning::Type warningType;
if (effect->ShouldBlockCompositorAnimations(aFrame,
performanceWarning)) {
warningType)) {
if (aMatches) {
aMatches->Clear();
}
effect->SetPerformanceWarning(aProperty,
performanceWarning);
effect->SetPerformanceWarning(
aProperty, AnimationPerformanceWarning(warningType));
return false;
}
@ -721,9 +722,10 @@ EffectCompositor::GetPresContext(Element* aElement)
}
/* static */ void
EffectCompositor::SetPerformanceWarning(const nsIFrame *aFrame,
nsCSSProperty aProperty,
const nsAString& aMessage)
EffectCompositor::SetPerformanceWarning(
const nsIFrame *aFrame,
nsCSSProperty aProperty,
const AnimationPerformanceWarning& aWarning)
{
EffectSet* effects = EffectSet::GetEffectSet(aFrame);
if (!effects) {
@ -731,7 +733,7 @@ EffectCompositor::SetPerformanceWarning(const nsIFrame *aFrame,
}
for (KeyframeEffectReadOnly* effect : *effects) {
effect->SetPerformanceWarning(aProperty, aMessage);
effect->SetPerformanceWarning(aProperty, aWarning);
}
}

View File

@ -30,6 +30,7 @@ namespace mozilla {
class EffectSet;
class RestyleTracker;
enum class CSSPseudoElementType : uint8_t;
struct AnimationPerformanceWarning;
namespace dom {
class Animation;
@ -187,11 +188,12 @@ public:
static Maybe<Pair<dom::Element*, CSSPseudoElementType>>
GetAnimationElementAndPseudoForFrame(const nsIFrame* aFrame);
// Associates a warning message with effects on |aFrame| if the effect
// has |aProperty|.
static void SetPerformanceWarning(const nsIFrame* aFrame,
nsCSSProperty aProperty,
const nsAString& aMessage);
// Associates a performance warning with effects on |aFrame| that animates
// |aProperty|.
static void SetPerformanceWarning(
const nsIFrame* aFrame,
nsCSSProperty aProperty,
const AnimationPerformanceWarning& aWarning);
private:
~EffectCompositor() = default;

View File

@ -1893,8 +1893,10 @@ KeyframeEffectReadOnly::GetPropertyState(
NS_ConvertASCIItoUTF16(nsCSSProps::GetStringValue(property.mProperty)));
state.mRunningOnCompositor.Construct(property.mIsRunningOnCompositor);
if (property.mPerformanceWarning.isSome()) {
state.mWarning.Construct(property.mPerformanceWarning.value());
nsXPIDLString localizedString;
if (property.mPerformanceWarning &&
property.mPerformanceWarning->ToLocalizedString(localizedString)) {
state.mWarning.Construct(localizedString);
}
aStates.AppendElement(state);
@ -2099,19 +2101,14 @@ KeyframeEffectReadOnly::IsGeometricProperty(
/* static */ bool
KeyframeEffectReadOnly::CanAnimateTransformOnCompositor(
const nsIFrame* aFrame,
nsAString& aPerformanceWarning)
AnimationPerformanceWarning::Type& aPerformanceWarning)
{
// Disallow OMTA for preserve-3d transform. Note that we check the style property
// rather than Extend3DContext() since that can recurse back into this function
// via HasOpacity(). See bug 779598.
if (aFrame->Combines3DTransformWithAncestors() ||
aFrame->StyleDisplay()->mTransformStyle == NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D) {
nsXPIDLString localizedMessage;
nsContentUtils::GetLocalizedString(
nsContentUtils::eLAYOUT_PROPERTIES,
"AnimationWarningTransformPreserve3D",
localizedMessage);
aPerformanceWarning = localizedMessage;
aPerformanceWarning = AnimationPerformanceWarning::Type::TransformPreserve3D;
return false;
}
// Note that testing BackfaceIsHidden() is not a sufficient test for
@ -2119,23 +2116,14 @@ KeyframeEffectReadOnly::CanAnimateTransformOnCompositor(
// remove the above test for Extend3DContext(); that would require
// looking at backface-visibility on descendants as well. See bug 1186204.
if (aFrame->StyleDisplay()->BackfaceIsHidden()) {
nsXPIDLString localizedMessage;
nsContentUtils::GetLocalizedString(
nsContentUtils::eLAYOUT_PROPERTIES,
"AnimationWarningTransformBackfaceVisibilityHidden",
localizedMessage);
aPerformanceWarning = localizedMessage;
aPerformanceWarning =
AnimationPerformanceWarning::Type::TransformBackfaceVisibilityHidden;
return false;
}
// Async 'transform' animations of aFrames with SVG transforms is not
// supported. See bug 779599.
if (aFrame->IsSVGTransformed()) {
nsXPIDLString localizedMessage;
nsContentUtils::GetLocalizedString(
nsContentUtils::eLAYOUT_PROPERTIES,
"AnimationWarningTransformSVG",
localizedMessage);
aPerformanceWarning = localizedMessage;
aPerformanceWarning = AnimationPerformanceWarning::Type::TransformSVG;
return false;
}
@ -2145,7 +2133,7 @@ KeyframeEffectReadOnly::CanAnimateTransformOnCompositor(
bool
KeyframeEffectReadOnly::ShouldBlockCompositorAnimations(
const nsIFrame* aFrame,
nsAString& aPerformanceWarning) const
AnimationPerformanceWarning::Type& aPerformanceWarning) const
{
// We currently only expect this method to be called when this effect
// is attached to a playing Animation. If that ever changes we'll need
@ -2162,12 +2150,8 @@ KeyframeEffectReadOnly::ShouldBlockCompositorAnimations(
}
// Check for geometric properties
if (IsGeometricProperty(property.mProperty)) {
nsXPIDLString localizedMessage;
nsContentUtils::GetLocalizedString(
nsContentUtils::eLAYOUT_PROPERTIES,
"AnimationWarningWithGeometricProperties",
localizedMessage);
aPerformanceWarning = localizedMessage;
aPerformanceWarning =
AnimationPerformanceWarning::Type::WithGeometricProperties;
return true;
}
@ -2184,16 +2168,20 @@ KeyframeEffectReadOnly::ShouldBlockCompositorAnimations(
}
void
KeyframeEffectReadOnly::SetPerformanceWarning(nsCSSProperty aProperty,
const nsAString &aMessage)
KeyframeEffectReadOnly::SetPerformanceWarning(
nsCSSProperty aProperty,
const AnimationPerformanceWarning& aWarning)
{
for (AnimationProperty& property : mProperties) {
if (property.mProperty == aProperty) {
property.mPerformanceWarning.reset();
property.mPerformanceWarning.emplace(aMessage);
if (property.mProperty == aProperty &&
(!property.mPerformanceWarning ||
*property.mPerformanceWarning != aWarning)) {
property.mPerformanceWarning = Some(aWarning);
if (nsLayoutUtils::IsAnimationLoggingEnabled()) {
nsAutoCString logMessage = NS_ConvertUTF16toUTF8(aMessage);
nsXPIDLString localizedString;
if (nsLayoutUtils::IsAnimationLoggingEnabled() &&
property.mPerformanceWarning->ToLocalizedString(localizedString)) {
nsAutoCString logMessage = NS_ConvertUTF16toUTF8(localizedString);
AnimationUtils::LogAsyncAnimationFailure(logMessage, mTarget);
}
return;

View File

@ -11,6 +11,7 @@
#include "nsCycleCollectionParticipant.h"
#include "nsIDocument.h"
#include "nsWrapperCache.h"
#include "mozilla/AnimationPerformanceWarning.h"
#include "mozilla/Attributes.h"
#include "mozilla/ComputedTimingFunction.h" // ComputedTimingFunction
#include "mozilla/LayerAnimationInfo.h" // LayerAnimations::kRecords
@ -146,9 +147,7 @@ struct AnimationProperty
// objects for equality.
bool mIsRunningOnCompositor = false;
// A warning string indicating why this property could not be animated
// on the compositor.
Maybe<nsString> mPerformanceWarning;
Maybe<AnimationPerformanceWarning> mPerformanceWarning;
InfallibleTArray<AnimationPropertySegment> mSegments;
@ -327,17 +326,20 @@ public:
//
// When returning true, |aOutPerformanceWarning| stores the reason why
// we shouldn't run the compositor animations.
bool ShouldBlockCompositorAnimations(const nsIFrame* aFrame,
nsAString& aPerformanceWarning) const;
bool ShouldBlockCompositorAnimations(
const nsIFrame* aFrame,
AnimationPerformanceWarning::Type& aPerformanceWarning) const;
nsIDocument* GetRenderedDocument() const;
nsPresContext* GetPresContext() const;
// Associates a warning string with the animated property on the specified
// frame indicating why, for example, the property could not be animated
// on the compositor.
void SetPerformanceWarning(nsCSSProperty aProperty,
const nsAString& aMessage);
// Associates a warning with the animated property on the specified frame
// indicating why, for example, the property could not be animated on the
// compositor. |aParams| and |aParamsLength| are optional parameters which
// will be used to generate a localized message for devtools.
void SetPerformanceWarning(
nsCSSProperty aProperty,
const AnimationPerformanceWarning& aWarning);
protected:
KeyframeEffectReadOnly(nsIDocument* aDocument,
@ -402,8 +404,9 @@ private:
// Returns true unless Gecko limitations prevent performing transform
// animations for |aFrame|. When returning true, the reason for the
// limitation is stored in |aOutPerformanceWarning|.
static bool CanAnimateTransformOnCompositor(const nsIFrame* aFrame,
nsAString& aPerformanceWarning);
static bool CanAnimateTransformOnCompositor(
const nsIFrame* aFrame,
AnimationPerformanceWarning::Type& aPerformanceWarning);
static bool IsGeometricProperty(const nsCSSProperty aProperty);
static const TimeDuration OverflowRegionRefreshInterval();

View File

@ -20,6 +20,7 @@ EXPORTS.mozilla.dom += [
EXPORTS.mozilla += [
'AnimationComparator.h',
'AnimationPerformanceWarning.h',
'AnimationUtils.h',
'AnimValuesStyleRule.h',
'ComputedTimingFunction.h',
@ -34,6 +35,7 @@ UNIFIED_SOURCES += [
'AnimationEffectReadOnly.cpp',
'AnimationEffectTiming.cpp',
'AnimationEffectTimingReadOnly.cpp',
'AnimationPerformanceWarning.cpp',
'AnimationTimeline.cpp',
'AnimationUtils.cpp',
'AnimValuesStyleRule.cpp',

View File

@ -52,6 +52,7 @@
#include "ImageContainer.h"
#include "nsCanvasFrame.h"
#include "StickyScrollContainer.h"
#include "mozilla/AnimationPerformanceWarning.h"
#include "mozilla/AnimationUtils.h"
#include "mozilla/EffectCompositor.h"
#include "mozilla/EventStates.h"
@ -5585,14 +5586,10 @@ nsDisplayOpacity::CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder)
return true;
}
nsXPIDLString localizedMessage;
nsContentUtils::GetLocalizedString(
nsContentUtils::eLAYOUT_PROPERTIES,
"AnimationWarningOpacityFrameInactive",
localizedMessage);
EffectCompositor::SetPerformanceWarning(mFrame,
eCSSProperty_opacity,
localizedMessage);
EffectCompositor::SetPerformanceWarning(
mFrame, eCSSProperty_transform,
AnimationPerformanceWarning(
AnimationPerformanceWarning::Type::OpacityFrameInactive));
return false;
}
@ -5640,14 +5637,11 @@ nsDisplayTransform::ShouldPrerenderTransformedContent(nsDisplayListBuilder* aBui
if (!ActiveLayerTracker::IsStyleMaybeAnimated(aFrame, eCSSProperty_transform) &&
!EffectCompositor::HasAnimationsForCompositor(aFrame,
eCSSProperty_transform)) {
nsXPIDLString localizedMessage;
nsContentUtils::GetLocalizedString(
nsContentUtils::eLAYOUT_PROPERTIES,
"AnimationWarningTransformFrameInactive",
localizedMessage);
EffectCompositor::SetPerformanceWarning(aFrame,
eCSSProperty_transform,
localizedMessage);
EffectCompositor::SetPerformanceWarning(
aFrame, eCSSProperty_transform,
AnimationPerformanceWarning(
AnimationPerformanceWarning::Type::TransformFrameInactive));
return false;
}
@ -5668,36 +5662,20 @@ nsDisplayTransform::ShouldPrerenderTransformedContent(nsDisplayListBuilder* aBui
nsRect visual = aFrame->GetVisualOverflowRect();
nsAutoString frameWidth, frameHeight,
refWidth, refHeight,
visualWidth, visualHeight,
maxInAppUnitsString;
frameWidth.AppendInt(nsPresContext::AppUnitsToIntCSSPixels(frameSize.width));
frameHeight.AppendInt(nsPresContext::AppUnitsToIntCSSPixels(frameSize.height));
refWidth.AppendInt(nsPresContext::AppUnitsToIntCSSPixels(refSize.width));
refHeight.AppendInt(nsPresContext::AppUnitsToIntCSSPixels(refSize.height));
visualWidth.AppendInt(nsPresContext::AppUnitsToIntCSSPixels(visual.width));
visualHeight.AppendInt(nsPresContext::AppUnitsToIntCSSPixels(visual.height));
maxInAppUnitsString.AppendInt(nsPresContext::AppUnitsToIntCSSPixels(maxInAppUnits));
const char16_t* params[7] = {
frameWidth.get(),
frameHeight.get(),
refWidth.get(),
refHeight.get(),
visualWidth.get(),
visualHeight.get(),
maxInAppUnitsString.get()
};
nsXPIDLString message;
nsContentUtils::FormatLocalizedString(nsContentUtils::eLAYOUT_PROPERTIES,
"AnimationWarningContentTooLarge",
params,
message);
EffectCompositor::SetPerformanceWarning(aFrame,
eCSSProperty_transform,
message);
EffectCompositor::SetPerformanceWarning(
aFrame, eCSSProperty_transform,
AnimationPerformanceWarning(
AnimationPerformanceWarning::Type::ContentTooLarge,
{
nsPresContext::AppUnitsToIntCSSPixels(frameSize.width),
nsPresContext::AppUnitsToIntCSSPixels(frameSize.height),
nsPresContext::AppUnitsToIntCSSPixels(refSize.width),
nsPresContext::AppUnitsToIntCSSPixels(refSize.height),
nsPresContext::AppUnitsToIntCSSPixels(visual.width),
nsPresContext::AppUnitsToIntCSSPixels(visual.height),
nsPresContext::AppUnitsToIntCSSPixels(maxInAppUnits)
}));
return false;
}