1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <limits> 6 #include <vector> 7 8 #include "cc/output/bsp_compare_result.h" 9 #include "cc/quads/draw_polygon.h" 10 #include "testing/gtest/include/gtest/gtest.h" 11 #include "ui/gfx/transform.h" 12 13 namespace cc { 14 namespace { 15 16 #define CREATE_NEW_DRAW_POLYGON(name, points_vector, normal, polygon_id) \ 17 DrawPolygon name(NULL, points_vector, normal, polygon_id) 18 19 #define EXPECT_FLOAT_WITHIN_EPSILON_OF(a, b) \ 20 EXPECT_TRUE(std::abs(a - b) < std::numeric_limits<float>::epsilon()); 21 22 #define EXPECT_POINT_EQ(point_a, point_b) \ 23 EXPECT_FLOAT_EQ(point_a.x(), point_b.x()); \ 24 EXPECT_FLOAT_EQ(point_a.y(), point_b.y()); \ 25 EXPECT_FLOAT_EQ(point_a.z(), point_b.z()); 26 27 static void ValidatePoints(const DrawPolygon& polygon, 28 const std::vector<gfx::Point3F>& points) { 29 EXPECT_EQ(polygon.points().size(), points.size()); 30 for (size_t i = 0; i < points.size(); i++) { 31 EXPECT_POINT_EQ(polygon.points()[i], points[i]); 32 } 33 } 34 35 // Two quads are definitely not touching and so no split should occur. 36 TEST(DrawPolygonSplitTest, NotTouchingNoSplit) { 37 std::vector<gfx::Point3F> vertices_a; 38 vertices_a.push_back(gfx::Point3F(0.0f, 10.0f, 0.0f)); 39 vertices_a.push_back(gfx::Point3F(0.0f, 0.0f, 0.0f)); 40 vertices_a.push_back(gfx::Point3F(10.0f, 0.0f, 0.0f)); 41 vertices_a.push_back(gfx::Point3F(10.0f, 10.0f, 0.0f)); 42 std::vector<gfx::Point3F> vertices_b; 43 vertices_b.push_back(gfx::Point3F(5.0f, 10.0f, 5.0f)); 44 vertices_b.push_back(gfx::Point3F(5.0f, 0.0f, 15.0f)); 45 vertices_b.push_back(gfx::Point3F(5.0f, 0.0f, 15.0f)); 46 vertices_b.push_back(gfx::Point3F(5.0f, 10.0f, 5.0f)); 47 48 CREATE_NEW_DRAW_POLYGON( 49 polygon_a, vertices_a, gfx::Vector3dF(0.0f, 0.0f, 1.0f), 0); 50 CREATE_NEW_DRAW_POLYGON( 51 polygon_b, vertices_b, gfx::Vector3dF(-1.0f, 0.0f, 0.0f), 1); 52 53 EXPECT_EQ(DrawPolygon::SideCompare(polygon_b, polygon_a), BSP_FRONT); 54 } 55 56 // One quad is resting against another, but doesn't cross its plane so no split 57 // should occur. 58 TEST(DrawPolygonSplitTest, BarelyTouchingNoSplit) { 59 std::vector<gfx::Point3F> vertices_a; 60 vertices_a.push_back(gfx::Point3F(0.0f, 10.0f, 0.0f)); 61 vertices_a.push_back(gfx::Point3F(0.0f, 0.0f, 0.0f)); 62 vertices_a.push_back(gfx::Point3F(10.0f, 0.0f, 0.0f)); 63 vertices_a.push_back(gfx::Point3F(10.0f, 10.0f, 0.0f)); 64 std::vector<gfx::Point3F> vertices_b; 65 vertices_b.push_back(gfx::Point3F(5.0f, 10.0f, 0.0f)); 66 vertices_b.push_back(gfx::Point3F(5.0f, 0.0f, -10.0f)); 67 vertices_b.push_back(gfx::Point3F(5.0f, 0.0f, -10.0f)); 68 vertices_b.push_back(gfx::Point3F(5.0f, 10.0f, 0.0f)); 69 70 CREATE_NEW_DRAW_POLYGON( 71 polygon_a, vertices_a, gfx::Vector3dF(0.0f, 0.0f, 1.0f), 0); 72 CREATE_NEW_DRAW_POLYGON( 73 polygon_b, vertices_b, gfx::Vector3dF(-1.0f, 0.0f, 0.0f), 1); 74 75 EXPECT_EQ(DrawPolygon::SideCompare(polygon_b, polygon_a), BSP_BACK); 76 } 77 78 // One quad intersects another and becomes two pieces. 79 TEST(DrawPolygonSplitTest, BasicSplit) { 80 std::vector<gfx::Point3F> vertices_a; 81 vertices_a.push_back(gfx::Point3F(0.0f, 10.0f, 0.0f)); 82 vertices_a.push_back(gfx::Point3F(0.0f, 0.0f, 0.0f)); 83 vertices_a.push_back(gfx::Point3F(10.0f, 0.0f, 0.0f)); 84 vertices_a.push_back(gfx::Point3F(10.0f, 10.0f, 0.0f)); 85 std::vector<gfx::Point3F> vertices_b; 86 vertices_b.push_back(gfx::Point3F(5.0f, 10.0f, -5.0f)); 87 vertices_b.push_back(gfx::Point3F(5.0f, 0.0f, -5.0f)); 88 vertices_b.push_back(gfx::Point3F(5.0f, 0.0f, 5.0f)); 89 vertices_b.push_back(gfx::Point3F(5.0f, 10.0f, 5.0f)); 90 91 CREATE_NEW_DRAW_POLYGON( 92 polygon_a, vertices_a, gfx::Vector3dF(0.0f, 0.0f, 1.0f), 0); 93 CREATE_NEW_DRAW_POLYGON( 94 polygon_b, vertices_b, gfx::Vector3dF(-1.0f, 0.0f, 0.0f), 1); 95 96 EXPECT_EQ(DrawPolygon::SideCompare(polygon_b, polygon_a), BSP_SPLIT); 97 98 scoped_ptr<DrawPolygon> front_polygon; 99 scoped_ptr<DrawPolygon> back_polygon; 100 polygon_b.Split(polygon_a, &front_polygon, &back_polygon); 101 EXPECT_EQ(DrawPolygon::SideCompare(*front_polygon, polygon_a), BSP_FRONT); 102 EXPECT_EQ(DrawPolygon::SideCompare(*back_polygon, polygon_a), BSP_BACK); 103 104 std::vector<gfx::Point3F> test_points_a; 105 test_points_a.push_back(gfx::Point3F(5.0f, 0.0f, 0.0f)); 106 test_points_a.push_back(gfx::Point3F(5.0f, 0.0f, 5.0f)); 107 test_points_a.push_back(gfx::Point3F(5.0f, 10.0f, 5.0f)); 108 test_points_a.push_back(gfx::Point3F(5.0f, 10.0f, 0.0f)); 109 std::vector<gfx::Point3F> test_points_b; 110 test_points_b.push_back(gfx::Point3F(5.0f, 10.0f, 0.0f)); 111 test_points_b.push_back(gfx::Point3F(5.0f, 10.0f, -5.0f)); 112 test_points_b.push_back(gfx::Point3F(5.0f, 0.0f, -5.0f)); 113 test_points_b.push_back(gfx::Point3F(5.0f, 0.0f, 0.0f)); 114 ValidatePoints(*(front_polygon.get()), test_points_a); 115 ValidatePoints(*(back_polygon.get()), test_points_b); 116 117 EXPECT_EQ(front_polygon->points().size(), 4u); 118 EXPECT_EQ(back_polygon->points().size(), 4u); 119 } 120 121 // In this test we cut the corner of a quad so that it creates a triangle and 122 // a pentagon as a result. 123 TEST(DrawPolygonSplitTest, AngledSplit) { 124 std::vector<gfx::Point3F> vertices_a; 125 vertices_a.push_back(gfx::Point3F(0.0f, 0.0f, 0.0f)); 126 vertices_a.push_back(gfx::Point3F(0.0f, 0.0f, 10.0f)); 127 vertices_a.push_back(gfx::Point3F(10.0f, 0.0f, 10.0f)); 128 vertices_a.push_back(gfx::Point3F(10.0f, 0.0f, 0.0f)); 129 std::vector<gfx::Point3F> vertices_b; 130 vertices_b.push_back(gfx::Point3F(2.0f, 5.0f, 1.0f)); 131 vertices_b.push_back(gfx::Point3F(2.0f, -5.0f, 1.0f)); 132 vertices_b.push_back(gfx::Point3F(-1.0f, -5.0f, -2.0f)); 133 vertices_b.push_back(gfx::Point3F(-1.0f, 5.0f, -2.0f)); 134 135 CREATE_NEW_DRAW_POLYGON( 136 polygon_a, vertices_a, gfx::Vector3dF(0.0f, 1.0f, 0.0f), 0); 137 CREATE_NEW_DRAW_POLYGON( 138 polygon_b, vertices_b, gfx::Vector3dF(0.707107f, 0.0f, -0.707107f), 1); 139 140 EXPECT_EQ(DrawPolygon::SideCompare(polygon_a, polygon_b), BSP_SPLIT); 141 142 scoped_ptr<DrawPolygon> front_polygon; 143 scoped_ptr<DrawPolygon> back_polygon; 144 polygon_a.Split(polygon_b, &front_polygon, &back_polygon); 145 EXPECT_EQ(DrawPolygon::SideCompare(*front_polygon, polygon_b), BSP_FRONT); 146 EXPECT_EQ(DrawPolygon::SideCompare(*back_polygon, polygon_b), BSP_BACK); 147 148 EXPECT_EQ(front_polygon->points().size(), 3u); 149 EXPECT_EQ(back_polygon->points().size(), 5u); 150 151 std::vector<gfx::Point3F> test_points_a; 152 test_points_a.push_back(gfx::Point3F(10.0f, 0.0f, 9.0f)); 153 test_points_a.push_back(gfx::Point3F(10.0f, 0.0f, 0.0f)); 154 test_points_a.push_back(gfx::Point3F(1.0f, 0.0f, 0.0f)); 155 std::vector<gfx::Point3F> test_points_b; 156 test_points_b.push_back(gfx::Point3F(1.0f, 0.0f, 0.0f)); 157 test_points_b.push_back(gfx::Point3F(0.0f, 0.0f, 0.0f)); 158 test_points_b.push_back(gfx::Point3F(0.0f, 0.0f, 10.0f)); 159 test_points_b.push_back(gfx::Point3F(10.0f, 0.0f, 10.0f)); 160 test_points_b.push_back(gfx::Point3F(10.0f, 0.0f, 9.0f)); 161 162 ValidatePoints(*(front_polygon.get()), test_points_a); 163 ValidatePoints(*(back_polygon.get()), test_points_b); 164 } 165 166 TEST(DrawPolygonTransformTest, TransformNormal) { 167 // We give this polygon no actual vertices because we're not interested 168 // in actually transforming any points, just the normal. 169 std::vector<gfx::Point3F> vertices_a; 170 CREATE_NEW_DRAW_POLYGON( 171 polygon_a, vertices_a, gfx::Vector3dF(0.707107f, 0.0f, -0.707107f), 0); 172 173 gfx::Transform transform; 174 transform.RotateAboutYAxis(45.0); 175 // This would transform the vertices as well, but we are transforming a 176 // DrawPolygon with 0 vertices just to make sure our normal transformation 177 // using the inverse tranpose matrix gives us the right result. 178 polygon_a.TransformToScreenSpace(transform); 179 180 // Note: We use EXPECT_FLOAT_WITHIN_EPSILON instead of EXPECT_FLOAT_EQUAL here 181 // because some architectures (e.g., Arm64) employ a fused multiply-add 182 // instruction which causes rounding asymmetry and reduces precision. 183 // http://crbug.com/401117. 184 EXPECT_FLOAT_WITHIN_EPSILON_OF(polygon_a.normal().x(), 0); 185 EXPECT_FLOAT_WITHIN_EPSILON_OF(polygon_a.normal().y(), 0); 186 EXPECT_FLOAT_WITHIN_EPSILON_OF(polygon_a.normal().z(), -1); 187 } 188 189 } // namespace 190 } // namespace cc 191