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