Chromium Code Reviews| 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/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 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 393 dest_rect_(dest_rect), | 393 dest_rect_(dest_rect), |
| 394 dest_to_content_scale_(0), | 394 dest_to_content_scale_(0), |
| 395 current_tile_(NULL), | 395 current_tile_(NULL), |
| 396 tile_i_(0), | 396 tile_i_(0), |
| 397 tile_j_(0), | 397 tile_j_(0), |
| 398 left_(0), | 398 left_(0), |
| 399 top_(0), | 399 top_(0), |
| 400 right_(-1), | 400 right_(-1), |
| 401 bottom_(-1) { | 401 bottom_(-1) { |
| 402 DCHECK(tiling_); | 402 DCHECK(tiling_); |
| 403 DCHECK_GE(dest_scale, tiling_->contents_scale_); | |
| 404 | |
| 405 // Clamp dest_rect_ to the bounds of the layer. | |
|
enne (OOO)
2016/09/09 21:46:34
What code was passing in a larger dest rect than t
trchen
2016/09/09 23:39:19
I don't know if we ever do that in real code, but
enne (OOO)
2016/09/15 18:06:23
This is fine. The code before was intersecting to
| |
| 406 gfx::Size dest_content_bounds = | |
| 407 gfx::ScaleToCeiledSize(tiling->raster_source_->GetSize(), dest_scale); | |
| 408 dest_rect_.Intersect(gfx::Rect(dest_content_bounds)); | |
| 403 if (dest_rect_.IsEmpty()) | 409 if (dest_rect_.IsEmpty()) |
| 404 return; | 410 return; |
| 405 | 411 |
| 406 dest_to_content_scale_ = tiling_->contents_scale_ / dest_scale; | 412 dest_to_content_scale_ = tiling_->contents_scale_ / dest_scale; |
| 407 | 413 |
| 408 gfx::Rect content_rect = | 414 // Find the indices of the texel samples that enclose the rect we want to |
| 409 gfx::ScaleToEnclosingRect(dest_rect_, | 415 // cover. |
| 410 dest_to_content_scale_, | 416 // Without MSAA, the sample point of a texel is at the center of that texel. |
| 411 dest_to_content_scale_); | 417 // For example, texel (12, 34) has sample point at (12.5, 34.5). |
|
enne (OOO)
2016/09/09 21:46:34
This isn't true when the layer is not aligned with
trchen
2016/09/09 23:39:19
It is referring to texels in the texture space. Ea
enne (OOO)
2016/09/15 18:06:23
Your description makes sense to me, but I don't fe
| |
| 412 // IndexFromSrcCoord clamps to valid tile ranges, so it's necessary to | 418 // Instead of trying to snapping to (i+0.5, j+0.5) half grids, just shift |
| 413 // check for non-intersection first. | 419 // everything by (-0.5, -0.5). |
| 414 content_rect.Intersect(gfx::Rect(tiling_->tiling_size())); | 420 gfx::RectF content_rect = |
| 415 if (content_rect.IsEmpty()) | 421 gfx::ScaleRect(gfx::RectF(dest_rect_), dest_to_content_scale_); |
| 416 return; | 422 content_rect.Offset(-0.5f, -0.5f); |
| 423 gfx::Rect wanted_texels = gfx::ToEnclosingRect(content_rect); | |
| 417 | 424 |
| 418 left_ = tiling_->tiling_data_.TileXIndexFromSrcCoord(content_rect.x()); | 425 const TilingData& data = tiling_->tiling_data_; |
| 419 top_ = tiling_->tiling_data_.TileYIndexFromSrcCoord(content_rect.y()); | 426 left_ = data.LastBorderTileXIndexFromSrcCoord(wanted_texels.x()); |
| 420 right_ = tiling_->tiling_data_.TileXIndexFromSrcCoord( | 427 top_ = data.LastBorderTileYIndexFromSrcCoord(wanted_texels.y()); |
| 421 content_rect.right() - 1); | 428 right_ = std::max( |
| 422 bottom_ = tiling_->tiling_data_.TileYIndexFromSrcCoord( | 429 left_, data.FirstBorderTileXIndexFromSrcCoord(wanted_texels.right())); |
| 423 content_rect.bottom() - 1); | 430 bottom_ = std::max( |
| 431 top_, data.FirstBorderTileYIndexFromSrcCoord(wanted_texels.bottom())); | |
| 424 | 432 |
| 425 tile_i_ = left_ - 1; | 433 tile_i_ = left_ - 1; |
| 426 tile_j_ = top_; | 434 tile_j_ = top_; |
| 427 ++(*this); | 435 ++(*this); |
| 428 } | 436 } |
| 429 | 437 |
| 430 PictureLayerTiling::CoverageIterator::~CoverageIterator() { | 438 PictureLayerTiling::CoverageIterator::~CoverageIterator() { |
| 431 } | 439 } |
| 432 | 440 |
| 433 PictureLayerTiling::CoverageIterator& | 441 PictureLayerTiling::CoverageIterator& |
| 434 PictureLayerTiling::CoverageIterator::operator++() { | 442 PictureLayerTiling::CoverageIterator::operator++() { |
| 435 if (tile_j_ > bottom_) | 443 if (tile_j_ > bottom_) |
| 436 return *this; | 444 return *this; |
| 437 | 445 |
| 438 bool first_time = tile_i_ < left_; | 446 bool first_time = tile_i_ < left_; |
| 439 bool new_row = false; | 447 bool new_row = false; |
| 440 tile_i_++; | 448 tile_i_++; |
| 441 if (tile_i_ > right_) { | 449 if (tile_i_ > right_) { |
| 442 tile_i_ = left_; | 450 tile_i_ = left_; |
| 443 tile_j_++; | 451 tile_j_++; |
| 444 new_row = true; | 452 new_row = true; |
| 445 if (tile_j_ > bottom_) { | 453 if (tile_j_ > bottom_) { |
| 446 current_tile_ = NULL; | 454 current_tile_ = NULL; |
| 447 return *this; | 455 return *this; |
| 448 } | 456 } |
| 449 } | 457 } |
| 450 | 458 |
| 451 current_tile_ = tiling_->TileAt(tile_i_, tile_j_); | 459 current_tile_ = tiling_->TileAt(tile_i_, tile_j_); |
| 452 | 460 |
| 453 // Calculate the current geometry rect. Due to floating point rounding | 461 // Calculate the current geometry rect. As we reserved 2px overlap between |
|
enne (OOO)
2016/09/09 21:46:34
I thought we reserved an extra border texel for bi
trchen
2016/09/09 23:39:19
Actually both... I don't know how to word this mor
enne (OOO)
2016/09/15 18:06:23
Maybe just say "due to border texels and floating
| |
| 454 // and ToEnclosingRect, tiles might overlap in destination space on the | 462 // tiles for error margin, tiles might overlap in destination space on the |
| 455 // edges. | 463 // edges. |
| 456 gfx::Rect last_geometry_rect = current_geometry_rect_; | 464 gfx::Rect last_geometry_rect = current_geometry_rect_; |
| 457 | 465 |
| 458 gfx::Rect content_rect = tiling_->tiling_data_.TileBounds(tile_i_, tile_j_); | 466 gfx::RectF texel_extent = tiling_->tiling_data_.TexelExtent(tile_i_, tile_j_); |
| 459 | 467 { |
| 460 current_geometry_rect_ = | 468 // Adjust tile extent to accommodate numerical errors. |
| 461 gfx::ScaleToEnclosingRect(content_rect, 1 / dest_to_content_scale_); | 469 // |
| 470 // For internal edges, allow the tile to overreach by 1/1024 texels to | |
| 471 // avoid seams between tiles. The constant 1/1024 is picked by the fact | |
|
enne (OOO)
2016/09/09 21:46:34
This is really because scaling from texture coordi
trchen
2016/09/09 23:39:19
It could happen due to FP error.
right_edge_of_ti
| |
| 472 // that with bilinear filtering, the maximum error in color value | |
| 473 // introduced by clamping error in both u/v axis can't exceed | |
| 474 // 255 * (1 - (1 - 1/1024) * (1 - 1/1024)) ~= 0.498 | |
| 475 // i.e. The color value can never flip over a rounding threshold. | |
| 476 // | |
| 477 // For external edges, extend tile bound by 1.5 texels. This is needed to | |
| 478 // fully cover the dest space. The number 1.5 came from the fact that the | |
| 479 // sample extent doesn't cover the last 0.5 texel to layer edge, and the | |
| 480 // dest space can be rounded up for up to 1 pixel. This overhang will never | |
| 481 // be sampled as the AA fragment shader clamps sample coordinate and apply | |
| 482 // antialiasing itself. | |
| 483 const TilingData& data = tiling_->tiling_data_; | |
| 484 constexpr float epsilon = 1.f / 1024.f; | |
| 485 texel_extent.Inset(tile_i_ ? -epsilon : -1.5, | |
|
enne (OOO)
2016/09/09 21:46:34
Can you set the texel_extent to be 0 if it's the l
trchen
2016/09/09 23:39:19
Yes I've considered that. That's more correct. How
enne (OOO)
2016/09/15 18:06:23
I'd rather be simple first and optimize later, sor
| |
| 486 tile_j_ ? -epsilon : -1.5, | |
| 487 (tile_i_ != data.num_tiles_x() - 1) ? -epsilon : -1.5, | |
| 488 (tile_j_ != data.num_tiles_y() - 1) ? -epsilon : -1.5); | |
| 489 } | |
| 490 current_geometry_rect_ = gfx::ToEnclosedRect( | |
| 491 gfx::ScaleRect(texel_extent, 1 / dest_to_content_scale_)); | |
| 462 | 492 |
| 463 current_geometry_rect_.Intersect(dest_rect_); | 493 current_geometry_rect_.Intersect(dest_rect_); |
| 464 DCHECK(!current_geometry_rect_.IsEmpty()); | 494 DCHECK(!current_geometry_rect_.IsEmpty()); |
| 465 | 495 |
| 466 if (first_time) | 496 if (first_time) |
| 467 return *this; | 497 return *this; |
| 468 | 498 |
| 469 // Iteration happens left->right, top->bottom. Running off the bottom-right | 499 // Iteration happens left->right, top->bottom. Running off the bottom-right |
| 470 // edge is handled by the intersection above with dest_rect_. Here we make | 500 // edge is handled by the intersection above with dest_rect_. Here we make |
| 471 // sure that the new current geometry rect doesn't overlap with the last. | 501 // sure that the new current geometry rect doesn't overlap with the last. |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 879 size_t PictureLayerTiling::GPUMemoryUsageInBytes() const { | 909 size_t PictureLayerTiling::GPUMemoryUsageInBytes() const { |
| 880 size_t amount = 0; | 910 size_t amount = 0; |
| 881 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | 911 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
| 882 const Tile* tile = it->second.get(); | 912 const Tile* tile = it->second.get(); |
| 883 amount += tile->GPUMemoryUsageInBytes(); | 913 amount += tile->GPUMemoryUsageInBytes(); |
| 884 } | 914 } |
| 885 return amount; | 915 return amount; |
| 886 } | 916 } |
| 887 | 917 |
| 888 } // namespace cc | 918 } // namespace cc |
| OLD | NEW |