зеркало из https://github.com/mozilla/gecko-dev.git
Bug 706179: Add support for animations to the Layers API r=roc, dbaron, cjones
This commit is contained in:
Родитель
a152b2b167
Коммит
687786c2e9
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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()
|
||||
{}
|
||||
|
||||
|
|
|
@ -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 :
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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) {}
|
||||
|
||||
/**
|
||||
|
|
Загрузка…
Ссылка в новой задаче