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 "config.h" | 5 #include "config.h" |
6 | 6 |
7 #include "cc/tiled_layer.h" | 7 #include "cc/tiled_layer.h" |
8 | 8 |
9 #include "Region.h" | 9 #include "Region.h" |
10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
| 11 #include "cc/geometry.h" |
11 #include "cc/layer_impl.h" | 12 #include "cc/layer_impl.h" |
12 #include "cc/layer_tree_host.h" | 13 #include "cc/layer_tree_host.h" |
13 #include "cc/overdraw_metrics.h" | 14 #include "cc/overdraw_metrics.h" |
14 #include "cc/tiled_layer_impl.h" | 15 #include "cc/tiled_layer_impl.h" |
15 #include "third_party/khronos/GLES2/gl2.h" | 16 #include "third_party/khronos/GLES2/gl2.h" |
| 17 #include "ui/gfx/rect_conversions.h" |
16 | 18 |
17 using namespace std; | 19 using namespace std; |
18 using WebKit::WebTransformationMatrix; | 20 using WebKit::WebTransformationMatrix; |
19 | 21 |
20 namespace cc { | 22 namespace cc { |
21 | 23 |
22 // Maximum predictive expansion of the visible area. | 24 // Maximum predictive expansion of the visible area. |
23 static const int maxPredictiveTilesCount = 2; | 25 static const int maxPredictiveTilesCount = 2; |
24 | 26 |
25 // Number of rows/columns of tiles to pre-paint. | 27 // Number of rows/columns of tiles to pre-paint. |
26 // We should increase these further as all textures are | 28 // We should increase these further as all textures are |
27 // prioritized and we insure performance doesn't suffer. | 29 // prioritized and we insure performance doesn't suffer. |
28 static const int prepaintRows = 4; | 30 static const int prepaintRows = 4; |
29 static const int prepaintColumns = 2; | 31 static const int prepaintColumns = 2; |
30 | 32 |
31 | 33 |
32 class UpdatableTile : public LayerTilingData::Tile { | 34 class UpdatableTile : public LayerTilingData::Tile { |
33 public: | 35 public: |
34 static scoped_ptr<UpdatableTile> create(scoped_ptr<LayerUpdater::Resource> u
pdaterResource) | 36 static scoped_ptr<UpdatableTile> create(scoped_ptr<LayerUpdater::Resource> u
pdaterResource) |
35 { | 37 { |
36 return make_scoped_ptr(new UpdatableTile(updaterResource.Pass())); | 38 return make_scoped_ptr(new UpdatableTile(updaterResource.Pass())); |
37 } | 39 } |
38 | 40 |
39 LayerUpdater::Resource* updaterResource() { return m_updaterResource.get();
} | 41 LayerUpdater::Resource* updaterResource() { return m_updaterResource.get();
} |
40 PrioritizedTexture* managedTexture() { return m_updaterResource->texture();
} | 42 PrioritizedTexture* managedTexture() { return m_updaterResource->texture();
} |
41 | 43 |
42 bool isDirty() const { return !dirtyRect.isEmpty(); } | 44 bool isDirty() const { return !dirtyRect.IsEmpty(); } |
43 | 45 |
44 // Reset update state for the current frame. This should occur before painti
ng | 46 // Reset update state for the current frame. This should occur before painti
ng |
45 // for all layers. Since painting one layer can invalidate another layer | 47 // for all layers. Since painting one layer can invalidate another layer |
46 // after it has already painted, mark all non-dirty tiles as valid before pa
inting | 48 // after it has already painted, mark all non-dirty tiles as valid before pa
inting |
47 // such that invalidations during painting won't prevent them from being pus
hed. | 49 // such that invalidations during painting won't prevent them from being pus
hed. |
48 void resetUpdateState() | 50 void resetUpdateState() |
49 { | 51 { |
50 updateRect = IntRect(); | 52 updateRect = gfx::Rect(); |
51 occluded = false; | 53 occluded = false; |
52 partialUpdate = false; | 54 partialUpdate = false; |
53 validForFrame = !isDirty(); | 55 validForFrame = !isDirty(); |
54 } | 56 } |
55 | 57 |
56 // This promises to update the tile and therefore also guarantees the tile | 58 // This promises to update the tile and therefore also guarantees the tile |
57 // will be valid for this frame. dirtyRect is copied into updateRect so | 59 // will be valid for this frame. dirtyRect is copied into updateRect so |
58 // we can continue to track re-entrant invalidations that occur during paint
ing. | 60 // we can continue to track re-entrant invalidations that occur during paint
ing. |
59 void markForUpdate() | 61 void markForUpdate() |
60 { | 62 { |
61 validForFrame = true; | 63 validForFrame = true; |
62 updateRect = dirtyRect; | 64 updateRect = dirtyRect; |
63 dirtyRect = IntRect(); | 65 dirtyRect = gfx::Rect(); |
64 } | 66 } |
65 | 67 |
66 IntRect dirtyRect; | 68 gfx::Rect dirtyRect; |
67 IntRect updateRect; | 69 gfx::Rect updateRect; |
68 bool partialUpdate; | 70 bool partialUpdate; |
69 bool validForFrame; | 71 bool validForFrame; |
70 bool occluded; | 72 bool occluded; |
71 | 73 |
72 private: | 74 private: |
73 explicit UpdatableTile(scoped_ptr<LayerUpdater::Resource> updaterResource) | 75 explicit UpdatableTile(scoped_ptr<LayerUpdater::Resource> updaterResource) |
74 : partialUpdate(false) | 76 : partialUpdate(false) |
75 , validForFrame(false) | 77 , validForFrame(false) |
76 , occluded(false) | 78 , occluded(false) |
77 , m_updaterResource(updaterResource.Pass()) | 79 , m_updaterResource(updaterResource.Pass()) |
78 { | 80 { |
79 } | 81 } |
80 | 82 |
81 scoped_ptr<LayerUpdater::Resource> m_updaterResource; | 83 scoped_ptr<LayerUpdater::Resource> m_updaterResource; |
82 | 84 |
83 DISALLOW_COPY_AND_ASSIGN(UpdatableTile); | 85 DISALLOW_COPY_AND_ASSIGN(UpdatableTile); |
84 }; | 86 }; |
85 | 87 |
86 TiledLayer::TiledLayer() | 88 TiledLayer::TiledLayer() |
87 : ContentsScalingLayer() | 89 : ContentsScalingLayer() |
88 , m_textureFormat(GL_INVALID_ENUM) | 90 , m_textureFormat(GL_INVALID_ENUM) |
89 , m_skipsDraw(false) | 91 , m_skipsDraw(false) |
90 , m_failedUpdate(false) | 92 , m_failedUpdate(false) |
91 , m_tilingOption(AutoTile) | 93 , m_tilingOption(AutoTile) |
92 { | 94 { |
93 m_tiler = LayerTilingData::create(IntSize(), LayerTilingData::HasBorderTexel
s); | 95 m_tiler = LayerTilingData::create(gfx::Size(), LayerTilingData::HasBorderTex
els); |
94 } | 96 } |
95 | 97 |
96 TiledLayer::~TiledLayer() | 98 TiledLayer::~TiledLayer() |
97 { | 99 { |
98 } | 100 } |
99 | 101 |
100 scoped_ptr<LayerImpl> TiledLayer::createLayerImpl() | 102 scoped_ptr<LayerImpl> TiledLayer::createLayerImpl() |
101 { | 103 { |
102 return TiledLayerImpl::create(id()).PassAs<LayerImpl>(); | 104 return TiledLayerImpl::create(id()).PassAs<LayerImpl>(); |
103 } | 105 } |
104 | 106 |
105 void TiledLayer::updateTileSizeAndTilingOption() | 107 void TiledLayer::updateTileSizeAndTilingOption() |
106 { | 108 { |
107 DCHECK(layerTreeHost()); | 109 DCHECK(layerTreeHost()); |
108 | 110 |
109 const IntSize& defaultTileSize = layerTreeHost()->settings().defaultTileSize
; | 111 gfx::Size defaultTileSize = layerTreeHost()->settings().defaultTileSize; |
110 const IntSize& maxUntiledLayerSize = layerTreeHost()->settings().maxUntiledL
ayerSize; | 112 gfx::Size maxUntiledLayerSize = layerTreeHost()->settings().maxUntiledLayerS
ize; |
111 int layerWidth = contentBounds().width(); | 113 int layerWidth = contentBounds().width(); |
112 int layerHeight = contentBounds().height(); | 114 int layerHeight = contentBounds().height(); |
113 | 115 |
114 const IntSize tileSize(min(defaultTileSize.width(), layerWidth), min(default
TileSize.height(), layerHeight)); | 116 gfx::Size tileSize(min(defaultTileSize.width(), layerWidth), min(defaultTile
Size.height(), layerHeight)); |
115 | 117 |
116 // Tile if both dimensions large, or any one dimension large and the other | 118 // Tile if both dimensions large, or any one dimension large and the other |
117 // extends into a second tile but the total layer area isn't larger than tha
t | 119 // extends into a second tile but the total layer area isn't larger than tha
t |
118 // of the largest possible untiled layer. This heuristic allows for long ski
nny layers | 120 // of the largest possible untiled layer. This heuristic allows for long ski
nny layers |
119 // (e.g. scrollbars) that are Nx1 tiles to minimize wasted texture space but
still avoids | 121 // (e.g. scrollbars) that are Nx1 tiles to minimize wasted texture space but
still avoids |
120 // creating very large tiles. | 122 // creating very large tiles. |
121 const bool anyDimensionLarge = layerWidth > maxUntiledLayerSize.width() || l
ayerHeight > maxUntiledLayerSize.height(); | 123 bool anyDimensionLarge = layerWidth > maxUntiledLayerSize.width() || layerHe
ight > maxUntiledLayerSize.height(); |
122 const bool anyDimensionOneTile = (layerWidth <= defaultTileSize.width() || l
ayerHeight <= defaultTileSize.height()) | 124 bool anyDimensionOneTile = (layerWidth <= defaultTileSize.width() || layerHe
ight <= defaultTileSize.height()) |
123 && (layerWidth * layerHeight) <= (maxUntil
edLayerSize.width() * maxUntiledLayerSize.height()); | 125 && (layerWidth * layerHeight) <= (maxUntil
edLayerSize.width() * maxUntiledLayerSize.height()); |
124 const bool autoTiled = anyDimensionLarge && !anyDimensionOneTile; | 126 bool autoTiled = anyDimensionLarge && !anyDimensionOneTile; |
125 | 127 |
126 bool isTiled; | 128 bool isTiled; |
127 if (m_tilingOption == AlwaysTile) | 129 if (m_tilingOption == AlwaysTile) |
128 isTiled = true; | 130 isTiled = true; |
129 else if (m_tilingOption == NeverTile) | 131 else if (m_tilingOption == NeverTile) |
130 isTiled = false; | 132 isTiled = false; |
131 else | 133 else |
132 isTiled = autoTiled; | 134 isTiled = autoTiled; |
133 | 135 |
134 IntSize requestedSize = isTiled ? tileSize : contentBounds(); | 136 gfx::Size requestedSize = isTiled ? tileSize : contentBounds(); |
135 const int maxSize = layerTreeHost()->rendererCapabilities().maxTextureSize; | 137 const int maxSize = layerTreeHost()->rendererCapabilities().maxTextureSize; |
136 IntSize clampedSize = requestedSize.shrunkTo(IntSize(maxSize, maxSize)); | 138 gfx::Size clampedSize = ClampSizeFromAbove(requestedSize, gfx::Size(maxSize,
maxSize)); |
137 setTileSize(clampedSize); | 139 setTileSize(clampedSize); |
138 } | 140 } |
139 | 141 |
140 void TiledLayer::updateBounds() | 142 void TiledLayer::updateBounds() |
141 { | 143 { |
142 IntSize oldBounds = m_tiler->bounds(); | 144 gfx::Size oldBounds = m_tiler->bounds(); |
143 IntSize newBounds = contentBounds(); | 145 gfx::Size newBounds = contentBounds(); |
144 if (oldBounds == newBounds) | 146 if (oldBounds == newBounds) |
145 return; | 147 return; |
146 m_tiler->setBounds(newBounds); | 148 m_tiler->setBounds(newBounds); |
147 | 149 |
148 // Invalidate any areas that the new bounds exposes. | 150 // Invalidate any areas that the new bounds exposes. |
149 Region oldRegion(IntRect(IntPoint(), oldBounds)); | 151 Region oldRegion = IntRect(IntPoint(), cc::IntSize(oldBounds)); |
150 Region newRegion(IntRect(IntPoint(), newBounds)); | 152 Region newRegion = IntRect(IntPoint(), cc::IntSize(newBounds)); |
151 newRegion.subtract(oldRegion); | 153 newRegion.subtract(oldRegion); |
152 Vector<WebCore::IntRect> rects = newRegion.rects(); | 154 Vector<WebCore::IntRect> rects = newRegion.rects(); |
153 for (size_t i = 0; i < rects.size(); ++i) | 155 for (size_t i = 0; i < rects.size(); ++i) |
154 invalidateContentRect(rects[i]); | 156 invalidateContentRect(cc::IntRect(rects[i])); |
155 } | 157 } |
156 | 158 |
157 void TiledLayer::setTileSize(const IntSize& size) | 159 void TiledLayer::setTileSize(const gfx::Size& size) |
158 { | 160 { |
159 m_tiler->setTileSize(size); | 161 m_tiler->setTileSize(size); |
160 } | 162 } |
161 | 163 |
162 void TiledLayer::setBorderTexelOption(LayerTilingData::BorderTexelOption borderT
exelOption) | 164 void TiledLayer::setBorderTexelOption(LayerTilingData::BorderTexelOption borderT
exelOption) |
163 { | 165 { |
164 m_tiler->setBorderTexelOption(borderTexelOption); | 166 m_tiler->setBorderTexelOption(borderTexelOption); |
165 } | 167 } |
166 | 168 |
167 bool TiledLayer::drawsContent() const | 169 bool TiledLayer::drawsContent() const |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 | 264 |
263 // Temporary diagnostic crash. | 265 // Temporary diagnostic crash. |
264 if (!addedTile) | 266 if (!addedTile) |
265 CRASH(); | 267 CRASH(); |
266 if (!tileAt(i, j)) | 268 if (!tileAt(i, j)) |
267 CRASH(); | 269 CRASH(); |
268 | 270 |
269 return addedTile; | 271 return addedTile; |
270 } | 272 } |
271 | 273 |
272 void TiledLayer::setNeedsDisplayRect(const FloatRect& dirtyRect) | 274 void TiledLayer::setNeedsDisplayRect(const gfx::RectF& dirtyRect) |
273 { | 275 { |
274 invalidateContentRect(layerRectToContentRect(dirtyRect)); | 276 invalidateContentRect(layerRectToContentRect(dirtyRect)); |
275 ContentsScalingLayer::setNeedsDisplayRect(dirtyRect); | 277 ContentsScalingLayer::setNeedsDisplayRect(dirtyRect); |
276 } | 278 } |
277 | 279 |
278 void TiledLayer::setUseLCDText(bool useLCDText) | 280 void TiledLayer::setUseLCDText(bool useLCDText) |
279 { | 281 { |
280 ContentsScalingLayer::setUseLCDText(useLCDText); | 282 ContentsScalingLayer::setUseLCDText(useLCDText); |
281 | 283 |
282 LayerTilingData::BorderTexelOption borderTexelOption; | 284 LayerTilingData::BorderTexelOption borderTexelOption; |
283 #if OS(ANDROID) | 285 #if OS(ANDROID) |
284 // Always want border texels and GL_LINEAR due to pinch zoom. | 286 // Always want border texels and GL_LINEAR due to pinch zoom. |
285 borderTexelOption = LayerTilingData::HasBorderTexels; | 287 borderTexelOption = LayerTilingData::HasBorderTexels; |
286 #else | 288 #else |
287 borderTexelOption = useLCDText ? LayerTilingData::NoBorderTexels : LayerTili
ngData::HasBorderTexels; | 289 borderTexelOption = useLCDText ? LayerTilingData::NoBorderTexels : LayerTili
ngData::HasBorderTexels; |
288 #endif | 290 #endif |
289 setBorderTexelOption(borderTexelOption); | 291 setBorderTexelOption(borderTexelOption); |
290 } | 292 } |
291 | 293 |
292 void TiledLayer::invalidateContentRect(const IntRect& contentRect) | 294 void TiledLayer::invalidateContentRect(const gfx::Rect& contentRect) |
293 { | 295 { |
294 updateBounds(); | 296 updateBounds(); |
295 if (m_tiler->isEmpty() || contentRect.isEmpty() || m_skipsDraw) | 297 if (m_tiler->isEmpty() || contentRect.IsEmpty() || m_skipsDraw) |
296 return; | 298 return; |
297 | 299 |
298 for (LayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(
); iter != m_tiler->tiles().end(); ++iter) { | 300 for (LayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(
); iter != m_tiler->tiles().end(); ++iter) { |
299 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); | 301 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); |
300 DCHECK(tile); | 302 DCHECK(tile); |
301 // FIXME: This should not ever be null. | 303 // FIXME: This should not ever be null. |
302 if (!tile) | 304 if (!tile) |
303 continue; | 305 continue; |
304 IntRect bound = m_tiler->tileRect(tile); | 306 gfx::Rect bound = m_tiler->tileRect(tile); |
305 bound.intersect(contentRect); | 307 bound.Intersect(contentRect); |
306 tile->dirtyRect.unite(bound); | 308 tile->dirtyRect.Union(bound); |
307 } | 309 } |
308 } | 310 } |
309 | 311 |
310 // Returns true if tile is dirty and only part of it needs to be updated. | 312 // Returns true if tile is dirty and only part of it needs to be updated. |
311 bool TiledLayer::tileOnlyNeedsPartialUpdate(UpdatableTile* tile) | 313 bool TiledLayer::tileOnlyNeedsPartialUpdate(UpdatableTile* tile) |
312 { | 314 { |
313 return !tile->dirtyRect.contains(m_tiler->tileRect(tile)) && tile->managedTe
xture()->haveBackingTexture(); | 315 return !tile->dirtyRect.Contains(m_tiler->tileRect(tile)) && tile->managedTe
xture()->haveBackingTexture(); |
314 } | 316 } |
315 | 317 |
316 bool TiledLayer::updateTiles(int left, int top, int right, int bottom, ResourceU
pdateQueue& queue, const OcclusionTracker* occlusion, RenderingStats& stats, boo
l& didPaint) | 318 bool TiledLayer::updateTiles(int left, int top, int right, int bottom, ResourceU
pdateQueue& queue, const OcclusionTracker* occlusion, RenderingStats& stats, boo
l& didPaint) |
317 { | 319 { |
318 didPaint = false; | 320 didPaint = false; |
319 createUpdaterIfNeeded(); | 321 createUpdaterIfNeeded(); |
320 | 322 |
321 bool ignoreOcclusions = !occlusion; | 323 bool ignoreOcclusions = !occlusion; |
322 if (!haveTexturesForTiles(left, top, right, bottom, ignoreOcclusions)) { | 324 if (!haveTexturesForTiles(left, top, right, bottom, ignoreOcclusions)) { |
323 m_failedUpdate = true; | 325 m_failedUpdate = true; |
324 return false; | 326 return false; |
325 } | 327 } |
326 | 328 |
327 IntRect paintRect = markTilesForUpdate(left, top, right, bottom, ignoreOcclu
sions); | 329 gfx::Rect paintRect = markTilesForUpdate(left, top, right, bottom, ignoreOcc
lusions); |
328 | 330 |
329 if (occlusion) | 331 if (occlusion) |
330 occlusion->overdrawMetrics().didPaint(paintRect); | 332 occlusion->overdrawMetrics().didPaint(cc::IntRect(paintRect)); |
331 | 333 |
332 if (paintRect.isEmpty()) | 334 if (paintRect.IsEmpty()) |
333 return true; | 335 return true; |
334 | 336 |
335 didPaint = true; | 337 didPaint = true; |
336 updateTileTextures(paintRect, left, top, right, bottom, queue, occlusion, st
ats); | 338 updateTileTextures(paintRect, left, top, right, bottom, queue, occlusion, st
ats); |
337 return true; | 339 return true; |
338 } | 340 } |
339 | 341 |
340 void TiledLayer::markOcclusionsAndRequestTextures(int left, int top, int right,
int bottom, const OcclusionTracker* occlusion) | 342 void TiledLayer::markOcclusionsAndRequestTextures(int left, int top, int right,
int bottom, const OcclusionTracker* occlusion) |
341 { | 343 { |
342 // There is some difficult dependancies between occlusions, recording occlus
ion metrics | 344 // There is some difficult dependancies between occlusions, recording occlus
ion metrics |
343 // and requesting memory so those are encapsulated in this function: | 345 // and requesting memory so those are encapsulated in this function: |
344 // - We only want to call requestLate on unoccluded textures (to preserve | 346 // - We only want to call requestLate on unoccluded textures (to preserve |
345 // memory for other layers when near OOM). | 347 // memory for other layers when near OOM). |
346 // - We only want to record occlusion metrics if all memory requests succeed
. | 348 // - We only want to record occlusion metrics if all memory requests succeed
. |
347 | 349 |
348 int occludedTileCount = 0; | 350 int occludedTileCount = 0; |
349 bool succeeded = true; | 351 bool succeeded = true; |
350 for (int j = top; j <= bottom; ++j) { | 352 for (int j = top; j <= bottom; ++j) { |
351 for (int i = left; i <= right; ++i) { | 353 for (int i = left; i <= right; ++i) { |
352 UpdatableTile* tile = tileAt(i, j); | 354 UpdatableTile* tile = tileAt(i, j); |
353 DCHECK(tile); // Did setTexturePriorities get skipped? | 355 DCHECK(tile); // Did setTexturePriorities get skipped? |
354 // FIXME: This should not ever be null. | 356 // FIXME: This should not ever be null. |
355 if (!tile) | 357 if (!tile) |
356 continue; | 358 continue; |
357 DCHECK(!tile->occluded); // Did resetUpdateState get skipped? Are we
doing more than one occlusion pass? | 359 DCHECK(!tile->occluded); // Did resetUpdateState get skipped? Are we
doing more than one occlusion pass? |
358 IntRect visibleTileRect = intersection(m_tiler->tileBounds(i, j), vi
sibleContentRect()); | 360 gfx::Rect visibleTileRect = gfx::IntersectRects(m_tiler->tileBounds(
i, j), visibleContentRect()); |
359 if (occlusion && occlusion->occluded(renderTarget(), visibleTileRect
, drawTransform(), drawTransformIsAnimating(), drawableContentRect())) { | 361 if (occlusion && occlusion->occluded(renderTarget(), visibleTileRect
, drawTransform(), drawTransformIsAnimating(), drawableContentRect())) { |
360 tile->occluded = true; | 362 tile->occluded = true; |
361 occludedTileCount++; | 363 occludedTileCount++; |
362 } else { | 364 } else { |
363 succeeded &= tile->managedTexture()->requestLate(); | 365 succeeded &= tile->managedTexture()->requestLate(); |
364 } | 366 } |
365 } | 367 } |
366 } | 368 } |
367 | 369 |
368 if (!succeeded) | 370 if (!succeeded) |
(...skipping 21 matching lines...) Expand all Loading... |
390 if (tile->occluded && !ignoreOcclusions) | 392 if (tile->occluded && !ignoreOcclusions) |
391 continue; | 393 continue; |
392 | 394 |
393 if (!tile->managedTexture()->canAcquireBackingTexture()) | 395 if (!tile->managedTexture()->canAcquireBackingTexture()) |
394 return false; | 396 return false; |
395 } | 397 } |
396 } | 398 } |
397 return true; | 399 return true; |
398 } | 400 } |
399 | 401 |
400 IntRect TiledLayer::markTilesForUpdate(int left, int top, int right, int bottom,
bool ignoreOcclusions) | 402 gfx::Rect TiledLayer::markTilesForUpdate(int left, int top, int right, int botto
m, bool ignoreOcclusions) |
401 { | 403 { |
402 IntRect paintRect; | 404 gfx::Rect paintRect; |
403 for (int j = top; j <= bottom; ++j) { | 405 for (int j = top; j <= bottom; ++j) { |
404 for (int i = left; i <= right; ++i) { | 406 for (int i = left; i <= right; ++i) { |
405 UpdatableTile* tile = tileAt(i, j); | 407 UpdatableTile* tile = tileAt(i, j); |
406 DCHECK(tile); // Did setTexturePriorites get skipped? | 408 DCHECK(tile); // Did setTexturePriorites get skipped? |
407 // FIXME: This should not ever be null. | 409 // FIXME: This should not ever be null. |
408 if (!tile) | 410 if (!tile) |
409 continue; | 411 continue; |
410 if (tile->occluded && !ignoreOcclusions) | 412 if (tile->occluded && !ignoreOcclusions) |
411 continue; | 413 continue; |
412 // FIXME: Decide if partial update should be allowed based on cost | 414 // FIXME: Decide if partial update should be allowed based on cost |
413 // of update. https://bugs.webkit.org/show_bug.cgi?id=77376 | 415 // of update. https://bugs.webkit.org/show_bug.cgi?id=77376 |
414 if (tile->isDirty() && layerTreeHost() && layerTreeHost()->bufferedU
pdates()) { | 416 if (tile->isDirty() && layerTreeHost() && layerTreeHost()->bufferedU
pdates()) { |
415 // If we get a partial update, we use the same texture, otherwis
e return the | 417 // If we get a partial update, we use the same texture, otherwis
e return the |
416 // current texture backing, so we don't update visible textures
non-atomically. | 418 // current texture backing, so we don't update visible textures
non-atomically. |
417 // If the current backing is in-use, it won't be deleted until a
fter the commit | 419 // If the current backing is in-use, it won't be deleted until a
fter the commit |
418 // as the texture manager will not allow deletion or recycling o
f in-use textures. | 420 // as the texture manager will not allow deletion or recycling o
f in-use textures. |
419 if (tileOnlyNeedsPartialUpdate(tile) && layerTreeHost()->request
PartialTextureUpdate()) | 421 if (tileOnlyNeedsPartialUpdate(tile) && layerTreeHost()->request
PartialTextureUpdate()) |
420 tile->partialUpdate = true; | 422 tile->partialUpdate = true; |
421 else { | 423 else { |
422 tile->dirtyRect = m_tiler->tileRect(tile); | 424 tile->dirtyRect = m_tiler->tileRect(tile); |
423 tile->managedTexture()->returnBackingTexture(); | 425 tile->managedTexture()->returnBackingTexture(); |
424 } | 426 } |
425 } | 427 } |
426 | 428 |
427 paintRect.unite(tile->dirtyRect); | 429 paintRect.Union(tile->dirtyRect); |
428 tile->markForUpdate(); | 430 tile->markForUpdate(); |
429 } | 431 } |
430 } | 432 } |
431 return paintRect; | 433 return paintRect; |
432 } | 434 } |
433 | 435 |
434 void TiledLayer::updateTileTextures(const IntRect& paintRect, int left, int top,
int right, int bottom, ResourceUpdateQueue& queue, const OcclusionTracker* occl
usion, RenderingStats& stats) | 436 void TiledLayer::updateTileTextures(const gfx::Rect& paintRect, int left, int to
p, int right, int bottom, ResourceUpdateQueue& queue, const OcclusionTracker* oc
clusion, RenderingStats& stats) |
435 { | 437 { |
436 // The updateRect should be in layer space. So we have to convert the paintR
ect from content space to layer space. | 438 // The updateRect should be in layer space. So we have to convert the paintR
ect from content space to layer space. |
437 m_updateRect = FloatRect(paintRect); | |
438 float widthScale = bounds().width() / static_cast<float>(contentBounds().wid
th()); | 439 float widthScale = bounds().width() / static_cast<float>(contentBounds().wid
th()); |
439 float heightScale = bounds().height() / static_cast<float>(contentBounds().h
eight()); | 440 float heightScale = bounds().height() / static_cast<float>(contentBounds().h
eight()); |
440 m_updateRect.scale(widthScale, heightScale); | 441 m_updateRect = gfx::ScaleRect(paintRect, widthScale, heightScale); |
441 | 442 |
442 // Calling prepareToUpdate() calls into WebKit to paint, which may have the
side | 443 // Calling prepareToUpdate() calls into WebKit to paint, which may have the
side |
443 // effect of disabling compositing, which causes our reference to the textur
e updater to be deleted. | 444 // effect of disabling compositing, which causes our reference to the textur
e updater to be deleted. |
444 // However, we can't free the memory backing the SkCanvas until the paint fi
nishes, | 445 // However, we can't free the memory backing the SkCanvas until the paint fi
nishes, |
445 // so we grab a local reference here to hold the updater alive until the pai
nt completes. | 446 // so we grab a local reference here to hold the updater alive until the pai
nt completes. |
446 scoped_refptr<LayerUpdater> protector(updater()); | 447 scoped_refptr<LayerUpdater> protector(updater()); |
447 gfx::Rect paintedOpaqueRect; | 448 gfx::Rect paintedOpaqueRect; |
448 updater()->prepareToUpdate(paintRect, m_tiler->tileSize(), 1 / widthScale, 1
/ heightScale, paintedOpaqueRect, stats); | 449 updater()->prepareToUpdate(paintRect, m_tiler->tileSize(), 1 / widthScale, 1
/ heightScale, paintedOpaqueRect, stats); |
449 | 450 |
450 for (int j = top; j <= bottom; ++j) { | 451 for (int j = top; j <= bottom; ++j) { |
451 for (int i = left; i <= right; ++i) { | 452 for (int i = left; i <= right; ++i) { |
452 UpdatableTile* tile = tileAt(i, j); | 453 UpdatableTile* tile = tileAt(i, j); |
453 DCHECK(tile); // Did setTexturePriorites get skipped? | 454 DCHECK(tile); // Did setTexturePriorites get skipped? |
454 // FIXME: This should not ever be null. | 455 // FIXME: This should not ever be null. |
455 if (!tile) | 456 if (!tile) |
456 continue; | 457 continue; |
457 | 458 |
458 IntRect tileRect = m_tiler->tileBounds(i, j); | 459 gfx::Rect tileRect = m_tiler->tileBounds(i, j); |
459 | 460 |
460 // Use updateRect as the above loop copied the dirty rect for this f
rame to updateRect. | 461 // Use updateRect as the above loop copied the dirty rect for this f
rame to updateRect. |
461 const IntRect& dirtyRect = tile->updateRect; | 462 const gfx::Rect& dirtyRect = tile->updateRect; |
462 if (dirtyRect.isEmpty()) | 463 if (dirtyRect.IsEmpty()) |
463 continue; | 464 continue; |
464 | 465 |
465 // Save what was painted opaque in the tile. Keep the old area if th
e paint didn't touch it, and didn't paint some | 466 // Save what was painted opaque in the tile. Keep the old area if th
e paint didn't touch it, and didn't paint some |
466 // other part of the tile opaque. | 467 // other part of the tile opaque. |
467 IntRect tilePaintedRect = intersection(tileRect, paintRect); | 468 gfx::Rect tilePaintedRect = gfx::IntersectRects(tileRect, paintRect)
; |
468 IntRect tilePaintedOpaqueRect = intersection(tileRect, cc::IntRect(p
aintedOpaqueRect)); | 469 gfx::Rect tilePaintedOpaqueRect = gfx::IntersectRects(tileRect, pain
tedOpaqueRect); |
469 if (!tilePaintedRect.isEmpty()) { | 470 if (!tilePaintedRect.IsEmpty()) { |
470 IntRect paintInsideTileOpaqueRect = intersection(tile->opaqueRec
t(), tilePaintedRect); | 471 gfx::Rect paintInsideTileOpaqueRect = gfx::IntersectRects(tile->
opaqueRect(), tilePaintedRect); |
471 bool paintInsideTileOpaqueRectIsNonOpaque = !tilePaintedOpaqueRe
ct.contains(paintInsideTileOpaqueRect); | 472 bool paintInsideTileOpaqueRectIsNonOpaque = !tilePaintedOpaqueRe
ct.Contains(paintInsideTileOpaqueRect); |
472 bool opaquePaintNotInsideTileOpaqueRect = !tilePaintedOpaqueRect
.isEmpty() && !tile->opaqueRect().contains(tilePaintedOpaqueRect); | 473 bool opaquePaintNotInsideTileOpaqueRect = !tilePaintedOpaqueRect
.IsEmpty() && !tile->opaqueRect().Contains(tilePaintedOpaqueRect); |
473 | 474 |
474 if (paintInsideTileOpaqueRectIsNonOpaque || opaquePaintNotInside
TileOpaqueRect) | 475 if (paintInsideTileOpaqueRectIsNonOpaque || opaquePaintNotInside
TileOpaqueRect) |
475 tile->setOpaqueRect(tilePaintedOpaqueRect); | 476 tile->setOpaqueRect(tilePaintedOpaqueRect); |
476 } | 477 } |
477 | 478 |
478 // sourceRect starts as a full-sized tile with border texels include
d. | 479 // sourceRect starts as a full-sized tile with border texels include
d. |
479 IntRect sourceRect = m_tiler->tileRect(tile); | 480 gfx::Rect sourceRect = m_tiler->tileRect(tile); |
480 sourceRect.intersect(dirtyRect); | 481 sourceRect.Intersect(dirtyRect); |
481 // Paint rect not guaranteed to line up on tile boundaries, so | 482 // Paint rect not guaranteed to line up on tile boundaries, so |
482 // make sure that sourceRect doesn't extend outside of it. | 483 // make sure that sourceRect doesn't extend outside of it. |
483 sourceRect.intersect(paintRect); | 484 sourceRect.Intersect(paintRect); |
484 | 485 |
485 tile->updateRect = sourceRect; | 486 tile->updateRect = sourceRect; |
486 | 487 |
487 if (sourceRect.isEmpty()) | 488 if (sourceRect.IsEmpty()) |
488 continue; | 489 continue; |
489 | 490 |
490 const IntPoint anchor = m_tiler->tileRect(tile).location(); | 491 const gfx::Point anchor = m_tiler->tileRect(tile).origin(); |
491 | 492 |
492 // Calculate tile-space rectangle to upload into. | 493 // Calculate tile-space rectangle to upload into. |
493 gfx::Vector2d destOffset(sourceRect.x() - anchor.x(), sourceRect.y()
- anchor.y()); | 494 gfx::Vector2d destOffset = sourceRect.origin() - anchor; |
494 if (destOffset.x() < 0) | 495 if (destOffset.x() < 0) |
495 CRASH(); | 496 CRASH(); |
496 if (destOffset.y() < 0) | 497 if (destOffset.y() < 0) |
497 CRASH(); | 498 CRASH(); |
498 | 499 |
499 // Offset from paint rectangle to this tile's dirty rectangle. | 500 // Offset from paint rectangle to this tile's dirty rectangle. |
500 gfx::Vector2d paintOffset(sourceRect.x() - paintRect.x(), sourceRect
.y() - paintRect.y()); | 501 gfx::Vector2d paintOffset = sourceRect.origin() - paintRect.origin()
; |
501 if (paintOffset.x() < 0) | 502 if (paintOffset.x() < 0) |
502 CRASH(); | 503 CRASH(); |
503 if (paintOffset.y() < 0) | 504 if (paintOffset.y() < 0) |
504 CRASH(); | 505 CRASH(); |
505 if (paintOffset.x() + sourceRect.width() > paintRect.width()) | 506 if (paintOffset.x() + sourceRect.width() > paintRect.width()) |
506 CRASH(); | 507 CRASH(); |
507 if (paintOffset.y() + sourceRect.height() > paintRect.height()) | 508 if (paintOffset.y() + sourceRect.height() > paintRect.height()) |
508 CRASH(); | 509 CRASH(); |
509 | 510 |
510 tile->updaterResource()->update(queue, sourceRect, destOffset, tile-
>partialUpdate, stats); | 511 tile->updaterResource()->update(queue, sourceRect, destOffset, tile-
>partialUpdate, stats); |
511 if (occlusion) | 512 if (occlusion) |
512 occlusion->overdrawMetrics().didUpload(WebTransformationMatrix()
, sourceRect, tile->opaqueRect()); | 513 occlusion->overdrawMetrics().didUpload(WebTransformationMatrix()
, cc::IntRect(sourceRect), cc::IntRect(tile->opaqueRect())); |
513 | 514 |
514 } | 515 } |
515 } | 516 } |
516 } | 517 } |
517 | 518 |
518 namespace { | 519 namespace { |
519 // This picks a small animated layer to be anything less than one viewport. This | 520 // This picks a small animated layer to be anything less than one viewport. This |
520 // is specifically for page transitions which are viewport-sized layers. The ext
ra | 521 // is specifically for page transitions which are viewport-sized layers. The ext
ra |
521 // 64 pixels is due to these layers being slightly larger than the viewport in s
ome cases. | 522 // 64 pixels is due to these layers being slightly larger than the viewport in s
ome cases. |
522 bool isSmallAnimatedLayer(TiledLayer* layer) | 523 bool isSmallAnimatedLayer(TiledLayer* layer) |
523 { | 524 { |
524 if (!layer->drawTransformIsAnimating() && !layer->screenSpaceTransformIsAnim
ating()) | 525 if (!layer->drawTransformIsAnimating() && !layer->screenSpaceTransformIsAnim
ating()) |
525 return false; | 526 return false; |
526 IntSize viewportSize = layer->layerTreeHost() ? layer->layerTreeHost()->devi
ceViewportSize() : IntSize(); | 527 gfx::Size viewportSize = layer->layerTreeHost() ? layer->layerTreeHost()->de
viceViewportSize() : gfx::Size(); |
527 IntRect contentRect(IntPoint::zero(), layer->contentBounds()); | 528 gfx::Rect contentRect(gfx::Point(), layer->contentBounds()); |
528 return contentRect.width() <= viewportSize.width() + 64 | 529 return contentRect.width() <= viewportSize.width() + 64 |
529 && contentRect.height() <= viewportSize.height() + 64; | 530 && contentRect.height() <= viewportSize.height() + 64; |
530 } | 531 } |
531 | 532 |
532 // FIXME: Remove this and make this based on distance once distance can be calcu
lated | 533 // FIXME: Remove this and make this based on distance once distance can be calcu
lated |
533 // for offscreen layers. For now, prioritize all small animated layers after 512 | 534 // for offscreen layers. For now, prioritize all small animated layers after 512 |
534 // pixels of pre-painting. | 535 // pixels of pre-painting. |
535 void setPriorityForTexture(const IntRect& visibleRect, | 536 void setPriorityForTexture(const gfx::Rect& visibleRect, |
536 const IntRect& tileRect, | 537 const gfx::Rect& tileRect, |
537 bool drawsToRoot, | 538 bool drawsToRoot, |
538 bool isSmallAnimatedLayer, | 539 bool isSmallAnimatedLayer, |
539 PrioritizedTexture* texture) | 540 PrioritizedTexture* texture) |
540 { | 541 { |
541 int priority = PriorityCalculator::lowestPriority(); | 542 int priority = PriorityCalculator::lowestPriority(); |
542 if (!visibleRect.isEmpty()) | 543 if (!visibleRect.IsEmpty()) |
543 priority = PriorityCalculator::priorityFromDistance(visibleRect, tileRec
t, drawsToRoot); | 544 priority = PriorityCalculator::priorityFromDistance(visibleRect, tileRec
t, drawsToRoot); |
544 if (isSmallAnimatedLayer) | 545 if (isSmallAnimatedLayer) |
545 priority = PriorityCalculator::maxPriority(priority, PriorityCalculator:
:smallAnimatedLayerMinPriority()); | 546 priority = PriorityCalculator::maxPriority(priority, PriorityCalculator:
:smallAnimatedLayerMinPriority()); |
546 if (priority != PriorityCalculator::lowestPriority()) | 547 if (priority != PriorityCalculator::lowestPriority()) |
547 texture->setRequestPriority(priority); | 548 texture->setRequestPriority(priority); |
548 } | 549 } |
549 } | 550 } |
550 | 551 |
551 void TiledLayer::setTexturePriorities(const PriorityCalculator& priorityCalc) | 552 void TiledLayer::setTexturePriorities(const PriorityCalculator& priorityCalc) |
552 { | 553 { |
553 updateBounds(); | 554 updateBounds(); |
554 resetUpdateState(); | 555 resetUpdateState(); |
555 updateScrollPrediction(); | 556 updateScrollPrediction(); |
556 | 557 |
557 if (m_tiler->hasEmptyBounds()) | 558 if (m_tiler->hasEmptyBounds()) |
558 return; | 559 return; |
559 | 560 |
560 bool drawsToRoot = !renderTarget()->parent(); | 561 bool drawsToRoot = !renderTarget()->parent(); |
561 bool smallAnimatedLayer = isSmallAnimatedLayer(this); | 562 bool smallAnimatedLayer = isSmallAnimatedLayer(this); |
562 | 563 |
563 // Minimally create the tiles in the desired pre-paint rect. | 564 // Minimally create the tiles in the desired pre-paint rect. |
564 IntRect createTilesRect = idlePaintRect(); | 565 gfx::Rect createTilesRect = idlePaintRect(); |
565 if (smallAnimatedLayer) | 566 if (smallAnimatedLayer) |
566 createTilesRect = IntRect(IntPoint::zero(), contentBounds()); | 567 createTilesRect = gfx::Rect(gfx::Point(), contentBounds()); |
567 if (!createTilesRect.isEmpty()) { | 568 if (!createTilesRect.IsEmpty()) { |
568 int left, top, right, bottom; | 569 int left, top, right, bottom; |
569 m_tiler->contentRectToTileIndices(createTilesRect, left, top, right, bot
tom); | 570 m_tiler->contentRectToTileIndices(createTilesRect, left, top, right, bot
tom); |
570 for (int j = top; j <= bottom; ++j) { | 571 for (int j = top; j <= bottom; ++j) { |
571 for (int i = left; i <= right; ++i) { | 572 for (int i = left; i <= right; ++i) { |
572 if (!tileAt(i, j)) | 573 if (!tileAt(i, j)) |
573 createTile(i, j); | 574 createTile(i, j); |
574 } | 575 } |
575 } | 576 } |
576 } | 577 } |
577 | 578 |
578 // Now update priorities on all tiles we have in the layer, no matter where
they are. | 579 // Now update priorities on all tiles we have in the layer, no matter where
they are. |
579 for (LayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(
); iter != m_tiler->tiles().end(); ++iter) { | 580 for (LayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(
); iter != m_tiler->tiles().end(); ++iter) { |
580 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); | 581 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); |
581 // FIXME: This should not ever be null. | 582 // FIXME: This should not ever be null. |
582 if (!tile) | 583 if (!tile) |
583 continue; | 584 continue; |
584 IntRect tileRect = m_tiler->tileRect(tile); | 585 gfx::Rect tileRect = m_tiler->tileRect(tile); |
585 setPriorityForTexture(m_predictedVisibleRect, tileRect, drawsToRoot, sma
llAnimatedLayer, tile->managedTexture()); | 586 setPriorityForTexture(m_predictedVisibleRect, tileRect, drawsToRoot, sma
llAnimatedLayer, tile->managedTexture()); |
586 } | 587 } |
587 } | 588 } |
588 | 589 |
589 Region TiledLayer::visibleContentOpaqueRegion() const | 590 Region TiledLayer::visibleContentOpaqueRegion() const |
590 { | 591 { |
591 if (m_skipsDraw) | 592 if (m_skipsDraw) |
592 return Region(); | 593 return Region(); |
593 if (contentsOpaque()) | 594 if (contentsOpaque()) |
594 return visibleContentRect(); | 595 return cc::IntRect(visibleContentRect()); |
595 return m_tiler->opaqueRegionInContentRect(visibleContentRect()); | 596 return m_tiler->opaqueRegionInContentRect(visibleContentRect()); |
596 } | 597 } |
597 | 598 |
598 void TiledLayer::resetUpdateState() | 599 void TiledLayer::resetUpdateState() |
599 { | 600 { |
600 m_skipsDraw = false; | 601 m_skipsDraw = false; |
601 m_failedUpdate = false; | 602 m_failedUpdate = false; |
602 | 603 |
603 LayerTilingData::TileMap::const_iterator end = m_tiler->tiles().end(); | 604 LayerTilingData::TileMap::const_iterator end = m_tiler->tiles().end(); |
604 for (LayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(
); iter != end; ++iter) { | 605 for (LayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(
); iter != end; ++iter) { |
605 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); | 606 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); |
606 // FIXME: This should not ever be null. | 607 // FIXME: This should not ever be null. |
607 if (!tile) | 608 if (!tile) |
608 continue; | 609 continue; |
609 tile->resetUpdateState(); | 610 tile->resetUpdateState(); |
610 } | 611 } |
611 } | 612 } |
612 | 613 |
613 namespace { | 614 namespace { |
614 IntRect expandRectByDelta(IntRect rect, IntSize delta) { | 615 gfx::Rect expandRectByDelta(gfx::Rect rect, gfx::Vector2d delta) { |
615 int width = rect.width() + abs(delta.width()); | 616 int width = rect.width() + abs(delta.x()); |
616 int height = rect.height() + abs(delta.height()); | 617 int height = rect.height() + abs(delta.y()); |
617 int x = rect.x() + ((delta.width() < 0) ? delta.width() : 0); | 618 int x = rect.x() + ((delta.x() < 0) ? delta.x() : 0); |
618 int y = rect.y() + ((delta.height() < 0) ? delta.height() : 0); | 619 int y = rect.y() + ((delta.y() < 0) ? delta.y() : 0); |
619 return IntRect(x, y, width, height); | 620 return gfx::Rect(x, y, width, height); |
620 } | 621 } |
621 } | 622 } |
622 | 623 |
623 void TiledLayer::updateScrollPrediction() | 624 void TiledLayer::updateScrollPrediction() |
624 { | 625 { |
625 // This scroll prediction is very primitive and should be replaced by a | 626 // This scroll prediction is very primitive and should be replaced by a |
626 // a recursive calculation on all layers which uses actual scroll/animation | 627 // a recursive calculation on all layers which uses actual scroll/animation |
627 // velocities. To insure this doesn't miss-predict, we only use it to predic
t | 628 // velocities. To insure this doesn't miss-predict, we only use it to predic
t |
628 // the visibleRect if: | 629 // the visibleRect if: |
629 // - contentBounds() hasn't changed. | 630 // - contentBounds() hasn't changed. |
630 // - visibleRect.size() hasn't changed. | 631 // - visibleRect.size() hasn't changed. |
631 // These two conditions prevent rotations, scales, pinch-zooms etc. where | 632 // These two conditions prevent rotations, scales, pinch-zooms etc. where |
632 // the prediction would be incorrect. | 633 // the prediction would be incorrect. |
633 IntSize delta = visibleContentRect().center() - m_previousVisibleRect.center
(); | 634 gfx::Vector2d delta = visibleContentRect().CenterPoint() - m_previousVisible
Rect.CenterPoint(); |
634 m_predictedScroll = -delta; | 635 m_predictedScroll = -delta; |
635 m_predictedVisibleRect = visibleContentRect(); | 636 m_predictedVisibleRect = visibleContentRect(); |
636 if (m_previousContentBounds == contentBounds() && m_previousVisibleRect.size
() == visibleContentRect().size()) { | 637 if (m_previousContentBounds == contentBounds() && m_previousVisibleRect.size
() == visibleContentRect().size()) { |
637 // Only expand the visible rect in the major scroll direction, to preven
t | 638 // Only expand the visible rect in the major scroll direction, to preven
t |
638 // massive paints due to diagonal scrolls. | 639 // massive paints due to diagonal scrolls. |
639 IntSize majorScrollDelta = (abs(delta.width()) > abs(delta.height())) ?
IntSize(delta.width(), 0) : IntSize(0, delta.height()); | 640 gfx::Vector2d majorScrollDelta = (abs(delta.x()) > abs(delta.y())) ? gfx
::Vector2d(delta.x(), 0) : gfx::Vector2d(0, delta.y()); |
640 m_predictedVisibleRect = expandRectByDelta(visibleContentRect(), majorSc
rollDelta); | 641 m_predictedVisibleRect = expandRectByDelta(visibleContentRect(), majorSc
rollDelta); |
641 | 642 |
642 // Bound the prediction to prevent unbounded paints, and clamp to conten
t bounds. | 643 // Bound the prediction to prevent unbounded paints, and clamp to conten
t bounds. |
643 IntRect bound = visibleContentRect(); | 644 gfx::Rect bound = visibleContentRect(); |
644 bound.inflateX(m_tiler->tileSize().width() * maxPredictiveTilesCount); | 645 bound.Inset(-m_tiler->tileSize().width() * maxPredictiveTilesCount, |
645 bound.inflateY(m_tiler->tileSize().height() * maxPredictiveTilesCount); | 646 -m_tiler->tileSize().height() * maxPredictiveTilesCount); |
646 bound.intersect(IntRect(IntPoint::zero(), contentBounds())); | 647 bound.Intersect(gfx::Rect(gfx::Point(), contentBounds())); |
647 m_predictedVisibleRect.intersect(bound); | 648 m_predictedVisibleRect.Intersect(bound); |
648 } | 649 } |
649 m_previousContentBounds = contentBounds(); | 650 m_previousContentBounds = contentBounds(); |
650 m_previousVisibleRect = visibleContentRect(); | 651 m_previousVisibleRect = visibleContentRect(); |
651 } | 652 } |
652 | 653 |
653 void TiledLayer::update(ResourceUpdateQueue& queue, const OcclusionTracker* occl
usion, RenderingStats& stats) | 654 void TiledLayer::update(ResourceUpdateQueue& queue, const OcclusionTracker* occl
usion, RenderingStats& stats) |
654 { | 655 { |
655 DCHECK(!m_skipsDraw && !m_failedUpdate); // Did resetUpdateState get skipped
? | 656 DCHECK(!m_skipsDraw && !m_failedUpdate); // Did resetUpdateState get skipped
? |
656 updateBounds(); | 657 updateBounds(); |
657 if (m_tiler->hasEmptyBounds() || !drawsContent()) | 658 if (m_tiler->hasEmptyBounds() || !drawsContent()) |
658 return; | 659 return; |
659 | 660 |
660 bool didPaint = false; | 661 bool didPaint = false; |
661 | 662 |
662 // Animation pre-paint. If the layer is small, try to paint it all | 663 // Animation pre-paint. If the layer is small, try to paint it all |
663 // immediately whether or not it is occluded, to avoid paint/upload | 664 // immediately whether or not it is occluded, to avoid paint/upload |
664 // hiccups while it is animating. | 665 // hiccups while it is animating. |
665 if (isSmallAnimatedLayer(this)) { | 666 if (isSmallAnimatedLayer(this)) { |
666 int left, top, right, bottom; | 667 int left, top, right, bottom; |
667 m_tiler->contentRectToTileIndices(IntRect(IntPoint::zero(), contentBound
s()), left, top, right, bottom); | 668 m_tiler->contentRectToTileIndices(gfx::Rect(gfx::Point(), contentBounds(
)), left, top, right, bottom); |
668 updateTiles(left, top, right, bottom, queue, 0, stats, didPaint); | 669 updateTiles(left, top, right, bottom, queue, 0, stats, didPaint); |
669 if (didPaint) | 670 if (didPaint) |
670 return; | 671 return; |
671 // This was an attempt to paint the entire layer so if we fail it's okay
, | 672 // This was an attempt to paint the entire layer so if we fail it's okay
, |
672 // just fallback on painting visible etc. below. | 673 // just fallback on painting visible etc. below. |
673 m_failedUpdate = false; | 674 m_failedUpdate = false; |
674 } | 675 } |
675 | 676 |
676 if (m_predictedVisibleRect.isEmpty()) | 677 if (m_predictedVisibleRect.IsEmpty()) |
677 return; | 678 return; |
678 | 679 |
679 // Visible painting. First occlude visible tiles and paint the non-occluded
tiles. | 680 // Visible painting. First occlude visible tiles and paint the non-occluded
tiles. |
680 int left, top, right, bottom; | 681 int left, top, right, bottom; |
681 m_tiler->contentRectToTileIndices(m_predictedVisibleRect, left, top, right,
bottom); | 682 m_tiler->contentRectToTileIndices(m_predictedVisibleRect, left, top, right,
bottom); |
682 markOcclusionsAndRequestTextures(left, top, right, bottom, occlusion); | 683 markOcclusionsAndRequestTextures(left, top, right, bottom, occlusion); |
683 m_skipsDraw = !updateTiles(left, top, right, bottom, queue, occlusion, stats
, didPaint); | 684 m_skipsDraw = !updateTiles(left, top, right, bottom, queue, occlusion, stats
, didPaint); |
684 if (m_skipsDraw) | 685 if (m_skipsDraw) |
685 m_tiler->reset(); | 686 m_tiler->reset(); |
686 if (m_skipsDraw || didPaint) | 687 if (m_skipsDraw || didPaint) |
687 return; | 688 return; |
688 | 689 |
689 // If we have already painting everything visible. Do some pre-painting whil
e idle. | 690 // If we have already painting everything visible. Do some pre-painting whil
e idle. |
690 IntRect idlePaintContentRect = idlePaintRect(); | 691 gfx::Rect idlePaintContentRect = idlePaintRect(); |
691 if (idlePaintContentRect.isEmpty()) | 692 if (idlePaintContentRect.IsEmpty()) |
692 return; | 693 return; |
693 | 694 |
694 // Prepaint anything that was occluded but inside the layer's visible region
. | 695 // Prepaint anything that was occluded but inside the layer's visible region
. |
695 if (!updateTiles(left, top, right, bottom, queue, 0, stats, didPaint) || did
Paint) | 696 if (!updateTiles(left, top, right, bottom, queue, 0, stats, didPaint) || did
Paint) |
696 return; | 697 return; |
697 | 698 |
698 int prepaintLeft, prepaintTop, prepaintRight, prepaintBottom; | 699 int prepaintLeft, prepaintTop, prepaintRight, prepaintBottom; |
699 m_tiler->contentRectToTileIndices(idlePaintContentRect, prepaintLeft, prepai
ntTop, prepaintRight, prepaintBottom); | 700 m_tiler->contentRectToTileIndices(idlePaintContentRect, prepaintLeft, prepai
ntTop, prepaintRight, prepaintBottom); |
700 | 701 |
701 // Then expand outwards one row/column at a time until we find a dirty row/c
olumn | 702 // Then expand outwards one row/column at a time until we find a dirty row/c
olumn |
702 // to update. Increment along the major and minor scroll directions first. | 703 // to update. Increment along the major and minor scroll directions first. |
703 IntSize delta = -m_predictedScroll; | 704 gfx::Vector2d delta = -m_predictedScroll; |
704 delta = IntSize(delta.width() == 0 ? 1 : delta.width(), | 705 delta = gfx::Vector2d(delta.x() == 0 ? 1 : delta.x(), |
705 delta.height() == 0 ? 1 : delta.height()); | 706 delta.y() == 0 ? 1 : delta.y()); |
706 IntSize majorDelta = (abs(delta.width()) > abs(delta.height())) ? IntSize(d
elta.width(), 0) : IntSize(0, delta.height()); | 707 gfx::Vector2d majorDelta = (abs(delta.x()) > abs(delta.y())) ? gfx::Vector2
d(delta.x(), 0) : gfx::Vector2d(0, delta.y()); |
707 IntSize minorDelta = (abs(delta.width()) <= abs(delta.height())) ? IntSize(d
elta.width(), 0) : IntSize(0, delta.height()); | 708 gfx::Vector2d minorDelta = (abs(delta.x()) <= abs(delta.y())) ? gfx::Vector2
d(delta.x(), 0) : gfx::Vector2d(0, delta.y()); |
708 IntSize deltas[4] = {majorDelta, minorDelta, -majorDelta, -minorDelta}; | 709 gfx::Vector2d deltas[4] = {majorDelta, minorDelta, -majorDelta, -minorDelta}
; |
709 for(int i = 0; i < 4; i++) { | 710 for(int i = 0; i < 4; i++) { |
710 if (deltas[i].height() > 0) { | 711 if (deltas[i].y() > 0) { |
711 while (bottom < prepaintBottom) { | 712 while (bottom < prepaintBottom) { |
712 ++bottom; | 713 ++bottom; |
713 if (!updateTiles(left, bottom, right, bottom, queue, 0, stats, d
idPaint) || didPaint) | 714 if (!updateTiles(left, bottom, right, bottom, queue, 0, stats, d
idPaint) || didPaint) |
714 return; | 715 return; |
715 } | 716 } |
716 } | 717 } |
717 if (deltas[i].height() < 0) { | 718 if (deltas[i].y() < 0) { |
718 while (top > prepaintTop) { | 719 while (top > prepaintTop) { |
719 --top; | 720 --top; |
720 if (!updateTiles(left, top, right, top, queue, 0, stats, didPain
t) || didPaint) | 721 if (!updateTiles(left, top, right, top, queue, 0, stats, didPain
t) || didPaint) |
721 return; | 722 return; |
722 } | 723 } |
723 } | 724 } |
724 if (deltas[i].width() < 0) { | 725 if (deltas[i].x() < 0) { |
725 while (left > prepaintLeft) { | 726 while (left > prepaintLeft) { |
726 --left; | 727 --left; |
727 if (!updateTiles(left, top, left, bottom, queue, 0, stats, didPa
int) || didPaint) | 728 if (!updateTiles(left, top, left, bottom, queue, 0, stats, didPa
int) || didPaint) |
728 return; | 729 return; |
729 } | 730 } |
730 } | 731 } |
731 if (deltas[i].width() > 0) { | 732 if (deltas[i].x() > 0) { |
732 while (right < prepaintRight) { | 733 while (right < prepaintRight) { |
733 ++right; | 734 ++right; |
734 if (!updateTiles(right, top, right, bottom, queue, 0, stats, did
Paint) || didPaint) | 735 if (!updateTiles(right, top, right, bottom, queue, 0, stats, did
Paint) || didPaint) |
735 return; | 736 return; |
736 } | 737 } |
737 } | 738 } |
738 } | 739 } |
739 } | 740 } |
740 | 741 |
741 bool TiledLayer::needsIdlePaint() | 742 bool TiledLayer::needsIdlePaint() |
742 { | 743 { |
743 // Don't trigger more paints if we failed (as we'll just fail again). | 744 // Don't trigger more paints if we failed (as we'll just fail again). |
744 if (m_failedUpdate || visibleContentRect().isEmpty() || m_tiler->hasEmptyBou
nds() || !drawsContent()) | 745 if (m_failedUpdate || visibleContentRect().IsEmpty() || m_tiler->hasEmptyBou
nds() || !drawsContent()) |
745 return false; | 746 return false; |
746 | 747 |
747 IntRect idlePaintContentRect = idlePaintRect(); | 748 gfx::Rect idlePaintContentRect = idlePaintRect(); |
748 if (idlePaintContentRect.isEmpty()) | 749 if (idlePaintContentRect.IsEmpty()) |
749 return false; | 750 return false; |
750 | 751 |
751 int left, top, right, bottom; | 752 int left, top, right, bottom; |
752 m_tiler->contentRectToTileIndices(idlePaintContentRect, left, top, right, bo
ttom); | 753 m_tiler->contentRectToTileIndices(idlePaintContentRect, left, top, right, bo
ttom); |
753 | 754 |
754 for (int j = top; j <= bottom; ++j) { | 755 for (int j = top; j <= bottom; ++j) { |
755 for (int i = left; i <= right; ++i) { | 756 for (int i = left; i <= right; ++i) { |
756 UpdatableTile* tile = tileAt(i, j); | 757 UpdatableTile* tile = tileAt(i, j); |
757 DCHECK(tile); // Did setTexturePriorities get skipped? | 758 DCHECK(tile); // Did setTexturePriorities get skipped? |
758 if (!tile) | 759 if (!tile) |
759 continue; | 760 continue; |
760 | 761 |
761 bool updated = !tile->updateRect.isEmpty(); | 762 bool updated = !tile->updateRect.IsEmpty(); |
762 bool canAcquire = tile->managedTexture()->canAcquireBackingTexture()
; | 763 bool canAcquire = tile->managedTexture()->canAcquireBackingTexture()
; |
763 bool dirty = tile->isDirty() || !tile->managedTexture()->haveBacking
Texture(); | 764 bool dirty = tile->isDirty() || !tile->managedTexture()->haveBacking
Texture(); |
764 if (!updated && canAcquire && dirty) | 765 if (!updated && canAcquire && dirty) |
765 return true; | 766 return true; |
766 } | 767 } |
767 } | 768 } |
768 return false; | 769 return false; |
769 } | 770 } |
770 | 771 |
771 IntRect TiledLayer::idlePaintRect() | 772 gfx::Rect TiledLayer::idlePaintRect() |
772 { | 773 { |
773 // Don't inflate an empty rect. | 774 // Don't inflate an empty rect. |
774 if (visibleContentRect().isEmpty()) | 775 if (visibleContentRect().IsEmpty()) |
775 return IntRect(); | 776 return gfx::Rect(); |
776 | 777 |
777 IntRect prepaintRect = visibleContentRect(); | 778 gfx::Rect prepaintRect = visibleContentRect(); |
778 prepaintRect.inflateX(m_tiler->tileSize().width() * prepaintColumns); | 779 prepaintRect.Inset(-m_tiler->tileSize().width() * prepaintColumns, |
779 prepaintRect.inflateY(m_tiler->tileSize().height() * prepaintRows); | 780 -m_tiler->tileSize().height() * prepaintRows); |
780 IntRect contentRect(IntPoint::zero(), contentBounds()); | 781 gfx::Rect contentRect(gfx::Point(), contentBounds()); |
781 prepaintRect.intersect(contentRect); | 782 prepaintRect.Intersect(contentRect); |
782 | 783 |
783 return prepaintRect; | 784 return prepaintRect; |
784 } | 785 } |
785 | 786 |
786 } | 787 } |
OLD | NEW |