OLD | NEW |
1 // Copyright 2011 The Chromium Authors. All rights reserved. | 1 // Copyright 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cc/layer_sorter.h" | 5 #include "cc/layer_sorter.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <deque> | 8 #include <deque> |
9 #include <limits> | 9 #include <limits> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "cc/math_util.h" | 13 #include "cc/math_util.h" |
14 #include "cc/render_surface_impl.h" | 14 #include "cc/render_surface_impl.h" |
15 #include "ui/gfx/transform.h" | 15 #include "ui/gfx/transform.h" |
16 | 16 |
17 namespace cc { | 17 namespace cc { |
18 | 18 |
| 19 // This epsilon is used to determine if two layers are too close to each other |
| 20 // to be able to tell which is in front of the other. It's a relative epsilon |
| 21 // so it is robust to changes in scene scale. This value was chosen by picking |
| 22 // a value near machine epsilon and then increasing it until the flickering on |
| 23 // the test scene went away. |
| 24 const float kLayerEpsilon = 1e-4f; |
| 25 |
19 inline static float perpProduct(const gfx::Vector2dF& u, const gfx::Vector2dF& v
) | 26 inline static float perpProduct(const gfx::Vector2dF& u, const gfx::Vector2dF& v
) |
20 { | 27 { |
21 return u.x() * v.y() - u.y() * v.x(); | 28 return u.x() * v.y() - u.y() * v.x(); |
22 } | 29 } |
23 | 30 |
24 // Tests if two edges defined by their endpoints (a,b) and (c,d) intersect. Retu
rns true and the | 31 // Tests if two edges defined by their endpoints (a,b) and (c,d) intersect. Retu
rns true and the |
25 // point of intersection if they do and false otherwise. | 32 // point of intersection if they do and false otherwise. |
26 static bool edgeEdgeTest(const gfx::PointF& a, const gfx::PointF& b, const gfx::
PointF& c, const gfx::PointF& d, gfx::PointF& r) | 33 static bool edgeEdgeTest(const gfx::PointF& a, const gfx::PointF& b, const gfx::
PointF& c, const gfx::PointF& d, gfx::PointF& r) |
27 { | 34 { |
28 gfx::Vector2dF u = b - a; | 35 gfx::Vector2dF u = b - a; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 | 69 |
63 LayerSorter::LayerSorter() | 70 LayerSorter::LayerSorter() |
64 : m_zRange(0) | 71 : m_zRange(0) |
65 { | 72 { |
66 } | 73 } |
67 | 74 |
68 LayerSorter::~LayerSorter() | 75 LayerSorter::~LayerSorter() |
69 { | 76 { |
70 } | 77 } |
71 | 78 |
| 79 static float const checkFloatingPointNumericAccuracy(float a, float b) |
| 80 { |
| 81 float absDif = std::abs(b - a); |
| 82 float absMax = std::max(std::abs(b), std::abs(a)); |
| 83 // Check to see if we've got a result with a reasonable amount of error. |
| 84 return absDif / absMax; |
| 85 } |
| 86 |
72 // Checks whether layer "a" draws on top of layer "b". The weight value returned
is an indication of | 87 // Checks whether layer "a" draws on top of layer "b". The weight value returned
is an indication of |
73 // the maximum z-depth difference between the layers or zero if the layers are f
ound to be intesecting | 88 // the maximum z-depth difference between the layers or zero if the layers are f
ound to be intesecting |
74 // (some features are in front and some are behind). | 89 // (some features are in front and some are behind). |
75 LayerSorter::ABCompareResult LayerSorter::checkOverlap(LayerShape* a, LayerShape
* b, float zThreshold, float& weight) | 90 LayerSorter::ABCompareResult LayerSorter::checkOverlap(LayerShape* a, LayerShape
* b, float zThreshold, float& weight) |
76 { | 91 { |
77 weight = 0; | 92 weight = 0; |
78 | 93 |
79 // Early out if the projected bounds don't overlap. | 94 // Early out if the projected bounds don't overlap. |
80 if (!a->projectedBounds.Intersects(b->projectedBounds)) | 95 if (!a->projectedBounds.Intersects(b->projectedBounds)) |
81 return None; | 96 return None; |
(...skipping 21 matching lines...) Expand all Loading... |
103 r)) | 118 r)) |
104 overlapPoints.push_back(r); | 119 overlapPoints.push_back(r); |
105 | 120 |
106 if (overlapPoints.empty()) | 121 if (overlapPoints.empty()) |
107 return None; | 122 return None; |
108 | 123 |
109 // Check the corresponding layer depth value for all overlap points to deter
mine | 124 // Check the corresponding layer depth value for all overlap points to deter
mine |
110 // which layer is in front. | 125 // which layer is in front. |
111 float maxPositive = 0; | 126 float maxPositive = 0; |
112 float maxNegative = 0; | 127 float maxNegative = 0; |
| 128 |
| 129 // This flag tracks the existance of a numerically accurate seperation |
| 130 // between two layers. If there is no accurate seperation, the layers |
| 131 // cannot be effectively sorted. |
| 132 bool accurate = false; |
| 133 |
113 for (unsigned o = 0; o < overlapPoints.size(); o++) { | 134 for (unsigned o = 0; o < overlapPoints.size(); o++) { |
114 float za = a->layerZFromProjectedPoint(overlapPoints[o]); | 135 float za = a->layerZFromProjectedPoint(overlapPoints[o]); |
115 float zb = b->layerZFromProjectedPoint(overlapPoints[o]); | 136 float zb = b->layerZFromProjectedPoint(overlapPoints[o]); |
116 | 137 |
| 138 // Here we attempt to avoid numeric issues with layers that are too |
| 139 // close together. If we have 2-sided quads that are very close |
| 140 // together then we will draw them in document order to avoid |
| 141 // flickering. The correct solution is for the content maker to turn |
| 142 // on back-face culling or move the quads apart (if they're not two |
| 143 // sides of one object). |
| 144 if (checkFloatingPointNumericAccuracy(za, zb) > kLayerEpsilon) |
| 145 accurate = true; |
| 146 |
117 float diff = za - zb; | 147 float diff = za - zb; |
118 if (diff > maxPositive) | 148 if (diff > maxPositive) |
119 maxPositive = diff; | 149 maxPositive = diff; |
120 if (diff < maxNegative) | 150 if (diff < maxNegative) |
121 maxNegative = diff; | 151 maxNegative = diff; |
122 } | 152 } |
123 | 153 |
| 154 // If we can't tell which should come first, we use document order. |
| 155 if (!accurate) |
| 156 return ABeforeB; |
| 157 |
124 float maxDiff = (fabsf(maxPositive) > fabsf(maxNegative) ? maxPositive : max
Negative); | 158 float maxDiff = (fabsf(maxPositive) > fabsf(maxNegative) ? maxPositive : max
Negative); |
125 | 159 |
126 // If the results are inconsistent (and the z difference substantial to rule
out | 160 // If the results are inconsistent (and the z difference substantial to rule
out |
127 // numerical errors) then the layers are intersecting. We will still return
an | 161 // numerical errors) then the layers are intersecting. We will still return
an |
128 // order based on the maximum depth difference but with an edge weight of ze
ro | 162 // order based on the maximum depth difference but with an edge weight of ze
ro |
129 // these layers will get priority if a graph cycle is present and needs to b
e broken. | 163 // these layers will get priority if a graph cycle is present and needs to b
e broken. |
130 if (maxPositive > zThreshold && maxNegative < -zThreshold) | 164 if (maxPositive > zThreshold && maxNegative < -zThreshold) |
131 weight = 0; | 165 weight = 0; |
132 else | 166 else |
133 weight = fabsf(maxDiff); | 167 weight = fabsf(maxDiff); |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 *it = sortedList[count++]->layer; | 437 *it = sortedList[count++]->layer; |
404 | 438 |
405 DVLOG(2) << "Sorting end ----"; | 439 DVLOG(2) << "Sorting end ----"; |
406 | 440 |
407 m_nodes.clear(); | 441 m_nodes.clear(); |
408 m_edges.clear(); | 442 m_edges.clear(); |
409 m_activeEdges.clear(); | 443 m_activeEdges.clear(); |
410 } | 444 } |
411 | 445 |
412 } // namespace cc | 446 } // namespace cc |
OLD | NEW |