Bug 706179: Add support for animations to the Layers API r=roc, dbaron, cjones

This commit is contained in:
David Zbarsky 2012-07-27 13:23:44 -07:00
parent 3d6d6246c4
commit 12752872fe
12 changed files with 663 additions and 54 deletions

View File

@ -17,6 +17,7 @@
#include "nsPrintfCString.h"
#include "mozilla/Util.h"
#include "LayerSorter.h"
#include "AnimationCommon.h"
using namespace mozilla::layers;
using namespace mozilla::gfx;
@ -220,6 +221,245 @@ LayerManager::CreateAsynchronousImageContainer()
//--------------------------------------------------
// Layer
Layer::Layer(LayerManager* aManager, void* aImplData) :
mManager(aManager),
mParent(nsnull),
mNextSibling(nsnull),
mPrevSibling(nsnull),
mImplData(aImplData),
mMaskLayer(nsnull),
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 = new css::ComputedTimingFunction();
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;
}
}
functions->AppendElement(ctf);
}
// 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()
{
@ -304,7 +544,7 @@ Layer::SnapTransform(const gfx3DMatrix& aTransform,
return result;
}
nsIntRect
nsIntRect
Layer::CalculateScissorRect(const nsIntRect& aCurrentScissorRect,
const gfxMatrix* aWorldTransform)
{
@ -361,21 +601,34 @@ Layer::CalculateScissorRect(const nsIntRect& aCurrentScissorRect,
return currentClip.Intersect(scissor);
}
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->GetShadowTransform();
return mTransform;
return shadow->GetShadowOpacity();
return mOpacity;
}
float
Layer::GetEffectiveOpacity()
{
float opacity = GetOpacity();
float opacity = GetLocalOpacity();
for (ContainerLayer* c = GetParent(); c && !c->UseIntermediateSurface();
c = c->GetParent()) {
opacity *= c->GetOpacity();
opacity *= c->GetLocalOpacity();
}
return opacity;
}
@ -790,7 +1043,7 @@ void
LayerManager::Dump(FILE* aFile, const char* aPrefix)
{
FILE* file = FILEOrDefault(aFile);
fprintf(file, "<ul><li><a ");
#ifdef MOZ_DUMP_PAINTING
WriteSnapshotLinkToDumpFile(this, file);
@ -807,7 +1060,7 @@ LayerManager::Dump(FILE* aFile, const char* aPrefix)
fprintf(file, "%s(null)</li></ul>", pfx.get());
return;
}
fprintf(file, "<ul>");
GetRoot()->Dump(file, pfx.get());
fprintf(file, "</ul></li></ul>");
@ -941,5 +1194,5 @@ LayerManager::PrintInfo(nsACString& aTo, const char* aPrefix)
PRLogModuleInfo* LayerManager::sLog;
} // namespace layers
} // namespace layers
} // namespace mozilla

View File

@ -18,6 +18,7 @@
#include "gfxPattern.h"
#include "nsTArray.h"
#include "nsThreadUtils.h"
#include "nsStyleAnimation.h"
#include "LayersBackend.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/TimeStamp.h"
@ -43,8 +44,14 @@ namespace gl {
class GLContext;
}
namespace css {
class ComputedTimingFunction;
}
namespace layers {
class Animation;
class CommonLayerAttributes;
class Layer;
class ThebesLayer;
class ContainerLayer;
@ -530,6 +537,13 @@ 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
@ -551,7 +565,7 @@ public:
TYPE_THEBES
};
virtual ~Layer() {}
virtual ~Layer();
/**
* Returns the LayerManager this Layer belongs to. Note that the layer
@ -708,6 +722,13 @@ public:
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
@ -716,6 +737,14 @@ 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
@ -736,10 +765,13 @@ public:
virtual Layer* GetFirstChild() { return nsnull; }
virtual Layer* GetLastChild() { return nsnull; }
const gfx3DMatrix& GetTransform() { return mTransform; }
float GetXScale() { return mXScale; }
float GetYScale() { return mYScale; }
bool GetIsFixedPosition() { return mIsFixedPosition; }
gfxPoint GetFixedPositionAnchor() { return mAnchor; }
Layer* GetMaskLayer() { return mMaskLayer; }
AnimationArray& GetAnimations() { return mAnimations; }
InfallibleTArray<AnimData>& GetAnimationData() { return mAnimationData; }
/**
* DRAWING PHASE ONLY
*
@ -940,20 +972,7 @@ public:
#endif
protected:
Layer(LayerManager* aManager, void* aImplData) :
mManager(aManager),
mParent(nsnull),
mNextSibling(nsnull),
mPrevSibling(nsnull),
mImplData(aImplData),
mMaskLayer(nsnull),
mOpacity(1.0),
mContentFlags(0),
mUseClipRect(false),
mUseTileSourceRect(false),
mIsFixedPosition(false),
mDebugColorIndex(0)
{}
Layer(LayerManager* aManager, void* aImplData);
void Mutated() { mManager->Mutated(this); }
@ -968,7 +987,13 @@ protected:
* Returns the local transform for this layer: either mTransform or,
* for shadow layers, GetShadowTransform()
*/
const gfx3DMatrix& GetLocalTransform();
const gfx3DMatrix GetLocalTransform();
/**
* Returns the local opacity for this layer: either mOpacity or,
* for shadow layers, GetShadowOpacity()
*/
const float GetLocalOpacity();
/**
* Computes a tweaked version of aTransform that snaps a point or a rectangle
@ -994,7 +1019,11 @@ 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

@ -21,6 +21,15 @@
#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;
@ -431,15 +440,15 @@ CompositorParent::Composite()
return;
}
Layer* aLayer = mLayerManager->GetRoot();
AutoResolveRefLayers resolve(aLayer);
Layer* layer = mLayerManager->GetRoot();
AutoResolveRefLayers resolve(layer);
bool requestNextFrame = TransformShadowTree(mLastCompose);
if (requestNextFrame) {
ScheduleComposition();
}
RenderTraceLayers(aLayer, "0000");
RenderTraceLayers(layer, "0000");
if (LAYERS_OPENGL == mLayerManager->GetBackendType() &&
!mTargetConfig.naturalBounds().IsEmpty()) {
@ -539,6 +548,7 @@ SetShadowProperties(Layer* aLayer)
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()) {
@ -546,6 +556,114 @@ 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(nsnull, 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,
@ -591,6 +709,10 @@ 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->GetTransform();
@ -686,7 +808,6 @@ 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.
*/
sync protocol PLayer {
async protocol PLayer {
manager PLayers;
/**
@ -32,7 +32,7 @@ sync protocol PLayer {
* being deleted "soon" (usually immediately).
*/
parent:
__delete__();
async __delete__();
};
} // layers

View File

@ -14,6 +14,14 @@ 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
@ -42,7 +50,7 @@ struct OpCreateRefLayer { PLayer layer; };
struct ThebesBuffer {
SurfaceDescriptor buffer;
nsIntRect rect;
nsIntPoint rotation;
nsIntPoint rotation;
};
union OptionalThebesBuffer { ThebesBuffer; null_t; };
@ -51,24 +59,129 @@ union CanvasSurface {
null_t;
};
// Change a layer's attributes
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;
};
struct CommonLayerAttributes {
nsIntRegion visibleRegion;
gfx3DMatrix transform;
TransformMatrix transform;
float xScale;
float yScale;
PRUint32 contentFlags;
float opacity;
Opacity 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 { gfxRGBA color; };
struct ColorLayerAttributes { Color color; };
struct CanvasLayerAttributes { GraphicsFilterType filter; };
struct RefLayerAttributes { int64_t id; };
struct ImageLayerAttributes {

View File

@ -300,6 +300,8 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies)
CommonLayerAttributes& common = attrs.common();
common.visibleRegion() = mutant->GetVisibleRegion();
common.transform() = mutant->GetTransform();
common.xScale() = mutant->GetXScale();
common.yScale() = mutant->GetYScale();
common.contentFlags() = mutant->GetContentFlags();
common.opacity() = mutant->GetOpacity();
common.useClipRect() = !!mutant->GetClipRect();
@ -313,6 +315,7 @@ 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,6 +524,11 @@ public:
mShadowVisibleRegion = aRegion;
}
void SetShadowOpacity(float aOpacity)
{
mShadowOpacity = aOpacity;
}
void SetShadowClipRect(const nsIntRect* aRect)
{
mUseShadowClipRect = aRect != nsnull;
@ -538,6 +543,7 @@ public:
}
// These getters can be used anytime.
float GetShadowOpacity() { return mShadowOpacity; }
const nsIntRect* GetShadowClipRect() { return mUseShadowClipRect ? &mShadowClipRect : nsnull; }
const nsIntRegion& GetShadowVisibleRegion() { return mShadowVisibleRegion; }
const gfx3DMatrix& GetShadowTransform() { return mShadowTransform; }
@ -547,6 +553,7 @@ public:
protected:
ShadowLayer()
: mAllocator(nsnull)
, mShadowOpacity(1.0)
, mUseShadowClipRect(false)
{}
@ -554,6 +561,7 @@ protected:
nsIntRegion mShadowVisibleRegion;
gfx3DMatrix mShadowTransform;
nsIntRect mShadowClipRect;
float mShadowOpacity;
bool mUseShadowClipRect;
};

View File

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

View File

@ -110,7 +110,7 @@ CanvasLayerOGL::Initialize(const Data& aData)
}
mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
// Check the maximum texture size supported by GL. glTexImage2D supports
// images of up to 2 + GL_MAX_TEXTURE_SIZE
GLint texSize = gl()->GetMaxTextureSize();
@ -119,7 +119,7 @@ CanvasLayerOGL::Initialize(const Data& aData)
MakeTextureIfNeeded(gl(), mTexture);
// This should only ever occur with 2d canvas, WebGL can't already have a texture
// of this size can it?
NS_ABORT_IF_FALSE(mCanvasSurface || mDrawTarget,
NS_ABORT_IF_FALSE(mCanvasSurface || mDrawTarget,
"Invalid texture size when WebGL surface already exists at that size?");
}
}
@ -291,7 +291,7 @@ ShadowCanvasLayerOGL::ShadowCanvasLayerOGL(LayerManagerOGL* aManager)
{
mImplData = static_cast<LayerOGL*>(this);
}
ShadowCanvasLayerOGL::~ShadowCanvasLayerOGL()
{}

View File

@ -199,6 +199,12 @@ 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,6 +9,7 @@
#include "chrome/common/ipc_message_utils.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Util.h"
#include "mozilla/gfx/2D.h"
@ -439,11 +440,28 @@ struct ParamTraits<gfxPoint>
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
{
if (ReadParam(aMsg, aIter, &aResult->x) &&
ReadParam(aMsg, aIter, &aResult->y))
return true;
return (ReadParam(aMsg, aIter, &aResult->x) &&
ReadParam(aMsg, aIter, &aResult->y));
}
};
return false;
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));
}
};
@ -577,11 +595,29 @@ 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>
{
typedef nsIntPoint paramType;
static void Write(Message* msg, const paramType& param)
{
WriteParam(msg, param.x);
@ -599,7 +635,7 @@ template<>
struct ParamTraits<nsIntRect>
{
typedef nsIntRect paramType;
static void Write(Message* msg, const paramType& param)
{
WriteParam(msg, param.x);
@ -648,11 +684,11 @@ template<>
struct ParamTraits<nsIntSize>
{
typedef nsIntSize paramType;
static void Write(Message* msg, const paramType& param)
{
WriteParam(msg, param.width);
WriteParam(msg, param.height);
WriteParam(msg, param.height);
}
static bool Read(const Message* msg, void** iter, paramType* result)
@ -666,11 +702,11 @@ template<>
struct ParamTraits<mozilla::gfx::Size>
{
typedef mozilla::gfx::Size paramType;
static void Write(Message* msg, const paramType& param)
{
WriteParam(msg, param.width);
WriteParam(msg, param.height);
WriteParam(msg, param.height);
}
static bool Read(const Message* msg, void** iter, paramType* result)
@ -706,7 +742,7 @@ template<>
struct ParamTraits<nsRect>
{
typedef nsRect paramType;
static void Write(Message* msg, const paramType& param)
{
WriteParam(msg, param.x);
@ -766,6 +802,34 @@ 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

@ -13,6 +13,10 @@
#include "nsDebug.h"
#include "prlong.h"
namespace IPC {
template <typename T> struct ParamTraits;
}
namespace mozilla {
class TimeStamp;
@ -95,6 +99,9 @@ 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
@ -111,6 +118,7 @@ public:
private:
friend class TimeStamp;
friend struct IPC::ParamTraits<mozilla::TimeDuration>;
static TimeDuration FromTicks(PRInt64 aTicks) {
TimeDuration t;
@ -265,6 +273,8 @@ public:
static NS_HIDDEN_(void) Shutdown();
private:
friend struct IPC::ParamTraits<mozilla::TimeStamp>;
TimeStamp(PRUint64 aValue) : mValue(aValue) {}
/**