Bug 952977: More gfx::Matrix cleanup in FrameLayerBuilder r=nical

This commit is contained in:
David Zbarsky 2014-07-29 19:18:52 -04:00
Родитель ecf49e22a2
Коммит 6cf4dc1afd
4 изменённых файлов: 62 добавлений и 18 удалений

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

@ -224,6 +224,16 @@ public:
!FuzzyEqual(_12, 0.0) || !FuzzyEqual(_21, 0.0);
}
/**
* Returns true if the matrix has any transform other
* than a translation or a -1 y scale (y axis flip)
*/
bool HasNonTranslationOrFlip() const {
return !FuzzyEqual(_11, 1.0) ||
(!FuzzyEqual(_22, 1.0) && !FuzzyEqual(_22, -1.0)) ||
!FuzzyEqual(_21, 0.0) || !FuzzyEqual(_12, 0.0);
}
/* Returns true if the matrix is an identity matrix.
*/
bool IsIdentity() const
@ -603,6 +613,36 @@ public:
gfx::FuzzyEqual(_43, o._43) && gfx::FuzzyEqual(_44, o._44);
}
bool IsBackfaceVisible() const
{
// Inverse()._33 < 0;
Float det = Determinant();
Float __33 = _12*_24*_41 - _14*_22*_41 +
_14*_21*_42 - _11*_24*_42 -
_12*_21*_44 + _11*_22*_44;
return (__33 * det) < 0;
}
void NudgeToIntegersFixedEpsilon()
{
static const float error = 1e-5;
NudgeToInteger(&_11, error);
NudgeToInteger(&_12, error);
NudgeToInteger(&_13, error);
NudgeToInteger(&_14, error);
NudgeToInteger(&_21, error);
NudgeToInteger(&_22, error);
NudgeToInteger(&_23, error);
NudgeToInteger(&_24, error);
NudgeToInteger(&_31, error);
NudgeToInteger(&_32, error);
NudgeToInteger(&_33, error);
NudgeToInteger(&_34, error);
NudgeToInteger(&_41, error);
NudgeToInteger(&_42, error);
NudgeToInteger(&_43, error);
NudgeToInteger(&_44, error);
}
// Set all the members of the matrix to NaN
void SetNAN();

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

@ -3564,7 +3564,7 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
nsDisplayListBuilder* aDisplayListBuilder,
nsIFrame* aContainerFrame,
const nsRect& aVisibleRect,
const gfx3DMatrix* aTransform,
const Matrix4x4* aTransform,
const ContainerLayerParameters& aIncomingScale,
ContainerLayer* aLayer,
LayerState aState,
@ -3572,8 +3572,8 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
{
nsIntPoint offset;
gfx3DMatrix transform =
gfx3DMatrix::ScalingMatrix(aIncomingScale.mXScale, aIncomingScale.mYScale, 1.0);
Matrix4x4 transform =
Matrix4x4().Scale(aIncomingScale.mXScale, aIncomingScale.mYScale, 1.0);
if (aTransform) {
// aTransform is applied first, then the scale is applied to the result
transform = (*aTransform)*transform;
@ -3584,7 +3584,7 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
// to depend on the scroll position.
transform.NudgeToIntegersFixedEpsilon();
}
gfxMatrix transform2d;
Matrix transform2d;
if (aContainerFrame &&
(aState == LAYER_INACTIVE || aState == LAYER_SVG_EFFECTS) &&
(!aTransform || (aTransform->Is2D(&transform2d) &&
@ -3602,7 +3602,7 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
NS_lround(NSAppUnitsToDoublePixels(appUnitOffset.x, appUnitsPerDevPixel)*aIncomingScale.mXScale),
NS_lround(NSAppUnitsToDoublePixels(appUnitOffset.y, appUnitsPerDevPixel)*aIncomingScale.mYScale));
}
transform = transform * gfx3DMatrix::Translation(offset.x + aIncomingScale.mOffset.x, offset.y + aIncomingScale.mOffset.y, 0);
transform = transform * Matrix4x4().Translate(offset.x + aIncomingScale.mOffset.x, offset.y + aIncomingScale.mOffset.y, 0);
if (transform.IsSingular()) {
return false;
@ -3620,14 +3620,14 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
scale = nsLayoutUtils::ComputeSuitableScaleForAnimation(aContainerFrame->GetContent());
} else {
// Scale factors are normalized to a power of 2 to reduce the number of resolution changes
scale = RoundToFloatPrecision(transform2d.ScaleFactors(true));
scale = RoundToFloatPrecision(ThebesMatrix(transform2d).ScaleFactors(true));
// For frames with a changing transform that's not just a translation,
// round scale factors up to nearest power-of-2 boundary so that we don't
// keep having to redraw the content as it scales up and down. Rounding up to nearest
// power-of-2 boundary ensures we never scale up, only down --- avoiding
// jaggies. It also ensures we never scale down by more than a factor of 2,
// avoiding bad downscaling quality.
gfxMatrix frameTransform;
Matrix frameTransform;
if (ActiveLayerTracker::IsStyleAnimated(aContainerFrame, eCSSProperty_transform) &&
aTransform &&
(!aTransform->Is2D(&frameTransform) || frameTransform.HasNonTranslationOrFlip())) {
@ -3665,7 +3665,7 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
}
// Store the inverse of our resolution-scale on the layer
aLayer->SetBaseTransform(ToMatrix4x4(transform));
aLayer->SetBaseTransform(transform);
aLayer->SetPreScale(1.0f/float(scale.width),
1.0f/float(scale.height));
aLayer->SetInheritedScale(aIncomingScale.mXScale,
@ -3728,7 +3728,7 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
nsDisplayItem* aContainerItem,
nsDisplayList* aChildren,
const ContainerLayerParameters& aParameters,
const gfx3DMatrix* aTransform,
const Matrix4x4* aTransform,
uint32_t aFlags)
{
uint32_t containerDisplayItemKey =

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

@ -29,6 +29,10 @@ class BasicLayerManager;
class ThebesLayer;
}
namespace gfx {
class Matrix4x4;
}
class FrameLayerBuilder;
class LayerManagerData;
class ThebesLayerData;
@ -229,7 +233,7 @@ public:
nsDisplayItem* aContainerItem,
nsDisplayList* aChildren,
const ContainerLayerParameters& aContainerParameters,
const gfx3DMatrix* aTransform,
const gfx::Matrix4x4* aTransform,
uint32_t aFlags = 0);
/**

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

@ -4747,7 +4747,7 @@ nsDisplayTransform::ShouldPrerenderTransformedContent(nsDisplayListBuilder* aBui
}
/* If the matrix is singular, or a hidden backface is shown, the frame won't be visible or hit. */
static bool IsFrameVisible(nsIFrame* aFrame, const gfx3DMatrix& aMatrix)
static bool IsFrameVisible(nsIFrame* aFrame, const Matrix4x4& aMatrix)
{
if (aMatrix.IsSingular()) {
return false;
@ -4798,7 +4798,7 @@ already_AddRefed<Layer> nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBu
LayerManager *aManager,
const ContainerLayerParameters& aContainerParameters)
{
const gfx3DMatrix& newTransformMatrix = To3DMatrix(GetTransform());
const Matrix4x4& newTransformMatrix = GetTransform();
if (mFrame->StyleDisplay()->mBackfaceVisibility == NS_STYLE_BACKFACE_VISIBILITY_HIDDEN &&
newTransformMatrix.IsBackfaceVisible()) {
@ -4912,7 +4912,7 @@ void nsDisplayTransform::HitTest(nsDisplayListBuilder *aBuilder,
*/
// GetTransform always operates in dev pixels.
float factor = mFrame->PresContext()->AppUnitsPerDevPixel();
gfx3DMatrix matrix = To3DMatrix(GetTransform());
Matrix4x4 matrix = GetTransform();
if (!IsFrameVisible(mFrame, matrix)) {
return;
@ -4927,7 +4927,7 @@ void nsDisplayTransform::HitTest(nsDisplayListBuilder *aBuilder,
nsRect resultingRect;
if (aRect.width == 1 && aRect.height == 1) {
// Magic width/height indicating we're hit testing a point, not a rect
gfxPointH3D point = matrix.Inverse().ProjectPoint(gfxPoint(NSAppUnitsToFloatPixels(aRect.x, factor),
gfxPointH3D point = To3DMatrix(matrix).Inverse().ProjectPoint(gfxPoint(NSAppUnitsToFloatPixels(aRect.x, factor),
NSAppUnitsToFloatPixels(aRect.y, factor)));
if (!point.HasPositiveWCoord()) {
return;
@ -4945,7 +4945,7 @@ void nsDisplayTransform::HitTest(nsDisplayListBuilder *aBuilder,
NSAppUnitsToFloatPixels(aRect.width, factor),
NSAppUnitsToFloatPixels(aRect.height, factor));
gfxRect rect = matrix.Inverse().ProjectRectBounds(originalRect);
gfxRect rect = To3DMatrix(matrix).Inverse().ProjectRectBounds(originalRect);
bool snap;
nsRect childBounds = mStoredList.GetBounds(aBuilder, &snap);
@ -4988,17 +4988,17 @@ nsDisplayTransform::GetHitDepthAtPoint(nsDisplayListBuilder* aBuilder, const nsP
{
// GetTransform always operates in dev pixels.
float factor = mFrame->PresContext()->AppUnitsPerDevPixel();
gfx3DMatrix matrix = To3DMatrix(GetTransform());
Matrix4x4 matrix = GetTransform();
NS_ASSERTION(IsFrameVisible(mFrame, matrix), "We can't have hit a frame that isn't visible!");
gfxPointH3D point = matrix.Inverse().ProjectPoint(gfxPoint(NSAppUnitsToFloatPixels(aPoint.x, factor),
gfxPointH3D point = To3DMatrix(matrix).Inverse().ProjectPoint(gfxPoint(NSAppUnitsToFloatPixels(aPoint.x, factor),
NSAppUnitsToFloatPixels(aPoint.y, factor)));
NS_ASSERTION(point.HasPositiveWCoord(), "Why are we trying to get the depth for a point we didn't hit?");
gfxPoint point2d = point.As2DPoint();
gfxPoint3D transformed = matrix.Transform3D(gfxPoint3D(point2d.x, point2d.y, 0));
Point3D transformed = matrix * Point3D(point2d.x, point2d.y, 0);
return transformed.z;
}