Merge m-c to inbound.

This commit is contained in:
Ryan VanderMeulen 2012-07-30 20:14:22 -04:00
commit ed3645f4ca
45 changed files with 641 additions and 1960 deletions

View File

@ -11,7 +11,6 @@
#include "nsChangeHint.h"
#include "nsINode.h"
#include "nsIDocument.h" // for IsInHTMLDocument
#include "nsCSSProperty.h"
// Forward declarations
class nsIAtom;

View File

@ -1291,8 +1291,6 @@ private:
NodeMayHaveDOMMutationObserver,
// Set if node is Content
NodeIsContent,
// Set if the node has animations or transitions
ElementHasAnimations,
// Guard value
BooleanFlagCount
};
@ -1358,8 +1356,6 @@ public:
bool HasPointerLock() const { return GetBoolFlag(ElementHasPointerLock); }
void SetPointerLock() { SetBoolFlag(ElementHasPointerLock); }
void ClearPointerLock() { ClearBoolFlag(ElementHasPointerLock); }
bool MayHaveAnimations() { return GetBoolFlag(ElementHasAnimations); }
void SetMayHaveAnimations() { SetBoolFlag(ElementHasAnimations); }
protected:
void SetParentIsContent(bool aValue) { SetBoolFlag(ParentIsContent, aValue); }
void SetInDocument() { SetBoolFlag(IsInDocument); }

View File

@ -26,11 +26,6 @@ public:
Init(aX1, aY1, aX2, aY2);
}
double X1() const { return mX1; }
double Y1() const { return mY1; }
double X2() const { return mX2; }
double Y2() const { return mY2; }
void Init(double aX1, double aY1,
double aX2, double aY2);

View File

@ -17,7 +17,6 @@
#include "nsPrintfCString.h"
#include "mozilla/Util.h"
#include "LayerSorter.h"
#include "AnimationCommon.h"
using namespace mozilla::layers;
using namespace mozilla::gfx;
@ -221,244 +220,6 @@ LayerManager::CreateAsynchronousImageContainer()
//--------------------------------------------------
// Layer
Layer::Layer(LayerManager* aManager, void* aImplData) :
mManager(aManager),
mParent(nullptr),
mNextSibling(nullptr),
mPrevSibling(nullptr),
mImplData(aImplData),
mMaskLayer(nullptr),
mXScale(1.0f),
mYScale(1.0f),
mOpacity(1.0),
mContentFlags(0),
mUseClipRect(false),
mUseTileSourceRect(false),
mIsFixedPosition(false),
mDebugColorIndex(0)
{}
Layer::~Layer()
{}
void
Layer::AddAnimation(const Animation& aAnimation)
{
if (!AsShadowableLayer() || !AsShadowableLayer()->HasShadow())
return;
MOZ_ASSERT(aAnimation.segments().Length() >= 1);
mAnimations.AppendElement(aAnimation);
Mutated();
}
void
Layer::ClearAnimations()
{
mAnimations.Clear();
mAnimationData.Clear();
Mutated();
}
static nsCSSValueList*
CreateCSSValueList(const InfallibleTArray<TransformFunction>& aFunctions)
{
nsAutoPtr<nsCSSValueList> result;
nsCSSValueList** resultTail = getter_Transfers(result);
for (PRUint32 i = 0; i < aFunctions.Length(); i++) {
nsRefPtr<nsCSSValue::Array> arr;
switch (aFunctions[i].type()) {
case TransformFunction::TRotationX:
{
float theta = aFunctions[i].get_RotationX().radians();
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_rotatex, resultTail);
arr->Item(1).SetFloatValue(theta, eCSSUnit_Radian);
break;
}
case TransformFunction::TRotationY:
{
float theta = aFunctions[i].get_RotationY().radians();
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_rotatey, resultTail);
arr->Item(1).SetFloatValue(theta, eCSSUnit_Radian);
break;
}
case TransformFunction::TRotationZ:
{
float theta = aFunctions[i].get_RotationZ().radians();
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_rotatez, resultTail);
arr->Item(1).SetFloatValue(theta, eCSSUnit_Radian);
break;
}
case TransformFunction::TRotation:
{
float theta = aFunctions[i].get_Rotation().radians();
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_rotate, resultTail);
arr->Item(1).SetFloatValue(theta, eCSSUnit_Radian);
break;
}
case TransformFunction::TRotation3D:
{
float x = aFunctions[i].get_Rotation3D().x();
float y = aFunctions[i].get_Rotation3D().y();
float z = aFunctions[i].get_Rotation3D().z();
float theta = aFunctions[i].get_Rotation3D().radians();
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_rotate3d, resultTail);
arr->Item(1).SetFloatValue(x, eCSSUnit_Number);
arr->Item(2).SetFloatValue(y, eCSSUnit_Number);
arr->Item(3).SetFloatValue(z, eCSSUnit_Number);
arr->Item(4).SetFloatValue(theta, eCSSUnit_Radian);
break;
}
case TransformFunction::TScale:
{
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_scale3d, resultTail);
arr->Item(1).SetFloatValue(aFunctions[i].get_Scale().x(), eCSSUnit_Number);
arr->Item(2).SetFloatValue(aFunctions[i].get_Scale().y(), eCSSUnit_Number);
arr->Item(3).SetFloatValue(aFunctions[i].get_Scale().z(), eCSSUnit_Number);
break;
}
case TransformFunction::TTranslation:
{
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_translate3d, resultTail);
arr->Item(1).SetFloatValue(aFunctions[i].get_Translation().x(), eCSSUnit_Pixel);
arr->Item(2).SetFloatValue(aFunctions[i].get_Translation().y(), eCSSUnit_Pixel);
arr->Item(3).SetFloatValue(aFunctions[i].get_Translation().z(), eCSSUnit_Pixel);
break;
}
case TransformFunction::TSkewX:
{
float x = aFunctions[i].get_SkewX().x();
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_skewx, resultTail);
arr->Item(1).SetFloatValue(x, eCSSUnit_Number);
break;
}
case TransformFunction::TSkewY:
{
float y = aFunctions[i].get_SkewY().y();
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_skewy, resultTail);
arr->Item(1).SetFloatValue(y, eCSSUnit_Number);
break;
}
case TransformFunction::TTransformMatrix:
{
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_matrix3d, resultTail);
const gfx3DMatrix& matrix = aFunctions[i].get_TransformMatrix().value();
arr->Item(1).SetFloatValue(matrix._11, eCSSUnit_Number);
arr->Item(2).SetFloatValue(matrix._12, eCSSUnit_Number);
arr->Item(3).SetFloatValue(matrix._13, eCSSUnit_Number);
arr->Item(4).SetFloatValue(matrix._14, eCSSUnit_Number);
arr->Item(5).SetFloatValue(matrix._21, eCSSUnit_Number);
arr->Item(6).SetFloatValue(matrix._22, eCSSUnit_Number);
arr->Item(7).SetFloatValue(matrix._23, eCSSUnit_Number);
arr->Item(8).SetFloatValue(matrix._24, eCSSUnit_Number);
arr->Item(9).SetFloatValue(matrix._31, eCSSUnit_Number);
arr->Item(10).SetFloatValue(matrix._32, eCSSUnit_Number);
arr->Item(11).SetFloatValue(matrix._33, eCSSUnit_Number);
arr->Item(12).SetFloatValue(matrix._34, eCSSUnit_Number);
arr->Item(13).SetFloatValue(matrix._41, eCSSUnit_Number);
arr->Item(14).SetFloatValue(matrix._42, eCSSUnit_Number);
arr->Item(15).SetFloatValue(matrix._43, eCSSUnit_Number);
arr->Item(16).SetFloatValue(matrix._44, eCSSUnit_Number);
break;
}
case TransformFunction::TPerspective:
{
float perspective = aFunctions[i].get_Perspective().value();
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_perspective, resultTail);
arr->Item(1).SetFloatValue(perspective, eCSSUnit_Pixel);
break;
}
default:
NS_ASSERTION(false, "All functions should be implemented?");
}
}
return result.forget();
}
void
Layer::SetAnimations(const AnimationArray& aAnimations)
{
mAnimations = aAnimations;
mAnimationData.Clear();
for (PRUint32 i = 0; i < mAnimations.Length(); i++) {
AnimData data;
InfallibleTArray<css::ComputedTimingFunction>* functions =
&data.mFunctions;
nsTArray<AnimationSegment> segments = mAnimations.ElementAt(i).segments();
for (PRUint32 j = 0; j < segments.Length(); j++) {
TimingFunction tf = segments.ElementAt(j).sampleFn();
css::ComputedTimingFunction* ctf = functions->AppendElement();
switch (tf.type()) {
case TimingFunction::TCubicBezierFunction: {
CubicBezierFunction cbf = tf.get_CubicBezierFunction();
ctf->Init(nsTimingFunction(cbf.x1(), cbf.y1(), cbf.x2(), cbf.y2()));
break;
}
default: {
NS_ASSERTION(tf.type() == TimingFunction::TStepFunction,
"Function must be bezier or step");
StepFunction sf = tf.get_StepFunction();
nsTimingFunction::Type type = sf.type() == 1 ? nsTimingFunction::StepStart
: nsTimingFunction::StepEnd;
ctf->Init(nsTimingFunction(type, sf.steps()));
break;
}
}
}
// Precompute the nsStyleAnimation::Values that we need if this is a transform
// animation.
InfallibleTArray<nsStyleAnimation::Value>* startValues =
&data.mStartValues;
InfallibleTArray<nsStyleAnimation::Value>* endValues =
&data.mEndValues;
for (PRUint32 j = 0; j < mAnimations[i].segments().Length(); j++) {
const AnimationSegment& segment = mAnimations[i].segments()[j];
if (segment.endState().type() == Animatable::TArrayOfTransformFunction) {
const InfallibleTArray<TransformFunction>& startFunctions =
segment.startState().get_ArrayOfTransformFunction();
nsStyleAnimation::Value startValue;
nsCSSValueList* startList;
if (startFunctions.Length() > 0) {
startList = CreateCSSValueList(startFunctions);
} else {
startList = new nsCSSValueList();
startList->mValue.SetNoneValue();
}
startValue.SetAndAdoptCSSValueListValue(startList, nsStyleAnimation::eUnit_Transform);
startValues->AppendElement(startValue);
const InfallibleTArray<TransformFunction>& endFunctions =
segment.endState().get_ArrayOfTransformFunction();
nsStyleAnimation::Value endValue;
nsCSSValueList* endList;
if (endFunctions.Length() > 0) {
endList = CreateCSSValueList(endFunctions);
} else {
endList = new nsCSSValueList();
endList->mValue.SetNoneValue();
}
endValue.SetAndAdoptCSSValueListValue(endList, nsStyleAnimation::eUnit_Transform);
endValues->AppendElement(endValue);
} else {
NS_ASSERTION(segment.endState().type() == Animatable::TOpacity,
"Unknown Animatable type");
nsStyleAnimation::Value startValue;
startValue.SetFloatValue(segment.startState().get_Opacity().value());
startValues->AppendElement(startValue);
nsStyleAnimation::Value endValue;
endValue.SetFloatValue(segment.endState().get_Opacity().value());
endValues->AppendElement(endValue);
}
}
mAnimationData.AppendElement(data);
}
Mutated();
}
bool
Layer::CanUseOpaqueSurface()
{
@ -600,42 +361,21 @@ Layer::CalculateScissorRect(const nsIntRect& aCurrentScissorRect,
return currentClip.Intersect(scissor);
}
const gfx3DMatrix
Layer::GetTransform()
{
gfx3DMatrix transform = mTransform;
transform.Scale(mXScale, mYScale, 1);
return transform;
}
const gfx3DMatrix
const gfx3DMatrix&
Layer::GetLocalTransform()
{
gfx3DMatrix transform;
if (ShadowLayer* shadow = AsShadowLayer()) {
transform = shadow->GetShadowTransform();
} else {
transform = mTransform;
}
transform.Scale(mXScale, mYScale, 1);
return transform;
}
const float
Layer::GetLocalOpacity()
{
if (ShadowLayer* shadow = AsShadowLayer())
return shadow->GetShadowOpacity();
return mOpacity;
return shadow->GetShadowTransform();
return mTransform;
}
float
Layer::GetEffectiveOpacity()
{
float opacity = GetLocalOpacity();
float opacity = GetOpacity();
for (ContainerLayer* c = GetParent(); c && !c->UseIntermediateSurface();
c = c->GetParent()) {
opacity *= c->GetLocalOpacity();
opacity *= c->GetOpacity();
}
return opacity;
}

View File

@ -18,7 +18,6 @@
#include "gfxPattern.h"
#include "nsTArray.h"
#include "nsThreadUtils.h"
#include "nsStyleAnimation.h"
#include "LayersBackend.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/TimeStamp.h"
@ -44,14 +43,8 @@ namespace gl {
class GLContext;
}
namespace css {
class ComputedTimingFunction;
}
namespace layers {
class Animation;
class CommonLayerAttributes;
class Layer;
class ThebesLayer;
class ContainerLayer;
@ -537,13 +530,6 @@ private:
};
class ThebesLayer;
typedef InfallibleTArray<Animation> AnimationArray;
struct AnimData {
InfallibleTArray<nsStyleAnimation::Value> mStartValues;
InfallibleTArray<nsStyleAnimation::Value> mEndValues;
InfallibleTArray<mozilla::css::ComputedTimingFunction> mFunctions;
};
/**
* A Layer represents anything that can be rendered onto a destination
@ -565,7 +551,7 @@ public:
TYPE_THEBES
};
virtual ~Layer();
virtual ~Layer() {}
/**
* Returns the LayerManager this Layer belongs to. Note that the layer
@ -716,19 +702,12 @@ public:
* XXX Currently only transformations corresponding to 2D affine transforms
* are supported.
*/
void SetBaseTransform(const gfx3DMatrix& aMatrix)
void SetTransform(const gfx3DMatrix& aMatrix)
{
mTransform = aMatrix;
Mutated();
}
void SetScale(float aXScale, float aYScale)
{
mXScale = aXScale;
mYScale = aYScale;
Mutated();
}
/**
* CONSTRUCTION PHASE ONLY
* A layer is "fixed position" when it draws content from a content
@ -737,14 +716,6 @@ public:
*/
void SetIsFixedPosition(bool aFixedPosition) { mIsFixedPosition = aFixedPosition; }
// Call AddAnimation to add an animation to this layer from layout code.
void AddAnimation(const Animation& aAnimation);
// ClearAnimations clears animations on this layer.
void ClearAnimations();
// 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 SetAnimations(const AnimationArray& aAnimations);
/**
* CONSTRUCTION PHASE ONLY
* If a layer is "fixed position", this determines which point on the layer
@ -764,15 +735,11 @@ public:
Layer* GetPrevSibling() { return mPrevSibling; }
virtual Layer* GetFirstChild() { return nullptr; }
virtual Layer* GetLastChild() { return nullptr; }
const gfx3DMatrix GetTransform();
const gfx3DMatrix& GetBaseTransform() { return mTransform; }
float GetXScale() { return mXScale; }
float GetYScale() { return mYScale; }
const gfx3DMatrix& GetTransform() { return mTransform; }
bool GetIsFixedPosition() { return mIsFixedPosition; }
gfxPoint GetFixedPositionAnchor() { return mAnchor; }
Layer* GetMaskLayer() { return mMaskLayer; }
AnimationArray& GetAnimations() { return mAnimations; }
InfallibleTArray<AnimData>& GetAnimationData() { return mAnimationData; }
/**
* DRAWING PHASE ONLY
*
@ -973,7 +940,20 @@ public:
#endif
protected:
Layer(LayerManager* aManager, void* aImplData);
Layer(LayerManager* aManager, void* aImplData) :
mManager(aManager),
mParent(nullptr),
mNextSibling(nullptr),
mPrevSibling(nullptr),
mImplData(aImplData),
mMaskLayer(nullptr),
mOpacity(1.0),
mContentFlags(0),
mUseClipRect(false),
mUseTileSourceRect(false),
mIsFixedPosition(false),
mDebugColorIndex(0)
{}
void Mutated() { mManager->Mutated(this); }
@ -988,13 +968,7 @@ protected:
* Returns the local transform for this layer: either mTransform or,
* for shadow layers, GetShadowTransform()
*/
const gfx3DMatrix GetLocalTransform();
/**
* Returns the local opacity for this layer: either mOpacity or,
* for shadow layers, GetShadowOpacity()
*/
const float GetLocalOpacity();
const gfx3DMatrix& GetLocalTransform();
/**
* Computes a tweaked version of aTransform that snaps a point or a rectangle
@ -1020,11 +994,7 @@ protected:
gfx::UserData mUserData;
nsIntRegion mVisibleRegion;
gfx3DMatrix mTransform;
float mXScale;
float mYScale;
gfx3DMatrix mEffectiveTransform;
AnimationArray mAnimations;
InfallibleTArray<AnimData> mAnimationData;
float mOpacity;
nsIntRect mClipRect;
nsIntRect mTileSourceRect;

View File

@ -31,18 +31,16 @@ EXPORTS = \
BasicLayers.h \
BasicTiledThebesLayer.h \
BasicImplData.h \
CompositorParent.h \
ImageLayers.h \
Layers.h \
LayersBackend.h \
LayerManagerOGLShaders.h \
LayerManagerOGL.h \
LayerManagerOGLProgram.h \
LayerSorter.h \
ReadbackLayer.h \
ShadowLayersManager.h \
SharedTextureImage.h \
LayerSorter.h \
TexturePoolOGL.h \
SharedTextureImage.h \
$(NULL)
CPPSRCS = \

View File

@ -21,15 +21,6 @@
#include "nsIWidget.h"
#include "RenderTrace.h"
#include "ShadowLayersParent.h"
#include "BasicLayers.h"
#include "LayerManagerOGL.h"
#include "nsIWidget.h"
#include "nsGkAtoms.h"
#include "RenderTrace.h"
#include "nsStyleAnimation.h"
#include "nsDisplayList.h"
#include "AnimationCommon.h"
#include "nsAnimationManager.h"
using namespace base;
using namespace mozilla::ipc;
@ -440,15 +431,15 @@ CompositorParent::Composite()
return;
}
Layer* layer = mLayerManager->GetRoot();
AutoResolveRefLayers resolve(layer);
Layer* aLayer = mLayerManager->GetRoot();
AutoResolveRefLayers resolve(aLayer);
bool requestNextFrame = TransformShadowTree(mLastCompose);
if (requestNextFrame) {
ScheduleComposition();
}
RenderTraceLayers(layer, "0000");
RenderTraceLayers(aLayer, "0000");
if (LAYERS_OPENGL == mLayerManager->GetBackendType() &&
!mTargetConfig.naturalBounds().IsEmpty()) {
@ -545,10 +536,9 @@ SetShadowProperties(Layer* aLayer)
{
// FIXME: Bug 717688 -- Do these updates in ShadowLayersParent::RecvUpdate.
ShadowLayer* shadow = aLayer->AsShadowLayer();
shadow->SetShadowTransform(aLayer->GetBaseTransform());
shadow->SetShadowTransform(aLayer->GetTransform());
shadow->SetShadowVisibleRegion(aLayer->GetVisibleRegion());
shadow->SetShadowClipRect(aLayer->GetClipRect());
shadow->SetShadowOpacity(aLayer->GetOpacity());
for (Layer* child = aLayer->GetFirstChild();
child; child = child->GetNextSibling()) {
@ -556,114 +546,6 @@ SetShadowProperties(Layer* aLayer)
}
}
// SampleValue should eventually take the CSS property as an argument. This
// will be needed if we ever animate two values with the same type but different
// interpolation rules.
static void
SampleValue(float aPortion, Animation& aAnimation, nsStyleAnimation::Value& aStart,
nsStyleAnimation::Value& aEnd, Animatable* aValue)
{
nsStyleAnimation::Value interpolatedValue;
NS_ASSERTION(aStart.GetUnit() == aEnd.GetUnit() ||
aStart.GetUnit() == nsStyleAnimation::eUnit_None ||
aEnd.GetUnit() == nsStyleAnimation::eUnit_None, "Must have same unit");
if (aStart.GetUnit() == nsStyleAnimation::eUnit_Transform ||
aEnd.GetUnit() == nsStyleAnimation::eUnit_Transform) {
nsStyleAnimation::Interpolate(eCSSProperty_transform, aStart, aEnd,
aPortion, interpolatedValue);
nsCSSValueList* interpolatedList = interpolatedValue.GetCSSValueListValue();
TransformData& data = aAnimation.data().get_TransformData();
gfx3DMatrix transform =
nsDisplayTransform::GetResultingTransformMatrix(nullptr, data.origin(), nsDeviceContext::AppUnitsPerCSSPixel(),
&data.bounds(), interpolatedList, &data.mozOrigin(),
&data.perspectiveOrigin(), &data.perspective());
InfallibleTArray<TransformFunction>* functions = new InfallibleTArray<TransformFunction>();
functions->AppendElement(TransformMatrix(transform));
*aValue = *functions;
return;
}
NS_ASSERTION(aStart.GetUnit() == nsStyleAnimation::eUnit_Float, "Should be opacity");
nsStyleAnimation::Interpolate(eCSSProperty_opacity, aStart, aEnd,
aPortion, interpolatedValue);
*aValue = interpolatedValue.GetFloatValue();
}
static bool
SampleAnimations(Layer* aLayer, TimeStamp aPoint)
{
AnimationArray& animations = aLayer->GetAnimations();
InfallibleTArray<AnimData>& animationData = aLayer->GetAnimationData();
bool activeAnimations = false;
for (PRUint32 i = animations.Length(); i-- !=0; ) {
Animation& animation = animations[i];
AnimData& animData = animationData[i];
double numIterations = animation.numIterations() != -1 ?
animation.numIterations() : NS_IEEEPositiveInfinity();
double positionInIteration =
ElementAnimations::GetPositionInIteration(animation.startTime(),
aPoint,
animation.duration(),
numIterations,
animation.direction());
if (positionInIteration == -1) {
animations.RemoveElementAt(i);
animationData.RemoveElementAt(i);
continue;
}
NS_ABORT_IF_FALSE(0.0 <= positionInIteration &&
positionInIteration <= 1.0,
"position should be in [0-1]");
int segmentIndex = 0;
AnimationSegment* segment = animation.segments().Elements();
while (segment->endPortion() < positionInIteration) {
++segment;
++segmentIndex;
}
double positionInSegment = (positionInIteration - segment->startPortion()) /
(segment->endPortion() - segment->startPortion());
double portion = animData.mFunctions[segmentIndex].GetValue(positionInSegment);
activeAnimations = true;
// interpolate the property
Animatable interpolatedValue;
SampleValue(portion, animation, animData.mStartValues[segmentIndex],
animData.mEndValues[segmentIndex], &interpolatedValue);
ShadowLayer* shadow = aLayer->AsShadowLayer();
switch (interpolatedValue.type()) {
case Animatable::TOpacity:
shadow->SetShadowOpacity(interpolatedValue.get_Opacity().value());
break;
case Animatable::TArrayOfTransformFunction: {
gfx3DMatrix matrix = interpolatedValue.get_ArrayOfTransformFunction()[0].get_TransformMatrix().value();
shadow->SetShadowTransform(matrix);
break;
}
default:
NS_WARNING("Unhandled animated property");
}
}
for (Layer* child = aLayer->GetFirstChild(); child;
child = child->GetNextSibling()) {
activeAnimations |= SampleAnimations(child, aPoint);
}
return activeAnimations;
}
bool
CompositorParent::ApplyAsyncContentTransformToTree(TimeStamp aCurrentFrame,
Layer *aLayer,
@ -709,13 +591,9 @@ CompositorParent::TransformShadowTree(TimeStamp aCurrentFrame)
ContainerLayer* container = layer->AsContainerLayer();
Layer* root = mLayerManager->GetRoot();
// NB: we must sample animations *before* sampling pan/zoom
// transforms.
wantNextFrame |= SampleAnimations(layer, mLastCompose);
const FrameMetrics& metrics = container->GetFrameMetrics();
const gfx3DMatrix& rootTransform = root->GetTransform();
const gfx3DMatrix& currentTransform = layer->GetBaseTransform();
const gfx3DMatrix& currentTransform = layer->GetTransform();
// FIXME/bug 775437: unify this interface with the ~native-fennec
// derived code
@ -808,6 +686,7 @@ CompositorParent::TransformShadowTree(TimeStamp aCurrentFrame)
shadow->SetShadowTransform(treeTransform * currentTransform);
TransformFixedLayers(layer, offset, scaleDiff);
}
return wantNextFrame;
}

View File

@ -14,7 +14,7 @@ namespace layers {
* PLayer represents a layer shared across thread contexts.
*/
async protocol PLayer {
sync protocol PLayer {
manager PLayers;
/**
@ -32,7 +32,7 @@ async protocol PLayer {
* being deleted "soon" (usually immediately).
*/
parent:
async __delete__();
__delete__();
};
} // layers

View File

@ -14,14 +14,6 @@ include protocol PRenderFrame;
include "gfxipc/ShadowLayerUtils.h";
include "mozilla/WidgetUtils.h";
include "mozilla/TimeStamp.h";
using gfxPoint3D;
using nscoord;
using nsRect;
using nsPoint;
using mozilla::TimeDuration;
using mozilla::TimeStamp;
/**
* The layers protocol is spoken between thread contexts that manage
@ -59,129 +51,24 @@ union CanvasSurface {
null_t;
};
struct CubicBezierFunction {
float x1;
float y1;
float x2;
float y2;
};
struct StepFunction {
int steps;
// 1 = nsTimingFunction::StepStart, 2 = nsTimingFunction::StepEnd
int type;
};
union TimingFunction {
CubicBezierFunction;
StepFunction;
};
struct Color { gfxRGBA value; };
struct Opacity { float value; };
struct Perspective { float value; };
struct RotationX { float radians; };
struct RotationY { float radians; };
struct RotationZ { float radians; };
struct Rotation { float radians; };
struct Rotation3D {
float x;
float y;
float z;
float radians;
};
struct Scale {
float x;
float y;
float z;
};
struct SkewX { float x; };
struct SkewY { float y; };
struct TransformMatrix { gfx3DMatrix value; };
struct Translation {
float x;
float y;
float z;
};
union TransformFunction {
Perspective;
RotationX;
RotationY;
RotationZ;
Rotation;
Rotation3D;
Scale;
SkewX;
SkewY;
Translation;
TransformMatrix;
};
union Animatable {
Color;
Opacity;
TransformFunction[];
};
struct AnimationSegment {
Animatable startState;
Animatable endState;
float startPortion;
float endPortion;
TimingFunction sampleFn;
};
// Transforms need extra information to correctly convert the list of transform
// functions to a gfx3DMatrix that can be applied directly to the layer.
struct TransformData {
nsPoint origin;
gfxPoint3D mozOrigin;
gfxPoint3D perspectiveOrigin;
nsRect bounds;
nscoord perspective;
};
union AnimationData {
null_t;
TransformData;
};
struct Animation {
TimeStamp startTime;
TimeDuration duration;
// For each frame, the interpolation point is computed based on the
// startTime, the direction, the duration, and the current time.
// The segments must uniquely cover the portion from 0.0 to 1.0
AnimationSegment[] segments;
// How many times to repeat the animation. < 0 means "forever".
float numIterations;
// This uses the NS_STYLE_ANIMATION_DIRECTION_* constants.
int32_t direction;
AnimationData data;
};
// Change a layer's attributes
struct CommonLayerAttributes {
nsIntRegion visibleRegion;
TransformMatrix transform;
float xScale;
float yScale;
gfx3DMatrix transform;
PRUint32 contentFlags;
Opacity opacity;
float opacity;
bool useClipRect;
nsIntRect clipRect;
bool isFixedPosition;
gfxPoint fixedPositionAnchor;
nullable PLayer maskLayer;
// Animated colors will only honored for ColorLayers.
Animation[] animations;
};
struct ThebesLayerAttributes {
nsIntRegion validRegion;
};
struct ContainerLayerAttributes{ FrameMetrics metrics; };
struct ColorLayerAttributes { Color color; };
struct ColorLayerAttributes { gfxRGBA color; };
struct CanvasLayerAttributes { GraphicsFilterType filter; };
struct RefLayerAttributes { int64_t id; };
struct ImageLayerAttributes {

View File

@ -299,9 +299,7 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies)
LayerAttributes attrs;
CommonLayerAttributes& common = attrs.common();
common.visibleRegion() = mutant->GetVisibleRegion();
common.transform() = mutant->GetBaseTransform();
common.xScale() = mutant->GetXScale();
common.yScale() = mutant->GetYScale();
common.transform() = mutant->GetTransform();
common.contentFlags() = mutant->GetContentFlags();
common.opacity() = mutant->GetOpacity();
common.useClipRect() = !!mutant->GetClipRect();
@ -315,7 +313,6 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies)
common.maskLayerChild() = NULL;
}
common.maskLayerParent() = NULL;
common.animations() = mutant->GetAnimations();
attrs.specific() = null_t();
mutant->FillSpecificAttributes(attrs.specific());

View File

@ -524,11 +524,6 @@ public:
mShadowVisibleRegion = aRegion;
}
void SetShadowOpacity(float aOpacity)
{
mShadowOpacity = aOpacity;
}
void SetShadowClipRect(const nsIntRect* aRect)
{
mUseShadowClipRect = aRect != nullptr;
@ -543,7 +538,6 @@ public:
}
// These getters can be used anytime.
float GetShadowOpacity() { return mShadowOpacity; }
const nsIntRect* GetShadowClipRect() { return mUseShadowClipRect ? &mShadowClipRect : nullptr; }
const nsIntRegion& GetShadowVisibleRegion() { return mShadowVisibleRegion; }
const gfx3DMatrix& GetShadowTransform() { return mShadowTransform; }
@ -553,7 +547,6 @@ public:
protected:
ShadowLayer()
: mAllocator(nullptr)
, mShadowOpacity(1.0)
, mUseShadowClipRect(false)
{}
@ -561,7 +554,6 @@ protected:
nsIntRegion mShadowVisibleRegion;
gfx3DMatrix mShadowTransform;
nsIntRect mShadowClipRect;
float mShadowOpacity;
bool mUseShadowClipRect;
};

View File

@ -214,10 +214,9 @@ ShadowLayersParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
const CommonLayerAttributes& common = attrs.common();
layer->SetVisibleRegion(common.visibleRegion());
layer->SetContentFlags(common.contentFlags());
layer->SetOpacity(common.opacity().value());
layer->SetOpacity(common.opacity());
layer->SetClipRect(common.useClipRect() ? &common.clipRect() : NULL);
layer->SetBaseTransform(common.transform().value());
layer->SetScale(common.xScale(), common.yScale());
layer->SetTransform(common.transform());
static bool fixedPositionLayersEnabled = getenv("MOZ_ENABLE_FIXED_POSITION_LAYERS") != 0;
if (fixedPositionLayersEnabled) {
layer->SetIsFixedPosition(common.isFixedPosition());
@ -228,7 +227,6 @@ ShadowLayersParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
} else {
layer->SetMaskLayer(NULL);
}
layer->SetAnimations(common.animations());
typedef SpecificLayerAttributes Specific;
const SpecificLayerAttributes& specific = attrs.specific();
@ -259,7 +257,7 @@ ShadowLayersParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
MOZ_LAYERS_LOG(("[ParentSide] color layer"));
static_cast<ColorLayer*>(layer)->SetColor(
specific.get_ColorLayerAttributes().color().value());
specific.get_ColorLayerAttributes().color());
break;
case Specific::TCanvasLayerAttributes:

View File

@ -199,12 +199,6 @@ struct NS_GFX nsRect :
inline nsIntRect ScaleToInsidePixels(float aXScale, float aYScale,
nscoord aAppUnitsPerPixel) const;
inline nsIntRect ToInsidePixels(nscoord aAppUnitsPerPixel) const;
// This is here only to keep IPDL-generated code happy. DO NOT USE.
bool operator==(const nsRect& aRect) const
{
return IsEqualEdges(aRect);
}
};
struct NS_GFX nsIntRect :

View File

@ -9,7 +9,6 @@
#include "chrome/common/ipc_message_utils.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Util.h"
#include "mozilla/gfx/2D.h"
@ -440,28 +439,11 @@ struct ParamTraits<gfxPoint>
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
{
return (ReadParam(aMsg, aIter, &aResult->x) &&
ReadParam(aMsg, aIter, &aResult->y));
}
};
if (ReadParam(aMsg, aIter, &aResult->x) &&
ReadParam(aMsg, aIter, &aResult->y))
return true;
template<>
struct ParamTraits<gfxPoint3D>
{
typedef gfxPoint3D paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.x);
WriteParam(aMsg, aParam.y);
WriteParam(aMsg, aParam.z);
}
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
{
return (ReadParam(aMsg, aIter, &aResult->x) &&
ReadParam(aMsg, aIter, &aResult->y) &&
ReadParam(aMsg, aIter, &aResult->z));
return false;
}
};
@ -595,24 +577,6 @@ struct ParamTraits<mozilla::null_t>
}
};
template<>
struct ParamTraits<nsPoint>
{
typedef nsPoint paramType;
static void Write(Message* msg, const paramType& param)
{
WriteParam(msg, param.x);
WriteParam(msg, param.y);
}
static bool Read(const Message* msg, void** iter, paramType* result)
{
return (ReadParam(msg, iter, &result->x) &&
ReadParam(msg, iter, &result->y));
}
};
template<>
struct ParamTraits<nsIntPoint>
{
@ -802,34 +766,6 @@ struct ParamTraits<nsID>
}
};
template<>
struct ParamTraits<mozilla::TimeDuration>
{
typedef mozilla::TimeDuration paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.mValue);
}
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
{
return ReadParam(aMsg, aIter, &aResult->mValue);
};
};
template<>
struct ParamTraits<mozilla::TimeStamp>
{
typedef mozilla::TimeStamp paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.mValue);
}
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
{
return ReadParam(aMsg, aIter, &aResult->mValue);
};
};
} /* namespace IPC */
#endif /* __IPC_GLUE_IPCMESSAGEUTILS_H__ */

View File

@ -166,24 +166,9 @@ dombindings_gen.cpp: $(srcdir)/dombindings.conf \
--makedepend-output $(MDDEPDIR)/dombindingsgen.pp \
$(srcdir)/dombindings.conf
DictionaryHelpers.$(OBJ_SUFFIX): DictionaryHelpers.h \
DictionaryHelpers.cpp
DictionaryHelpers.$(OBJ_SUFFIX): DictionaryHelpers.cpp
DictionaryHelpers.h: $(srcdir)/dictionary_helper_gen.conf \
event_impl_gen.conf \
$(srcdir)/dictionary_helper_gen.py \
$(srcdir)/codegen.py \
$(LIBXUL_DIST)/sdk/bin/header.py \
$(LIBXUL_DIST)/sdk/bin/xpidl.py \
$(DEPTH)/js/src/js-confdefs.h
$(PYTHON) $(topsrcdir)/config/pythonpath.py \
$(PLY_INCLUDE) \
-I$(LIBXUL_DIST)/sdk/bin \
$(srcdir)/dictionary_helper_gen.py \
-I $(DEPTH)/dist/idl \
--header-output DictionaryHelpers.h \
$(srcdir)/dictionary_helper_gen.conf \
event_impl_gen.conf
DictionaryHelpers.h: DictionaryHelpers.cpp
DictionaryHelpers.cpp: $(srcdir)/dictionary_helper_gen.conf \
event_impl_gen.conf \
@ -197,6 +182,7 @@ DictionaryHelpers.cpp: $(srcdir)/dictionary_helper_gen.conf \
-I$(LIBXUL_DIST)/sdk/bin \
$(srcdir)/dictionary_helper_gen.py \
-I $(DEPTH)/dist/idl \
--header-output DictionaryHelpers.h \
--stub-output DictionaryHelpers.cpp \
--makedepend-output $(MDDEPDIR)/dictionary_helper_gen.pp \
$(srcdir)/dictionary_helper_gen.conf \

View File

@ -357,10 +357,6 @@ if __name__ == '__main__':
conf = readConfigFile(filename)
if options.header_output is not None:
outfd = open(options.header_output, 'w')
print_header_file(outfd, conf)
outfd.close()
if options.stub_output is not None:
make_targets.append(options.stub_output)
outfd = open(options.stub_output, 'w')
@ -368,4 +364,8 @@ if __name__ == '__main__':
outfd.close()
if options.makedepend_output is not None:
writeMakeDependOutput(options.makedepend_output)
if options.header_output is not None:
outfd = open(options.header_output, 'w')
print_header_file(outfd, conf)
outfd.close()

View File

@ -21,9 +21,6 @@
#include "mozilla/Preferences.h"
#include "sampler.h"
#include "nsAnimationManager.h"
#include "nsTransitionManager.h"
#ifdef DEBUG
#include <stdio.h>
#endif
@ -947,7 +944,6 @@ ContainerState::CreateOrRecycleColorLayer()
// We will reapply any necessary clipping.
layer->SetClipRect(nullptr);
layer->SetMaskLayer(nullptr);
layer->SetScale(1.0f, 1.0f);
} else {
// Create a new layer
layer = mManager->CreateColorLayer();
@ -971,7 +967,6 @@ ContainerState::CreateOrRecycleImageLayer()
// We will reapply any necessary clipping.
layer->SetClipRect(nullptr);
layer->SetMaskLayer(nullptr);
layer->SetScale(1.0f, 1.0f);
} else {
// Create a new layer
layer = mManager->CreateImageLayer();
@ -989,7 +984,6 @@ ContainerState::CreateOrRecycleMaskImageLayerFor(Layer* aLayer)
nsRefPtr<ImageLayer> result = mRecycledMaskImageLayers.Get(aLayer);
if (result) {
mRecycledMaskImageLayers.Remove(aLayer);
result->SetScale(1.0f, 1.0f);
// XXX if we use clip on mask layers, null it out here
} else {
// Create a new layer
@ -1064,7 +1058,6 @@ ContainerState::CreateOrRecycleThebesLayer(nsIFrame* aActiveScrolledRoot)
// We will reapply any necessary clipping.
layer->SetClipRect(nullptr);
layer->SetMaskLayer(nullptr);
layer->SetScale(1.0f, 1.0f);
data = static_cast<ThebesDisplayItemLayerUserData*>
(layer->GetUserData(&gThebesDisplayItemLayerUserData));
@ -1118,8 +1111,7 @@ ContainerState::CreateOrRecycleThebesLayer(nsIFrame* aActiveScrolledRoot)
RoundToMatchResidual(scaledOffset.y, data->mActiveScrolledRootPosition.y));
gfxMatrix matrix;
matrix.Translate(gfxPoint(pixOffset.x, pixOffset.y));
layer->SetBaseTransform(gfx3DMatrix::From2D(matrix));
layer->SetScale(1.0f, 1.0f);
layer->SetTransform(gfx3DMatrix::From2D(matrix));
// FIXME: Temporary workaround for bug 681192 and bug 724786.
#ifndef MOZ_JAVA_COMPOSITOR
@ -1274,7 +1266,7 @@ ContainerState::PopThebesLayerData()
// The layer's current transform is applied first, then the result is scaled.
gfx3DMatrix transform = imageLayer->GetTransform()*
gfx3DMatrix::ScalingMatrix(mParameters.mXScale, mParameters.mYScale, 1.0f);
imageLayer->SetBaseTransform(transform);
imageLayer->SetTransform(transform);
if (data->mItemClip.mHaveClipRect) {
nsIntRect clip = ScaleToNearestPixels(data->mItemClip.mClipRect);
imageLayer->IntersectClipRect(clip);
@ -1285,9 +1277,8 @@ ContainerState::PopThebesLayerData()
colorLayer->SetIsFixedPosition(data->mLayer->GetIsFixedPosition());
colorLayer->SetColor(data->mSolidColor);
// Copy transform and scale
colorLayer->SetBaseTransform(data->mLayer->GetBaseTransform());
colorLayer->SetScale(data->mLayer->GetXScale(), data->mLayer->GetYScale());
// Copy transform
colorLayer->SetTransform(data->mLayer->GetTransform());
// Clip colorLayer to its visible region, since ColorLayers are
// allowed to paint outside the visible region. Here we rely on the
@ -1786,7 +1777,7 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
// The layer's current transform is applied first, then the result is scaled.
gfx3DMatrix transform = ownLayer->GetTransform()*
gfx3DMatrix::ScalingMatrix(mParameters.mXScale, mParameters.mYScale, 1.0f);
ownLayer->SetBaseTransform(transform);
ownLayer->SetTransform(transform);
}
ownLayer->SetIsFixedPosition(
@ -2130,9 +2121,9 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
scale = gfxSize(1.0, 1.0);
}
aLayer->SetBaseTransform(transform);
// Store the inverse of our resolution-scale on the layer
aLayer->SetScale(1.0f/float(scale.width), 1.0f/float(scale.height));
// Apply the inverse of our resolution-scale before the rest of our transform
transform = gfx3DMatrix::ScalingMatrix(1.0/scale.width, 1.0/scale.height, 1.0)*transform;
aLayer->SetTransform(transform);
FrameLayerBuilder::ContainerParameters
result(scale.width, scale.height, aIncomingScale);
@ -3138,7 +3129,7 @@ ContainerState::SetupMaskLayer(Layer *aLayer, const FrameLayerBuilder::Clip& aCl
}
maskLayer->SetContainer(container);
maskLayer->SetBaseTransform(gfx3DMatrix::From2D(maskTransform.Invert()));
maskLayer->SetTransform(gfx3DMatrix::From2D(maskTransform.Invert()));
// save the details of the clip in user data
userData->mScaleX = newData.mScaleX;

View File

@ -10,8 +10,6 @@
* used during painting and hit testing
*/
#include "mozilla/layers/PLayers.h"
#include "nsDisplayList.h"
#include "nsCSSRendering.h"
@ -38,9 +36,6 @@
#include "nsSVGElement.h"
#include "nsSVGClipPathFrame.h"
#include "sampler.h"
#include "nsAnimationManager.h"
#include "nsTransitionManager.h"
#include "nsIViewManager.h"
#include "mozilla/StandardInteger.h"
@ -48,367 +43,6 @@ using namespace mozilla;
using namespace mozilla::layers;
typedef FrameMetrics::ViewID ViewID;
static void AddTransformFunctions(nsCSSValueList* aList,
nsStyleContext* aContext,
nsPresContext* aPresContext,
nsRect& aBounds,
float aAppUnitsPerPixel,
InfallibleTArray<TransformFunction>& aFunctions)
{
if (aList->mValue.GetUnit() == eCSSUnit_None) {
return;
}
for (const nsCSSValueList* curr = aList; curr; curr = curr->mNext) {
const nsCSSValue& currElem = curr->mValue;
NS_ASSERTION(currElem.GetUnit() == eCSSUnit_Function,
"Stream should consist solely of functions!");
nsCSSValue::Array* array = currElem.GetArrayValue();
bool canStoreInRuleTree = true;
switch (nsStyleTransformMatrix::TransformFunctionOf(array)) {
case eCSSKeyword_rotatex:
{
double theta = array->Item(1).GetAngleValueInRadians();
aFunctions.AppendElement(RotationX(theta));
break;
}
case eCSSKeyword_rotatey:
{
double theta = array->Item(1).GetAngleValueInRadians();
aFunctions.AppendElement(RotationY(theta));
break;
}
case eCSSKeyword_rotatez:
{
double theta = array->Item(1).GetAngleValueInRadians();
aFunctions.AppendElement(RotationZ(theta));
break;
}
case eCSSKeyword_rotate:
{
double theta = array->Item(1).GetAngleValueInRadians();
aFunctions.AppendElement(Rotation(theta));
break;
}
case eCSSKeyword_rotate3d:
{
double x = array->Item(1).GetFloatValue();
double y = array->Item(2).GetFloatValue();
double z = array->Item(3).GetFloatValue();
double theta = array->Item(4).GetAngleValueInRadians();
aFunctions.AppendElement(Rotation3D(x, y, z, theta));
break;
}
case eCSSKeyword_scalex:
{
double x = array->Item(1).GetFloatValue();
aFunctions.AppendElement(Scale(x, 1, 1));
break;
}
case eCSSKeyword_scaley:
{
double y = array->Item(1).GetFloatValue();
aFunctions.AppendElement(Scale(1, y, 1));
break;
}
case eCSSKeyword_scalez:
{
double z = array->Item(1).GetFloatValue();
aFunctions.AppendElement(Scale(1, 1, z));
break;
}
case eCSSKeyword_scale:
{
double x = array->Item(1).GetFloatValue();
// scale(x) is shorthand for scale(x, x);
double y = array->Count() == 2 ? x : array->Item(2).GetFloatValue();
aFunctions.AppendElement(Scale(x, y, 1));
break;
}
case eCSSKeyword_scale3d:
{
double x = array->Item(1).GetFloatValue();
double y = array->Item(2).GetFloatValue();
double z = array->Item(3).GetFloatValue();
aFunctions.AppendElement(Scale(x, y, z));
break;
}
case eCSSKeyword_translatex:
{
double x = nsStyleTransformMatrix::ProcessTranslatePart(
array->Item(1), aContext, aPresContext, canStoreInRuleTree,
aBounds.Width(), aAppUnitsPerPixel);
aFunctions.AppendElement(Translation(x, 0, 0));
break;
}
case eCSSKeyword_translatey:
{
double y = nsStyleTransformMatrix::ProcessTranslatePart(
array->Item(1), aContext, aPresContext, canStoreInRuleTree,
aBounds.Height(), aAppUnitsPerPixel);
aFunctions.AppendElement(Translation(0, y, 0));
break;
}
case eCSSKeyword_translatez:
{
double z = nsStyleTransformMatrix::ProcessTranslatePart(
array->Item(1), aContext, aPresContext, canStoreInRuleTree,
0, aAppUnitsPerPixel);
aFunctions.AppendElement(Translation(0, 0, z));
break;
}
case eCSSKeyword_translate:
{
double x = nsStyleTransformMatrix::ProcessTranslatePart(
array->Item(1), aContext, aPresContext, canStoreInRuleTree,
aBounds.Width(), aAppUnitsPerPixel);
// translate(x) is shorthand for translate(x, 0)
double y = 0;
if (array->Count() == 3) {
y = nsStyleTransformMatrix::ProcessTranslatePart(
array->Item(2), aContext, aPresContext, canStoreInRuleTree,
aBounds.Height(), aAppUnitsPerPixel);
}
aFunctions.AppendElement(Translation(x, y, 0));
break;
}
case eCSSKeyword_translate3d:
{
double x = nsStyleTransformMatrix::ProcessTranslatePart(
array->Item(1), aContext, aPresContext, canStoreInRuleTree,
aBounds.Width(), aAppUnitsPerPixel);
double y = nsStyleTransformMatrix::ProcessTranslatePart(
array->Item(2), aContext, aPresContext, canStoreInRuleTree,
aBounds.Height(), aAppUnitsPerPixel);
double z = nsStyleTransformMatrix::ProcessTranslatePart(
array->Item(3), aContext, aPresContext, canStoreInRuleTree,
0, aAppUnitsPerPixel);
aFunctions.AppendElement(Translation(x, y, z));
break;
}
case eCSSKeyword_skewx:
{
double x = array->Item(1).GetFloatValue();
aFunctions.AppendElement(SkewX(x));
break;
}
case eCSSKeyword_skewy:
{
double y = array->Item(1).GetFloatValue();
aFunctions.AppendElement(SkewY(y));
break;
}
case eCSSKeyword_matrix:
{
gfx3DMatrix matrix;
matrix._11 = array->Item(1).GetFloatValue();
matrix._12 = array->Item(2).GetFloatValue();
matrix._13 = 0;
matrix._14 = array->Item(3).GetFloatValue();
matrix._21 = array->Item(4).GetFloatValue();
matrix._22 = array->Item(5).GetFloatValue();
matrix._23 = 0;
matrix._24 = array->Item(6).GetFloatValue();
matrix._31 = 0;
matrix._32 = 0;
matrix._33 = 1;
matrix._34 = 0;
matrix._41 = 0;
matrix._42 = 0;
matrix._43 = 0;
matrix._44 = 1;
aFunctions.AppendElement(TransformMatrix(matrix));
break;
}
case eCSSKeyword_matrix3d:
{
gfx3DMatrix matrix;
matrix._11 = array->Item(1).GetFloatValue();
matrix._12 = array->Item(2).GetFloatValue();
matrix._13 = array->Item(3).GetFloatValue();
matrix._14 = array->Item(4).GetFloatValue();
matrix._21 = array->Item(5).GetFloatValue();
matrix._22 = array->Item(6).GetFloatValue();
matrix._23 = array->Item(7).GetFloatValue();
matrix._24 = array->Item(8).GetFloatValue();
matrix._31 = array->Item(9).GetFloatValue();
matrix._32 = array->Item(10).GetFloatValue();
matrix._33 = array->Item(11).GetFloatValue();
matrix._34 = array->Item(12).GetFloatValue();
matrix._41 = array->Item(13).GetFloatValue();
matrix._42 = array->Item(14).GetFloatValue();
matrix._43 = array->Item(15).GetFloatValue();
matrix._44 = array->Item(16).GetFloatValue();
aFunctions.AppendElement(TransformMatrix(matrix));
break;
}
case eCSSKeyword_perspective:
{
aFunctions.AppendElement(Perspective(array->Item(1).GetFloatValue()));
break;
}
default:
NS_ERROR("Function not handled yet!");
}
}
}
static TimingFunction
ToTimingFunction(css::ComputedTimingFunction& aCTF)
{
if (aCTF.GetType() == nsTimingFunction::Function) {
const nsSMILKeySpline* spline = aCTF.GetFunction();
return TimingFunction(CubicBezierFunction(spline->X1(), spline->Y1(),
spline->X2(), spline->Y2()));
}
PRUint32 type = aCTF.GetType() == nsTimingFunction::StepStart ? 1 : 2;
return TimingFunction(StepFunction(aCTF.GetSteps(), type));
}
static void
AddAnimationsForProperty(nsIFrame* aFrame, nsCSSProperty aProperty,
ElementAnimation* ea, Layer* aLayer,
AnimationData& aData)
{
NS_ASSERTION(aLayer->AsContainerLayer(), "Should only animate ContainerLayer");
nsStyleContext* styleContext = aFrame->GetStyleContext();
nsPresContext* presContext = aFrame->PresContext();
nsRect bounds = nsDisplayTransform::GetFrameBoundsForTransform(aFrame);
float scale = nsDeviceContext::AppUnitsPerCSSPixel();
float iterations = ea->mIterationCount != NS_IEEEPositiveInfinity()
? ea->mIterationCount : -1;
for (PRUint32 propIdx = 0; propIdx < ea->mProperties.Length(); propIdx++) {
AnimationProperty* property = &ea->mProperties[propIdx];
InfallibleTArray<AnimationSegment> segments;
if (aProperty != property->mProperty) {
continue;
}
for (PRUint32 segIdx = 0; segIdx < property->mSegments.Length(); segIdx++) {
AnimationPropertySegment* segment = &property->mSegments[segIdx];
if (aProperty == eCSSProperty_transform) {
nsCSSValueList* list = segment->mFromValue.GetCSSValueListValue();
InfallibleTArray<TransformFunction> fromFunctions;
AddTransformFunctions(list, styleContext,
presContext, bounds,
scale, fromFunctions);
list = segment->mToValue.GetCSSValueListValue();
InfallibleTArray<TransformFunction> toFunctions;
AddTransformFunctions(list, styleContext,
presContext, bounds,
scale, toFunctions);
segments.AppendElement(AnimationSegment(fromFunctions, toFunctions,
segment->mFromKey, segment->mToKey,
ToTimingFunction(segment->mTimingFunction)));
} else if (aProperty == eCSSProperty_opacity) {
segments.AppendElement(AnimationSegment(Opacity(segment->mFromValue.GetFloatValue()),
Opacity(segment->mToValue.GetFloatValue()),
segment->mFromKey,
segment->mToKey,
ToTimingFunction(segment->mTimingFunction)));
}
}
aLayer->AddAnimation(Animation(ea->mStartTime,
ea->mIterationDuration,
segments,
iterations,
ea->mDirection,
aData));
}
}
static void
AddAnimationsAndTransitionsToLayer(Layer* aLayer, nsDisplayItem* aItem,
nsCSSProperty aProperty)
{
aLayer->ClearAnimations();
nsIFrame* frame = aItem->GetUnderlyingFrame();
nsIContent* aContent = frame->GetContent();
ElementTransitions* et =
nsTransitionManager::GetTransitionsForCompositor(aContent, aProperty);
ElementAnimations* ea =
nsAnimationManager::GetAnimationsForCompositor(aContent, aProperty);
if (!ea && !et) {
return;
}
mozilla::TimeStamp currentTime =
frame->PresContext()->RefreshDriver()->MostRecentRefresh();
AnimationData data;
if (aProperty == eCSSProperty_transform) {
nsRect bounds = nsDisplayTransform::GetFrameBoundsForTransform(frame);
float scale = nsDeviceContext::AppUnitsPerCSSPixel();
gfxPoint3D offsetToTransformOrigin =
nsDisplayTransform::GetDeltaToMozTransformOrigin(frame, scale, &bounds);
gfxPoint3D offsetToPerspectiveOrigin =
nsDisplayTransform::GetDeltaToMozPerspectiveOrigin(frame, scale);
nscoord perspective = 0.0;
nsStyleContext* parentStyleContext = frame->GetStyleContext()->GetParent();
if (parentStyleContext) {
const nsStyleDisplay* disp = parentStyleContext->GetStyleDisplay();
if (disp && disp->mChildPerspective.GetUnit() == eStyleUnit_Coord) {
perspective = disp->mChildPerspective.GetCoordValue();
}
}
nsPoint origin = aItem->ToReferenceFrame();
data = TransformData(origin, offsetToTransformOrigin,
offsetToPerspectiveOrigin, bounds, perspective);
} else if (aProperty == eCSSProperty_opacity) {
data = null_t();
}
if (et) {
for (PRUint32 tranIdx = 0; tranIdx < et->mPropertyTransitions.Length(); tranIdx++) {
ElementPropertyTransition* pt = &et->mPropertyTransitions[tranIdx];
if (!pt->CanPerformOnCompositor(et->mElement, currentTime)) {
continue;
}
ElementAnimation anim;
anim.mIterationCount = 1;
anim.mDirection = NS_STYLE_ANIMATION_DIRECTION_NORMAL;
anim.mFillMode = NS_STYLE_ANIMATION_FILL_MODE_NONE;
anim.mStartTime = pt->mStartTime;
anim.mIterationDuration = pt->mDuration;
AnimationProperty& prop = *anim.mProperties.AppendElement();
prop.mProperty = pt->mProperty;
AnimationPropertySegment& segment = *prop.mSegments.AppendElement();
segment.mFromKey = 0;
segment.mToKey = 1;
segment.mFromValue = pt->mStartValue;
segment.mToValue = pt->mEndValue;
segment.mTimingFunction = pt->mTimingFunction;
AddAnimationsForProperty(frame, aProperty, &anim,
aLayer, data);
}
}
if (ea) {
for (PRUint32 animIdx = 0; animIdx < ea->mAnimations.Length(); animIdx++) {
ElementAnimation* anim = &ea->mAnimations[animIdx];
if (!anim->CanPerformOnCompositor(ea->mElement, currentTime)) {
continue;
}
AddAnimationsForProperty(frame, aProperty, anim,
aLayer, data);
}
}
}
nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
Mode aMode, bool aBuildCaret)
: mReferenceFrame(aReferenceFrame),
@ -565,8 +199,7 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
nsRect contentBounds = scrollableFrame->GetScrollRange();
contentBounds.width += scrollableFrame->GetScrollPortRect().width;
contentBounds.height += scrollableFrame->GetScrollPortRect().height;
metrics.mCSSContentRect =
mozilla::gfx::Rect(nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.x),
metrics.mCSSContentRect = gfx::Rect(nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.x),
nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.y),
nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.width),
nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.height));
@ -577,8 +210,7 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
}
else {
nsRect contentBounds = aForFrame->GetRect();
metrics.mCSSContentRect =
mozilla::gfx::Rect(nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.x),
metrics.mCSSContentRect = gfx::Rect(nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.x),
nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.y),
nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.width),
nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.height));
@ -988,8 +620,10 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
return;
}
// Root is being scaled up by the X/Y resolution. Scale it back down.
root->SetScale(1.0f/containerParameters.mXScale,
1.0f/containerParameters.mYScale);
gfx3DMatrix rootTransform = root->GetTransform()*
gfx3DMatrix::ScalingMatrix(1.0f/containerParameters.mXScale,
1.0f/containerParameters.mYScale, 1.0f);
root->SetTransform(rootTransform);
ViewID id = presContext->IsRootContentDocument() ? FrameMetrics::ROOT_SCROLL_ID
: FrameMetrics::NULL_SCROLL_ID;
@ -1648,7 +1282,7 @@ nsDisplayBackground::ConfigureLayer(ImageLayer* aLayer)
transform.Translate(mDestRect.TopLeft());
transform.Scale(mDestRect.width/imageSize.width,
mDestRect.height/imageSize.height);
aLayer->SetBaseTransform(gfx3DMatrix::From2D(transform));
aLayer->SetTransform(gfx3DMatrix::From2D(transform));
aLayer->SetVisibleRegion(nsIntRect(0, 0, imageSize.width, imageSize.height));
}
@ -2345,16 +1979,14 @@ already_AddRefed<Layer>
nsDisplayOpacity::BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerParameters& aContainerParameters) {
nsRefPtr<Layer> container = GetLayerBuilderForManager(aManager)->
nsRefPtr<Layer> layer = GetLayerBuilderForManager(aManager)->
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList,
aContainerParameters, nullptr);
if (!container)
if (!layer)
return nullptr;
container->SetOpacity(mFrame->GetStyleDisplay()->mOpacity);
AddAnimationsAndTransitionsToLayer(container, this, eCSSProperty_opacity);
return container.forget();
layer->SetOpacity(mFrame->GetStyleDisplay()->mOpacity);
return layer.forget();
}
/**
@ -2379,12 +2011,6 @@ nsDisplayOpacity::GetLayerState(nsDisplayListBuilder* aBuilder,
if (mFrame->AreLayersMarkedActive(nsChangeHint_UpdateOpacityLayer) &&
!IsItemTooSmallForActiveLayer(this))
return LAYER_ACTIVE;
if (mFrame->GetContent()) {
if (nsLayoutUtils::HasAnimationsForCompositor(mFrame->GetContent(),
eCSSProperty_opacity)) {
return LAYER_ACTIVE;
}
}
nsIFrame* activeScrolledRoot =
nsLayoutUtils::GetActiveScrolledRootFor(mFrame, nullptr);
return !ChildrenCanBeInactive(aBuilder, aManager, aParameters, mList, activeScrolledRoot)
@ -3046,11 +2672,10 @@ nsDisplayTransform::GetFrameBoundsForTransform(const nsIFrame* aFrame)
/* Returns the delta specified by the -moz-transform-origin property.
* This is a positive delta, meaning that it indicates the direction to move
* to get from (0, 0) of the frame to the transform origin. This function is
* called off the main thread.
* to get from (0, 0) of the frame to the transform origin.
*/
/* static */ gfxPoint3D
nsDisplayTransform::GetDeltaToMozTransformOrigin(const nsIFrame* aFrame,
static
gfxPoint3D GetDeltaToMozTransformOrigin(const nsIFrame* aFrame,
float aAppUnitsPerPixel,
const nsRect* aBoundsOverride)
{
@ -3067,7 +2692,8 @@ nsDisplayTransform::GetDeltaToMozTransformOrigin(const nsIFrame* aFrame,
nsDisplayTransform::GetFrameBoundsForTransform(aFrame));
/* Allows us to access named variables by index. */
float coords[3];
gfxPoint3D result;
gfxFloat* coords[3] = {&result.x, &result.y, &result.z};
const nscoord* dimensions[2] =
{&boundingRect.width, &boundingRect.height};
@ -3078,17 +2704,17 @@ nsDisplayTransform::GetDeltaToMozTransformOrigin(const nsIFrame* aFrame,
const nsStyleCoord &coord = display->mTransformOrigin[index];
if (coord.GetUnit() == eStyleUnit_Calc) {
const nsStyleCoord::Calc *calc = coord.GetCalcValue();
coords[index] =
*coords[index] =
NSAppUnitsToFloatPixels(*dimensions[index], aAppUnitsPerPixel) *
calc->mPercent +
NSAppUnitsToFloatPixels(calc->mLength, aAppUnitsPerPixel);
} else if (coord.GetUnit() == eStyleUnit_Percent) {
coords[index] =
*coords[index] =
NSAppUnitsToFloatPixels(*dimensions[index], aAppUnitsPerPixel) *
coord.GetPercentValue();
} else {
NS_ABORT_IF_FALSE(coord.GetUnit() == eStyleUnit_Coord, "unexpected unit");
coords[index] =
*coords[index] =
NSAppUnitsToFloatPixels(coord.GetCoordValue(), aAppUnitsPerPixel);
}
if ((aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) &&
@ -3097,26 +2723,25 @@ nsDisplayTransform::GetDeltaToMozTransformOrigin(const nsIFrame* aFrame,
// user space, not the top left of its bounds, so we must adjust for that:
nscoord offset =
(index == 0) ? aFrame->GetPosition().x : aFrame->GetPosition().y;
coords[index] -= NSAppUnitsToFloatPixels(offset, aAppUnitsPerPixel);
*coords[index] -= NSAppUnitsToFloatPixels(offset, aAppUnitsPerPixel);
}
}
coords[2] = NSAppUnitsToFloatPixels(display->mTransformOrigin[2].GetCoordValue(),
*coords[2] = NSAppUnitsToFloatPixels(display->mTransformOrigin[2].GetCoordValue(),
aAppUnitsPerPixel);
/* Adjust based on the origin of the rectangle. */
coords[0] += NSAppUnitsToFloatPixels(boundingRect.x, aAppUnitsPerPixel);
coords[1] += NSAppUnitsToFloatPixels(boundingRect.y, aAppUnitsPerPixel);
result.x += NSAppUnitsToFloatPixels(boundingRect.x, aAppUnitsPerPixel);
result.y += NSAppUnitsToFloatPixels(boundingRect.y, aAppUnitsPerPixel);
return gfxPoint3D(coords[0], coords[1], coords[2]);
return result;
}
/* Returns the delta specified by the -moz-perspective-origin property.
* This is a positive delta, meaning that it indicates the direction to move
* to get from (0, 0) of the frame to the perspective origin. This function is
* called off the main thread.
* to get from (0, 0) of the frame to the perspective origin.
*/
/* static */ gfxPoint3D
nsDisplayTransform::GetDeltaToMozPerspectiveOrigin(const nsIFrame* aFrame,
static
gfxPoint3D GetDeltaToMozPerspectiveOrigin(const nsIFrame* aFrame,
float aAppUnitsPerPixel)
{
NS_PRECONDITION(aFrame, "Can't get delta for a null frame!");
@ -3180,22 +2805,12 @@ nsDisplayTransform::GetDeltaToMozPerspectiveOrigin(const nsIFrame* aFrame,
*/
gfx3DMatrix
nsDisplayTransform::GetResultingTransformMatrix(const nsIFrame* aFrame,
const nsPoint& aOrigin,
const nsPoint &aOrigin,
float aAppUnitsPerPixel,
const nsRect* aBoundsOverride,
const nsCSSValueList* aTransformOverride,
gfxPoint3D* aToMozOrigin,
gfxPoint3D* aToPerspectiveOrigin,
nscoord* aChildPerspective,
nsIFrame** aOutAncestor)
{
NS_PRECONDITION(aFrame || (aToMozOrigin && aBoundsOverride && aToPerspectiveOrigin &&
aTransformOverride && aChildPerspective),
"Should have frame or necessary infromation to construct matrix");
NS_PRECONDITION(!(aFrame && (aToMozOrigin || aToPerspectiveOrigin ||
aTransformOverride || aChildPerspective)),
"Should not have both frame and necessary infromation to construct matrix");
NS_PRECONDITION(aFrame, "Cannot get transform matrix for a null frame!");
if (aOutAncestor) {
*aOutAncestor = nsLayoutUtils::GetCrossDocParentFrame(aFrame);
@ -3205,7 +2820,7 @@ nsDisplayTransform::GetResultingTransformMatrix(const nsIFrame* aFrame,
* coordinate space to the new origin.
*/
gfxPoint3D toMozOrigin =
aFrame ? GetDeltaToMozTransformOrigin(aFrame, aAppUnitsPerPixel, aBoundsOverride) : *aToMozOrigin;
GetDeltaToMozTransformOrigin(aFrame, aAppUnitsPerPixel, aBoundsOverride);
gfxPoint3D newOrigin =
gfxPoint3D(NSAppUnitsToFloatPixels(aOrigin.x, aAppUnitsPerPixel),
NSAppUnitsToFloatPixels(aOrigin.y, aAppUnitsPerPixel),
@ -3214,7 +2829,7 @@ nsDisplayTransform::GetResultingTransformMatrix(const nsIFrame* aFrame,
/* Get the underlying transform matrix. This requires us to get the
* bounds of the frame.
*/
const nsStyleDisplay* disp = aFrame ? aFrame->GetStyleDisplay() : nullptr;
const nsStyleDisplay* disp = aFrame->GetStyleDisplay();
nsRect bounds = (aBoundsOverride ? *aBoundsOverride :
nsDisplayTransform::GetFrameBoundsForTransform(aFrame));
@ -3225,12 +2840,9 @@ nsDisplayTransform::GetResultingTransformMatrix(const nsIFrame* aFrame,
// disp->mSpecifiedTransform, since we still need any transformFromSVGParent.
gfxMatrix svgTransform, transformFromSVGParent;
bool hasSVGTransforms =
aFrame && aFrame->IsSVGTransformed(&svgTransform, &transformFromSVGParent);
aFrame->IsSVGTransformed(&svgTransform, &transformFromSVGParent);
/* Transformed frames always have a transform, or are preserving 3d (and might still have perspective!) */
if (aTransformOverride) {
result = nsStyleTransformMatrix::ReadTransforms(aTransformOverride, nullptr, nullptr,
dummy, bounds, aAppUnitsPerPixel);
} else if (disp->mSpecifiedTransform) {
if (disp->mSpecifiedTransform) {
result = nsStyleTransformMatrix::ReadTransforms(disp->mSpecifiedTransform,
aFrame->GetStyleContext(),
aFrame->PresContext(),
@ -3242,6 +2854,10 @@ nsDisplayTransform::GetResultingTransformMatrix(const nsIFrame* aFrame,
svgTransform.x0 *= pixelsPerCSSPx;
svgTransform.y0 *= pixelsPerCSSPx;
result = gfx3DMatrix::From2D(svgTransform);
} else {
NS_ASSERTION(aFrame->GetStyleDisplay()->mTransformStyle == NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D ||
aFrame->GetStyleDisplay()->mBackfaceVisibility == NS_STYLE_BACKFACE_VISIBILITY_HIDDEN,
"If we don't have a transform, then we must have another reason to have an nsDisplayTransform created");
}
if (hasSVGTransforms && !transformFromSVGParent.IsIdentity()) {
@ -3254,40 +2870,32 @@ nsDisplayTransform::GetResultingTransformMatrix(const nsIFrame* aFrame,
}
const nsStyleDisplay* parentDisp = nullptr;
nsStyleContext* parentStyleContext = aFrame ? aFrame->GetStyleContext()->GetParent(): nullptr;
nsStyleContext* parentStyleContext = aFrame->GetStyleContext()->GetParent();
if (parentStyleContext) {
parentDisp = parentStyleContext->GetStyleDisplay();
}
nscoord perspectiveCoord = 0;
if (parentDisp && parentDisp->mChildPerspective.GetUnit() == eStyleUnit_Coord) {
perspectiveCoord = parentDisp->mChildPerspective.GetCoordValue();
}
if (aChildPerspective) {
perspectiveCoord = *aChildPerspective;
}
if (nsLayoutUtils::Are3DTransformsEnabled() && perspectiveCoord > 0.0) {
if (nsLayoutUtils::Are3DTransformsEnabled() &&
parentDisp && parentDisp->mChildPerspective.GetUnit() == eStyleUnit_Coord &&
parentDisp->mChildPerspective.GetCoordValue() > 0.0) {
gfx3DMatrix perspective;
perspective._34 =
-1.0 / NSAppUnitsToFloatPixels(perspectiveCoord, aAppUnitsPerPixel);
-1.0 / NSAppUnitsToFloatPixels(parentDisp->mChildPerspective.GetCoordValue(),
aAppUnitsPerPixel);
/* At the point when perspective is applied, we have been translated to the transform origin.
* The translation to the perspective origin is the difference between these values.
*/
gfxPoint3D toPerspectiveOrigin = aFrame ? GetDeltaToMozPerspectiveOrigin(aFrame, aAppUnitsPerPixel) : *aToPerspectiveOrigin;
gfxPoint3D toPerspectiveOrigin = GetDeltaToMozPerspectiveOrigin(aFrame, aAppUnitsPerPixel);
result = result * nsLayoutUtils::ChangeMatrixBasis(toPerspectiveOrigin - toMozOrigin, perspective);
}
if (aFrame && aFrame->Preserves3D() && nsLayoutUtils::Are3DTransformsEnabled()) {
if (aFrame->Preserves3D() && nsLayoutUtils::Are3DTransformsEnabled()) {
// Include the transform set on our parent
NS_ASSERTION(aFrame->GetParent() &&
aFrame->GetParent()->IsTransformed() &&
aFrame->GetParent()->Preserves3DChildren(),
"Preserve3D mismatch!");
gfx3DMatrix parent =
GetResultingTransformMatrix(aFrame->GetParent(),
aOrigin - aFrame->GetPosition(),
aAppUnitsPerPixel, nullptr, nullptr, nullptr,
nullptr, nullptr, aOutAncestor);
gfx3DMatrix parent = GetResultingTransformMatrix(aFrame->GetParent(), aOrigin - aFrame->GetPosition(),
aAppUnitsPerPixel, nullptr, aOutAncestor);
return nsLayoutUtils::ChangeMatrixBasis(newOrigin + toMozOrigin, result) * parent;
}
@ -3336,7 +2944,8 @@ nsDisplayTransform::GetTransform(float aAppUnitsPerPixel)
if (mTransform.IsIdentity() || mCachedAppUnitsPerPixel != aAppUnitsPerPixel) {
mTransform =
GetResultingTransformMatrix(mFrame, ToReferenceFrame(),
aAppUnitsPerPixel);
aAppUnitsPerPixel,
nullptr);
mCachedAppUnitsPerPixel = aAppUnitsPerPixel;
}
return mTransform;
@ -3362,8 +2971,6 @@ already_AddRefed<Layer> nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBu
if (mFrame->Preserves3D() || mFrame->Preserves3DChildren()) {
container->SetContentFlags(container->GetContentFlags() | Layer::CONTENT_PRESERVE_3D);
}
AddAnimationsAndTransitionsToLayer(container, this, eCSSProperty_transform);
return container.forget();
}
@ -3378,12 +2985,6 @@ nsDisplayTransform::GetLayerState(nsDisplayListBuilder* aBuilder,
return LAYER_ACTIVE;
if (!GetTransform(mFrame->PresContext()->AppUnitsPerDevPixel()).Is2D() || mFrame->Preserves3D())
return LAYER_ACTIVE;
if (mFrame->GetContent()) {
if (nsLayoutUtils::HasAnimationsForCompositor(mFrame->GetContent(),
eCSSProperty_transform)) {
return LAYER_ACTIVE;
}
}
nsIFrame* activeScrolledRoot =
nsLayoutUtils::GetActiveScrolledRootFor(mFrame, nullptr);
return !mStoredList.ChildrenCanBeInactive(aBuilder,
@ -3698,7 +3299,7 @@ bool nsDisplayTransform::UntransformRect(const nsRect &aUntransformedBounds,
* empty rect.
*/
float factor = nsPresContext::AppUnitsPerCSSPixel();
gfx3DMatrix matrix = GetResultingTransformMatrix(aFrame, aOrigin, factor);
gfx3DMatrix matrix = GetResultingTransformMatrix(aFrame, aOrigin, factor, nullptr);
return UntransformRectMatrix(aUntransformedBounds, matrix, factor, aOutRect);
}

View File

@ -2353,13 +2353,6 @@ public:
float aAppUnitsPerPixel,
nsRect* aOutRect);
static gfxPoint3D GetDeltaToMozTransformOrigin(const nsIFrame* aFrame,
float aAppUnitsPerPixel,
const nsRect* aBoundsOverride);
static gfxPoint3D GetDeltaToMozPerspectiveOrigin(const nsIFrame* aFrame,
float aAppUnitsPerPixel);
/**
* Returns the bounds of a frame as defined for resolving percentage
* <translation-value>s in CSS transforms. If
@ -2393,10 +2386,6 @@ public:
const nsPoint& aOrigin,
float aAppUnitsPerPixel,
const nsRect* aBoundsOverride = nullptr,
const nsCSSValueList* aTransformOverride = nullptr,
gfxPoint3D* aToMozOrigin = nullptr,
gfxPoint3D* aToPerspectiveOrigin = nullptr,
nscoord* aChildPerspective = nullptr,
nsIFrame** aOutAncestor = nullptr);
/**
* Return true when we should try to prerender the entire contents of the

View File

@ -4,7 +4,6 @@
* 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 "base/basictypes.h"
#include "mozilla/Util.h"
#include "nsLayoutUtils.h"
@ -71,7 +70,7 @@
#include "nsTextFrame.h"
#include "nsFontFaceList.h"
#include "nsFontInflationData.h"
#include "CompositorParent.h"
#include "nsSVGUtils.h"
#include "nsSVGIntegrationUtils.h"
#include "nsSVGForeignObjectFrame.h"
@ -84,8 +83,6 @@
#endif
#include "sampler.h"
#include "nsAnimationManager.h"
#include "nsTransitionManager.h"
using namespace mozilla;
using namespace mozilla::layers;
@ -116,32 +113,6 @@ static ContentMap& GetContentMap() {
return *sContentMap;
}
bool
nsLayoutUtils::HasAnimationsForCompositor(nsIContent* aContent,
nsCSSProperty aProperty)
{
if (!aContent->MayHaveAnimations())
return false;
ElementAnimations* animations =
static_cast<ElementAnimations*>(aContent->GetProperty(nsGkAtoms::animationsProperty));
if (animations) {
bool propertyMatches = animations->HasAnimationOfProperty(aProperty);
if (propertyMatches && animations->CanPerformOnCompositorThread()) {
return true;
}
}
ElementTransitions* transitions =
static_cast<ElementTransitions*>(aContent->GetProperty(nsGkAtoms::transitionsProperty));
if (transitions) {
bool propertyMatches = transitions->HasTransitionOfProperty(aProperty);
if (propertyMatches && transitions->CanPerformOnCompositorThread()) {
return true;
}
}
return false;
}
bool
nsLayoutUtils::Are3DTransformsEnabled()
@ -158,36 +129,6 @@ nsLayoutUtils::Are3DTransformsEnabled()
return s3DTransformsEnabled;
}
bool
nsLayoutUtils::AreOpacityAnimationsEnabled()
{
static bool sAreOpacityAnimationsEnabled;
static bool sOpacityPrefCached = false;
if (!sOpacityPrefCached) {
sOpacityPrefCached = true;
Preferences::AddBoolVarCache(&sAreOpacityAnimationsEnabled,
"layers.offmainthreadcomposition.animate-opacity");
}
return sAreOpacityAnimationsEnabled && CompositorParent::CompositorLoop();
}
bool
nsLayoutUtils::AreTransformAnimationsEnabled()
{
static bool sAreTransformAnimationsEnabled;
static bool sTransformPrefCached = false;
if (!sTransformPrefCached) {
sTransformPrefCached = true;
Preferences::AddBoolVarCache(&sAreTransformAnimationsEnabled,
"layers.offmainthreadcomposition.animate-transform");
}
return sAreTransformAnimationsEnabled && CompositorParent::CompositorLoop();
}
bool
nsLayoutUtils::UseBackgroundNearestFiltering()
{

View File

@ -1497,24 +1497,11 @@ public:
nsMallocSizeOfFun aMallocSizeOf,
bool clear);
/**
* Returns true if the content node has animations or transitions that can be
* performed on the compositor.
*/
static bool HasAnimationsForCompositor(nsIContent* aContent,
nsCSSProperty aProperty);
/**
* Checks if CSS 3D transforms are currently enabled.
*/
static bool Are3DTransformsEnabled();
/**
* Checks if off-main-thread transform and opacity animations are enabled.
*/
static bool AreOpacityAnimationsEnabled();
static bool AreTransformAnimationsEnabled();
/**
* Checks if we should forcibly use nearest pixel filtering for the
* background.

View File

@ -92,8 +92,6 @@
#include "CSSCalc.h"
#include "nsAbsoluteContainingBlock.h"
#include "nsFontInflationData.h"
#include "nsAnimationManager.h"
#include "nsTransitionManager.h"
#include "mozilla/Preferences.h"
#include "mozilla/LookAndFeel.h"
@ -937,20 +935,9 @@ nsIFrame::GetPaddingRect() const
bool
nsIFrame::IsTransformed() const
{
return ((mState & NS_FRAME_MAY_BE_TRANSFORMED) &&
return (mState & NS_FRAME_MAY_BE_TRANSFORMED) &&
(GetStyleDisplay()->HasTransform() ||
IsSVGTransformed() ||
(mContent &&
nsLayoutUtils::HasAnimationsForCompositor(mContent,
eCSSProperty_transform))));
}
bool
nsIFrame::HasOpacity() const
{
return GetStyleDisplay()->mOpacity < 1.0f || (mContent &&
nsLayoutUtils::HasAnimationsForCompositor(mContent,
eCSSProperty_opacity));
IsSVGTransformed());
}
bool
@ -1777,12 +1764,9 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
nsRect clipPropClip;
const nsStyleDisplay* disp = GetStyleDisplay();
// We can stop right away if this is a zero-opacity stacking context and
// we're painting, and we're not animating opacity.
if (disp->mOpacity == 0.0 && aBuilder->IsForPainting() &&
!nsLayoutUtils::HasAnimationsForCompositor(mContent,
eCSSProperty_opacity)) {
// we're painting.
if (disp->mOpacity == 0.0 && aBuilder->IsForPainting())
return NS_OK;
}
bool applyClipPropClipping =
ApplyClipPropClipping(aBuilder, disp, this, &clipPropClip);
@ -1927,6 +1911,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
// resultList was emptied
resultList.AppendToTop(item);
}
/* If there are any SVG effects, wrap the list up in an SVG effects item
* (which also handles CSS group opacity). Note that we create an SVG effects
* item even if resultList is empty, since a filter can produce graphical
@ -1942,7 +1927,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
/* Else, if the list is non-empty and there is CSS group opacity without SVG
* effects, wrap it up in an opacity item.
*/
else if (HasOpacity() &&
else if (disp->mOpacity < 1.0f &&
!nsSVGUtils::CanOptimizeOpacity(this) &&
!resultList.IsEmpty()) {
rv = resultList.AppendNewToTop(
@ -2096,7 +2081,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
// Child is composited if it's transformed, partially transparent, or has
// SVG effects.
const nsStyleDisplay* disp = child->GetStyleDisplay();
bool isVisuallyAtomic = child->HasOpacity()
bool isVisuallyAtomic = disp->mOpacity != 1.0f
|| child->IsTransformed()
|| nsSVGIntegrationUtils::UsingEffectsForFrame(child);
@ -4764,8 +4749,8 @@ nsIFrame::GetTransformMatrix(nsIFrame* aStopAtAncestor,
PRInt32 scaleFactor = PresContext()->AppUnitsPerDevPixel();
gfx3DMatrix result =
nsDisplayTransform::GetResultingTransformMatrix(this, nsPoint(0, 0), scaleFactor, nullptr,
nullptr, nullptr, nullptr, nullptr, aOutAncestor);
nsDisplayTransform::GetResultingTransformMatrix(this, nsPoint(0, 0),
scaleFactor, nullptr, aOutAncestor);
// XXXjwatt: seems like this will double count offsets in the face of preserve-3d:
nsPoint delta = GetOffsetToCrossDoc(*aOutAncestor);
/* Combine the raw transform with a translation to our parent. */

View File

@ -278,7 +278,7 @@ nsHTMLCanvasFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
gfxMatrix transform;
transform.Translate(r.TopLeft());
transform.Scale(r.Width()/canvasSize.width, r.Height()/canvasSize.height);
layer->SetBaseTransform(gfx3DMatrix::From2D(transform));
layer->SetTransform(gfx3DMatrix::From2D(transform));
layer->SetFilter(nsLayoutUtils::GetGraphicsFilterForFrame(this));
layer->SetVisibleRegion(nsIntRect(0, 0, canvasSize.width, canvasSize.height));

View File

@ -1228,8 +1228,6 @@ public:
*/
bool IsTransformed() const;
bool HasOpacity() const;
/**
* Returns true if this frame is an SVG frame that has SVG transforms applied
* to it, or if its parent frame is an SVG frame that has children-only

View File

@ -1289,7 +1289,7 @@ nsDisplayImage::ConfigureLayer(ImageLayer *aLayer)
transform.Translate(destRect.TopLeft());
transform.Scale(destRect.Width()/imageWidth,
destRect.Height()/imageHeight);
aLayer->SetBaseTransform(gfx3DMatrix::From2D(transform));
aLayer->SetTransform(gfx3DMatrix::From2D(transform));
aLayer->SetVisibleRegion(nsIntRect(0, 0, imageWidth, imageHeight));
}

View File

@ -1723,7 +1723,7 @@ nsObjectFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
gfxMatrix transform;
transform.Translate(r.TopLeft());
layer->SetBaseTransform(gfx3DMatrix::From2D(transform));
layer->SetTransform(gfx3DMatrix::From2D(transform));
layer->SetVisibleRegion(nsIntRect(0, 0, size.width, size.height));
return layer.forget();
}

View File

@ -206,7 +206,7 @@ nsVideoFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
gfxMatrix transform;
transform.Translate(r.TopLeft());
transform.Scale(r.Width()/frameSize.width, r.Height()/frameSize.height);
layer->SetBaseTransform(gfx3DMatrix::From2D(transform));
layer->SetTransform(gfx3DMatrix::From2D(transform));
layer->SetVisibleRegion(nsIntRect(0, 0, frameSize.width, frameSize.height));
nsRefPtr<Layer> result = layer.forget();
return result.forget();

View File

@ -246,11 +246,10 @@ TransformShadowTree(nsDisplayListBuilder* aBuilder, nsFrameLoader* aFrameLoader,
ShadowLayer* shadow = aLayer->AsShadowLayer();
shadow->SetShadowClipRect(aLayer->GetClipRect());
shadow->SetShadowVisibleRegion(aLayer->GetVisibleRegion());
shadow->SetShadowOpacity(aLayer->GetOpacity());
const FrameMetrics* metrics = GetFrameMetrics(aLayer);
gfx3DMatrix shadowTransform = aLayer->GetBaseTransform();
gfx3DMatrix shadowTransform = aLayer->GetTransform();
ViewTransform layerTransform = aTransform;
if (metrics && metrics->IsScrollable()) {
@ -605,7 +604,7 @@ RenderFrameParent::BuildLayer(nsDisplayListBuilder* aBuilder,
layer->SetReferentId(id);
layer->SetVisibleRegion(aVisibleRect);
nsIntPoint rootFrameOffset = GetRootFrameOffset(aFrame, aBuilder);
layer->SetBaseTransform(
layer->SetTransform(
gfx3DMatrix::Translation(rootFrameOffset.x, rootFrameOffset.y, 0.0));
return layer.forget();

View File

@ -7,9 +7,6 @@
#include "nsRuleData.h"
#include "nsCSSValue.h"
#include "nsStyleContext.h"
#include "nsIFrame.h"
#include "nsAnimationManager.h"
#include "nsLayoutUtils.h"
namespace mozilla {
namespace css {
@ -216,26 +213,5 @@ ComputedTimingFunction::GetValue(double aPortion) const
}
}
bool
CommonElementAnimationData::CanAnimatePropertyOnCompositor(const dom::Element *aElement,
nsCSSProperty aProperty)
{
nsIFrame* frame = aElement->GetPrimaryFrame();
if (aProperty == eCSSProperty_opacity) {
return nsLayoutUtils::AreOpacityAnimationsEnabled();
}
if (aProperty == eCSSProperty_transform && !(frame &&
frame->Preserves3D() &&
frame->Preserves3DChildren())) {
if (frame && frame->IsSVGTransformed()) {
return false;
}
return nsLayoutUtils::AreTransformAnimationsEnabled();
}
return false;
}
}
}

View File

@ -107,12 +107,6 @@ public:
typedef nsTimingFunction::Type Type;
void Init(const nsTimingFunction &aFunction);
double GetValue(double aPortion) const;
const nsSMILKeySpline* GetFunction() const {
NS_ASSERTION(mType == nsTimingFunction::Function, "Type mismatch");
return &mTimingFunction;
}
Type GetType() const { return mType; }
PRUint32 GetSteps() const { return mSteps; }
private:
Type mType;
nsSMILKeySpline mTimingFunction;
@ -148,10 +142,6 @@ struct CommonElementAnimationData : public PRCList
mElement->DeleteProperty(mElementProperty);
}
static bool
CanAnimatePropertyOnCompositor(const dom::Element *aElement,
nsCSSProperty aProperty);
dom::Element *mElement;
// the atom we use in mElement's prop table (must be a static atom,

View File

@ -22,8 +22,6 @@ LIBXUL_LIBRARY = 1
EXPORTS_NAMESPACES = mozilla/css
EXPORTS = \
AnimationCommon.h \
nsAnimationManager.h \
nsCSSAnonBoxList.h \
nsCSSAnonBoxes.h \
nsCSSFontDescList.h \
@ -57,7 +55,6 @@ EXPORTS = \
nsRuleNode.h \
nsRuleProcessorData.h \
nsRuleWalker.h \
nsStyleAnimation.h \
nsStyleContext.h \
nsStyleCoord.h \
nsStyleSet.h \
@ -127,9 +124,7 @@ FORCE_STATIC_LIB = 1
include $(topsrcdir)/config/rules.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk
LOCAL_INCLUDES += \
LOCAL_INCLUDES = \
-I$(srcdir)/../base \
-I$(srcdir)/../generic \
-I$(srcdir)/../xul/base/src \

View File

@ -11,18 +11,113 @@
#include "nsStyleAnimation.h"
#include "nsSMILKeySpline.h"
#include "nsEventDispatcher.h"
#include "nsDisplayList.h"
#include "nsCSSFrameConstructor.h"
using namespace mozilla;
ElementAnimations::ElementAnimations(mozilla::dom::Element *aElement, nsIAtom *aElementProperty,
struct AnimationPropertySegment
{
float mFromKey, mToKey;
nsStyleAnimation::Value mFromValue, mToValue;
css::ComputedTimingFunction mTimingFunction;
};
struct AnimationProperty
{
nsCSSProperty mProperty;
InfallibleTArray<AnimationPropertySegment> mSegments;
};
/**
* Data about one animation (i.e., one of the values of
* 'animation-name') running on an element.
*/
struct ElementAnimation
{
ElementAnimation()
: mLastNotification(LAST_NOTIFICATION_NONE)
{
}
nsString mName; // empty string for 'none'
float mIterationCount; // NS_IEEEPositiveInfinity() means infinite
PRUint8 mDirection;
PRUint8 mFillMode;
PRUint8 mPlayState;
bool FillsForwards() const {
return mFillMode == NS_STYLE_ANIMATION_FILL_MODE_BOTH ||
mFillMode == NS_STYLE_ANIMATION_FILL_MODE_FORWARDS;
}
bool FillsBackwards() const {
return mFillMode == NS_STYLE_ANIMATION_FILL_MODE_BOTH ||
mFillMode == NS_STYLE_ANIMATION_FILL_MODE_BACKWARDS;
}
bool IsPaused() const {
return mPlayState == NS_STYLE_ANIMATION_PLAY_STATE_PAUSED;
}
TimeStamp mStartTime; // with delay taken into account
TimeStamp mPauseStart;
TimeDuration mIterationDuration;
enum {
LAST_NOTIFICATION_NONE = PRUint32(-1),
LAST_NOTIFICATION_END = PRUint32(-2)
};
// One of the above constants, or an integer for the iteration
// whose start we last notified on.
PRUint32 mLastNotification;
InfallibleTArray<AnimationProperty> mProperties;
};
typedef nsAnimationManager::EventArray EventArray;
typedef nsAnimationManager::AnimationEventInfo AnimationEventInfo;
/**
* Data about all of the animations running on an element.
*/
struct ElementAnimations : public mozilla::css::CommonElementAnimationData
{
ElementAnimations(dom::Element *aElement, nsIAtom *aElementProperty,
nsAnimationManager *aAnimationManager)
: CommonElementAnimationData(aElement, aElementProperty,
aAnimationManager),
mNeedsRefreshes(true)
{
}
{
}
void EnsureStyleRuleFor(TimeStamp aRefreshTime,
EventArray &aEventsToDispatch);
bool IsForElement() const { // rather than for a pseudo-element
return mElementProperty == nsGkAtoms::animationsProperty;
}
void PostRestyleForAnimation(nsPresContext *aPresContext) {
nsRestyleHint hint = IsForElement() ? eRestyle_Self : eRestyle_Subtree;
aPresContext->PresShell()->RestyleForAnimation(mElement, hint);
}
// This style rule contains the style data for currently animating
// values. It only matches when styling with animation. When we
// style without animation, we need to not use it so that we can
// detect any new changes; if necessary we restyle immediately
// afterwards with animation.
// NOTE: If we don't need to apply any styles, mStyleRule will be
// null, but mStyleRuleRefreshTime will still be valid.
nsRefPtr<css::AnimValuesStyleRule> mStyleRule;
// The refresh time associated with mStyleRule.
TimeStamp mStyleRuleRefreshTime;
// False when we know that our current style rule is valid
// indefinitely into the future (because all of our animations are
// either completed or paused). May be invalidated by a style change.
bool mNeedsRefreshes;
InfallibleTArray<ElementAnimation> mAnimations;
};
static void
ElementAnimationsPropertyDtor(void *aObject,
@ -38,114 +133,6 @@ ElementAnimationsPropertyDtor(void *aObject,
delete ea;
}
double
ElementAnimations::GetPositionInIteration(TimeStamp aStartTime, TimeStamp aCurrentTime,
TimeDuration aDuration, double aIterationCount,
PRUint32 aDirection, bool aIsForElement,
ElementAnimation* aAnimation,
ElementAnimations* aEa,
EventArray* aEventsToDispatch)
{
// Set |currentIterationCount| to the (fractional) number of
// iterations we've completed up to the current position.
TimeDuration currentTimeDuration = aCurrentTime - aStartTime;
double currentIterationCount =
currentTimeDuration / aDuration;
bool dispatchStartOrIteration = false;
if (currentIterationCount >= aIterationCount) {
if (!aAnimation) {
// We are on the compositor, so send a signal that the animation is over.
// The main thread will fire the animationend event.
return -1;
}
// Dispatch 'animationend' when needed.
if (aIsForElement &&
aAnimation->mLastNotification !=
ElementAnimation::LAST_NOTIFICATION_END) {
aAnimation->mLastNotification = ElementAnimation::LAST_NOTIFICATION_END;
// XXXdz: if this animation was done on the compositor, we should
// invalidate the frame and update style once we start throttling style
// updates.
AnimationEventInfo ei(aEa->mElement, aAnimation->mName, NS_ANIMATION_END,
currentTimeDuration);
aEventsToDispatch->AppendElement(ei);
}
if (!aAnimation->FillsForwards()) {
// No animation data.
return -1;
}
currentIterationCount = double(aAnimation->mIterationCount);
} else {
if (aAnimation && !aAnimation->IsPaused()) {
aEa->mNeedsRefreshes = true;
}
if (currentIterationCount < 0.0) {
NS_ASSERTION(aAnimation, "Should not run animation that hasn't started yet on the compositor");
if (!aAnimation->FillsBackwards()) {
// No animation data.
return -1;
}
currentIterationCount = 0.0;
} else {
dispatchStartOrIteration = aAnimation && !aAnimation->IsPaused();
}
}
// Set |positionInIteration| to the position from 0% to 100% along
// the keyframes.
NS_ABORT_IF_FALSE(currentIterationCount >= 0.0, "must be positive");
PRUint32 whichIteration = int(currentIterationCount);
if (whichIteration == aIterationCount && whichIteration != 0) {
// When the animation's iteration count is an integer (as it
// normally is), we need to end at 100% of its last iteration
// rather than 0% of the next one (unless it's zero).
--whichIteration;
}
double positionInIteration =
currentIterationCount - double(whichIteration);
bool thisIterationReverse = false;
switch (aDirection) {
case NS_STYLE_ANIMATION_DIRECTION_NORMAL:
thisIterationReverse = false;
break;
case NS_STYLE_ANIMATION_DIRECTION_REVERSE:
thisIterationReverse = true;
break;
case NS_STYLE_ANIMATION_DIRECTION_ALTERNATE:
thisIterationReverse = (whichIteration & 1) == 1;
break;
case NS_STYLE_ANIMATION_DIRECTION_ALTERNATE_REVERSE:
thisIterationReverse = (whichIteration & 1) == 0;
break;
}
if (thisIterationReverse) {
positionInIteration = 1.0 - positionInIteration;
}
// Dispatch 'animationstart' or 'animationiteration' when needed.
if (aAnimation && aIsForElement && dispatchStartOrIteration &&
whichIteration != aAnimation->mLastNotification) {
// Notify 'animationstart' even if a negative delay puts us
// past the first iteration.
// Note that when somebody changes the animation-duration
// dynamically, this will fire an extra iteration event
// immediately in many cases. It's not clear to me if that's the
// right thing to do.
PRUint32 message =
aAnimation->mLastNotification == ElementAnimation::LAST_NOTIFICATION_NONE
? NS_ANIMATION_START : NS_ANIMATION_ITERATION;
// XXXdz: If this is a start, invalidate the frame here once we throttle animations.
aAnimation->mLastNotification = whichIteration;
AnimationEventInfo ei(aEa->mElement, aAnimation->mName, message,
currentTimeDuration);
aEventsToDispatch->AppendElement(ei);
}
return positionInIteration;
}
void
ElementAnimations::EnsureStyleRuleFor(TimeStamp aRefreshTime,
EventArray& aEventsToDispatch)
@ -178,24 +165,98 @@ ElementAnimations::EnsureStyleRuleFor(TimeStamp aRefreshTime,
continue;
}
TimeStamp currentTime;
TimeDuration currentTimeDuration;
if (anim.IsPaused()) {
// FIXME: avoid recalculating every time
currentTime = anim.mPauseStart;
currentTimeDuration = anim.mPauseStart - anim.mStartTime;
} else {
currentTime = aRefreshTime;
currentTimeDuration = aRefreshTime - anim.mStartTime;
}
double positionInIteration =
GetPositionInIteration(anim.mStartTime, currentTime,
anim.mIterationDuration, anim.mIterationCount,
anim.mDirection, IsForElement(),
&anim, this, &aEventsToDispatch);
// Set |currentIterationCount| to the (fractional) number of
// iterations we've completed up to the current position.
double currentIterationCount =
currentTimeDuration / anim.mIterationDuration;
bool dispatchStartOrIteration = false;
if (currentIterationCount >= double(anim.mIterationCount)) {
// Dispatch 'animationend' when needed.
if (IsForElement() &&
anim.mLastNotification !=
ElementAnimation::LAST_NOTIFICATION_END) {
anim.mLastNotification = ElementAnimation::LAST_NOTIFICATION_END;
AnimationEventInfo ei(mElement, anim.mName, NS_ANIMATION_END,
currentTimeDuration);
aEventsToDispatch.AppendElement(ei);
}
// The position is -1 when we don't have fill data for the current time,
// so we shouldn't animate.
if (positionInIteration == -1)
if (!anim.FillsForwards()) {
// No animation data.
continue;
}
currentIterationCount = double(anim.mIterationCount);
} else {
if (!anim.IsPaused()) {
mNeedsRefreshes = true;
}
if (currentIterationCount < 0.0) {
if (!anim.FillsBackwards()) {
// No animation data.
continue;
}
currentIterationCount = 0.0;
} else {
dispatchStartOrIteration = !anim.IsPaused();
}
}
// Set |positionInIteration| to the position from 0% to 100% along
// the keyframes.
NS_ABORT_IF_FALSE(currentIterationCount >= 0.0, "must be positive");
PRUint32 whichIteration = int(currentIterationCount);
if (whichIteration == anim.mIterationCount && whichIteration != 0) {
// When the animation's iteration count is an integer (as it
// normally is), we need to end at 100% of its last iteration
// rather than 0% of the next one (unless it's zero).
--whichIteration;
}
double positionInIteration =
currentIterationCount - double(whichIteration);
bool thisIterationReverse = false;
switch (anim.mDirection) {
case NS_STYLE_ANIMATION_DIRECTION_NORMAL:
thisIterationReverse = false;
break;
case NS_STYLE_ANIMATION_DIRECTION_REVERSE:
thisIterationReverse = true;
break;
case NS_STYLE_ANIMATION_DIRECTION_ALTERNATE:
thisIterationReverse = (whichIteration & 1) == 1;
break;
case NS_STYLE_ANIMATION_DIRECTION_ALTERNATE_REVERSE:
thisIterationReverse = (whichIteration & 1) == 0;
break;
}
if (thisIterationReverse) {
positionInIteration = 1.0 - positionInIteration;
}
// Dispatch 'animationstart' or 'animationiteration' when needed.
if (IsForElement() && dispatchStartOrIteration &&
whichIteration != anim.mLastNotification) {
// Notify 'animationstart' even if a negative delay puts us
// past the first iteration.
// Note that when somebody changes the animation-duration
// dynamically, this will fire an extra iteration event
// immediately in many cases. It's not clear to me if that's the
// right thing to do.
PRUint32 message =
anim.mLastNotification == ElementAnimation::LAST_NOTIFICATION_NONE
? NS_ANIMATION_START : NS_ANIMATION_ITERATION;
anim.mLastNotification = whichIteration;
AnimationEventInfo ei(mElement, anim.mName, message,
currentTimeDuration);
aEventsToDispatch.AppendElement(ei);
}
NS_ABORT_IF_FALSE(0.0 <= positionInIteration &&
positionInIteration <= 1.0,
@ -262,66 +323,6 @@ ElementAnimations::EnsureStyleRuleFor(TimeStamp aRefreshTime,
}
}
static bool
CanPerformAnimationOnCompositor(const ElementAnimation* aAnim,
mozilla::dom::Element* aElement)
{
for (PRUint32 propIdx = 0, propEnd = aAnim->mProperties.Length();
propIdx != propEnd; ++propIdx) {
const AnimationProperty &prop = aAnim->mProperties[propIdx];
if (!mozilla::css::CommonElementAnimationData::
CanAnimatePropertyOnCompositor(aElement,
prop.mProperty)) {
return false;
}
}
return true;
}
bool
ElementAnimation::CanPerformOnCompositor(mozilla::dom::Element* aElement,
TimeStamp aTime) const
{
return CanPerformAnimationOnCompositor(this, aElement) &&
!IsPaused() && aTime > mStartTime &&
(aTime - mStartTime) / mIterationDuration < mIterationCount;
}
bool
ElementAnimations::HasAnimationOfProperty(nsCSSProperty aProperty) const
{
for (PRUint32 animIdx = mAnimations.Length(); animIdx-- != 0; ) {
const ElementAnimation &anim = mAnimations[animIdx];
for (PRUint32 propIdx = 0, propEnd = anim.mProperties.Length();
propIdx != propEnd; ++propIdx) {
const AnimationProperty &prop = anim.mProperties[propIdx];
if (aProperty == prop.mProperty) {
return true;
}
}
}
return false;
}
bool
ElementAnimations::CanPerformOnCompositorThread() const
{
if (mElementProperty != nsGkAtoms::animationsProperty)
return false;
for (PRUint32 animIdx = mAnimations.Length(); animIdx-- != 0; ) {
const ElementAnimation &anim = mAnimations[animIdx];
if (anim.mIterationDuration.ToMilliseconds() <= 0.0) {
// No animation data
continue;
}
if (!CanPerformAnimationOnCompositor(&anim, mElement))
return false;
}
return true;
}
ElementAnimations*
nsAnimationManager::GetElementAnimations(dom::Element *aElement,
nsCSSPseudoElements::Type aPseudoType,
@ -350,6 +351,10 @@ nsAnimationManager::GetElementAnimations(dom::Element *aElement,
if (!ea && aCreateIfNeeded) {
// FIXME: Consider arena-allocating?
ea = new ElementAnimations(aElement, propName, this);
if (!ea) {
NS_WARNING("out of memory");
return nullptr;
}
nsresult rv = aElement->SetProperty(propName, ea,
ElementAnimationsPropertyDtor, nullptr);
if (NS_FAILED(rv)) {
@ -357,9 +362,6 @@ nsAnimationManager::GetElementAnimations(dom::Element *aElement,
delete ea;
return nullptr;
}
if (propName == nsGkAtoms::animationsProperty) {
aElement->SetMayHaveAnimations();
}
AddElementData(ea);
}
@ -461,8 +463,6 @@ nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext,
TimeStamp refreshTime = mPresContext->RefreshDriver()->MostRecentRefresh();
if (ea) {
// XXXdz: Invalidate the frame since the animation changed.
// The cached style rule is invalid.
ea->mStyleRule = nullptr;
ea->mStyleRuleRefreshTime = TimeStamp();

View File

@ -11,10 +11,12 @@
#include "nsDataHashtable.h"
#include "nsGUIEvent.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Preferences.h"
#include "nsThreadUtils.h"
class nsCSSKeyframesRule;
struct AnimationPropertySegment;
struct ElementAnimation;
struct ElementAnimations;
namespace mozilla {
namespace css {
@ -22,7 +24,17 @@ class Declaration;
}
}
struct AnimationEventInfo {
class nsAnimationManager : public mozilla::css::CommonAnimationManager
{
public:
nsAnimationManager(nsPresContext *aPresContext)
: mozilla::css::CommonAnimationManager(aPresContext),
mKeyframesListIsDirty(true)
{
mKeyframesRules.Init(16); // FIXME: make infallible!
}
struct AnimationEventInfo {
nsRefPtr<mozilla::dom::Element> mElement;
nsAnimationEvent mEvent;
@ -42,159 +54,7 @@ struct AnimationEventInfo {
aOther.mEvent.animationName, aOther.mEvent.elapsedTime)
{
}
};
typedef InfallibleTArray<AnimationEventInfo> EventArray;
struct AnimationPropertySegment
{
float mFromKey, mToKey;
nsStyleAnimation::Value mFromValue, mToValue;
mozilla::css::ComputedTimingFunction mTimingFunction;
};
struct AnimationProperty
{
nsCSSProperty mProperty;
InfallibleTArray<AnimationPropertySegment> mSegments;
};
/**
* Data about one animation (i.e., one of the values of
* 'animation-name') running on an element.
*/
struct ElementAnimation
{
ElementAnimation()
: mLastNotification(LAST_NOTIFICATION_NONE)
{
}
nsString mName; // empty string for 'none'
float mIterationCount; // NS_IEEEPositiveInfinity() means infinite
PRUint8 mDirection;
PRUint8 mFillMode;
PRUint8 mPlayState;
bool FillsForwards() const {
return mFillMode == NS_STYLE_ANIMATION_FILL_MODE_BOTH ||
mFillMode == NS_STYLE_ANIMATION_FILL_MODE_FORWARDS;
}
bool FillsBackwards() const {
return mFillMode == NS_STYLE_ANIMATION_FILL_MODE_BOTH ||
mFillMode == NS_STYLE_ANIMATION_FILL_MODE_BACKWARDS;
}
bool IsPaused() const {
return mPlayState == NS_STYLE_ANIMATION_PLAY_STATE_PAUSED;
}
bool CanPerformOnCompositor(mozilla::dom::Element* aElement,
mozilla::TimeStamp aTime) const;
mozilla::TimeStamp mStartTime; // with delay taken into account
mozilla::TimeStamp mPauseStart;
mozilla::TimeDuration mIterationDuration;
enum {
LAST_NOTIFICATION_NONE = PRUint32(-1),
LAST_NOTIFICATION_END = PRUint32(-2)
};
// One of the above constants, or an integer for the iteration
// whose start we last notified on.
PRUint32 mLastNotification;
InfallibleTArray<AnimationProperty> mProperties;
};
/**
* Data about all of the animations running on an element.
*/
struct ElementAnimations : public mozilla::css::CommonElementAnimationData
{
typedef mozilla::TimeStamp TimeStamp;
typedef mozilla::TimeDuration TimeDuration;
ElementAnimations(mozilla::dom::Element *aElement, nsIAtom *aElementProperty,
nsAnimationManager *aAnimationManager);
// This function takes as input the start time, duration, and direction of an
// animation and returns the position in the current iteration. Note that
// this only works when we know that the animation is currently running.
// This way of calling the function can be used from the compositor. Note
// that if the animation has not started yet, has already ended, or is paused,
// it should not be run from the compositor. When this function is called
// from the main thread, we need the actual ElementAnimation* in order to
// get correct animation-fill behavior and to fire animation events.
// This function returns -1 for the position if the animation should not be
// run (because it is not currently active and has no fill behavior.)
static double GetPositionInIteration(TimeStamp aStartTime,
TimeStamp aCurrentTime,
TimeDuration aDuration,
double aIterationCount,
PRUint32 aDirection,
bool IsForElement = true,
ElementAnimation* aAnimation = nullptr,
ElementAnimations* aEa = nullptr,
EventArray* aEventsToDispatch = nullptr);
void EnsureStyleRuleFor(TimeStamp aRefreshTime,
EventArray &aEventsToDispatch);
bool IsForElement() const { // rather than for a pseudo-element
return mElementProperty == nsGkAtoms::animationsProperty;
}
void PostRestyleForAnimation(nsPresContext *aPresContext) {
nsRestyleHint styleHint = IsForElement() ? eRestyle_Self : eRestyle_Subtree;
aPresContext->PresShell()->RestyleForAnimation(mElement, styleHint);
}
// True if this animation can be performed on the compositor thread.
bool CanPerformOnCompositorThread() const;
bool HasAnimationOfProperty(nsCSSProperty aProperty) const;
// This style rule contains the style data for currently animating
// values. It only matches when styling with animation. When we
// style without animation, we need to not use it so that we can
// detect any new changes; if necessary we restyle immediately
// afterwards with animation.
// NOTE: If we don't need to apply any styles, mStyleRule will be
// null, but mStyleRuleRefreshTime will still be valid.
nsRefPtr<mozilla::css::AnimValuesStyleRule> mStyleRule;
// The refresh time associated with mStyleRule.
TimeStamp mStyleRuleRefreshTime;
// False when we know that our current style rule is valid
// indefinitely into the future (because all of our animations are
// either completed or paused). May be invalidated by a style change.
bool mNeedsRefreshes;
InfallibleTArray<ElementAnimation> mAnimations;
};
class nsAnimationManager : public mozilla::css::CommonAnimationManager
{
public:
nsAnimationManager(nsPresContext *aPresContext)
: mozilla::css::CommonAnimationManager(aPresContext)
, mKeyframesListIsDirty(true)
{
mKeyframesRules.Init(16); // FIXME: make infallible!
}
static ElementAnimations* GetAnimationsForCompositor(nsIContent* aContent,
nsCSSProperty aProperty)
{
if (!aContent->MayHaveAnimations())
return nullptr;
ElementAnimations* animations = static_cast<ElementAnimations*>(
aContent->GetProperty(nsGkAtoms::animationsProperty));
if (!animations)
return nullptr;
bool propertyMatches = animations->HasAnimationOfProperty(aProperty);
return (propertyMatches && animations->CanPerformOnCompositorThread()) ?
animations : nullptr;
}
// nsIStyleRuleProcessor (parts)
virtual void RulesMatching(ElementRuleProcessorData* aData);
@ -229,6 +89,8 @@ public:
mKeyframesListIsDirty = true;
}
typedef InfallibleTArray<AnimationEventInfo> EventArray;
/**
* Dispatch any pending events. We accumulate animationend and
* animationiteration events only during refresh driver notifications

View File

@ -1122,8 +1122,8 @@ AddTransformScale(const nsCSSValue &aValue1, double aCoeff1,
aResult.SetFloatValue(result + 1.0f, eCSSUnit_Number);
}
/* static */ already_AddRefed<nsCSSValue::Array>
nsStyleAnimation::AppendTransformFunction(nsCSSKeyword aTransformFunction,
static already_AddRefed<nsCSSValue::Array>
AppendTransformFunction(nsCSSKeyword aTransformFunction,
nsCSSValueList**& aListTail)
{
nsRefPtr<nsCSSValue::Array> arr = AppendFunction(aTransformFunction);
@ -1457,7 +1457,7 @@ AddDifferentTransformLists(const nsCSSValueList* aList1, double aCoeff1,
nsCSSValueList **resultTail = getter_Transfers(result);
nsRefPtr<nsCSSValue::Array> arr;
arr = nsStyleAnimation::AppendTransformFunction(eCSSKeyword_interpolatematrix, resultTail);
arr = AppendTransformFunction(eCSSKeyword_interpolatematrix, resultTail);
// FIXME: We should change the other transform code to also only
// take a single progress value, as having values that don't
@ -1503,7 +1503,7 @@ AddTransformLists(const nsCSSValueList* aList1, double aCoeff1,
tfunc != eCSSKeyword_interpolatematrix &&
tfunc != eCSSKeyword_rotate3d &&
tfunc != eCSSKeyword_perspective) {
arr = nsStyleAnimation::AppendTransformFunction(tfunc, resultTail);
arr = AppendTransformFunction(tfunc, resultTail);
}
switch (tfunc) {

View File

@ -15,10 +15,14 @@
#include "nsCSSProperty.h"
#include "nsCoord.h"
#include "nsColor.h"
#include "nsCSSValue.h"
class nsPresContext;
class nsStyleContext;
class nsCSSValue;
struct nsCSSValueList;
struct nsCSSValuePair;
struct nsCSSValueTriplet;
struct nsCSSValuePairList;
struct nsCSSRect;
class gfx3DMatrix;
@ -202,10 +206,6 @@ public:
const gfx3DMatrix &aMatrix2,
double aProgress);
static already_AddRefed<nsCSSValue::Array>
AppendTransformFunction(nsCSSKeyword aTransformFunction,
nsCSSValueList**& aListTail);
/**
* The types and values for the values that we extract and animate.
*/

View File

@ -39,13 +39,12 @@ static double FlushToZero(double aVal)
return aVal;
}
float
static float
ProcessTranslatePart(const nsCSSValue& aValue,
nsStyleContext* aContext,
nsPresContext* aPresContext,
bool& aCanStoreInRuleTree,
nscoord aSize,
float aAppUnitsPerMatrixUnit)
nscoord aSize, float aAppUnitsPerMatrixUnit)
{
nscoord offset = 0;
float percent = 0.0f;

View File

@ -30,13 +30,6 @@ namespace nsStyleTransformMatrix {
*/
nsCSSKeyword TransformFunctionOf(const nsCSSValue::Array* aData);
float ProcessTranslatePart(const nsCSSValue& aValue,
nsStyleContext* aContext,
nsPresContext* aPresContext,
bool& aCanStoreInRuleTree,
nscoord aSize,
float aAppUnitsPerMatrixUnit);
/**
* Given an nsCSSValueList containing -moz-transform functions,
* returns a matrix containing the value of those functions.

View File

@ -22,8 +22,6 @@
#include "nsEventDispatcher.h"
#include "nsGUIEvent.h"
#include "mozilla/dom/Element.h"
#include "nsIFrame.h"
#include "nsCSSFrameConstructor.h"
using mozilla::TimeStamp;
using mozilla::TimeDuration;
@ -31,12 +29,53 @@ using mozilla::TimeDuration;
namespace dom = mozilla::dom;
namespace css = mozilla::css;
ElementTransitions::ElementTransitions(mozilla::dom::Element *aElement, nsIAtom *aElementProperty,
nsTransitionManager *aTransitionManager)
: CommonElementAnimationData(aElement, aElementProperty,
aTransitionManager)
/*****************************************************************************
* Per-Element data *
*****************************************************************************/
struct ElementPropertyTransition
{
}
nsCSSProperty mProperty;
nsStyleAnimation::Value mStartValue, mEndValue;
TimeStamp mStartTime; // actual start plus transition delay
// data from the relevant nsTransition
TimeDuration mDuration;
css::ComputedTimingFunction mTimingFunction;
// This is the start value to be used for a check for whether a
// transition is being reversed. Normally the same as mStartValue,
// except when this transition started as the reversal of another
// in-progress transition. Needed so we can handle two reverses in a
// row.
nsStyleAnimation::Value mStartForReversingTest;
// Likewise, the portion (in value space) of the "full" reversed
// transition that we're actually covering. For example, if a :hover
// effect has a transition that moves the element 10px to the right
// (by changing 'left' from 0px to 10px), and the mouse moves in to
// the element (starting the transition) but then moves out after the
// transition has advanced 4px, the second transition (from 10px/4px
// to 0px) will have mReversePortion of 0.4. (If the mouse then moves
// in again when the transition is back to 2px, the mReversePortion
// for the third transition (from 0px/2px to 10px) will be 0.8.
double mReversePortion;
// Compute the portion of the *value* space that we should be through
// at the given time. (The input to the transition timing function
// has time units, the output has value units.)
double ValuePortionFor(TimeStamp aRefreshTime) const;
bool IsRemovedSentinel() const
{
return mStartTime.IsNull();
}
void SetRemovedSentinel()
{
// assign the null time stamp
mStartTime = TimeStamp();
}
};
double
ElementPropertyTransition::ValuePortionFor(TimeStamp aRefreshTime) const
@ -66,6 +105,32 @@ ElementPropertyTransition::ValuePortionFor(TimeStamp aRefreshTime) const
return mTimingFunction.GetValue(timePortion);
}
struct ElementTransitions : public mozilla::css::CommonElementAnimationData
{
ElementTransitions(dom::Element *aElement, nsIAtom *aElementProperty,
nsTransitionManager *aTransitionManager)
: CommonElementAnimationData(aElement, aElementProperty,
aTransitionManager)
{
}
void EnsureStyleRuleFor(TimeStamp aRefreshTime);
// Either zero or one for each CSS property:
nsTArray<ElementPropertyTransition> mPropertyTransitions;
// This style rule overrides style data with the currently
// transitioning value for an element that is executing a transition.
// It only matches when styling with animation. When we style without
// animation, we need to not use it so that we can detect any new
// changes; if necessary we restyle immediately afterwards with
// animation.
nsRefPtr<css::AnimValuesStyleRule> mStyleRule;
// The refresh time associated with mStyleRule.
TimeStamp mStyleRuleRefreshTime;
};
static void
ElementTransitionsPropertyDtor(void *aObject,
nsIAtom *aPropertyName,
@ -108,41 +173,6 @@ ElementTransitions::EnsureStyleRuleFor(TimeStamp aRefreshTime)
}
}
bool
ElementPropertyTransition::CanPerformOnCompositor(mozilla::dom::Element* aElement,
TimeStamp aTime) const {
return css::CommonElementAnimationData::
CanAnimatePropertyOnCompositor(aElement, mProperty) && !IsRemovedSentinel() &&
mStartTime < aTime && aTime < mStartTime + mDuration;
}
bool
ElementTransitions::HasTransitionOfProperty(nsCSSProperty aProperty) const
{
for (PRUint32 tranIdx = mPropertyTransitions.Length(); tranIdx-- != 0; ) {
if (aProperty == mPropertyTransitions[tranIdx].mProperty) {
return true;
}
}
return false;
}
bool
ElementTransitions::CanPerformOnCompositorThread() const
{
for (PRUint32 i = 0, i_end = mPropertyTransitions.Length(); i < i_end; ++i) {
const ElementPropertyTransition &pt = mPropertyTransitions[i];
if (pt.IsRemovedSentinel()) {
continue;
}
if (!css::CommonElementAnimationData::CanAnimatePropertyOnCompositor(mElement,
pt.mProperty)) {
return false;
}
}
return true;
}
/*****************************************************************************
* nsTransitionManager *
*****************************************************************************/
@ -197,6 +227,7 @@ nsTransitionManager::StyleContextChanged(dom::Element *aElement,
return nullptr;
}
if (aNewStyleContext->PresContext()->IsProcessingAnimationStyleChange()) {
return nullptr;
}
@ -333,6 +364,10 @@ nsTransitionManager::StyleContextChanged(dom::Element *aElement,
// rule.
nsRefPtr<css::AnimValuesStyleRule> coverRule = new css::AnimValuesStyleRule;
if (!coverRule) {
NS_WARNING("out of memory");
return nullptr;
}
nsTArray<ElementPropertyTransition> &pts = et->mPropertyTransitions;
for (PRUint32 i = 0, i_end = pts.Length(); i < i_end; ++i) {
@ -378,19 +413,9 @@ nsTransitionManager::ConsiderStartingTransition(nsCSSProperty aProperty,
pt.mStartValue) &&
ExtractComputedValueForTransition(aProperty, aNewStyleContext,
pt.mEndValue);
bool haveChange = pt.mStartValue != pt.mEndValue;
bool haveOMTA = false;
if (!aNewStyleContext->GetPseudoType()) {
ElementTransitions* et = nsTransitionManager::GetTransitions(aElement);
if (et) {
haveOMTA = et->CanPerformOnCompositorThread();
}
}
bool shouldAnimate =
haveValues &&
(haveChange || haveOMTA) &&
pt.mStartValue != pt.mEndValue &&
// Check that we can interpolate between these values
// (If this is ever a performance problem, we could add a
// CanInterpolate method, but it seems fine for now.)
@ -491,7 +516,6 @@ nsTransitionManager::ConsiderStartingTransition(nsCSSProperty aProperty,
// reduce positive delays.
if (delay < 0.0f)
delay *= valuePortion;
duration *= valuePortion;
pt.mStartForReversingTest = oldPT.mEndValue;
@ -503,6 +527,7 @@ nsTransitionManager::ConsiderStartingTransition(nsCSSProperty aProperty,
pt.mStartTime = mostRecentRefresh + TimeDuration::FromMilliseconds(delay);
pt.mDuration = TimeDuration::FromMilliseconds(duration);
pt.mTimingFunction.Init(tf);
if (!aElementTransitions) {
aElementTransitions =
GetElementTransitions(aElement, aNewStyleContext->GetPseudoType(),
@ -536,7 +561,6 @@ nsTransitionManager::ConsiderStartingTransition(nsCSSProperty aProperty,
nsCSSPseudoElements::ePseudo_NotPseudoElement ?
eRestyle_Self : eRestyle_Subtree;
presContext->PresShell()->RestyleForAnimation(aElement, hint);
// XXXdz: invalidate the frame here, once animations are throttled.
*aStartedAny = true;
aWhichStarted->AddProperty(aProperty);
@ -570,6 +594,10 @@ nsTransitionManager::GetElementTransitions(dom::Element *aElement,
if (!et && aCreateIfNeeded) {
// FIXME: Consider arena-allocating?
et = new ElementTransitions(aElement, propName, this);
if (!et) {
NS_WARNING("out of memory");
return nullptr;
}
nsresult rv = aElement->SetProperty(propName, et,
ElementTransitionsPropertyDtor, nullptr);
if (NS_FAILED(rv)) {
@ -577,9 +605,6 @@ nsTransitionManager::GetElementTransitions(dom::Element *aElement,
delete et;
return nullptr;
}
if (propName == nsGkAtoms::transitionsProperty) {
aElement->SetMayHaveAnimations();
}
AddElementData(et);
}
@ -733,6 +758,8 @@ nsTransitionManager::WillRefresh(mozilla::TimeStamp aTime)
// completion. See comment below.
et->mPropertyTransitions.RemoveElementAt(i);
} else if (pt.mStartTime + pt.mDuration <= aTime) {
// This transition has completed.
// Fire transitionend events only for transitions on elements
// and not those on pseudo-elements, since we can't target an
// event at pseudo-elements.
@ -766,9 +793,6 @@ nsTransitionManager::WillRefresh(mozilla::TimeStamp aTime)
nsRestyleHint hint = et->mElementProperty == nsGkAtoms::transitionsProperty ?
eRestyle_Self : eRestyle_Subtree;
mPresContext->PresShell()->RestyleForAnimation(et->mElement, hint);
// XXXdz: if we have started a transition since the last tick and are
// performing the transition off the main thread, we need to invalidate
// the frame once we start throttling animation ticks.
if (et->mPropertyTransitions.IsEmpty()) {
et->Destroy();

View File

@ -15,86 +15,7 @@ class nsStyleContext;
class nsPresContext;
class nsCSSPropertySet;
struct nsTransition;
/*****************************************************************************
* Per-Element data *
*****************************************************************************/
struct ElementPropertyTransition
{
ElementPropertyTransition() {}
nsCSSProperty mProperty;
nsStyleAnimation::Value mStartValue, mEndValue;
mozilla::TimeStamp mStartTime; // actual start plus transition delay
// data from the relevant nsTransition
mozilla::TimeDuration mDuration;
mozilla::css::ComputedTimingFunction mTimingFunction;
// This is the start value to be used for a check for whether a
// transition is being reversed. Normally the same as mStartValue,
// except when this transition started as the reversal of another
// in-progress transition. Needed so we can handle two reverses in a
// row.
nsStyleAnimation::Value mStartForReversingTest;
// Likewise, the portion (in value space) of the "full" reversed
// transition that we're actually covering. For example, if a :hover
// effect has a transition that moves the element 10px to the right
// (by changing 'left' from 0px to 10px), and the mouse moves in to
// the element (starting the transition) but then moves out after the
// transition has advanced 4px, the second transition (from 10px/4px
// to 0px) will have mReversePortion of 0.4. (If the mouse then moves
// in again when the transition is back to 2px, the mReversePortion
// for the third transition (from 0px/2px to 10px) will be 0.8.
double mReversePortion;
// Compute the portion of the *value* space that we should be through
// at the given time. (The input to the transition timing function
// has time units, the output has value units.)
double ValuePortionFor(mozilla::TimeStamp aRefreshTime) const;
bool IsRemovedSentinel() const
{
return mStartTime.IsNull();
}
void SetRemovedSentinel()
{
// assign the null time stamp
mStartTime = mozilla::TimeStamp();
}
bool CanPerformOnCompositor(mozilla::dom::Element* aElement,
mozilla::TimeStamp aTime) const;
};
struct ElementTransitions : public mozilla::css::CommonElementAnimationData
{
ElementTransitions(mozilla::dom::Element *aElement, nsIAtom *aElementProperty,
nsTransitionManager *aTransitionManager);
void EnsureStyleRuleFor(mozilla::TimeStamp aRefreshTime);
bool HasTransitionOfProperty(nsCSSProperty aProperty) const;
// True if this animation can be performed on the compositor thread.
bool CanPerformOnCompositorThread() const;
// Either zero or one for each CSS property:
nsTArray<ElementPropertyTransition> mPropertyTransitions;
// This style rule overrides style data with the currently
// transitioning value for an element that is executing a transition.
// It only matches when styling with animation. When we style without
// animation, we need to not use it so that we can detect any new
// changes; if necessary we restyle immediately afterwards with
// animation.
nsRefPtr<mozilla::css::AnimValuesStyleRule> mStyleRule;
// The refresh time associated with mStyleRule.
mozilla::TimeStamp mStyleRuleRefreshTime;
};
struct ElementTransitions;
class nsTransitionManager : public mozilla::css::CommonAnimationManager
{
@ -104,26 +25,6 @@ public:
{
}
static ElementTransitions* GetTransitions(nsIContent* aContent) {
return static_cast<ElementTransitions*>
(aContent->GetProperty(nsGkAtoms::transitionsProperty));
}
static ElementTransitions*
GetTransitionsForCompositor(nsIContent* aContent,
nsCSSProperty aProperty)
{
if (!aContent->MayHaveAnimations())
return nullptr;
ElementTransitions* transitions = GetTransitions(aContent);
if (!transitions ||
!transitions->HasTransitionOfProperty(aProperty) ||
!transitions->CanPerformOnCompositorThread()) {
return nullptr;
}
return transitions;
}
/**
* StyleContextChanged
*

View File

@ -3512,10 +3512,6 @@ pref("layers.acceleration.force-enabled", false);
pref("layers.acceleration.draw-fps", false);
// Whether to animate simple opacity and transforms on the compositor
pref("layers.offmainthreadcomposition.animate-opacity", false);
pref("layers.offmainthreadcomposition.animate-transform", false);
#ifdef MOZ_X11
#ifdef MOZ_WIDGET_GTK2
pref("gfx.xrender.enabled",true);

View File

@ -0,0 +1,63 @@
#!/bin/bash
# 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/.
PYTHON=$1
if [ -z "${PYTHON}" ]
then
echo "No python found"
exit 1
fi
if [ -z "${MARIONETTE_HOME}" ]
then
echo "No MARIONETTE_HOME found"
exit 1
fi
if [ -z "${XPCSHELLTEST_HOME}" ]
then
echo "No XPCSHELLTEST_HOME found"
exit 1
fi
echo "Detected Marionette home in $MARIONETTE_HOME"
# If a GECKO_OBJDIR environemnt variable exists, we will create the Python
# virtual envirnoment there. Otherwise we create it in the PWD.
VENV_DIR="marionette_venv"
if [ -z $GECKO_OBJDIR ]
then
VENV_DIR="$MARIONETTE_HOME/$VENV_DIR"
else
VENV_DIR="$GECKO_OBJDIR/$VENV_DIR"
fi
# Check if environment exists, if not, create a virtualenv:
if [ -d $VENV_DIR ]
then
echo "Using virtual environment in $VENV_DIR"
cd $VENV_DIR
. bin/activate
else
echo "Creating a virtual environment in $VENV_DIR"
curl https://raw.github.com/pypa/virtualenv/develop/virtualenv.py | ${PYTHON} - $VENV_DIR
cd $VENV_DIR
. bin/activate
# set up mozbase
git clone git://github.com/mozilla/mozbase.git
cd mozbase
python setup_development.py
fi
# update the marionette_client
cd $MARIONETTE_HOME
python setup.py develop
cd $XPCSHELLTEST_HOME
# pop off the python parameter
shift
python runtestsb2g.py $@

View File

@ -101,6 +101,11 @@ class XPCShellRemote(xpcshell.XPCShellTests, object):
self.device.pushFile(self.options.localAPK, self.remoteBinDir)
self.pushLibs()
self.device.chmodDir(self.remoteBinDir)
def pushLibs(self):
if self.options.localAPK:
localLib = os.path.join(self.options.objdir, "dist/fennec")
if not os.path.exists(localLib):
@ -126,7 +131,6 @@ class XPCShellRemote(xpcshell.XPCShellTests, object):
if (file.endswith(".so")):
self.device.pushFile(os.path.join(root, file), self.remoteBinDir)
self.device.chmodDir(self.remoteBinDir)
def setupTestDir(self):
xpcDir = os.path.join(self.options.objdir, "_tests/xpcshell")
@ -197,10 +201,13 @@ class XPCShellRemote(xpcshell.XPCShellTests, object):
self.log.info("TEST-INFO | profile dir is %s" % self.profileDir)
return self.profileDir
def setLD_LIBRARY_PATH(self, env):
env["LD_LIBRARY_PATH"]=self.remoteBinDir
def launchProcess(self, cmd, stdout, stderr, env, cwd):
cmd[0] = self.remoteJoin(self.remoteBinDir, "xpcshell")
env = dict()
env["LD_LIBRARY_PATH"]=self.remoteBinDir
env = {}
self.setLD_LIBRARY_PATH(env)
env["MOZ_LINKER_CACHE"]=self.remoteBinDir
if self.options.localAPK and self.appRoot:
env["GRE_HOME"]=self.appRoot

View File

@ -29,8 +29,21 @@ class B2GXPCShellRemote(XPCShellRemote):
XPCShellRemote.setupUtilities(self)
def clean(self):
print >>sys.stderr, "\nCleaning files from previous run.."
self.device.removeDir(DEVICE_TEST_ROOT)
# Overridden
def pushLibs(self):
if not self.options.use_device_libs:
XPCShellRemote.pushLibs(self)
# Overridden
def setLD_LIBRARY_PATH(self, env):
if self.options.use_device_libs:
env['LD_LIBRARY_PATH'] = '/system/b2g'
else:
XPCShellRemote.setLD_LIBRARY_PATH(self, env)
# Overridden
# This returns 1 even when tests pass - this is why it's switched to 0
# https://bugzilla.mozilla.org/show_bug.cgi?id=773703
@ -52,10 +65,11 @@ class B2GOptions(RemoteXPCShellOptions):
help="Path to B2G repo or qemu dir")
defaults['b2g_path'] = None
self.add_option('--marionette', action='store',
type='string', dest='marionette',
help="host:port to use when connecting to Marionette")
defaults['marionette'] = None
self.add_option('--emupath', action='store',
type='string', dest='emu_path',
help="Path to emulator folder (if different "
"from b2gpath")
defaults['emu_path'] = None
self.add_option('--emulator', action='store',
type='string', dest='emulator',
@ -72,6 +86,16 @@ class B2GOptions(RemoteXPCShellOptions):
help="Path to adb")
defaults['adb_path'] = 'adb'
self.add_option('--address', action='store',
type='string', dest='address',
help="host:port of running Gecko instance to connect to")
defaults['address'] = None
self.add_option('--use-device-libs', action='store_true',
dest='use_device_libs',
help="Don't push .so's")
defaults['use_device_libs'] = False
defaults['dm_trans'] = 'adb'
defaults['debugger'] = None
defaults['debuggerArgs'] = None
@ -97,11 +121,14 @@ def main():
if options.no_window:
kwargs['noWindow'] = True
if options.b2g_path:
kwargs['homedir'] = options.b2g_path
if options.marionette:
host, port = options.marionette.split(':')
kwargs['homedir'] = options.emu_path or options.b2g_path
if options.address:
host, port = options.address.split(':')
kwargs['host'] = host
kwargs['port'] = int(port)
kwargs['baseurl'] = 'http://%s:%d/' % (host, int(port))
if options.emulator:
kwargs['connectToRunningEmulator'] = True
marionette = Marionette(**kwargs)
# Create the DeviceManager instance

View File

@ -13,10 +13,6 @@
#include "nsDebug.h"
#include "prlong.h"
namespace IPC {
template <typename T> struct ParamTraits;
}
namespace mozilla {
class TimeStamp;
@ -99,9 +95,6 @@ public:
bool operator>(const TimeDuration& aOther) const {
return mValue > aOther.mValue;
}
bool operator==(const TimeDuration& aOther) const {
return mValue == aOther.mValue;
}
// Return a best guess at the system's current timing resolution,
// which might be variable. TimeDurations below this order of
@ -118,7 +111,6 @@ public:
private:
friend class TimeStamp;
friend struct IPC::ParamTraits<mozilla::TimeDuration>;
static TimeDuration FromTicks(PRInt64 aTicks) {
TimeDuration t;
@ -273,8 +265,6 @@ public:
static NS_HIDDEN_(void) Shutdown();
private:
friend struct IPC::ParamTraits<mozilla::TimeStamp>;
TimeStamp(PRUint64 aValue) : mValue(aValue) {}
/**