OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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 "cc/resources/picture_pile.h" | 5 #include "cc/resources/picture_pile.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "cc/base/region.h" | 11 #include "cc/base/region.h" |
12 #include "cc/debug/rendering_stats_instrumentation.h" | 12 #include "cc/resources/picture_pile_impl.h" |
13 #include "cc/resources/raster_worker_pool.h" | 13 #include "cc/resources/raster_worker_pool.h" |
14 #include "skia/ext/analysis_canvas.h" | 14 #include "skia/ext/analysis_canvas.h" |
15 | 15 |
16 namespace { | 16 namespace { |
17 // Layout pixel buffer around the visible layer rect to record. Any base | 17 // Layout pixel buffer around the visible layer rect to record. Any base |
18 // picture that intersects the visible layer rect expanded by this distance | 18 // picture that intersects the visible layer rect expanded by this distance |
19 // will be recorded. | 19 // will be recorded. |
20 const int kPixelDistanceToRecord = 8000; | 20 const int kPixelDistanceToRecord = 8000; |
21 // We don't perform solid color analysis on images that have more than 10 skia | 21 // We don't perform solid color analysis on images that have more than 10 skia |
22 // operations. | 22 // operations. |
23 const int kOpCountThatIsOkToAnalyze = 10; | 23 const int kOpCountThatIsOkToAnalyze = 10; |
24 | 24 |
| 25 // Dimensions of the tiles in this picture pile as well as the dimensions of |
| 26 // the base picture in each tile. |
| 27 const int kBasePictureSize = 512; |
| 28 const int kTileGridBorderPixels = 1; |
| 29 #ifdef NDEBUG |
| 30 const bool kDefaultClearCanvasSetting = false; |
| 31 #else |
| 32 const bool kDefaultClearCanvasSetting = true; |
| 33 #endif |
| 34 |
| 35 // Invalidation frequency settings. kInvalidationFrequencyThreshold is a value |
| 36 // between 0 and 1 meaning invalidation frequency between 0% and 100% that |
| 37 // indicates when to stop invalidating offscreen regions. |
| 38 // kFrequentInvalidationDistanceThreshold defines what it means to be |
| 39 // "offscreen" in terms of distance to visible in css pixels. |
| 40 const float kInvalidationFrequencyThreshold = 0.75f; |
| 41 const int kFrequentInvalidationDistanceThreshold = 512; |
| 42 |
25 // TODO(humper): The density threshold here is somewhat arbitrary; need a | 43 // TODO(humper): The density threshold here is somewhat arbitrary; need a |
26 // way to set // this from the command line so we can write a benchmark | 44 // way to set // this from the command line so we can write a benchmark |
27 // script and find a sweet spot. | 45 // script and find a sweet spot. |
28 const float kDensityThreshold = 0.5f; | 46 const float kDensityThreshold = 0.5f; |
29 | 47 |
30 bool rect_sort_y(const gfx::Rect& r1, const gfx::Rect& r2) { | 48 bool rect_sort_y(const gfx::Rect& r1, const gfx::Rect& r2) { |
31 return r1.y() < r2.y() || (r1.y() == r2.y() && r1.x() < r2.x()); | 49 return r1.y() < r2.y() || (r1.y() == r2.y() && r1.x() < r2.x()); |
32 } | 50 } |
33 | 51 |
34 bool rect_sort_x(const gfx::Rect& r1, const gfx::Rect& r2) { | 52 bool rect_sort_x(const gfx::Rect& r1, const gfx::Rect& r2) { |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 | 160 |
143 *record_rects = vertical_clustering; | 161 *record_rects = vertical_clustering; |
144 return vertical_density; | 162 return vertical_density; |
145 } | 163 } |
146 | 164 |
147 } // namespace | 165 } // namespace |
148 | 166 |
149 namespace cc { | 167 namespace cc { |
150 | 168 |
151 PicturePile::PicturePile() | 169 PicturePile::PicturePile() |
152 : is_suitable_for_gpu_rasterization_(true), | 170 : min_contents_scale_(0), |
153 pixel_record_distance_(kPixelDistanceToRecord) { | 171 slow_down_raster_scale_factor_for_debug_(0), |
| 172 contents_opaque_(false), |
| 173 contents_fill_bounds_completely_(false), |
| 174 clear_canvas_with_debug_color_(kDefaultClearCanvasSetting), |
| 175 has_any_recordings_(false), |
| 176 is_mask_(false), |
| 177 is_solid_color_(false), |
| 178 solid_color_(SK_ColorTRANSPARENT), |
| 179 pixel_record_distance_(kPixelDistanceToRecord), |
| 180 is_suitable_for_gpu_rasterization_(true) { |
| 181 tiling_.SetMaxTextureSize(gfx::Size(kBasePictureSize, kBasePictureSize)); |
| 182 tile_grid_info_.fTileInterval.setEmpty(); |
| 183 tile_grid_info_.fMargin.setEmpty(); |
| 184 tile_grid_info_.fOffset.setZero(); |
154 } | 185 } |
155 | 186 |
156 PicturePile::~PicturePile() { | 187 PicturePile::~PicturePile() { |
157 } | 188 } |
158 | 189 |
159 bool PicturePile::UpdateAndExpandInvalidation( | 190 bool PicturePile::UpdateAndExpandInvalidation( |
160 ContentLayerClient* painter, | 191 ContentLayerClient* painter, |
161 Region* invalidation, | 192 Region* invalidation, |
162 SkColor background_color, | 193 SkColor background_color, |
163 bool contents_opaque, | 194 bool contents_opaque, |
164 bool contents_fill_bounds_completely, | 195 bool contents_fill_bounds_completely, |
165 const gfx::Size& layer_size, | 196 const gfx::Size& layer_size, |
166 const gfx::Rect& visible_layer_rect, | 197 const gfx::Rect& visible_layer_rect, |
167 int frame_number, | 198 int frame_number, |
168 Picture::RecordingMode recording_mode, | 199 Picture::RecordingMode recording_mode) { |
169 RenderingStatsInstrumentation* stats_instrumentation) { | |
170 background_color_ = background_color; | 200 background_color_ = background_color; |
171 contents_opaque_ = contents_opaque; | 201 contents_opaque_ = contents_opaque; |
172 contents_fill_bounds_completely_ = contents_fill_bounds_completely; | 202 contents_fill_bounds_completely_ = contents_fill_bounds_completely; |
173 | 203 |
174 bool updated = false; | 204 bool updated = false; |
175 | 205 |
176 Region resize_invalidation; | 206 Region resize_invalidation; |
177 gfx::Size old_tiling_size = tiling_size(); | 207 gfx::Size old_tiling_size = GetSize(); |
178 if (old_tiling_size != layer_size) { | 208 if (old_tiling_size != layer_size) { |
179 tiling_.SetTilingSize(layer_size); | 209 tiling_.SetTilingSize(layer_size); |
180 updated = true; | 210 updated = true; |
181 } | 211 } |
182 | 212 |
183 gfx::Rect interest_rect = visible_layer_rect; | 213 gfx::Rect interest_rect = visible_layer_rect; |
184 interest_rect.Inset(-pixel_record_distance_, -pixel_record_distance_); | 214 interest_rect.Inset(-pixel_record_distance_, -pixel_record_distance_); |
185 recorded_viewport_ = interest_rect; | 215 recorded_viewport_ = interest_rect; |
186 recorded_viewport_.Intersect(gfx::Rect(tiling_size())); | 216 recorded_viewport_.Intersect(gfx::Rect(GetSize())); |
187 | 217 |
188 gfx::Rect interest_rect_over_tiles = | 218 gfx::Rect interest_rect_over_tiles = |
189 tiling_.ExpandRectToTileBounds(interest_rect); | 219 tiling_.ExpandRectToTileBounds(interest_rect); |
190 | 220 |
| 221 gfx::Size min_tiling_size( |
| 222 std::min(GetSize().width(), old_tiling_size.width()), |
| 223 std::min(GetSize().height(), old_tiling_size.height())); |
| 224 gfx::Size max_tiling_size( |
| 225 std::max(GetSize().width(), old_tiling_size.width()), |
| 226 std::max(GetSize().height(), old_tiling_size.height())); |
| 227 |
191 if (old_tiling_size != layer_size) { | 228 if (old_tiling_size != layer_size) { |
192 has_any_recordings_ = false; | 229 has_any_recordings_ = false; |
193 | 230 |
194 // Drop recordings that are outside the new layer bounds or that changed | 231 // Drop recordings that are outside the new or old layer bounds or that |
195 // size. | 232 // changed size. Newly exposed areas are considered invalidated. |
| 233 // Previously exposed areas that are now outside of bounds also need to |
| 234 // be invalidated, as they may become part of raster when scale < 1. |
196 std::vector<PictureMapKey> to_erase; | 235 std::vector<PictureMapKey> to_erase; |
197 int min_toss_x = tiling_.num_tiles_x(); | 236 int min_toss_x = tiling_.num_tiles_x(); |
198 if (tiling_size().width() > old_tiling_size.width()) { | 237 if (max_tiling_size.width() > min_tiling_size.width()) { |
199 min_toss_x = | 238 min_toss_x = |
200 tiling_.FirstBorderTileXIndexFromSrcCoord(old_tiling_size.width()); | 239 tiling_.FirstBorderTileXIndexFromSrcCoord(min_tiling_size.width()); |
201 } | 240 } |
202 int min_toss_y = tiling_.num_tiles_y(); | 241 int min_toss_y = tiling_.num_tiles_y(); |
203 if (tiling_size().height() > old_tiling_size.height()) { | 242 if (max_tiling_size.height() > min_tiling_size.height()) { |
204 min_toss_y = | 243 min_toss_y = |
205 tiling_.FirstBorderTileYIndexFromSrcCoord(old_tiling_size.height()); | 244 tiling_.FirstBorderTileYIndexFromSrcCoord(min_tiling_size.height()); |
206 } | 245 } |
207 for (PictureMap::const_iterator it = picture_map_.begin(); | 246 for (PictureMap::const_iterator it = picture_map_.begin(); |
208 it != picture_map_.end(); | 247 it != picture_map_.end(); |
209 ++it) { | 248 ++it) { |
210 const PictureMapKey& key = it->first; | 249 const PictureMapKey& key = it->first; |
211 if (key.first < min_toss_x && key.second < min_toss_y) { | 250 if (key.first < min_toss_x && key.second < min_toss_y) { |
212 has_any_recordings_ |= !!it->second.GetPicture(); | 251 has_any_recordings_ |= !!it->second.GetPicture(); |
213 continue; | 252 continue; |
214 } | 253 } |
215 to_erase.push_back(key); | 254 to_erase.push_back(key); |
216 } | 255 } |
217 | 256 |
218 for (size_t i = 0; i < to_erase.size(); ++i) | 257 for (size_t i = 0; i < to_erase.size(); ++i) |
219 picture_map_.erase(to_erase[i]); | 258 picture_map_.erase(to_erase[i]); |
220 | 259 |
221 // If a recording is dropped and not re-recorded below, invalidate that | 260 // If a recording is dropped and not re-recorded below, invalidate that |
222 // full recording to cause any raster tiles that would use it to be | 261 // full recording to cause any raster tiles that would use it to be |
223 // dropped. | 262 // dropped. |
224 // If the recording will be replaced below, just invalidate newly exposed | 263 // If the recording will be replaced below, invalidate newly exposed |
225 // areas to force raster tiles that include the old recording to know | 264 // areas and previously exposed areas to force raster tiles that include the |
226 // there is new recording to display. | 265 // old recording to know there is new recording to display. |
227 gfx::Rect old_tiling_rect_over_tiles = | 266 gfx::Rect min_tiling_rect_over_tiles = |
228 tiling_.ExpandRectToTileBounds(gfx::Rect(old_tiling_size)); | 267 tiling_.ExpandRectToTileBounds(gfx::Rect(min_tiling_size)); |
229 if (min_toss_x < tiling_.num_tiles_x()) { | 268 if (min_toss_x < tiling_.num_tiles_x()) { |
230 // The bounds which we want to invalidate are the tiles along the old | 269 // The bounds which we want to invalidate are the tiles along the old |
231 // edge of the pile. We'll call this bounding box the OLD EDGE RECT. | 270 // edge of the pile when expanding, or the new edge of the pile when |
| 271 // shrinking. In either case, it's the difference of the two, so we'll |
| 272 // call this bounding box the DELTA EDGE RECT. |
232 // | 273 // |
233 // In the picture below, the old edge rect would be the bounding box | 274 // In the picture below, the delta edge rect would be the bounding box of |
234 // of tiles {h,i,j}. |min_toss_x| would be equal to the horizontal index | 275 // tiles {h,i,j}. |min_toss_x| would be equal to the horizontal index of |
235 // of the same tiles. | 276 // the same tiles. |
236 // | 277 // |
237 // old pile edge-v new pile edge-v | 278 // min pile edge-v max pile edge-v |
238 // ---------------+ - - - - - - - -+ | 279 // ---------------+ - - - - - - - -+ |
239 // mmppssvvyybbeeh|h . | 280 // mmppssvvyybbeeh|h . |
240 // mmppssvvyybbeeh|h . | 281 // mmppssvvyybbeeh|h . |
241 // nnqqttwwzzccffi|i . | 282 // nnqqttwwzzccffi|i . |
242 // nnqqttwwzzccffi|i . | 283 // nnqqttwwzzccffi|i . |
243 // oorruuxxaaddggj|j . | 284 // oorruuxxaaddggj|j . |
244 // oorruuxxaaddggj|j . | 285 // oorruuxxaaddggj|j . |
245 // ---------------+ - - - - - - - -+ <- old pile edge | 286 // ---------------+ - - - - - - - -+ <- min pile edge |
246 // . | 287 // . |
247 // - - - - - - - - - - - - - - - -+ <- new pile edge | 288 // - - - - - - - - - - - - - - - -+ <- max pile edge |
248 // | 289 // |
249 // If you were to slide a vertical beam from the left edge of the | 290 // If you were to slide a vertical beam from the left edge of the |
250 // old edge rect toward the right, it would either hit the right edge | 291 // delta edge rect toward the right, it would either hit the right edge |
251 // of the old edge rect, or the interest rect (expanded to the bounds | 292 // of the delta edge rect, or the interest rect (expanded to the bounds |
252 // of the tiles it touches). The same is true for a beam parallel to | 293 // of the tiles it touches). The same is true for a beam parallel to |
253 // any of the four edges, sliding accross the old edge rect. We use | 294 // any of the four edges, sliding across the delta edge rect. We use |
254 // the union of these four rectangles generated by these beams to | 295 // the union of these four rectangles generated by these beams to |
255 // determine which part of the old edge rect is outside of the expanded | 296 // determine which part of the delta edge rect is outside of the expanded |
256 // interest rect. | 297 // interest rect. |
257 // | 298 // |
258 // Case 1: Intersect rect is outside the old edge rect. It can be | 299 // Case 1: Intersect rect is outside the delta edge rect. It can be |
259 // either on the left or the right. The |left_rect| and |right_rect|, | 300 // either on the left or the right. The |left_rect| and |right_rect|, |
260 // cover this case, one will be empty and one will cover the full | 301 // cover this case, one will be empty and one will cover the full |
261 // old edge rect. In the picture below, |left_rect| would cover the | 302 // delta edge rect. In the picture below, |left_rect| would cover the |
262 // old edge rect, and |right_rect| would be empty. | 303 // delta edge rect, and |right_rect| would be empty. |
263 // +----------------------+ |^^^^^^^^^^^^^^^| | 304 // +----------------------+ |^^^^^^^^^^^^^^^| |
264 // |===> OLD EDGE RECT | | | | 305 // |===> DELTA EDGE RECT | | | |
265 // |===> | | INTEREST RECT | | 306 // |===> | | INTEREST RECT | |
266 // |===> | | | | 307 // |===> | | | |
267 // |===> | | | | 308 // |===> | | | |
268 // +----------------------+ |vvvvvvvvvvvvvvv| | 309 // +----------------------+ |vvvvvvvvvvvvvvv| |
269 // | 310 // |
270 // Case 2: Interest rect is inside the old edge rect. It will always | 311 // Case 2: Interest rect is inside the delta edge rect. It will always |
271 // fill the entire old edge rect horizontally since the old edge rect | 312 // fill the entire delta edge rect horizontally since the old edge rect |
272 // is a single tile wide, and the interest rect has been expanded to the | 313 // is a single tile wide, and the interest rect has been expanded to the |
273 // bounds of the tiles it touches. In this case the |left_rect| and | 314 // bounds of the tiles it touches. In this case the |left_rect| and |
274 // |right_rect| will be empty, but the case is handled by the |top_rect| | 315 // |right_rect| will be empty, but the case is handled by the |top_rect| |
275 // and |bottom_rect|. In the picture below, neither the |top_rect| nor | 316 // and |bottom_rect|. In the picture below, neither the |top_rect| nor |
276 // |bottom_rect| would empty, they would each cover the area of the old | 317 // |bottom_rect| would empty, they would each cover the area of the old |
277 // edge rect outside the expanded interest rect. | 318 // edge rect outside the expanded interest rect. |
278 // +-----------------+ | 319 // +-----------------+ |
279 // |:::::::::::::::::| | 320 // |:::::::::::::::::| |
280 // |:::::::::::::::::| | 321 // |:::::::::::::::::| |
281 // |vvvvvvvvvvvvvvvvv| | 322 // |vvvvvvvvvvvvvvvvv| |
282 // | | | 323 // | | |
283 // +-----------------+ | 324 // +-----------------+ |
284 // | INTEREST RECT | | 325 // | INTEREST RECT | |
285 // | | | 326 // | | |
286 // +-----------------+ | 327 // +-----------------+ |
287 // | | | 328 // | | |
288 // | OLD EDGE RECT | | 329 // | DELTA EDGE RECT | |
289 // +-----------------+ | 330 // +-----------------+ |
290 // | 331 // |
291 // Lastly, we need to consider tiles inside the expanded interest rect. | 332 // Lastly, we need to consider tiles inside the expanded interest rect. |
292 // For those tiles, we want to invalidate exactly the newly exposed | 333 // For those tiles, we want to invalidate exactly the newly exposed |
293 // pixels. In the picture below the tiles in the old edge rect have been | 334 // pixels. In the picture below the tiles in the delta edge rect have |
294 // resized and the area covered by periods must be invalidated. The | 335 // been resized and the area covered by periods must be invalidated. The |
295 // |exposed_rect| will cover exactly that area. | 336 // |exposed_rect| will cover exactly that area. |
296 // v-old pile edge | 337 // v-min pile edge |
297 // +---------+-------+ | 338 // +---------+-------+ |
298 // | ........| | 339 // | ........| |
299 // | ........| | 340 // | ........| |
300 // | OLD EDGE.RECT..| | 341 // | DELTA EDGE.RECT.| |
301 // | ........| | 342 // | ........| |
302 // | ........| | 343 // | ........| |
303 // | ........| | 344 // | ........| |
304 // | ........| | 345 // | ........| |
305 // | ........| | 346 // | ........| |
306 // | ........| | 347 // | ........| |
307 // +---------+-------+ | 348 // +---------+-------+ |
308 | 349 |
309 int left = tiling_.TilePositionX(min_toss_x); | 350 int left = tiling_.TilePositionX(min_toss_x); |
310 int right = left + tiling_.TileSizeX(min_toss_x); | 351 int right = left + tiling_.TileSizeX(min_toss_x); |
311 int top = old_tiling_rect_over_tiles.y(); | 352 int top = min_tiling_rect_over_tiles.y(); |
312 int bottom = old_tiling_rect_over_tiles.bottom(); | 353 int bottom = min_tiling_rect_over_tiles.bottom(); |
313 | 354 |
314 int left_until = std::min(interest_rect_over_tiles.x(), right); | 355 int left_until = std::min(interest_rect_over_tiles.x(), right); |
315 int right_until = std::max(interest_rect_over_tiles.right(), left); | 356 int right_until = std::max(interest_rect_over_tiles.right(), left); |
316 int top_until = std::min(interest_rect_over_tiles.y(), bottom); | 357 int top_until = std::min(interest_rect_over_tiles.y(), bottom); |
317 int bottom_until = std::max(interest_rect_over_tiles.bottom(), top); | 358 int bottom_until = std::max(interest_rect_over_tiles.bottom(), top); |
318 | 359 |
319 int exposed_left = old_tiling_size.width(); | 360 int exposed_left = min_tiling_size.width(); |
320 int exposed_left_until = tiling_size().width(); | 361 int exposed_left_until = max_tiling_size.width(); |
321 int exposed_top = top; | 362 int exposed_top = top; |
322 int exposed_bottom = tiling_size().height(); | 363 int exposed_bottom = max_tiling_size.height(); |
323 DCHECK_GE(exposed_left, left); | 364 DCHECK_GE(exposed_left, left); |
324 | 365 |
325 gfx::Rect left_rect(left, top, left_until - left, bottom - top); | 366 gfx::Rect left_rect(left, top, left_until - left, bottom - top); |
326 gfx::Rect right_rect(right_until, top, right - right_until, bottom - top); | 367 gfx::Rect right_rect(right_until, top, right - right_until, bottom - top); |
327 gfx::Rect top_rect(left, top, right - left, top_until - top); | 368 gfx::Rect top_rect(left, top, right - left, top_until - top); |
328 gfx::Rect bottom_rect( | 369 gfx::Rect bottom_rect( |
329 left, bottom_until, right - left, bottom - bottom_until); | 370 left, bottom_until, right - left, bottom - bottom_until); |
330 gfx::Rect exposed_rect(exposed_left, | 371 gfx::Rect exposed_rect(exposed_left, |
331 exposed_top, | 372 exposed_top, |
332 exposed_left_until - exposed_left, | 373 exposed_left_until - exposed_left, |
333 exposed_bottom - exposed_top); | 374 exposed_bottom - exposed_top); |
334 resize_invalidation.Union(left_rect); | 375 resize_invalidation.Union(left_rect); |
335 resize_invalidation.Union(right_rect); | 376 resize_invalidation.Union(right_rect); |
336 resize_invalidation.Union(top_rect); | 377 resize_invalidation.Union(top_rect); |
337 resize_invalidation.Union(bottom_rect); | 378 resize_invalidation.Union(bottom_rect); |
338 resize_invalidation.Union(exposed_rect); | 379 resize_invalidation.Union(exposed_rect); |
339 } | 380 } |
340 if (min_toss_y < tiling_.num_tiles_y()) { | 381 if (min_toss_y < tiling_.num_tiles_y()) { |
341 // The same thing occurs here as in the case above, but the invalidation | 382 // The same thing occurs here as in the case above, but the invalidation |
342 // rect is the bounding box around the bottom row of tiles in the old | 383 // rect is the bounding box around the bottom row of tiles in the min |
343 // pile. This would be tiles {o,r,u,x,a,d,g,j} in the above picture. | 384 // pile. This would be tiles {o,r,u,x,a,d,g,j} in the above picture. |
344 | 385 |
345 int top = tiling_.TilePositionY(min_toss_y); | 386 int top = tiling_.TilePositionY(min_toss_y); |
346 int bottom = top + tiling_.TileSizeY(min_toss_y); | 387 int bottom = top + tiling_.TileSizeY(min_toss_y); |
347 int left = old_tiling_rect_over_tiles.x(); | 388 int left = min_tiling_rect_over_tiles.x(); |
348 int right = old_tiling_rect_over_tiles.right(); | 389 int right = min_tiling_rect_over_tiles.right(); |
349 | 390 |
350 int top_until = std::min(interest_rect_over_tiles.y(), bottom); | 391 int top_until = std::min(interest_rect_over_tiles.y(), bottom); |
351 int bottom_until = std::max(interest_rect_over_tiles.bottom(), top); | 392 int bottom_until = std::max(interest_rect_over_tiles.bottom(), top); |
352 int left_until = std::min(interest_rect_over_tiles.x(), right); | 393 int left_until = std::min(interest_rect_over_tiles.x(), right); |
353 int right_until = std::max(interest_rect_over_tiles.right(), left); | 394 int right_until = std::max(interest_rect_over_tiles.right(), left); |
354 | 395 |
355 int exposed_top = old_tiling_size.height(); | 396 int exposed_top = min_tiling_size.height(); |
356 int exposed_top_until = tiling_size().height(); | 397 int exposed_top_until = max_tiling_size.height(); |
357 int exposed_left = left; | 398 int exposed_left = left; |
358 int exposed_right = tiling_size().width(); | 399 int exposed_right = max_tiling_size.width(); |
359 DCHECK_GE(exposed_top, top); | 400 DCHECK_GE(exposed_top, top); |
360 | 401 |
361 gfx::Rect left_rect(left, top, left_until - left, bottom - top); | 402 gfx::Rect left_rect(left, top, left_until - left, bottom - top); |
362 gfx::Rect right_rect(right_until, top, right - right_until, bottom - top); | 403 gfx::Rect right_rect(right_until, top, right - right_until, bottom - top); |
363 gfx::Rect top_rect(left, top, right - left, top_until - top); | 404 gfx::Rect top_rect(left, top, right - left, top_until - top); |
364 gfx::Rect bottom_rect( | 405 gfx::Rect bottom_rect( |
365 left, bottom_until, right - left, bottom - bottom_until); | 406 left, bottom_until, right - left, bottom - bottom_until); |
366 gfx::Rect exposed_rect(exposed_left, | 407 gfx::Rect exposed_rect(exposed_left, |
367 exposed_top, | 408 exposed_top, |
368 exposed_right - exposed_left, | 409 exposed_right - exposed_left, |
369 exposed_top_until - exposed_top); | 410 exposed_top_until - exposed_top); |
370 resize_invalidation.Union(left_rect); | 411 resize_invalidation.Union(left_rect); |
371 resize_invalidation.Union(right_rect); | 412 resize_invalidation.Union(right_rect); |
372 resize_invalidation.Union(top_rect); | 413 resize_invalidation.Union(top_rect); |
373 resize_invalidation.Union(bottom_rect); | 414 resize_invalidation.Union(bottom_rect); |
374 resize_invalidation.Union(exposed_rect); | 415 resize_invalidation.Union(exposed_rect); |
375 } | 416 } |
376 } | 417 } |
377 | 418 |
378 // Detect cases where the full pile is invalidated, in this situation we | 419 // Detect cases where the full pile is invalidated, in this situation we |
379 // can just drop/invalidate everything. | 420 // can just drop/invalidate everything. |
380 if (invalidation->Contains(gfx::Rect(old_tiling_size)) || | 421 if (invalidation->Contains(gfx::Rect(old_tiling_size)) || |
381 invalidation->Contains(gfx::Rect(tiling_size()))) { | 422 invalidation->Contains(gfx::Rect(GetSize()))) { |
382 for (auto& it : picture_map_) | 423 for (auto& it : picture_map_) |
383 updated = it.second.Invalidate(frame_number) || updated; | 424 updated = it.second.Invalidate(frame_number) || updated; |
384 } else { | 425 } else { |
385 // Expand invalidation that is on tiles that aren't in the interest rect and | 426 // Expand invalidation that is on tiles that aren't in the interest rect and |
386 // will not be re-recorded below. These tiles are no longer valid and should | 427 // will not be re-recorded below. These tiles are no longer valid and should |
387 // be considerered fully invalid, so we can know to not keep around raster | 428 // be considerered fully invalid, so we can know to not keep around raster |
388 // tiles that intersect with these recording tiles. | 429 // tiles that intersect with these recording tiles. |
389 Region invalidation_expanded_to_full_tiles; | 430 Region invalidation_expanded_to_full_tiles; |
390 | 431 |
391 for (Region::Iterator i(*invalidation); i.has_rect(); i.next()) { | 432 for (Region::Iterator i(*invalidation); i.has_rect(); i.next()) { |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
482 int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_); | 523 int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_); |
483 scoped_refptr<Picture> picture; | 524 scoped_refptr<Picture> picture; |
484 | 525 |
485 // Note: Currently, gathering of pixel refs when using a single | 526 // Note: Currently, gathering of pixel refs when using a single |
486 // raster thread doesn't provide any benefit. This might change | 527 // raster thread doesn't provide any benefit. This might change |
487 // in the future but we avoid it for now to reduce the cost of | 528 // in the future but we avoid it for now to reduce the cost of |
488 // Picture::Create. | 529 // Picture::Create. |
489 bool gather_pixel_refs = RasterWorkerPool::GetNumRasterThreads() > 1; | 530 bool gather_pixel_refs = RasterWorkerPool::GetNumRasterThreads() > 1; |
490 | 531 |
491 { | 532 { |
492 base::TimeDelta best_duration = base::TimeDelta::Max(); | |
493 for (int i = 0; i < repeat_count; i++) { | 533 for (int i = 0; i < repeat_count; i++) { |
494 base::TimeTicks start_time = stats_instrumentation->StartRecording(); | |
495 picture = Picture::Create(record_rect, | 534 picture = Picture::Create(record_rect, |
496 painter, | 535 painter, |
497 tile_grid_info_, | 536 tile_grid_info_, |
498 gather_pixel_refs, | 537 gather_pixel_refs, |
499 recording_mode); | 538 recording_mode); |
500 // Note the '&&' with previous is-suitable state. | 539 // Note the '&&' with previous is-suitable state. |
501 // This means that once a picture-pile becomes unsuitable for gpu | 540 // This means that once a picture-pile becomes unsuitable for gpu |
502 // rasterization due to some content, it will continue to be unsuitable | 541 // rasterization due to some content, it will continue to be unsuitable |
503 // even if that content is replaced by gpu-friendly content. | 542 // even if that content is replaced by gpu-friendly content. |
504 // This is an optimization to avoid iterating though all pictures in | 543 // This is an optimization to avoid iterating though all pictures in |
505 // the pile after each invalidation. | 544 // the pile after each invalidation. |
506 is_suitable_for_gpu_rasterization_ &= | 545 is_suitable_for_gpu_rasterization_ &= |
507 picture->IsSuitableForGpuRasterization(); | 546 picture->IsSuitableForGpuRasterization(); |
508 base::TimeDelta duration = | |
509 stats_instrumentation->EndRecording(start_time); | |
510 best_duration = std::min(duration, best_duration); | |
511 } | 547 } |
512 int recorded_pixel_count = | |
513 picture->LayerRect().width() * picture->LayerRect().height(); | |
514 stats_instrumentation->AddRecord(best_duration, recorded_pixel_count); | |
515 } | 548 } |
516 | 549 |
517 bool found_tile_for_recorded_picture = false; | 550 bool found_tile_for_recorded_picture = false; |
518 | 551 |
519 bool include_borders = true; | 552 bool include_borders = true; |
520 for (TilingData::Iterator it(&tiling_, record_rect, include_borders); it; | 553 for (TilingData::Iterator it(&tiling_, record_rect, include_borders); it; |
521 ++it) { | 554 ++it) { |
522 const PictureMapKey& key = it.index(); | 555 const PictureMapKey& key = it.index(); |
523 gfx::Rect tile = PaddedRect(key); | 556 gfx::Rect tile = PaddedRect(key); |
524 if (record_rect.Contains(tile)) { | 557 if (record_rect.Contains(tile)) { |
525 PictureInfo& info = picture_map_[key]; | 558 PictureInfo& info = picture_map_[key]; |
526 info.SetPicture(picture); | 559 info.SetPicture(picture); |
527 found_tile_for_recorded_picture = true; | 560 found_tile_for_recorded_picture = true; |
528 } | 561 } |
529 } | 562 } |
530 DetermineIfSolidColor(); | 563 DetermineIfSolidColor(); |
531 DCHECK(found_tile_for_recorded_picture); | 564 DCHECK(found_tile_for_recorded_picture); |
532 } | 565 } |
533 | 566 |
534 has_any_recordings_ = true; | 567 has_any_recordings_ = true; |
535 DCHECK(CanRasterSlowTileCheck(recorded_viewport_)); | 568 DCHECK(CanRasterSlowTileCheck(recorded_viewport_)); |
536 return true; | 569 return true; |
537 } | 570 } |
538 | 571 |
| 572 gfx::Size PicturePile::GetSize() const { |
| 573 return tiling_.tiling_size(); |
| 574 } |
| 575 |
539 void PicturePile::SetEmptyBounds() { | 576 void PicturePile::SetEmptyBounds() { |
540 tiling_.SetTilingSize(gfx::Size()); | 577 tiling_.SetTilingSize(gfx::Size()); |
541 Clear(); | 578 Clear(); |
542 } | 579 } |
543 | 580 |
| 581 void PicturePile::SetMinContentsScale(float min_contents_scale) { |
| 582 DCHECK(min_contents_scale); |
| 583 if (min_contents_scale_ == min_contents_scale) |
| 584 return; |
| 585 |
| 586 // Picture contents are played back scaled. When the final contents scale is |
| 587 // less than 1 (i.e. low res), then multiple recorded pixels will be used |
| 588 // to raster one final pixel. To avoid splitting a final pixel across |
| 589 // pictures (which would result in incorrect rasterization due to blending), a |
| 590 // buffer margin is added so that any picture can be snapped to integral |
| 591 // final pixels. |
| 592 // |
| 593 // For example, if a 1/4 contents scale is used, then that would be 3 buffer |
| 594 // pixels, since that's the minimum number of pixels to add so that resulting |
| 595 // content can be snapped to a four pixel aligned grid. |
| 596 int buffer_pixels = static_cast<int>(ceil(1 / min_contents_scale) - 1); |
| 597 buffer_pixels = std::max(0, buffer_pixels); |
| 598 SetBufferPixels(buffer_pixels); |
| 599 min_contents_scale_ = min_contents_scale; |
| 600 } |
| 601 |
| 602 // static |
| 603 void PicturePile::ComputeTileGridInfo(const gfx::Size& tile_grid_size, |
| 604 SkTileGridFactory::TileGridInfo* info) { |
| 605 DCHECK(info); |
| 606 info->fTileInterval.set(tile_grid_size.width() - 2 * kTileGridBorderPixels, |
| 607 tile_grid_size.height() - 2 * kTileGridBorderPixels); |
| 608 DCHECK_GT(info->fTileInterval.width(), 0); |
| 609 DCHECK_GT(info->fTileInterval.height(), 0); |
| 610 info->fMargin.set(kTileGridBorderPixels, kTileGridBorderPixels); |
| 611 // Offset the tile grid coordinate space to take into account the fact |
| 612 // that the top-most and left-most tiles do not have top and left borders |
| 613 // respectively. |
| 614 info->fOffset.set(-kTileGridBorderPixels, -kTileGridBorderPixels); |
| 615 } |
| 616 |
| 617 void PicturePile::SetTileGridSize(const gfx::Size& tile_grid_size) { |
| 618 ComputeTileGridInfo(tile_grid_size, &tile_grid_info_); |
| 619 } |
| 620 |
| 621 void PicturePile::SetSlowdownRasterScaleFactor(int factor) { |
| 622 slow_down_raster_scale_factor_for_debug_ = factor; |
| 623 } |
| 624 |
| 625 void PicturePile::SetIsMask(bool is_mask) { |
| 626 is_mask_ = is_mask; |
| 627 } |
| 628 |
| 629 void PicturePile::SetUnsuitableForGpuRasterizationForTesting() { |
| 630 is_suitable_for_gpu_rasterization_ = false; |
| 631 } |
| 632 |
| 633 bool PicturePile::IsSuitableForGpuRasterization() const { |
| 634 return is_suitable_for_gpu_rasterization_; |
| 635 } |
| 636 |
| 637 scoped_refptr<RasterSource> PicturePile::CreateRasterSource() const { |
| 638 return scoped_refptr<RasterSource>( |
| 639 PicturePileImpl::CreateFromPicturePile(this)); |
| 640 } |
| 641 |
| 642 SkTileGridFactory::TileGridInfo PicturePile::GetTileGridInfoForTesting() const { |
| 643 return tile_grid_info_; |
| 644 } |
| 645 |
| 646 bool PicturePile::CanRasterSlowTileCheck(const gfx::Rect& layer_rect) const { |
| 647 bool include_borders = false; |
| 648 for (TilingData::Iterator tile_iter(&tiling_, layer_rect, include_borders); |
| 649 tile_iter; ++tile_iter) { |
| 650 PictureMap::const_iterator map_iter = picture_map_.find(tile_iter.index()); |
| 651 if (map_iter == picture_map_.end()) |
| 652 return false; |
| 653 if (!map_iter->second.GetPicture()) |
| 654 return false; |
| 655 } |
| 656 return true; |
| 657 } |
| 658 |
544 void PicturePile::DetermineIfSolidColor() { | 659 void PicturePile::DetermineIfSolidColor() { |
545 is_solid_color_ = false; | 660 is_solid_color_ = false; |
546 solid_color_ = SK_ColorTRANSPARENT; | 661 solid_color_ = SK_ColorTRANSPARENT; |
547 | 662 |
548 if (picture_map_.empty()) { | 663 if (picture_map_.empty()) { |
549 return; | 664 return; |
550 } | 665 } |
551 | 666 |
552 PictureMap::const_iterator it = picture_map_.begin(); | 667 PictureMap::const_iterator it = picture_map_.begin(); |
553 const Picture* picture = it->second.GetPicture(); | 668 const Picture* picture = it->second.GetPicture(); |
(...skipping 12 matching lines...) Expand all Loading... |
566 if (it->second.GetPicture() != picture) | 681 if (it->second.GetPicture() != picture) |
567 return; | 682 return; |
568 } | 683 } |
569 skia::AnalysisCanvas canvas(recorded_viewport_.width(), | 684 skia::AnalysisCanvas canvas(recorded_viewport_.width(), |
570 recorded_viewport_.height()); | 685 recorded_viewport_.height()); |
571 canvas.translate(-recorded_viewport_.x(), -recorded_viewport_.y()); | 686 canvas.translate(-recorded_viewport_.x(), -recorded_viewport_.y()); |
572 picture->Raster(&canvas, nullptr, Region(), 1.0f); | 687 picture->Raster(&canvas, nullptr, Region(), 1.0f); |
573 is_solid_color_ = canvas.GetColorIfSolid(&solid_color_); | 688 is_solid_color_ = canvas.GetColorIfSolid(&solid_color_); |
574 } | 689 } |
575 | 690 |
| 691 gfx::Rect PicturePile::PaddedRect(const PictureMapKey& key) const { |
| 692 gfx::Rect tile = tiling_.TileBounds(key.first, key.second); |
| 693 return PadRect(tile); |
| 694 } |
| 695 |
| 696 gfx::Rect PicturePile::PadRect(const gfx::Rect& rect) const { |
| 697 gfx::Rect padded_rect = rect; |
| 698 padded_rect.Inset(-buffer_pixels(), -buffer_pixels(), -buffer_pixels(), |
| 699 -buffer_pixels()); |
| 700 return padded_rect; |
| 701 } |
| 702 |
| 703 void PicturePile::Clear() { |
| 704 picture_map_.clear(); |
| 705 recorded_viewport_ = gfx::Rect(); |
| 706 has_any_recordings_ = false; |
| 707 is_solid_color_ = false; |
| 708 } |
| 709 |
| 710 PicturePile::PictureInfo::PictureInfo() : last_frame_number_(0) { |
| 711 } |
| 712 |
| 713 PicturePile::PictureInfo::~PictureInfo() { |
| 714 } |
| 715 |
| 716 void PicturePile::PictureInfo::AdvanceInvalidationHistory(int frame_number) { |
| 717 DCHECK_GE(frame_number, last_frame_number_); |
| 718 if (frame_number == last_frame_number_) |
| 719 return; |
| 720 |
| 721 invalidation_history_ <<= (frame_number - last_frame_number_); |
| 722 last_frame_number_ = frame_number; |
| 723 } |
| 724 |
| 725 bool PicturePile::PictureInfo::Invalidate(int frame_number) { |
| 726 AdvanceInvalidationHistory(frame_number); |
| 727 invalidation_history_.set(0); |
| 728 |
| 729 bool did_invalidate = !!picture_.get(); |
| 730 picture_ = NULL; |
| 731 return did_invalidate; |
| 732 } |
| 733 |
| 734 bool PicturePile::PictureInfo::NeedsRecording(int frame_number, |
| 735 int distance_to_visible) { |
| 736 AdvanceInvalidationHistory(frame_number); |
| 737 |
| 738 // We only need recording if we don't have a picture. Furthermore, we only |
| 739 // need a recording if we're within frequent invalidation distance threshold |
| 740 // or the invalidation is not frequent enough (below invalidation frequency |
| 741 // threshold). |
| 742 return !picture_.get() && |
| 743 ((distance_to_visible <= kFrequentInvalidationDistanceThreshold) || |
| 744 (GetInvalidationFrequency() < kInvalidationFrequencyThreshold)); |
| 745 } |
| 746 |
| 747 void PicturePile::SetBufferPixels(int new_buffer_pixels) { |
| 748 if (new_buffer_pixels == buffer_pixels()) |
| 749 return; |
| 750 |
| 751 Clear(); |
| 752 tiling_.SetBorderTexels(new_buffer_pixels); |
| 753 } |
| 754 |
| 755 void PicturePile::PictureInfo::SetPicture(scoped_refptr<Picture> picture) { |
| 756 picture_ = picture; |
| 757 } |
| 758 |
| 759 const Picture* PicturePile::PictureInfo::GetPicture() const { |
| 760 return picture_.get(); |
| 761 } |
| 762 |
| 763 float PicturePile::PictureInfo::GetInvalidationFrequency() const { |
| 764 return invalidation_history_.count() / |
| 765 static_cast<float>(INVALIDATION_FRAMES_TRACKED); |
| 766 } |
| 767 |
576 } // namespace cc | 768 } // namespace cc |
OLD | NEW |