Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2810)

Unified Diff: cc/tiled_layer.cc

Issue 11193010: cc: Add predictive pre-painting. (Closed) Base URL: http://git.chromium.org/chromium/src.git@PTM_TiledLayerChromium_fixes
Patch Set: Add constants. Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « cc/tiled_layer.h ('k') | cc/tiled_layer_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/tiled_layer.cc
diff --git a/cc/tiled_layer.cc b/cc/tiled_layer.cc
index 1f968ad4bb1820562fdc697e508cd824058ac052..aa487fff3abf57bf22362d2eacd5a4bfd32e11d2 100644
--- a/cc/tiled_layer.cc
+++ b/cc/tiled_layer.cc
@@ -19,6 +19,16 @@ using WebKit::WebTransformationMatrix;
namespace cc {
+// Maximum predictive expansion of the visible area.
+static const int maxPredictiveTilesCount = 2;
+
+// Number of rows/columns of tiles to pre-paint.
+// We should increase these further as all textures are
+// prioritized and we insure performance doesn't suffer.
+static const int prepaintRows = 4;
+static const int prepaintColumns = 2;
+
+
class UpdatableTile : public LayerTilingData::Tile {
public:
static scoped_ptr<UpdatableTile> create(scoped_ptr<LayerTextureUpdater::Texture> texture)
@@ -566,6 +576,7 @@ void TiledLayer::setTexturePriorities(const PriorityCalculator& priorityCalc)
{
updateBounds();
resetUpdateState();
+ updateScrollPrediction();
if (m_tiler->hasEmptyBounds())
return;
@@ -635,7 +646,7 @@ void TiledLayer::setTexturePriorities(const PriorityCalculator& priorityCalc)
if (!tile)
continue;
IntRect tileRect = m_tiler->tileRect(tile);
- setPriorityForTexture(visibleContentRect(), tileRect, drawsToRoot, smallAnimatedLayer, tile->managedTexture());
+ setPriorityForTexture(m_predictedVisibleRect, tileRect, drawsToRoot, smallAnimatedLayer, tile->managedTexture());
}
}
@@ -663,6 +674,46 @@ void TiledLayer::resetUpdateState()
}
}
+namespace {
+IntRect expandRectByDelta(IntRect rect, IntSize delta) {
+ int width = rect.width() + abs(delta.width());
+ int height = rect.height() + abs(delta.height());
+ int x = rect.x() + ((delta.width() < 0) ? delta.width() : 0);
+ int y = rect.y() + ((delta.height() < 0) ? delta.height() : 0);
+ return IntRect(x, y, width, height);
+}
+}
+
+void TiledLayer::updateScrollPrediction()
+{
+ // This scroll prediction is very primitive and should be replaced by a
+ // a recursive calculation on all layers which uses actual scroll/animation
+ // velocities. To insure this doesn't miss-predict, we only use it to predict
+ // the visibleRect if:
+ // - contentBounds() hasn't changed.
+ // - visibleRect.size() hasn't changed.
+ // These two conditions prevent rotations, scales, pinch-zooms etc. where
+ // the prediction would be incorrect.
+ IntSize delta = visibleContentRect().center() - m_previousVisibleRect.center();
+ m_predictedScroll = -delta;
+ m_predictedVisibleRect = visibleContentRect();
+ if (m_previousContentBounds == contentBounds() && m_previousVisibleRect.size() == visibleContentRect().size()) {
+ // Only expand the visible rect in the major scroll direction, to prevent
+ // massive paints due to diagonal scrolls.
+ IntSize majorScrollDelta = (abs(delta.width()) > abs(delta.height())) ? IntSize(delta.width(), 0) : IntSize(0, delta.height());
+ m_predictedVisibleRect = expandRectByDelta(visibleContentRect(), majorScrollDelta);
+
+ // Bound the prediction to prevent unbounded paints, and clamp to content bounds.
+ IntRect bound = visibleContentRect();
+ bound.inflateX(m_tiler->tileSize().width() * maxPredictiveTilesCount);
+ bound.inflateY(m_tiler->tileSize().height() * maxPredictiveTilesCount);
+ bound.intersect(IntRect(IntPoint::zero(), contentBounds()));
+ m_predictedVisibleRect.intersect(bound);
+ }
+ m_previousContentBounds = contentBounds();
+ m_previousVisibleRect = visibleContentRect();
+}
+
void TiledLayer::update(TextureUpdateQueue& queue, const OcclusionTracker* occlusion, RenderingStats& stats)
{
DCHECK(!m_skipsDraw && !m_failedUpdate); // Did resetUpdateState get skipped?
@@ -686,12 +737,12 @@ void TiledLayer::update(TextureUpdateQueue& queue, const OcclusionTracker* occlu
m_failedUpdate = false;
}
- if (visibleContentRect().isEmpty())
+ if (m_predictedVisibleRect.isEmpty())
return;
// Visible painting. First occlude visible tiles and paint the non-occluded tiles.
int left, top, right, bottom;
- m_tiler->contentRectToTileIndices(visibleContentRect(), left, top, right, bottom);
+ m_tiler->contentRectToTileIndices(m_predictedVisibleRect, left, top, right, bottom);
markOcclusionsAndRequestTextures(left, top, right, bottom, occlusion);
m_skipsDraw = !updateTiles(left, top, right, bottom, queue, occlusion, stats, didPaint);
if (m_skipsDraw)
@@ -711,27 +762,42 @@ void TiledLayer::update(TextureUpdateQueue& queue, const OcclusionTracker* occlu
int prepaintLeft, prepaintTop, prepaintRight, prepaintBottom;
m_tiler->contentRectToTileIndices(idlePaintContentRect, prepaintLeft, prepaintTop, prepaintRight, prepaintBottom);
- // Then expand outwards from the visible area until we find a dirty row or column to update.
- while (left > prepaintLeft || top > prepaintTop || right < prepaintRight || bottom < prepaintBottom) {
- if (bottom < prepaintBottom) {
- ++bottom;
- if (!updateTiles(left, bottom, right, bottom, queue, 0, stats, didPaint) || didPaint)
- return;
+ // Then expand outwards one row/column at a time until we find a dirty row/column
+ // to update. Increment along the major and minor scroll directions first.
+ IntSize delta = -m_predictedScroll;
+ delta = IntSize(delta.width() == 0 ? 1 : delta.width(),
+ delta.height() == 0 ? 1 : delta.height());
+ IntSize majorDelta = (abs(delta.width()) > abs(delta.height())) ? IntSize(delta.width(), 0) : IntSize(0, delta.height());
+ IntSize minorDelta = (abs(delta.width()) <= abs(delta.height())) ? IntSize(delta.width(), 0) : IntSize(0, delta.height());
+ IntSize deltas[4] = {majorDelta, minorDelta, -majorDelta, -minorDelta};
+ for(int i = 0; i < 4; i++) {
+ if (deltas[i].height() > 0) {
+ while (bottom < prepaintBottom) {
+ ++bottom;
+ if (!updateTiles(left, bottom, right, bottom, queue, 0, stats, didPaint) || didPaint)
+ return;
+ }
}
- if (top > prepaintTop) {
- --top;
- if (!updateTiles(left, top, right, top, queue, 0, stats, didPaint) || didPaint)
- return;
+ if (deltas[i].height() < 0) {
+ while (top > prepaintTop) {
+ --top;
+ if (!updateTiles(left, top, right, top, queue, 0, stats, didPaint) || didPaint)
+ return;
+ }
}
- if (left > prepaintLeft) {
- --left;
- if (!updateTiles(left, top, left, bottom, queue, 0, stats, didPaint) || didPaint)
- return;
+ if (deltas[i].width() < 0) {
+ while (left > prepaintLeft) {
+ --left;
+ if (!updateTiles(left, top, left, bottom, queue, 0, stats, didPaint) || didPaint)
+ return;
+ }
}
- if (right < prepaintRight) {
- ++right;
- if (!updateTiles(right, top, right, bottom, queue, 0, stats, didPaint) || didPaint)
- return;
+ if (deltas[i].width() > 0) {
+ while (right < prepaintRight) {
+ ++right;
+ if (!updateTiles(right, top, right, bottom, queue, 0, stats, didPaint) || didPaint)
+ return;
+ }
}
}
}
@@ -772,11 +838,9 @@ IntRect TiledLayer::idlePaintRect()
if (visibleContentRect().isEmpty())
return IntRect();
- // FIXME: This can be made a lot larger now! We should increase
- // this slowly while insuring it doesn't cause any perf issues.
IntRect prepaintRect = visibleContentRect();
- prepaintRect.inflateX(m_tiler->tileSize().width());
- prepaintRect.inflateY(m_tiler->tileSize().height() * 2);
+ prepaintRect.inflateX(m_tiler->tileSize().width() * prepaintColumns);
+ prepaintRect.inflateY(m_tiler->tileSize().height() * prepaintRows);
IntRect contentRect(IntPoint::zero(), contentBounds());
prepaintRect.intersect(contentRect);
« no previous file with comments | « cc/tiled_layer.h ('k') | cc/tiled_layer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698