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

Side by Side Diff: cc/tiles/picture_layer_tiling.cc

Issue 2566613002: [4/5] Add translated rasterization support for PictureLayerTilingSet & below (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/tiles/picture_layer_tiling.h" 5 #include "cc/tiles/picture_layer_tiling.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <cmath> 10 #include <cmath>
(...skipping 11 matching lines...) Expand all
22 #include "cc/tiles/prioritized_tile.h" 22 #include "cc/tiles/prioritized_tile.h"
23 #include "cc/tiles/tile.h" 23 #include "cc/tiles/tile.h"
24 #include "cc/tiles/tile_priority.h" 24 #include "cc/tiles/tile_priority.h"
25 #include "ui/gfx/geometry/point_conversions.h" 25 #include "ui/gfx/geometry/point_conversions.h"
26 #include "ui/gfx/geometry/rect_conversions.h" 26 #include "ui/gfx/geometry/rect_conversions.h"
27 #include "ui/gfx/geometry/rect_f.h" 27 #include "ui/gfx/geometry/rect_f.h"
28 #include "ui/gfx/geometry/safe_integer_conversions.h" 28 #include "ui/gfx/geometry/safe_integer_conversions.h"
29 #include "ui/gfx/geometry/size_conversions.h" 29 #include "ui/gfx/geometry/size_conversions.h"
30 30
31 namespace cc { 31 namespace cc {
32 namespace {
33 // The math is similar to gfx::Rect::ManhattanInternalDistance except that each
34 // component is scaled by the specified |scale|.
35 float ComputeScaledManhattalInternalDistance(const gfx::Rect& a,
36 const gfx::Rect& b,
37 const gfx::SizeF& scale) {
38 gfx::Rect combined(a);
39 combined.Union(b);
40
41 float x =
42 scale.width() * std::max(0, combined.width() - a.width() - b.width() + 1);
43 float y = scale.height() *
44 std::max(0, combined.height() - a.height() - b.height() + 1);
45 return x + y;
46 }
47 } // namespace
48 32
49 PictureLayerTiling::PictureLayerTiling( 33 PictureLayerTiling::PictureLayerTiling(
50 WhichTree tree, 34 WhichTree tree,
51 const gfx::SizeF& raster_scales, 35 const ScaleTranslate2d& raster_transform,
52 scoped_refptr<RasterSource> raster_source, 36 scoped_refptr<RasterSource> raster_source,
53 PictureLayerTilingClient* client, 37 PictureLayerTilingClient* client,
54 float min_preraster_distance, 38 float min_preraster_distance,
55 float max_preraster_distance) 39 float max_preraster_distance)
56 : raster_scales_(raster_scales), 40 : raster_transform_(raster_transform),
57 client_(client), 41 client_(client),
58 tree_(tree), 42 tree_(tree),
59 raster_source_(raster_source), 43 raster_source_(raster_source),
60 min_preraster_distance_(min_preraster_distance), 44 min_preraster_distance_(min_preraster_distance),
61 max_preraster_distance_(max_preraster_distance) { 45 max_preraster_distance_(max_preraster_distance) {
62 DCHECK(!raster_source->IsSolidColor()); 46 DCHECK(!raster_source->IsSolidColor());
63 gfx::Size content_bounds = 47 DCHECK_GE(raster_transform.translation().x(), 0.f);
64 gfx::ScaleToCeiledSize(raster_source_->GetSize(), raster_scales_.width(), 48 DCHECK_LT(raster_transform.translation().x(), 1.f);
65 raster_scales_.height()); 49 DCHECK_GE(raster_transform.translation().y(), 0.f);
66 gfx::Size tile_size = client_->CalculateTileSize(content_bounds); 50 DCHECK_LT(raster_transform.translation().y(), 1.f);
67 51
68 DCHECK(!gfx::ScaleToFlooredSize(raster_source_->GetSize(), 52 DCHECK(!gfx::ScaleToFlooredSize(raster_source_->GetSize(),
69 raster_scales_.width(), 53 raster_transform.scale())
70 raster_scales_.height())
71 .IsEmpty()) 54 .IsEmpty())
72 << "Tiling created with scale too small as contents become empty." 55 << "Tiling created with scale too small as contents become empty."
73 << " Layer bounds: " << raster_source_->GetSize().ToString() 56 << " Layer bounds: " << raster_source_->GetSize().ToString()
74 << " Raster scales: " << raster_scales_.ToString(); 57 << " Raster transform: " << raster_transform_.ToString();
75 58
76 tiling_data_.SetTilingSize(content_bounds); 59 gfx::Rect content_bounds_rect =
60 EnclosingContentsRectFromLayerRect(gfx::Rect(raster_source_->GetSize()));
61 gfx::Size tiling_size = gfx::Size(content_bounds_rect.bottom_right().x(),
62 content_bounds_rect.bottom_right().y());
63 tiling_data_.SetTilingSize(tiling_size);
64 gfx::Size tile_size = client_->CalculateTileSize(tiling_size);
77 tiling_data_.SetMaxTextureSize(tile_size); 65 tiling_data_.SetMaxTextureSize(tile_size);
78 } 66 }
79 67
80 PictureLayerTiling::~PictureLayerTiling() { 68 PictureLayerTiling::~PictureLayerTiling() {
81 } 69 }
82 70
83 Tile* PictureLayerTiling::CreateTile(const Tile::CreateInfo& info) { 71 Tile* PictureLayerTiling::CreateTile(const Tile::CreateInfo& info) {
84 const int i = info.tiling_i_index; 72 const int i = info.tiling_i_index;
85 const int j = info.tiling_j_index; 73 const int j = info.tiling_j_index;
86 TileMapKey key(i, j); 74 TileMapKey key(i, j);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 // If this is the pending tree, then the active twin tiling may contain 107 // If this is the pending tree, then the active twin tiling may contain
120 // the previous content ID of these tiles. In that case, we need only 108 // the previous content ID of these tiles. In that case, we need only
121 // partially raster the tile content. 109 // partially raster the tile content.
122 if (tile && invalidation && TilingMatchesTileIndices(active_twin)) { 110 if (tile && invalidation && TilingMatchesTileIndices(active_twin)) {
123 if (const Tile* old_tile = 111 if (const Tile* old_tile =
124 active_twin->TileAt(key.index_x, key.index_y)) { 112 active_twin->TileAt(key.index_x, key.index_y)) {
125 gfx::Rect tile_rect = tile->content_rect(); 113 gfx::Rect tile_rect = tile->content_rect();
126 gfx::Rect invalidated; 114 gfx::Rect invalidated;
127 for (Region::Iterator iter(*invalidation); iter.has_rect(); 115 for (Region::Iterator iter(*invalidation); iter.has_rect();
128 iter.next()) { 116 iter.next()) {
129 gfx::Rect invalid_content_rect = gfx::ScaleToEnclosingRect( 117 gfx::Rect invalid_content_rect =
130 iter.rect(), raster_scales_.width(), raster_scales_.height()); 118 EnclosingContentsRectFromLayerRect(iter.rect());
131 invalid_content_rect.Intersect(tile_rect); 119 invalid_content_rect.Intersect(tile_rect);
132 invalidated.Union(invalid_content_rect); 120 invalidated.Union(invalid_content_rect);
133 } 121 }
134 tile->SetInvalidated(invalidated, old_tile->id()); 122 tile->SetInvalidated(invalidated, old_tile->id());
135 } 123 }
136 } 124 }
137 } 125 }
138 } 126 }
139 VerifyLiveTilesRect(false); 127 VerifyLiveTilesRect(false);
140 } 128 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 pending_twin->current_eventually_rect_, 170 pending_twin->current_eventually_rect_,
183 pending_twin->current_occlusion_in_layer_space_); 171 pending_twin->current_occlusion_in_layer_space_);
184 } 172 }
185 173
186 void PictureLayerTiling::SetRasterSourceAndResize( 174 void PictureLayerTiling::SetRasterSourceAndResize(
187 scoped_refptr<RasterSource> raster_source) { 175 scoped_refptr<RasterSource> raster_source) {
188 DCHECK(!raster_source->IsSolidColor()); 176 DCHECK(!raster_source->IsSolidColor());
189 gfx::Size old_layer_bounds = raster_source_->GetSize(); 177 gfx::Size old_layer_bounds = raster_source_->GetSize();
190 raster_source_ = std::move(raster_source); 178 raster_source_ = std::move(raster_source);
191 gfx::Size new_layer_bounds = raster_source_->GetSize(); 179 gfx::Size new_layer_bounds = raster_source_->GetSize();
192 gfx::Size content_bounds = gfx::ScaleToCeiledSize( 180 gfx::Rect content_rect =
193 new_layer_bounds, raster_scales_.width(), raster_scales_.height()); 181 EnclosingContentsRectFromLayerRect(gfx::Rect(new_layer_bounds));
194 gfx::Size tile_size = client_->CalculateTileSize(content_bounds); 182 DCHECK(content_rect.origin() == gfx::Point());
183 gfx::Size tile_size = client_->CalculateTileSize(content_rect.size());
195 184
196 if (tile_size != tiling_data_.max_texture_size()) { 185 if (tile_size != tiling_data_.max_texture_size()) {
197 tiling_data_.SetTilingSize(content_bounds); 186 tiling_data_.SetTilingSize(content_rect.size());
198 tiling_data_.SetMaxTextureSize(tile_size); 187 tiling_data_.SetMaxTextureSize(tile_size);
199 // When the tile size changes, the TilingData positions no longer work 188 // When the tile size changes, the TilingData positions no longer work
200 // as valid keys to the TileMap, so just drop all tiles and clear the live 189 // as valid keys to the TileMap, so just drop all tiles and clear the live
201 // tiles rect. 190 // tiles rect.
202 Reset(); 191 Reset();
203 return; 192 return;
204 } 193 }
205 194
206 if (old_layer_bounds == new_layer_bounds) 195 if (old_layer_bounds == new_layer_bounds)
207 return; 196 return;
208 197
209 // The SetLiveTilesRect() method would drop tiles outside the new bounds, 198 // The SetLiveTilesRect() method would drop tiles outside the new bounds,
210 // but may do so incorrectly if resizing the tiling causes the number of 199 // but may do so incorrectly if resizing the tiling causes the number of
211 // tiles in the tiling_data_ to change. 200 // tiles in the tiling_data_ to change.
212 gfx::Rect content_rect(content_bounds);
213 int before_left = tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.x()); 201 int before_left = tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.x());
214 int before_top = tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.y()); 202 int before_top = tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.y());
215 int before_right = 203 int before_right =
216 tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.right() - 1); 204 tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.right() - 1);
217 int before_bottom = 205 int before_bottom =
218 tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.bottom() - 1); 206 tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.bottom() - 1);
219 207
220 // The live_tiles_rect_ is clamped to stay within the tiling size as we 208 // The live_tiles_rect_ is clamped to stay within the tiling size as we
221 // change it. 209 // change it.
222 live_tiles_rect_.Intersect(content_rect); 210 live_tiles_rect_.Intersect(content_rect);
223 tiling_data_.SetTilingSize(content_bounds); 211 tiling_data_.SetTilingSize(content_rect.size());
224 212
225 int after_right = -1; 213 int after_right = -1;
226 int after_bottom = -1; 214 int after_bottom = -1;
227 if (!live_tiles_rect_.IsEmpty()) { 215 if (!live_tiles_rect_.IsEmpty()) {
228 after_right = 216 after_right =
229 tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.right() - 1); 217 tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.right() - 1);
230 after_bottom = 218 after_bottom =
231 tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.bottom() - 1); 219 tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.bottom() - 1);
232 } 220 }
233 221
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 // 16 is fast enough. If an invalidation is huge we will fall back to a 265 // 16 is fast enough. If an invalidation is huge we will fall back to a
278 // unordered_map instead of a vector in the SmallMap. 266 // unordered_map instead of a vector in the SmallMap.
279 base::SmallMap<std::unordered_map<TileMapKey, gfx::Rect, TileMapKeyHash>, 16> 267 base::SmallMap<std::unordered_map<TileMapKey, gfx::Rect, TileMapKeyHash>, 16>
280 remove_tiles; 268 remove_tiles;
281 gfx::Rect expanded_live_tiles_rect = 269 gfx::Rect expanded_live_tiles_rect =
282 tiling_data_.ExpandRectToTileBounds(live_tiles_rect_); 270 tiling_data_.ExpandRectToTileBounds(live_tiles_rect_);
283 for (Region::Iterator iter(layer_invalidation); iter.has_rect(); 271 for (Region::Iterator iter(layer_invalidation); iter.has_rect();
284 iter.next()) { 272 iter.next()) {
285 gfx::Rect layer_rect = iter.rect(); 273 gfx::Rect layer_rect = iter.rect();
286 // The pixels which are invalid in content space. 274 // The pixels which are invalid in content space.
287 gfx::Rect invalid_content_rect = gfx::ScaleToEnclosingRect( 275 gfx::Rect invalid_content_rect =
288 layer_rect, raster_scales_.width(), raster_scales_.height()); 276 EnclosingContentsRectFromLayerRect(layer_rect);
289 gfx::Rect coverage_content_rect = invalid_content_rect; 277 gfx::Rect coverage_content_rect = invalid_content_rect;
290 // Avoid needless work by not bothering to invalidate where there aren't 278 // Avoid needless work by not bothering to invalidate where there aren't
291 // tiles. 279 // tiles.
292 coverage_content_rect.Intersect(expanded_live_tiles_rect); 280 coverage_content_rect.Intersect(expanded_live_tiles_rect);
293 if (coverage_content_rect.IsEmpty()) 281 if (coverage_content_rect.IsEmpty())
294 continue; 282 continue;
295 // Since the content_rect needs to invalidate things that only touch a 283 // Since the content_rect needs to invalidate things that only touch a
296 // border of a tile, we need to include the borders while iterating. 284 // border of a tile, we need to include the borders while iterating.
297 bool include_borders = true; 285 bool include_borders = true;
298 for (TilingData::Iterator iter(&tiling_data_, coverage_content_rect, 286 for (TilingData::Iterator iter(&tiling_data_, coverage_content_rect,
(...skipping 15 matching lines...) Expand all
314 Tile::CreateInfo info = CreateInfoForTile(key.index_x, key.index_y); 302 Tile::CreateInfo info = CreateInfoForTile(key.index_x, key.index_y);
315 if (Tile* tile = CreateTile(info)) 303 if (Tile* tile = CreateTile(info))
316 tile->SetInvalidated(invalid_content_rect, old_tile->id()); 304 tile->SetInvalidated(invalid_content_rect, old_tile->id());
317 } 305 }
318 } 306 }
319 } 307 }
320 308
321 Tile::CreateInfo PictureLayerTiling::CreateInfoForTile(int i, int j) const { 309 Tile::CreateInfo PictureLayerTiling::CreateInfoForTile(int i, int j) const {
322 gfx::Rect tile_rect = tiling_data_.TileBoundsWithBorder(i, j); 310 gfx::Rect tile_rect = tiling_data_.TileBoundsWithBorder(i, j);
323 tile_rect.set_size(tiling_data_.max_texture_size()); 311 tile_rect.set_size(tiling_data_.max_texture_size());
324 gfx::Rect enclosing_layer_rect = gfx::ScaleToEnclosingRect( 312 gfx::Rect enclosing_layer_rect =
325 tile_rect, 1.f / raster_scales_.width(), 1.f / raster_scales_.height()); 313 EnclosingLayerRectFromContentsRect(tile_rect);
326 return Tile::CreateInfo(i, j, enclosing_layer_rect, tile_rect, 314 return Tile::CreateInfo(i, j, enclosing_layer_rect, tile_rect,
327 raster_scales_); 315 raster_transform_);
328 } 316 }
329 317
330 bool PictureLayerTiling::ShouldCreateTileAt( 318 bool PictureLayerTiling::ShouldCreateTileAt(
331 const Tile::CreateInfo& info) const { 319 const Tile::CreateInfo& info) const {
332 const int i = info.tiling_i_index; 320 const int i = info.tiling_i_index;
333 const int j = info.tiling_j_index; 321 const int j = info.tiling_j_index;
334 // Active tree should always create a tile. The reason for this is that active 322 // Active tree should always create a tile. The reason for this is that active
335 // tree represents content that we draw on screen, which means that whenever 323 // tree represents content that we draw on screen, which means that whenever
336 // we check whether a tile should exist somewhere, the answer is yes. This 324 // we check whether a tile should exist somewhere, the answer is yes. This
337 // doesn't mean it will actually be created (if raster source doesn't cover 325 // doesn't mean it will actually be created (if raster source doesn't cover
(...skipping 18 matching lines...) Expand all
356 if (!active_twin->raster_source()->CoversRect(info.enclosing_layer_rect)) 344 if (!active_twin->raster_source()->CoversRect(info.enclosing_layer_rect))
357 return true; 345 return true;
358 346
359 const Region* layer_invalidation = client_->GetPendingInvalidation(); 347 const Region* layer_invalidation = client_->GetPendingInvalidation();
360 348
361 // If this tile is invalidated, then the pending tree should create one. 349 // If this tile is invalidated, then the pending tree should create one.
362 // Do the intersection test in content space to match the corresponding check 350 // Do the intersection test in content space to match the corresponding check
363 // on the active tree and avoid floating point inconsistencies. 351 // on the active tree and avoid floating point inconsistencies.
364 for (Region::Iterator iter(*layer_invalidation); iter.has_rect(); 352 for (Region::Iterator iter(*layer_invalidation); iter.has_rect();
365 iter.next()) { 353 iter.next()) {
366 gfx::Rect invalid_content_rect = gfx::ScaleToEnclosingRect( 354 gfx::Rect invalid_content_rect =
367 iter.rect(), raster_scales_.width(), raster_scales_.height()); 355 EnclosingContentsRectFromLayerRect(iter.rect());
368 if (invalid_content_rect.Intersects(info.content_rect)) 356 if (invalid_content_rect.Intersects(info.content_rect))
369 return true; 357 return true;
370 } 358 }
371 // If the active tree doesn't have a tile here, but it's in the pending tree's 359 // If the active tree doesn't have a tile here, but it's in the pending tree's
372 // visible rect, then the pending tree should create a tile. This can happen 360 // visible rect, then the pending tree should create a tile. This can happen
373 // if the pending visible rect is outside of the active tree's live tiles 361 // if the pending visible rect is outside of the active tree's live tiles
374 // rect. In those situations, we need to block activation until we're ready to 362 // rect. In those situations, we need to block activation until we're ready to
375 // display content, which will have to come from the pending tree. 363 // display content, which will have to come from the pending tree.
376 if (!active_twin->TileAt(i, j) && 364 if (!active_twin->TileAt(i, j) &&
377 current_visible_rect_.Intersects(info.content_rect)) 365 current_visible_rect_.Intersects(info.content_rect))
378 return true; 366 return true;
379 367
380 // In all other cases, the pending tree doesn't need to create a tile. 368 // In all other cases, the pending tree doesn't need to create a tile.
381 return false; 369 return false;
382 } 370 }
383 371
384 bool PictureLayerTiling::TilingMatchesTileIndices( 372 bool PictureLayerTiling::TilingMatchesTileIndices(
385 const PictureLayerTiling* twin) const { 373 const PictureLayerTiling* twin) const {
386 return tiling_data_.max_texture_size() == 374 return tiling_data_.max_texture_size() ==
387 twin->tiling_data_.max_texture_size(); 375 twin->tiling_data_.max_texture_size();
388 } 376 }
389 377
390 PictureLayerTiling::CoverageIterator::CoverageIterator() = default; 378 PictureLayerTiling::CoverageIterator::CoverageIterator() = default;
391 379
392 PictureLayerTiling::CoverageIterator::CoverageIterator( 380 PictureLayerTiling::CoverageIterator::CoverageIterator(
393 const PictureLayerTiling* tiling, 381 const PictureLayerTiling* tiling,
394 float coverage_scale, 382 float coverage_scale,
395 const gfx::Rect& coverage_rect) 383 const gfx::Rect& coverage_rect)
396 : tiling_(tiling), coverage_rect_(coverage_rect) { 384 : tiling_(tiling)
385 , coverage_rect_(coverage_rect)
386 , coverage_to_content_(ScaleTranslate2d::PreScale(tiling->raster_transform() , 1.f / coverage_scale)) {
397 DCHECK(tiling_); 387 DCHECK(tiling_);
398 // In order to avoid artifacts in geometry_rect scaling and clamping to ints, 388 // In order to avoid artifacts in geometry_rect scaling and clamping to ints,
399 // the |coverage_scale| should always be at least as big as the tiling's 389 // the |coverage_scale| should always be at least as big as the tiling's
400 // raster scales. 390 // raster scales.
401 DCHECK_GE(coverage_scale, tiling_->raster_scales_.width()); 391 DCHECK_GE(coverage_scale, tiling_->raster_transform_.scale());
402 DCHECK_GE(coverage_scale, tiling_->raster_scales_.height());
403 392
404 // Clamp |coverage_rect| to the bounds of this tiling's raster source. 393 // Clamp |coverage_rect| to the bounds of this tiling's raster source.
405 coverage_rect_max_bounds_ = 394 coverage_rect_max_bounds_ =
406 gfx::ScaleToCeiledSize(tiling->raster_source_->GetSize(), coverage_scale); 395 gfx::ScaleToCeiledSize(tiling->raster_source_->GetSize(), coverage_scale);
407 coverage_rect_.Intersect(gfx::Rect(coverage_rect_max_bounds_)); 396 coverage_rect_.Intersect(gfx::Rect(coverage_rect_max_bounds_));
408 if (coverage_rect_.IsEmpty()) 397 if (coverage_rect_.IsEmpty())
409 return; 398 return;
410 399
411 coverage_to_content_scale_ =
412 gfx::SizeF(tiling_->raster_scales_.width() / coverage_scale,
413 tiling_->raster_scales_.height() / coverage_scale);
414
415 // Find the indices of the texel samples that enclose the rect we want to 400 // Find the indices of the texel samples that enclose the rect we want to
416 // cover. 401 // cover.
417 // Because we don't know the target transform at this point, we have to be 402 // Because we don't know the target transform at this point, we have to be
418 // pessimistic, i.e. assume every point (a pair of real number, not necessary 403 // pessimistic, i.e. assume every point (a pair of real number, not necessary
419 // snapped to a pixel sample) inside of the content rect may be sampled. 404 // snapped to a pixel sample) inside of the content rect may be sampled.
420 // This code maps the boundary points into contents space, then find out the 405 // This code maps the boundary points into contents space, then find out the
421 // enclosing texture samples. For example, assume we have: 406 // enclosing texture samples. For example, assume we have:
422 // dest_scale : content_scale = 1.23 : 1 407 // coverage_scale : content_scale = 1.23 : 1
423 // dest_rect = (l:123, t:234, r:345, b:456) 408 // coverage_rect = (l:123, t:234, r:345, b:456)
424 // Then it follows that: 409 // Then it follows that:
425 // content_rect = (l:100.00, t:190.24, r:280.49, b:370.73) 410 // content_rect = (l:100.00, t:190.24, r:280.49, b:370.73)
426 // Without MSAA, the sample point of a texel is at the center of that texel, 411 // Without MSAA, the sample point of a texel is at the center of that texel,
427 // thus the sample points we need to cover content_rect are: 412 // thus the sample points we need to cover content_rect are:
428 // wanted_texels(sample coordinates) = (l:99.5, t:189.5, r:280.5, b:371.5) 413 // wanted_texels(sample coordinates) = (l:99.5, t:189.5, r:280.5, b:371.5)
429 // Or in integer index: 414 // Or in integer index:
430 // wanted_texels(integer index) = (l:99, t:189, r:280, b:371) 415 // wanted_texels(integer index) = (l:99, t:189, r:280, b:371)
431 gfx::RectF content_rect = gfx::ScaleRect(gfx::RectF(coverage_rect_), 416 gfx::RectF content_rect = coverage_to_content_.TransformRect(gfx::RectF(covera ge_rect_));
enne (OOO) 2017/01/03 22:53:53 Iterator changes definitely need unit tests.
trchen 2017/03/28 21:44:01 Done.
432 coverage_to_content_scale_.width(),
433 coverage_to_content_scale_.height());
434 content_rect.Offset(-0.5f, -0.5f); 417 content_rect.Offset(-0.5f, -0.5f);
435 gfx::Rect wanted_texels = gfx::ToEnclosingRect(content_rect); 418 gfx::Rect wanted_texels = gfx::ToEnclosingRect(content_rect);
436 419
437 const TilingData& data = tiling_->tiling_data_; 420 const TilingData& data = tiling_->tiling_data_;
438 left_ = data.LastBorderTileXIndexFromSrcCoord(wanted_texels.x()); 421 left_ = data.LastBorderTileXIndexFromSrcCoord(wanted_texels.x());
439 top_ = data.LastBorderTileYIndexFromSrcCoord(wanted_texels.y()); 422 top_ = data.LastBorderTileYIndexFromSrcCoord(wanted_texels.y());
440 right_ = std::max( 423 right_ = std::max(
441 left_, data.FirstBorderTileXIndexFromSrcCoord(wanted_texels.right())); 424 left_, data.FirstBorderTileXIndexFromSrcCoord(wanted_texels.right()));
442 bottom_ = std::max( 425 bottom_ = std::max(
443 top_, data.FirstBorderTileYIndexFromSrcCoord(wanted_texels.bottom())); 426 top_, data.FirstBorderTileYIndexFromSrcCoord(wanted_texels.bottom()));
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 // error in both u/v axis can't exceed 468 // error in both u/v axis can't exceed
486 // 255 * (1 - (1 - 1/1024) * (1 - 1/1024)) ~= 0.498 469 // 255 * (1 - (1 - 1/1024) * (1 - 1/1024)) ~= 0.498
487 // i.e. The color value can never flip over a rounding threshold. 470 // i.e. The color value can never flip over a rounding threshold.
488 constexpr float epsilon = 1.f / 1024.f; 471 constexpr float epsilon = 1.f / 1024.f;
489 texel_extent.Inset(-epsilon, -epsilon); 472 texel_extent.Inset(-epsilon, -epsilon);
490 } 473 }
491 474
492 // Convert texel_extent to coverage scale, which is what we have to report 475 // Convert texel_extent to coverage scale, which is what we have to report
493 // geometry_rect in. 476 // geometry_rect in.
494 current_geometry_rect_ = gfx::ToEnclosedRect( 477 current_geometry_rect_ = gfx::ToEnclosedRect(
495 gfx::ScaleRect(texel_extent, 1.f / coverage_to_content_scale_.width(), 478 coverage_to_content_.TransformRectReverse(texel_extent));
496 1.f / coverage_to_content_scale_.height()));
497 { 479 {
498 // Adjust external edges to cover the whole layer in dest space. 480 // Adjust external edges to cover the whole layer in dest space.
499 // 481 //
500 // For external edges, extend the tile to scaled layer bounds. This is 482 // For external edges, extend the tile to scaled layer bounds. This is
501 // needed to fully cover the coverage space because the sample extent 483 // needed to fully cover the coverage space because the sample extent
502 // doesn't cover the last 0.5 texel to layer edge, and also the coverage 484 // doesn't cover the last 0.5 texel to layer edge, and also the coverage
503 // space can be rounded up for up to 1 pixel. This overhang will never be 485 // space can be rounded up for up to 1 pixel. This overhang will never be
504 // sampled as the AA fragment shader clamps sample coordinate and 486 // sampled as the AA fragment shader clamps sample coordinate and
505 // antialiasing itself. 487 // antialiasing itself.
506 const TilingData& data = tiling_->tiling_data_; 488 const TilingData& data = tiling_->tiling_data_;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 } 531 }
550 532
551 gfx::Rect PictureLayerTiling::CoverageIterator::geometry_rect() const { 533 gfx::Rect PictureLayerTiling::CoverageIterator::geometry_rect() const {
552 return current_geometry_rect_; 534 return current_geometry_rect_;
553 } 535 }
554 536
555 gfx::RectF PictureLayerTiling::CoverageIterator::texture_rect() const { 537 gfx::RectF PictureLayerTiling::CoverageIterator::texture_rect() const {
556 auto tex_origin = gfx::PointF( 538 auto tex_origin = gfx::PointF(
557 tiling_->tiling_data_.TileBoundsWithBorder(tile_i_, tile_j_).origin()); 539 tiling_->tiling_data_.TileBoundsWithBorder(tile_i_, tile_j_).origin());
558 540
559 // Convert from dest space => content space => texture space. 541 // Convert from coverage space => content space => texture space.
560 gfx::RectF texture_rect(current_geometry_rect_); 542 gfx::RectF texture_rect(current_geometry_rect_);
561 texture_rect.Scale(coverage_to_content_scale_.width(), 543 texture_rect = coverage_to_content_.TransformRect(texture_rect);
562 coverage_to_content_scale_.height());
563 texture_rect.Intersect(gfx::RectF(gfx::SizeF(tiling_->tiling_size()))); 544 texture_rect.Intersect(gfx::RectF(gfx::SizeF(tiling_->tiling_size())));
564 if (texture_rect.IsEmpty()) 545 if (texture_rect.IsEmpty())
565 return texture_rect; 546 return texture_rect;
566 texture_rect.Offset(-tex_origin.OffsetFromOrigin()); 547 texture_rect.Offset(-tex_origin.OffsetFromOrigin());
567 548
568 return texture_rect; 549 return texture_rect;
569 } 550 }
570 551
571 ScopedTilePtr PictureLayerTiling::TakeTileAt(int i, int j) { 552 ScopedTilePtr PictureLayerTiling::TakeTileAt(int i, int j) {
572 TileMap::iterator found = tiles_.find(TileMapKey(i, j)); 553 TileMap::iterator found = tiles_.find(TileMapKey(i, j));
(...skipping 25 matching lines...) Expand all
598 const gfx::Rect& eventually_rect_in_layer_space, 579 const gfx::Rect& eventually_rect_in_layer_space,
599 float ideal_contents_scale, 580 float ideal_contents_scale,
600 const Occlusion& occlusion_in_layer_space) { 581 const Occlusion& occlusion_in_layer_space) {
601 // If we have, or had occlusions, mark the tiles as 'not done' to ensure that 582 // If we have, or had occlusions, mark the tiles as 'not done' to ensure that
602 // we reiterate the tiles for rasterization. 583 // we reiterate the tiles for rasterization.
603 if (occlusion_in_layer_space.HasOcclusion() || 584 if (occlusion_in_layer_space.HasOcclusion() ||
604 current_occlusion_in_layer_space_.HasOcclusion()) { 585 current_occlusion_in_layer_space_.HasOcclusion()) {
605 set_all_tiles_done(false); 586 set_all_tiles_done(false);
606 } 587 }
607 588
608 gfx::SizeF content_to_screen_scale( 589 const float content_to_screen_scale =
609 ideal_contents_scale / raster_scales_.width(), 590 ideal_contents_scale / raster_transform_.scale();
610 ideal_contents_scale / raster_scales_.height());
611 591
612 const gfx::Rect* input_rects[] = { 592 const gfx::Rect* input_rects[] = {
613 &visible_rect_in_layer_space, &skewport_in_layer_space, 593 &visible_rect_in_layer_space, &skewport_in_layer_space,
614 &soon_border_rect_in_layer_space, &eventually_rect_in_layer_space}; 594 &soon_border_rect_in_layer_space, &eventually_rect_in_layer_space};
615 gfx::Rect output_rects[4]; 595 gfx::Rect output_rects[4];
616 for (size_t i = 0; i < arraysize(input_rects); ++i) { 596 for (size_t i = 0; i < arraysize(input_rects); ++i)
617 output_rects[i] = gfx::ToEnclosingRect( 597 output_rects[i] = EnclosingContentsRectFromLayerRect(*input_rects[i]);
618 gfx::ScaleRect(gfx::RectF(*input_rects[i]), raster_scales_.width(),
619 raster_scales_.height()));
620 }
621 // Make sure the eventually rect is aligned to tile bounds. 598 // Make sure the eventually rect is aligned to tile bounds.
622 output_rects[3] = 599 output_rects[3] =
623 tiling_data_.ExpandRectIgnoringBordersToTileBounds(output_rects[3]); 600 tiling_data_.ExpandRectIgnoringBordersToTileBounds(output_rects[3]);
624 601
625 SetTilePriorityRects(content_to_screen_scale, output_rects[0], 602 SetTilePriorityRects(content_to_screen_scale, output_rects[0],
626 output_rects[1], output_rects[2], output_rects[3], 603 output_rects[1], output_rects[2], output_rects[3],
627 occlusion_in_layer_space); 604 occlusion_in_layer_space);
628 SetLiveTilesRect(output_rects[3]); 605 SetLiveTilesRect(output_rects[3]);
629 } 606 }
630 607
631 void PictureLayerTiling::SetTilePriorityRects( 608 void PictureLayerTiling::SetTilePriorityRects(
632 const gfx::SizeF& content_to_screen_scale, 609 float content_to_screen_scale,
633 const gfx::Rect& visible_rect_in_content_space, 610 const gfx::Rect& visible_rect_in_content_space,
634 const gfx::Rect& skewport, 611 const gfx::Rect& skewport,
635 const gfx::Rect& soon_border_rect, 612 const gfx::Rect& soon_border_rect,
636 const gfx::Rect& eventually_rect, 613 const gfx::Rect& eventually_rect,
637 const Occlusion& occlusion_in_layer_space) { 614 const Occlusion& occlusion_in_layer_space) {
638 current_visible_rect_ = visible_rect_in_content_space; 615 current_visible_rect_ = visible_rect_in_content_space;
639 current_skewport_rect_ = skewport; 616 current_skewport_rect_ = skewport;
640 current_soon_border_rect_ = soon_border_rect; 617 current_soon_border_rect_ = soon_border_rect;
641 current_eventually_rect_ = eventually_rect; 618 current_eventually_rect_ = eventually_rect;
642 current_occlusion_in_layer_space_ = occlusion_in_layer_space; 619 current_occlusion_in_layer_space_ = occlusion_in_layer_space;
643 current_content_to_screen_scale_ = content_to_screen_scale; 620 current_content_to_screen_scale_ = content_to_screen_scale;
644 621
645 gfx::Rect tiling_rect(tiling_size()); 622 gfx::Rect tiling_rect(tiling_size());
646 has_visible_rect_tiles_ = tiling_rect.Intersects(current_visible_rect_); 623 has_visible_rect_tiles_ = tiling_rect.Intersects(current_visible_rect_);
647 has_skewport_rect_tiles_ = tiling_rect.Intersects(current_skewport_rect_); 624 has_skewport_rect_tiles_ = tiling_rect.Intersects(current_skewport_rect_);
648 has_soon_border_rect_tiles_ = 625 has_soon_border_rect_tiles_ =
649 tiling_rect.Intersects(current_soon_border_rect_); 626 tiling_rect.Intersects(current_soon_border_rect_);
650 has_eventually_rect_tiles_ = tiling_rect.Intersects(current_eventually_rect_); 627 has_eventually_rect_tiles_ = tiling_rect.Intersects(current_eventually_rect_);
651 628
652 // Note that we use the largest skewport extent from the viewport as the 629 // Note that we use the largest skewport extent from the viewport as the
653 // "skewport extent". Also note that this math can't produce negative numbers, 630 // "skewport extent". Also note that this math can't produce negative numbers,
654 // since skewport.Contains(visible_rect) is always true. 631 // since skewport.Contains(visible_rect) is always true.
655 max_skewport_extent_in_screen_space_ = std::max( 632 max_skewport_extent_in_screen_space_ =
656 current_content_to_screen_scale_.width() * 633 current_content_to_screen_scale_ *
657 std::max( 634 std::max(std::max(current_visible_rect_.x() - current_skewport_rect_.x(),
658 current_visible_rect_.x() - current_skewport_rect_.x(), 635 current_skewport_rect_.right() -
659 current_skewport_rect_.right() - current_visible_rect_.right()), 636 current_visible_rect_.right()),
660 current_content_to_screen_scale_.height() * 637 std::max(current_visible_rect_.y() - current_skewport_rect_.y(),
661 std::max(current_visible_rect_.y() - current_skewport_rect_.y(), 638 current_skewport_rect_.bottom() -
662 current_skewport_rect_.bottom() - 639 current_visible_rect_.bottom()));
663 current_visible_rect_.bottom()));
664 } 640 }
665 641
666 void PictureLayerTiling::SetLiveTilesRect( 642 void PictureLayerTiling::SetLiveTilesRect(
667 const gfx::Rect& new_live_tiles_rect) { 643 const gfx::Rect& new_live_tiles_rect) {
668 DCHECK(new_live_tiles_rect.IsEmpty() || 644 DCHECK(new_live_tiles_rect.IsEmpty() ||
669 gfx::Rect(tiling_size()).Contains(new_live_tiles_rect)) 645 gfx::Rect(tiling_size()).Contains(new_live_tiles_rect))
670 << "tiling_size: " << tiling_size().ToString() 646 << "tiling_size: " << tiling_size().ToString()
671 << " new_live_tiles_rect: " << new_live_tiles_rect.ToString(); 647 << " new_live_tiles_rect: " << new_live_tiles_rect.ToString();
672 if (live_tiles_rect_ == new_live_tiles_rect) 648 if (live_tiles_rect_ == new_live_tiles_rect)
673 return; 649 return;
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
754 bool PictureLayerTiling::IsTileOccludedOnCurrentTree(const Tile* tile) const { 730 bool PictureLayerTiling::IsTileOccludedOnCurrentTree(const Tile* tile) const {
755 if (!current_occlusion_in_layer_space_.HasOcclusion()) 731 if (!current_occlusion_in_layer_space_.HasOcclusion())
756 return false; 732 return false;
757 gfx::Rect tile_query_rect = 733 gfx::Rect tile_query_rect =
758 gfx::IntersectRects(tile->content_rect(), current_visible_rect_); 734 gfx::IntersectRects(tile->content_rect(), current_visible_rect_);
759 // Explicitly check if the tile is outside the viewport. If so, we need to 735 // Explicitly check if the tile is outside the viewport. If so, we need to
760 // return false, since occlusion for this tile is unknown. 736 // return false, since occlusion for this tile is unknown.
761 if (tile_query_rect.IsEmpty()) 737 if (tile_query_rect.IsEmpty())
762 return false; 738 return false;
763 739
764 if (raster_scales_ != gfx::SizeF(1.f, 1.f)) { 740 tile_query_rect = EnclosingLayerRectFromContentsRect(tile_query_rect);
765 tile_query_rect =
766 gfx::ScaleToEnclosingRect(tile_query_rect, 1.f / raster_scales_.width(),
767 1.f / raster_scales_.height());
768 }
769 return current_occlusion_in_layer_space_.IsOccluded(tile_query_rect); 741 return current_occlusion_in_layer_space_.IsOccluded(tile_query_rect);
770 } 742 }
771 743
772 bool PictureLayerTiling::IsTileRequiredForActivation(const Tile* tile) const { 744 bool PictureLayerTiling::IsTileRequiredForActivation(const Tile* tile) const {
773 if (tree_ == PENDING_TREE) { 745 if (tree_ == PENDING_TREE) {
774 if (!can_require_tiles_for_activation_) 746 if (!can_require_tiles_for_activation_)
775 return false; 747 return false;
776 748
777 if (resolution_ != HIGH_RESOLUTION) 749 if (resolution_ != HIGH_RESOLUTION)
778 return false; 750 return false;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
840 tile->set_required_for_activation(IsTileRequiredForActivation(tile)); 812 tile->set_required_for_activation(IsTileRequiredForActivation(tile));
841 tile->set_required_for_draw(IsTileRequiredForDraw(tile)); 813 tile->set_required_for_draw(IsTileRequiredForDraw(tile));
842 } 814 }
843 815
844 PrioritizedTile PictureLayerTiling::MakePrioritizedTile( 816 PrioritizedTile PictureLayerTiling::MakePrioritizedTile(
845 Tile* tile, 817 Tile* tile,
846 PriorityRectType priority_rect_type) const { 818 PriorityRectType priority_rect_type) const {
847 DCHECK(tile); 819 DCHECK(tile);
848 DCHECK(raster_source()->CoversRect(tile->enclosing_layer_rect())) 820 DCHECK(raster_source()->CoversRect(tile->enclosing_layer_rect()))
849 << "Recording rect: " 821 << "Recording rect: "
850 << gfx::ScaleToEnclosingRect(tile->content_rect(), 822 << EnclosingLayerRectFromContentsRect(tile->content_rect()).ToString();
851 1.f / tile->raster_scales().width(),
852 1.f / tile->raster_scales().height())
853 .ToString();
854 823
855 const auto& tile_priority = ComputePriorityForTile(tile, priority_rect_type); 824 const auto& tile_priority = ComputePriorityForTile(tile, priority_rect_type);
856 // Note that TileManager will consider this flag but may rasterize the tile 825 // Note that TileManager will consider this flag but may rasterize the tile
857 // anyway (if tile is required for activation for example). We should process 826 // anyway (if tile is required for activation for example). We should process
858 // the tile for images only if it's further than half of the skewport extent. 827 // the tile for images only if it's further than half of the skewport extent.
859 bool process_for_images_only = 828 bool process_for_images_only =
860 tile_priority.distance_to_visible > min_preraster_distance_ && 829 tile_priority.distance_to_visible > min_preraster_distance_ &&
861 (tile_priority.distance_to_visible > max_preraster_distance_ || 830 (tile_priority.distance_to_visible > max_preraster_distance_ ||
862 tile_priority.distance_to_visible > 831 tile_priority.distance_to_visible >
863 0.5f * max_skewport_extent_in_screen_space_); 832 0.5f * max_skewport_extent_in_screen_space_);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
897 if (priority_bin < TilePriority::SOON) 866 if (priority_bin < TilePriority::SOON)
898 priority_bin = TilePriority::SOON; 867 priority_bin = TilePriority::SOON;
899 break; 868 break;
900 case EVENTUALLY_RECT: 869 case EVENTUALLY_RECT:
901 priority_bin = TilePriority::EVENTUALLY; 870 priority_bin = TilePriority::EVENTUALLY;
902 break; 871 break;
903 } 872 }
904 873
905 gfx::Rect tile_bounds = 874 gfx::Rect tile_bounds =
906 tiling_data_.TileBounds(tile->tiling_i_index(), tile->tiling_j_index()); 875 tiling_data_.TileBounds(tile->tiling_i_index(), tile->tiling_j_index());
907 DCHECK_GT(current_content_to_screen_scale_.width(), 0.f); 876 DCHECK_GT(current_content_to_screen_scale_, 0.f);
908 DCHECK_GT(current_content_to_screen_scale_.height(), 0.f); 877 float distance_to_visible =
909 float distance_to_visible = ComputeScaledManhattalInternalDistance( 878 current_visible_rect_.ManhattanInternalDistance(tile_bounds) *
910 current_visible_rect_, tile_bounds, current_content_to_screen_scale_); 879 current_content_to_screen_scale_;
911 880
912 return TilePriority(resolution_, priority_bin, distance_to_visible); 881 return TilePriority(resolution_, priority_bin, distance_to_visible);
913 } 882 }
914 883
915 PictureLayerTiling::PriorityRectType 884 PictureLayerTiling::PriorityRectType
916 PictureLayerTiling::ComputePriorityRectTypeForTile(const Tile* tile) const { 885 PictureLayerTiling::ComputePriorityRectTypeForTile(const Tile* tile) const {
917 DCHECK_EQ(TileAt(tile->tiling_i_index(), tile->tiling_j_index()), tile); 886 DCHECK_EQ(TileAt(tile->tiling_i_index(), tile->tiling_j_index()), tile);
918 gfx::Rect tile_bounds = 887 gfx::Rect tile_bounds =
919 tiling_data_.TileBounds(tile->tiling_i_index(), tile->tiling_j_index()); 888 tiling_data_.TileBounds(tile->tiling_i_index(), tile->tiling_j_index());
920 889
(...skipping 21 matching lines...) Expand all
942 MakePrioritizedTile(tile, ComputePriorityRectTypeForTile(tile))); 911 MakePrioritizedTile(tile, ComputePriorityRectTypeForTile(tile)));
943 } 912 }
944 } 913 }
945 914
946 void PictureLayerTiling::AsValueInto( 915 void PictureLayerTiling::AsValueInto(
947 base::trace_event::TracedValue* state) const { 916 base::trace_event::TracedValue* state) const {
948 state->SetInteger("num_tiles", base::saturated_cast<int>(tiles_.size())); 917 state->SetInteger("num_tiles", base::saturated_cast<int>(tiles_.size()));
949 // TODO(vmpstr): Change frameviewer to use raster scales. 918 // TODO(vmpstr): Change frameviewer to use raster scales.
950 state->SetDouble("content_scale", contents_scale_key()); 919 state->SetDouble("content_scale", contents_scale_key());
951 920
952 state->BeginArray("raster_scales"); 921 state->BeginArray("raster_transform");
953 state->AppendDouble(raster_scales_.width()); 922 state->AppendDouble(raster_transform_.scale());
954 state->AppendDouble(raster_scales_.height()); 923 state->AppendDouble(raster_transform_.translation().x());
924 state->AppendDouble(raster_transform_.translation().y());
955 state->EndArray(); 925 state->EndArray();
956 926
957 MathUtil::AddToTracedValue("visible_rect", current_visible_rect_, state); 927 MathUtil::AddToTracedValue("visible_rect", current_visible_rect_, state);
958 MathUtil::AddToTracedValue("skewport_rect", current_skewport_rect_, state); 928 MathUtil::AddToTracedValue("skewport_rect", current_skewport_rect_, state);
959 MathUtil::AddToTracedValue("soon_rect", current_soon_border_rect_, state); 929 MathUtil::AddToTracedValue("soon_rect", current_soon_border_rect_, state);
960 MathUtil::AddToTracedValue("eventually_rect", current_eventually_rect_, 930 MathUtil::AddToTracedValue("eventually_rect", current_eventually_rect_,
961 state); 931 state);
962 MathUtil::AddToTracedValue("tiling_size", tiling_size(), state); 932 MathUtil::AddToTracedValue("tiling_size", tiling_size(), state);
963 } 933 }
964 934
965 size_t PictureLayerTiling::GPUMemoryUsageInBytes() const { 935 size_t PictureLayerTiling::GPUMemoryUsageInBytes() const {
966 size_t amount = 0; 936 size_t amount = 0;
967 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { 937 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
968 const Tile* tile = it->second.get(); 938 const Tile* tile = it->second.get();
969 amount += tile->GPUMemoryUsageInBytes(); 939 amount += tile->GPUMemoryUsageInBytes();
970 } 940 }
971 return amount; 941 return amount;
972 } 942 }
973 943
944 gfx::Rect PictureLayerTiling::EnclosingContentsRectFromLayerRect(
945 const gfx::Rect& layer_rect) const {
946 return ToEnclosingRect(raster_transform_.TransformRect(gfx::RectF(layer_rect)) );
947 }
948
949 gfx::Rect PictureLayerTiling::EnclosingLayerRectFromContentsRect(
950 const gfx::Rect& contents_rect) const {
951 return ToEnclosingRect(
952 raster_transform_.TransformRectReverse(gfx::RectF(contents_rect)));
953 }
954
974 } // namespace cc 955 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698