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
3 // found in the LICENSE file.
5 #include "cc/layer_sorter.h"
12 #include "base/logging.h"
13 #include "cc/math_util.h"
14 #include "cc/render_surface_impl.h"
15 #include "ui/gfx/transform.h"
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
;
26 inline static float perpProduct(const gfx::Vector2dF
& u
, const gfx::Vector2dF
& v
)
28 return u
.x() * v
.y() - u
.y() * v
.x();
31 // Tests if two edges defined by their endpoints (a,b) and (c,d) intersect. Returns true and the
32 // point of intersection if they do and false otherwise.
33 static bool edgeEdgeTest(const gfx::PointF
& a
, const gfx::PointF
& b
, const gfx::PointF
& c
, const gfx::PointF
& d
, gfx::PointF
& r
)
35 gfx::Vector2dF u
= b
- a
;
36 gfx::Vector2dF v
= d
- c
;
37 gfx::Vector2dF w
= a
- c
;
39 float denom
= perpProduct(u
, v
);
41 // If denom == 0 then the edges are parallel. While they could be overlapping
42 // we don't bother to check here as the we'll find their intersections from the
43 // corner to quad tests.
47 float s
= perpProduct(v
, w
) / denom
;
51 float t
= perpProduct(u
, w
) / denom
;
60 GraphNode::GraphNode(LayerImpl
* layerImpl
)
62 , incomingEdgeWeight(0)
66 GraphNode::~GraphNode()
70 LayerSorter::LayerSorter()
75 LayerSorter::~LayerSorter()
79 static float const checkFloatingPointNumericAccuracy(float a
, float b
)
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
;
87 // Checks whether layer "a" draws on top of layer "b". The weight value returned is an indication of
88 // the maximum z-depth difference between the layers or zero if the layers are found to be intesecting
89 // (some features are in front and some are behind).
90 LayerSorter::ABCompareResult
LayerSorter::checkOverlap(LayerShape
* a
, LayerShape
* b
, float zThreshold
, float& weight
)
94 // Early out if the projected bounds don't overlap.
95 if (!a
->projectedBounds
.Intersects(b
->projectedBounds
))
98 gfx::PointF aPoints
[4] = {a
->projectedQuad
.p1(), a
->projectedQuad
.p2(), a
->projectedQuad
.p3(), a
->projectedQuad
.p4() };
99 gfx::PointF bPoints
[4] = {b
->projectedQuad
.p1(), b
->projectedQuad
.p2(), b
->projectedQuad
.p3(), b
->projectedQuad
.p4() };
101 // Make a list of points that inside both layer quad projections.
102 std::vector
<gfx::PointF
> overlapPoints
;
104 // Check all four corners of one layer against the other layer's quad.
105 for (int i
= 0; i
< 4; ++i
) {
106 if (a
->projectedQuad
.Contains(bPoints
[i
]))
107 overlapPoints
.push_back(bPoints
[i
]);
108 if (b
->projectedQuad
.Contains(aPoints
[i
]))
109 overlapPoints
.push_back(aPoints
[i
]);
112 // Check all the edges of one layer for intersection with the other layer's edges.
114 for (int ea
= 0; ea
< 4; ++ea
)
115 for (int eb
= 0; eb
< 4; ++eb
)
116 if (edgeEdgeTest(aPoints
[ea
], aPoints
[(ea
+ 1) % 4],
117 bPoints
[eb
], bPoints
[(eb
+ 1) % 4],
119 overlapPoints
.push_back(r
);
121 if (overlapPoints
.empty())
124 // Check the corresponding layer depth value for all overlap points to determine
125 // which layer is in front.
126 float maxPositive
= 0;
127 float maxNegative
= 0;
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;
134 for (unsigned o
= 0; o
< overlapPoints
.size(); o
++) {
135 float za
= a
->layerZFromProjectedPoint(overlapPoints
[o
]);
136 float zb
= b
->layerZFromProjectedPoint(overlapPoints
[o
]);
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
)
147 float diff
= za
- zb
;
148 if (diff
> maxPositive
)
150 if (diff
< maxNegative
)
154 // If we can't tell which should come first, we use document order.
158 float maxDiff
= (fabsf(maxPositive
) > fabsf(maxNegative
) ? maxPositive
: maxNegative
);
160 // If the results are inconsistent (and the z difference substantial to rule out
161 // numerical errors) then the layers are intersecting. We will still return an
162 // order based on the maximum depth difference but with an edge weight of zero
163 // these layers will get priority if a graph cycle is present and needs to be broken.
164 if (maxPositive
> zThreshold
&& maxNegative
< -zThreshold
)
167 weight
= fabsf(maxDiff
);
169 // Maintain relative order if the layers have the same depth at all intersection points.
176 LayerShape::LayerShape()
180 LayerShape::LayerShape(float width
, float height
, const gfx::Transform
& drawTransform
)
182 gfx::QuadF
layerQuad(gfx::RectF(0, 0, width
, height
));
184 // Compute the projection of the layer quad onto the z = 0 plane.
186 gfx::PointF clippedQuad
[8];
187 int numVerticesInClippedQuad
;
188 MathUtil::mapClippedQuad(drawTransform
, layerQuad
, clippedQuad
, numVerticesInClippedQuad
);
190 if (numVerticesInClippedQuad
< 3) {
191 projectedBounds
= gfx::RectF();
195 projectedBounds
= MathUtil::computeEnclosingRectOfVertices(clippedQuad
, numVerticesInClippedQuad
);
197 // NOTE: it will require very significant refactoring and overhead to deal with
198 // generalized polygons or multiple quads per layer here. For the sake of layer
199 // sorting it is equally correct to take a subsection of the polygon that can be made
200 // into a quad. This will only be incorrect in the case of intersecting layers, which
201 // are not supported yet anyway.
202 projectedQuad
.set_p1(clippedQuad
[0]);
203 projectedQuad
.set_p2(clippedQuad
[1]);
204 projectedQuad
.set_p3(clippedQuad
[2]);
205 if (numVerticesInClippedQuad
>= 4)
206 projectedQuad
.set_p4(clippedQuad
[3]);
208 projectedQuad
.set_p4(clippedQuad
[2]); // this will be a degenerate quad that is actually a triangle.
210 // Compute the normal of the layer's plane.
211 bool clipped
= false;
212 gfx::Point3F c1
= MathUtil::mapPoint(drawTransform
, gfx::Point3F(0, 0, 0), clipped
);
213 gfx::Point3F c2
= MathUtil::mapPoint(drawTransform
, gfx::Point3F(0, 1, 0), clipped
);
214 gfx::Point3F c3
= MathUtil::mapPoint(drawTransform
, gfx::Point3F(1, 0, 0), clipped
);
215 // FIXME: Deal with clipping.
216 gfx::Vector3dF c12
= c2
- c1
;
217 gfx::Vector3dF c13
= c3
- c1
;
218 layerNormal
= gfx::CrossProduct(c13
, c12
);
220 transformOrigin
= c1
;
223 LayerShape::~LayerShape()
227 // Returns the Z coordinate of a point on the layer that projects
228 // to point p which lies on the z = 0 plane. It does it by computing the
229 // intersection of a line starting from p along the Z axis and the plane
231 float LayerShape::layerZFromProjectedPoint(const gfx::PointF
& p
) const
233 gfx::Vector3dF
zAxis(0, 0, 1);
234 gfx::Vector3dF w
= gfx::Point3F(p
) - transformOrigin
;
236 float d
= gfx::DotProduct(layerNormal
, zAxis
);
237 float n
= -gfx::DotProduct(layerNormal
, w
);
239 // Check if layer is parallel to the z = 0 axis which will make it
240 // invisible and hence returning zero is fine.
244 // The intersection point would be given by:
245 // p + (n / d) * u but since we are only interested in the
246 // z coordinate and p's z coord is zero, all we need is the value of n/d.
250 void LayerSorter::createGraphNodes(LayerList::iterator first
, LayerList::iterator last
)
252 DVLOG(2) << "Creating graph nodes:";
253 float minZ
= FLT_MAX
;
254 float maxZ
= -FLT_MAX
;
255 for (LayerList::const_iterator it
= first
; it
< last
; it
++) {
256 m_nodes
.push_back(GraphNode(*it
));
257 GraphNode
& node
= m_nodes
.at(m_nodes
.size() - 1);
258 RenderSurfaceImpl
* renderSurface
= node
.layer
->renderSurface();
259 if (!node
.layer
->drawsContent() && !renderSurface
)
262 DVLOG(2) << "Layer " << node
.layer
->id() << " (" << node
.layer
->bounds().width() << " x " << node
.layer
->bounds().height() << ")";
264 gfx::Transform drawTransform
;
265 float layerWidth
, layerHeight
;
267 drawTransform
= renderSurface
->drawTransform();
268 layerWidth
= renderSurface
->contentRect().width();
269 layerHeight
= renderSurface
->contentRect().height();
271 drawTransform
= node
.layer
->drawTransform();
272 layerWidth
= node
.layer
->contentBounds().width();
273 layerHeight
= node
.layer
->contentBounds().height();
276 node
.shape
= LayerShape(layerWidth
, layerHeight
, drawTransform
);
278 maxZ
= std::max(maxZ
, node
.shape
.transformOrigin
.z());
279 minZ
= std::min(minZ
, node
.shape
.transformOrigin
.z());
282 m_zRange
= fabsf(maxZ
- minZ
);
285 void LayerSorter::createGraphEdges()
287 DVLOG(2) << "Edges:";
288 // Fraction of the total zRange below which z differences
289 // are not considered reliable.
290 const float zThresholdFactor
= 0.01f
;
291 float zThreshold
= m_zRange
* zThresholdFactor
;
293 for (unsigned na
= 0; na
< m_nodes
.size(); na
++) {
294 GraphNode
& nodeA
= m_nodes
[na
];
295 if (!nodeA
.layer
->drawsContent() && !nodeA
.layer
->renderSurface())
297 for (unsigned nb
= na
+ 1; nb
< m_nodes
.size(); nb
++) {
298 GraphNode
& nodeB
= m_nodes
[nb
];
299 if (!nodeB
.layer
->drawsContent() && !nodeB
.layer
->renderSurface())
302 ABCompareResult overlapResult
= checkOverlap(&nodeA
.shape
, &nodeB
.shape
, zThreshold
, weight
);
303 GraphNode
* startNode
= 0;
304 GraphNode
* endNode
= 0;
305 if (overlapResult
== ABeforeB
) {
308 } else if (overlapResult
== BBeforeA
) {
314 DVLOG(2) << startNode
->layer
->id() << " -> " << endNode
->layer
->id();
315 m_edges
.push_back(GraphEdge(startNode
, endNode
, weight
));
320 for (unsigned i
= 0; i
< m_edges
.size(); i
++) {
321 GraphEdge
& edge
= m_edges
[i
];
322 m_activeEdges
[&edge
] = &edge
;
323 edge
.from
->outgoing
.push_back(&edge
);
324 edge
.to
->incoming
.push_back(&edge
);
325 edge
.to
->incomingEdgeWeight
+= edge
.weight
;
329 // Finds and removes an edge from the list by doing a swap with the
330 // last element of the list.
331 void LayerSorter::removeEdgeFromList(GraphEdge
* edge
, std::vector
<GraphEdge
*>& list
)
333 std::vector
<GraphEdge
*>::iterator iter
= std::find(list
.begin(), list
.end(), edge
);
334 DCHECK(iter
!= list
.end());
338 // Sorts the given list of layers such that they can be painted in a back-to-front
339 // order. Sorting produces correct results for non-intersecting layers that don't have
340 // cyclical order dependencies. Cycles and intersections are broken (somewhat) aribtrarily.
341 // Sorting of layers is done via a topological sort of a directed graph whose nodes are
342 // the layers themselves. An edge from node A to node B signifies that layer A needs to
343 // be drawn before layer B. If A and B have no dependency between each other, then we
344 // preserve the ordering of those layers as they were in the original list.
346 // The draw order between two layers is determined by projecting the two triangles making
347 // up each layer quad to the Z = 0 plane, finding points of intersection between the triangles
348 // and backprojecting those points to the plane of the layer to determine the corresponding Z
349 // coordinate. The layer with the lower Z coordinate (farther from the eye) needs to be rendered
352 // If the layer projections don't intersect, then no edges (dependencies) are created
353 // between them in the graph. HOWEVER, in this case we still need to preserve the ordering
354 // of the original list of layers, since that list should already have proper z-index
355 // ordering of layers.
357 void LayerSorter::sort(LayerList::iterator first
, LayerList::iterator last
)
359 DVLOG(2) << "Sorting start ----";
360 createGraphNodes(first
, last
);
364 std::vector
<GraphNode
*> sortedList
;
365 std::deque
<GraphNode
*> noIncomingEdgeNodeList
;
367 // Find all the nodes that don't have incoming edges.
368 for (NodeList::iterator la
= m_nodes
.begin(); la
< m_nodes
.end(); la
++) {
369 if (!la
->incoming
.size())
370 noIncomingEdgeNodeList
.push_back(&(*la
));
373 DVLOG(2) << "Sorted list: ";
374 while (m_activeEdges
.size() || noIncomingEdgeNodeList
.size()) {
375 while (noIncomingEdgeNodeList
.size()) {
377 // It is necessary to preserve the existing ordering of layers, when there are
378 // no explicit dependencies (because this existing ordering has correct
379 // z-index/layout ordering). To preserve this ordering, we process Nodes in
380 // the same order that they were added to the list.
381 GraphNode
* fromNode
= noIncomingEdgeNodeList
.front();
382 noIncomingEdgeNodeList
.pop_front();
384 // Add it to the final list.
385 sortedList
.push_back(fromNode
);
387 DVLOG(2) << fromNode
->layer
->id() << ", ";
389 // Remove all its outgoing edges from the graph.
390 for (unsigned i
= 0; i
< fromNode
->outgoing
.size(); i
++) {
391 GraphEdge
* outgoingEdge
= fromNode
->outgoing
[i
];
393 m_activeEdges
.erase(outgoingEdge
);
394 removeEdgeFromList(outgoingEdge
, outgoingEdge
->to
->incoming
);
395 outgoingEdge
->to
->incomingEdgeWeight
-= outgoingEdge
->weight
;
397 if (!outgoingEdge
->to
->incoming
.size())
398 noIncomingEdgeNodeList
.push_back(outgoingEdge
->to
);
400 fromNode
->outgoing
.clear();
403 if (!m_activeEdges
.size())
406 // If there are still active edges but the list of nodes without incoming edges
407 // is empty then we have run into a cycle. Break the cycle by finding the node
408 // with the smallest overall incoming edge weight and use it. This will favor
409 // nodes that have zero-weight incoming edges i.e. layers that are being
410 // occluded by a layer that intersects them.
411 float minIncomingEdgeWeight
= FLT_MAX
;
412 GraphNode
* nextNode
= 0;
413 for (unsigned i
= 0; i
< m_nodes
.size(); i
++) {
414 if (m_nodes
[i
].incoming
.size() && m_nodes
[i
].incomingEdgeWeight
< minIncomingEdgeWeight
) {
415 minIncomingEdgeWeight
= m_nodes
[i
].incomingEdgeWeight
;
416 nextNode
= &m_nodes
[i
];
420 // Remove all its incoming edges.
421 for (unsigned e
= 0; e
< nextNode
->incoming
.size(); e
++) {
422 GraphEdge
* incomingEdge
= nextNode
->incoming
[e
];
424 m_activeEdges
.erase(incomingEdge
);
425 removeEdgeFromList(incomingEdge
, incomingEdge
->from
->outgoing
);
427 nextNode
->incoming
.clear();
428 nextNode
->incomingEdgeWeight
= 0;
429 noIncomingEdgeNodeList
.push_back(nextNode
);
430 DVLOG(2) << "Breaking cycle by cleaning up incoming edges from " << nextNode
->layer
->id() << " (weight = " << minIncomingEdgeWeight
<< ")";
433 // Note: The original elements of the list are in no danger of having their ref count go to zero
434 // here as they are all nodes of the layer hierarchy and are kept alive by their parent nodes.
436 for (LayerList::iterator it
= first
; it
< last
; it
++)
437 *it
= sortedList
[count
++]->layer
;
439 DVLOG(2) << "Sorting end ----";
443 m_activeEdges
.clear();