summaryrefslogtreecommitdiffstats
path: root/cc/layer_sorter_unittest.cc
diff options
context:
space:
mode:
authorenne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-12 19:40:56 +0000
committerenne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-12 19:40:56 +0000
commitc79f147c0474a311a83829a44b55aaffa42c6237 (patch)
tree8bb41fcb74068042828da31c279b0d53dd0844fa /cc/layer_sorter_unittest.cc
parente62f2909e0aabf37131a65c7e50e85c1f07473f8 (diff)
downloadchromium_src-c79f147c0474a311a83829a44b55aaffa42c6237.zip
chromium_src-c79f147c0474a311a83829a44b55aaffa42c6237.tar.gz
chromium_src-c79f147c0474a311a83829a44b55aaffa42c6237.tar.bz2
[cc] Change cc_tests.gyp filenames to Chromium style
BUG=155413 Review URL: https://codereview.chromium.org/11108020 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@161642 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc/layer_sorter_unittest.cc')
-rw-r--r--cc/layer_sorter_unittest.cc267
1 files changed, 267 insertions, 0 deletions
diff --git a/cc/layer_sorter_unittest.cc b/cc/layer_sorter_unittest.cc
new file mode 100644
index 0000000..e2bb912
--- /dev/null
+++ b/cc/layer_sorter_unittest.cc
@@ -0,0 +1,267 @@
+// Copyright 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+
+#include "CCLayerSorter.h"
+
+#include "CCLayerImpl.h"
+#include "CCMathUtil.h"
+#include "CCSingleThreadProxy.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include <public/WebTransformationMatrix.h>
+
+using namespace cc;
+using WebKit::WebTransformationMatrix;
+
+namespace {
+
+// Note: In the following overlap tests, the "camera" is looking down the negative Z axis,
+// meaning that layers with smaller z values (more negative) are further from the camera
+// and therefore must be drawn before layers with higher z values.
+
+TEST(CCLayerSorterTest, BasicOverlap)
+{
+ CCLayerSorter::ABCompareResult overlapResult;
+ const float zThreshold = 0.1f;
+ float weight = 0;
+
+ // Trivial test, with one layer directly obscuring the other.
+ WebTransformationMatrix neg4Translate;
+ neg4Translate.translate3d(0, 0, -4);
+ CCLayerSorter::LayerShape front(2, 2, neg4Translate);
+
+ WebTransformationMatrix neg5Translate;
+ neg5Translate.translate3d(0, 0, -5);
+ CCLayerSorter::LayerShape back(2, 2, neg5Translate);
+
+ overlapResult = CCLayerSorter::checkOverlap(&front, &back, zThreshold, weight);
+ EXPECT_EQ(CCLayerSorter::BBeforeA, overlapResult);
+ EXPECT_EQ(1, weight);
+
+ overlapResult = CCLayerSorter::checkOverlap(&back, &front, zThreshold, weight);
+ EXPECT_EQ(CCLayerSorter::ABeforeB, overlapResult);
+ EXPECT_EQ(1, weight);
+
+ // One layer translated off to the right. No overlap should be detected.
+ WebTransformationMatrix rightTranslate;
+ rightTranslate.translate3d(10, 0, -5);
+ CCLayerSorter::LayerShape backRight(2, 2, rightTranslate);
+ overlapResult = CCLayerSorter::checkOverlap(&front, &backRight, zThreshold, weight);
+ EXPECT_EQ(CCLayerSorter::None, overlapResult);
+
+ // When comparing a layer with itself, z difference is always 0.
+ overlapResult = CCLayerSorter::checkOverlap(&front, &front, zThreshold, weight);
+ EXPECT_EQ(0, weight);
+}
+
+TEST(CCLayerSorterTest, RightAngleOverlap)
+{
+ CCLayerSorter::ABCompareResult overlapResult;
+ const float zThreshold = 0.1f;
+ float weight = 0;
+
+ WebTransformationMatrix perspectiveMatrix;
+ perspectiveMatrix.applyPerspective(1000);
+
+ // Two layers forming a right angle with a perspective viewing transform.
+ WebTransformationMatrix leftFaceMatrix;
+ leftFaceMatrix.rotate3d(0, 1, 0, -90);
+ leftFaceMatrix.translateRight3d(-1, 0, -5);
+ leftFaceMatrix.translate(-1, -1);
+ CCLayerSorter::LayerShape leftFace(2, 2, perspectiveMatrix * leftFaceMatrix);
+ WebTransformationMatrix frontFaceMatrix;
+ frontFaceMatrix.translate3d(0, 0, -4);
+ frontFaceMatrix.translate(-1, -1);
+ CCLayerSorter::LayerShape frontFace(2, 2, perspectiveMatrix * frontFaceMatrix);
+
+ overlapResult = CCLayerSorter::checkOverlap(&frontFace, &leftFace, zThreshold, weight);
+ EXPECT_EQ(CCLayerSorter::BBeforeA, overlapResult);
+}
+
+TEST(CCLayerSorterTest, IntersectingLayerOverlap)
+{
+ CCLayerSorter::ABCompareResult overlapResult;
+ const float zThreshold = 0.1f;
+ float weight = 0;
+
+ WebTransformationMatrix perspectiveMatrix;
+ perspectiveMatrix.applyPerspective(1000);
+
+ // Intersecting layers. An explicit order will be returned based on relative z
+ // values at the overlapping features but the weight returned should be zero.
+ WebTransformationMatrix frontFaceMatrix;
+ frontFaceMatrix.translate3d(0, 0, -4);
+ frontFaceMatrix.translate(-1, -1);
+ CCLayerSorter::LayerShape frontFace(2, 2, perspectiveMatrix * frontFaceMatrix);
+
+ WebTransformationMatrix throughMatrix;
+ throughMatrix.rotate3d(0, 1, 0, 45);
+ throughMatrix.translateRight3d(0, 0, -4);
+ throughMatrix.translate(-1, -1);
+ CCLayerSorter::LayerShape rotatedFace(2, 2, perspectiveMatrix * throughMatrix);
+ overlapResult = CCLayerSorter::checkOverlap(&frontFace, &rotatedFace, zThreshold, weight);
+ EXPECT_NE(CCLayerSorter::None, overlapResult);
+ EXPECT_EQ(0, weight);
+}
+
+TEST(CCLayerSorterTest, LayersAtAngleOverlap)
+{
+ CCLayerSorter::ABCompareResult overlapResult;
+ const float zThreshold = 0.1f;
+ float weight = 0;
+
+ // Trickier test with layers at an angle.
+ //
+ // -x . . . . 0 . . . . +x
+ // -z /
+ // : /----B----
+ // 0 C
+ // : ----A----/
+ // +z /
+ //
+ // C is in front of A and behind B (not what you'd expect by comparing centers).
+ // A and B don't overlap, so they're incomparable.
+
+ WebTransformationMatrix transformA;
+ transformA.translate3d(-6, 0, 1);
+ transformA.translate(-4, -10);
+ CCLayerSorter::LayerShape layerA(8, 20, transformA);
+
+ WebTransformationMatrix transformB;
+ transformB.translate3d(6, 0, -1);
+ transformB.translate(-4, -10);
+ CCLayerSorter::LayerShape layerB(8, 20, transformB);
+
+ WebTransformationMatrix transformC;
+ transformC.rotate3d(0, 1, 0, 40);
+ transformC.translate(-4, -10);
+ CCLayerSorter::LayerShape layerC(8, 20, transformC);
+
+ overlapResult = CCLayerSorter::checkOverlap(&layerA, &layerC, zThreshold, weight);
+ EXPECT_EQ(CCLayerSorter::ABeforeB, overlapResult);
+ overlapResult = CCLayerSorter::checkOverlap(&layerC, &layerB, zThreshold, weight);
+ EXPECT_EQ(CCLayerSorter::ABeforeB, overlapResult);
+ overlapResult = CCLayerSorter::checkOverlap(&layerA, &layerB, zThreshold, weight);
+ EXPECT_EQ(CCLayerSorter::None, overlapResult);
+}
+
+TEST(CCLayerSorterTest, LayersUnderPathologicalPerspectiveTransform)
+{
+ CCLayerSorter::ABCompareResult overlapResult;
+ const float zThreshold = 0.1f;
+ float weight = 0;
+
+ // On perspective projection, if w becomes negative, the re-projected point will be
+ // invalid and un-usable. Correct code needs to clip away portions of the geometry
+ // where w < 0. If the code uses the invalid value, it will think that a layer has
+ // different bounds than it really does, which can cause things to sort incorrectly.
+
+ WebTransformationMatrix perspectiveMatrix;
+ perspectiveMatrix.applyPerspective(1);
+
+ WebTransformationMatrix transformA;
+ transformA.translate3d(-15, 0, -2);
+ transformA.translate(-5, -5);
+ CCLayerSorter::LayerShape layerA(10, 10, perspectiveMatrix * transformA);
+
+ // With this sequence of transforms, when layer B is correctly clipped, it will be
+ // visible on the left half of the projection plane, in front of layerA. When it is
+ // not clipped, its bounds will actually incorrectly appear much smaller and the
+ // correct sorting dependency will not be found.
+ WebTransformationMatrix transformB;
+ transformB.translate3d(0, 0, 0.7);
+ transformB.rotate3d(0, 45, 0);
+ transformB.translate(-5, -5);
+ CCLayerSorter::LayerShape layerB(10, 10, perspectiveMatrix * transformB);
+
+ // Sanity check that the test case actually covers the intended scenario, where part
+ // of layer B go behind the w = 0 plane.
+ FloatQuad testQuad = FloatQuad(FloatRect(FloatPoint(-0.5, -0.5), FloatSize(1, 1)));
+ bool clipped = false;
+ CCMathUtil::mapQuad(perspectiveMatrix * transformB, testQuad, clipped);
+ ASSERT_TRUE(clipped);
+
+ overlapResult = CCLayerSorter::checkOverlap(&layerA, &layerB, zThreshold, weight);
+ EXPECT_EQ(CCLayerSorter::ABeforeB, overlapResult);
+}
+
+TEST(CCLayerSorterTest, verifyExistingOrderingPreservedWhenNoZDiff)
+{
+ DebugScopedSetImplThread thisScopeIsOnImplThread;
+
+ // If there is no reason to re-sort the layers (i.e. no 3d z difference), then the
+ // existing ordering provided on input should be retained. This test covers the fix in
+ // https://bugs.webkit.org/show_bug.cgi?id=75046. Before this fix, ordering was
+ // accidentally reversed, causing bugs in z-index ordering on websites when
+ // preserves3D triggered the CCLayerSorter.
+
+ // Input list of layers: [1, 2, 3, 4, 5].
+ // Expected output: [3, 4, 1, 2, 5].
+ // - 1, 2, and 5 do not have a 3d z difference, and therefore their relative ordering should be retained.
+ // - 3 and 4 do not have a 3d z difference, and therefore their relative ordering should be retained.
+ // - 3 and 4 should be re-sorted so they are in front of 1, 2, and 5.
+
+ scoped_ptr<CCLayerImpl> layer1 = CCLayerImpl::create(1);
+ scoped_ptr<CCLayerImpl> layer2 = CCLayerImpl::create(2);
+ scoped_ptr<CCLayerImpl> layer3 = CCLayerImpl::create(3);
+ scoped_ptr<CCLayerImpl> layer4 = CCLayerImpl::create(4);
+ scoped_ptr<CCLayerImpl> layer5 = CCLayerImpl::create(5);
+
+ WebTransformationMatrix BehindMatrix;
+ BehindMatrix.translate3d(0, 0, 2);
+ WebTransformationMatrix FrontMatrix;
+ FrontMatrix.translate3d(0, 0, 1);
+
+ layer1->setBounds(IntSize(10, 10));
+ layer1->setContentBounds(IntSize(10, 10));
+ layer1->setDrawTransform(BehindMatrix);
+ layer1->setDrawsContent(true);
+
+ layer2->setBounds(IntSize(20, 20));
+ layer2->setContentBounds(IntSize(20, 20));
+ layer2->setDrawTransform(BehindMatrix);
+ layer2->setDrawsContent(true);
+
+ layer3->setBounds(IntSize(30, 30));
+ layer3->setContentBounds(IntSize(30, 30));
+ layer3->setDrawTransform(FrontMatrix);
+ layer3->setDrawsContent(true);
+
+ layer4->setBounds(IntSize(40, 40));
+ layer4->setContentBounds(IntSize(40, 40));
+ layer4->setDrawTransform(FrontMatrix);
+ layer4->setDrawsContent(true);
+
+ layer5->setBounds(IntSize(50, 50));
+ layer5->setContentBounds(IntSize(50, 50));
+ layer5->setDrawTransform(BehindMatrix);
+ layer5->setDrawsContent(true);
+
+ std::vector<CCLayerImpl*> layerList;
+ layerList.push_back(layer1.get());
+ layerList.push_back(layer2.get());
+ layerList.push_back(layer3.get());
+ layerList.push_back(layer4.get());
+ layerList.push_back(layer5.get());
+
+ ASSERT_EQ(static_cast<size_t>(5), layerList.size());
+ EXPECT_EQ(1, layerList[0]->id());
+ EXPECT_EQ(2, layerList[1]->id());
+ EXPECT_EQ(3, layerList[2]->id());
+ EXPECT_EQ(4, layerList[3]->id());
+ EXPECT_EQ(5, layerList[4]->id());
+
+ CCLayerSorter layerSorter;
+ layerSorter.sort(layerList.begin(), layerList.end());
+
+ ASSERT_EQ(static_cast<size_t>(5), layerList.size());
+ EXPECT_EQ(3, layerList[0]->id());
+ EXPECT_EQ(4, layerList[1]->id());
+ EXPECT_EQ(1, layerList[2]->id());
+ EXPECT_EQ(2, layerList[3]->id());
+ EXPECT_EQ(5, layerList[4]->id());
+}
+
+} // namespace