From 006529d8b2758bc58d5378c4b9fc5ca876435048 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20H=C3=B6glund?= Date: Mon, 9 Sep 2013 17:26:23 +0200 Subject: [PATCH] kwin: Optimize WindowQuadList::makeRegularGrid() Instead of looping over every quad for every grid cell and checking for possible intersections, loop over the quads once and compute the top left corner of the first intersecting grid cell. Then loop over all the intersecting cells from that point and create the sub quads. This new algorithm also preserves the order of the quads in the original list. --- libkwineffects/kwineffects.cpp | 59 +++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/libkwineffects/kwineffects.cpp b/libkwineffects/kwineffects.cpp index 3efb07a9a5..1b921ef486 100644 --- a/libkwineffects/kwineffects.cpp +++ b/libkwineffects/kwineffects.cpp @@ -1039,40 +1039,53 @@ WindowQuadList WindowQuadList::makeRegularGrid(int xSubdivisions, int ySubdivisi { if (empty()) return *this; - // find the bounding rectangle - double left = first().left(); - double right = first().right(); - double top = first().top(); + + // Find the bounding rectangle + double left = first().left(); + double right = first().right(); + double top = first().top(); double bottom = first().bottom(); - foreach (const WindowQuad & quad, *this) { + + foreach (const WindowQuad &quad, *this) { #ifndef NDEBUG if (quad.isTransformed()) - kFatal(1212) << "Splitting quads is allowed only in pre-paint calls!" ; + kFatal(1212) << "Splitting quads is allowed only in pre-paint calls!"; #endif - left = qMin(left, quad.left()); - right = qMax(right, quad.right()); - top = qMin(top, quad.top()); + left = qMin(left, quad.left()); + right = qMax(right, quad.right()); + top = qMin(top, quad.top()); bottom = qMax(bottom, quad.bottom()); } - double xincrement = (right - left) / xSubdivisions; - double yincrement = (bottom - top) / ySubdivisions; + double xIncrement = (right - left) / xSubdivisions; + double yIncrement = (bottom - top) / ySubdivisions; + WindowQuadList ret; - for (double y = top; - y < bottom; - y += yincrement) { - for (double x = left; - x < right; - x += xincrement) { - foreach (const WindowQuad & quad, *this) { - if (QRectF(QPointF(quad.left(), quad.top()), QPointF(quad.right(), quad.bottom())) - .intersects(QRectF(x, y, xincrement, yincrement))) { - ret.append(quad.makeSubQuad(qMax(x, quad.left()), qMax(y, quad.top()), - qMin(quad.right(), x + xincrement), qMin(quad.bottom(), y + yincrement))); - } + + foreach (const WindowQuad &quad, *this) { + const double quadLeft = quad.left(); + const double quadRight = quad.right(); + const double quadTop = quad.top(); + const double quadBottom = quad.bottom(); + + // Compute the top-left corner of the first intersecting grid cell + const double xBegin = left + qFloor((quadLeft - left) / xIncrement) * xIncrement; + const double yBegin = top + qFloor((quadTop - top) / yIncrement) * yIncrement; + + // Loop over all intersecting cells and add sub-quads + for (double y = yBegin; y < quadBottom; y += yIncrement) { + const double y0 = qMax(y, quadTop); + const double y1 = qMin(quadBottom, y + yIncrement); + + for (double x = xBegin; x < quadRight; x += xIncrement) { + const double x0 = qMax(x, quadLeft); + const double x1 = qMin(quadRight, x + xIncrement); + + ret.append(quad.makeSubQuad(x0, y0, x1, y1)); } } } + return ret; }