add a use_alsa gyp setting
[chromium-blink-merge.git] / cc / layer_sorter.cc
blob97aa47cd3f01b2a19b51c5371339340deb98e7d2
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"
7 #include <algorithm>
8 #include <deque>
9 #include <limits>
10 #include <vector>
12 #include "base/logging.h"
13 #include "cc/math_util.h"
14 #include "cc/render_surface_impl.h"
15 #include "ui/gfx/transform.h"
17 namespace cc {
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.
44 if (!denom)
45 return false;
47 float s = perpProduct(v, w) / denom;
48 if (s < 0 || s > 1)
49 return false;
51 float t = perpProduct(u, w) / denom;
52 if (t < 0 || t > 1)
53 return false;
55 u.Scale(s);
56 r = a + u;
57 return true;
60 GraphNode::GraphNode(LayerImpl* layerImpl)
61 : layer(layerImpl)
62 , incomingEdgeWeight(0)
66 GraphNode::~GraphNode()
70 LayerSorter::LayerSorter()
71 : m_zRange(0)
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)
92 weight = 0;
94 // Early out if the projected bounds don't overlap.
95 if (!a->projectedBounds.Intersects(b->projectedBounds))
96 return None;
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.
113 gfx::PointF r;
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())
122 return None;
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)
145 accurate = true;
147 float diff = za - zb;
148 if (diff > maxPositive)
149 maxPositive = diff;
150 if (diff < maxNegative)
151 maxNegative = diff;
154 // If we can't tell which should come first, we use document order.
155 if (!accurate)
156 return ABeforeB;
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)
165 weight = 0;
166 else
167 weight = fabsf(maxDiff);
169 // Maintain relative order if the layers have the same depth at all intersection points.
170 if (maxDiff <= 0)
171 return ABeforeB;
173 return BBeforeA;
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();
192 return;
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]);
207 else
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
230 // of the layer.
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.
241 if (!d)
242 return 0;
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.
247 return 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)
260 continue;
262 DVLOG(2) << "Layer " << node.layer->id() << " (" << node.layer->bounds().width() << " x " << node.layer->bounds().height() << ")";
264 gfx::Transform drawTransform;
265 float layerWidth, layerHeight;
266 if (renderSurface) {
267 drawTransform = renderSurface->drawTransform();
268 layerWidth = renderSurface->contentRect().width();
269 layerHeight = renderSurface->contentRect().height();
270 } else {
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())
296 continue;
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())
300 continue;
301 float weight = 0;
302 ABCompareResult overlapResult = checkOverlap(&nodeA.shape, &nodeB.shape, zThreshold, weight);
303 GraphNode* startNode = 0;
304 GraphNode* endNode = 0;
305 if (overlapResult == ABeforeB) {
306 startNode = &nodeA;
307 endNode = &nodeB;
308 } else if (overlapResult == BBeforeA) {
309 startNode = &nodeB;
310 endNode = &nodeA;
313 if (startNode) {
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());
335 list.erase(iter);
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
350 // first.
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);
362 createGraphEdges();
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())
404 break;
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];
419 DCHECK(nextNode);
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.
435 int count = 0;
436 for (LayerList::iterator it = first; it < last; it++)
437 *it = sortedList[count++]->layer;
439 DVLOG(2) << "Sorting end ----";
441 m_nodes.clear();
442 m_edges.clear();
443 m_activeEdges.clear();
446 } // namespace cc