Chromium Code Reviews| Index: cc/tiles/picture_layer_tiling.cc |
| diff --git a/cc/tiles/picture_layer_tiling.cc b/cc/tiles/picture_layer_tiling.cc |
| index 94a36cdde51411ad70db1f54187c9c44e042301d..6ef7a709e671b17fd13bd5fd8c6b95f24213b67e 100644 |
| --- a/cc/tiles/picture_layer_tiling.cc |
| +++ b/cc/tiles/picture_layer_tiling.cc |
| @@ -400,27 +400,35 @@ PictureLayerTiling::CoverageIterator::CoverageIterator( |
| right_(-1), |
| bottom_(-1) { |
| DCHECK(tiling_); |
| + DCHECK_GE(dest_scale, tiling_->contents_scale_); |
| + |
| + // 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
|
| + gfx::Size dest_content_bounds = |
| + gfx::ScaleToCeiledSize(tiling->raster_source_->GetSize(), dest_scale); |
| + dest_rect_.Intersect(gfx::Rect(dest_content_bounds)); |
| if (dest_rect_.IsEmpty()) |
| return; |
| dest_to_content_scale_ = tiling_->contents_scale_ / dest_scale; |
| - gfx::Rect content_rect = |
| - gfx::ScaleToEnclosingRect(dest_rect_, |
| - dest_to_content_scale_, |
| - dest_to_content_scale_); |
| - // IndexFromSrcCoord clamps to valid tile ranges, so it's necessary to |
| - // check for non-intersection first. |
| - content_rect.Intersect(gfx::Rect(tiling_->tiling_size())); |
| - if (content_rect.IsEmpty()) |
| - return; |
| - |
| - left_ = tiling_->tiling_data_.TileXIndexFromSrcCoord(content_rect.x()); |
| - top_ = tiling_->tiling_data_.TileYIndexFromSrcCoord(content_rect.y()); |
| - right_ = tiling_->tiling_data_.TileXIndexFromSrcCoord( |
| - content_rect.right() - 1); |
| - bottom_ = tiling_->tiling_data_.TileYIndexFromSrcCoord( |
| - content_rect.bottom() - 1); |
| + // Find the indices of the texel samples that enclose the rect we want to |
| + // cover. |
| + // Without MSAA, the sample point of a texel is at the center of that texel. |
| + // 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
|
| + // Instead of trying to snapping to (i+0.5, j+0.5) half grids, just shift |
| + // everything by (-0.5, -0.5). |
| + gfx::RectF content_rect = |
| + gfx::ScaleRect(gfx::RectF(dest_rect_), dest_to_content_scale_); |
| + content_rect.Offset(-0.5f, -0.5f); |
| + gfx::Rect wanted_texels = gfx::ToEnclosingRect(content_rect); |
| + |
| + const TilingData& data = tiling_->tiling_data_; |
| + left_ = data.LastBorderTileXIndexFromSrcCoord(wanted_texels.x()); |
| + top_ = data.LastBorderTileYIndexFromSrcCoord(wanted_texels.y()); |
| + right_ = std::max( |
| + left_, data.FirstBorderTileXIndexFromSrcCoord(wanted_texels.right())); |
| + bottom_ = std::max( |
| + top_, data.FirstBorderTileYIndexFromSrcCoord(wanted_texels.bottom())); |
| tile_i_ = left_ - 1; |
| tile_j_ = top_; |
| @@ -450,15 +458,37 @@ PictureLayerTiling::CoverageIterator::operator++() { |
| current_tile_ = tiling_->TileAt(tile_i_, tile_j_); |
| - // Calculate the current geometry rect. Due to floating point rounding |
| - // and ToEnclosingRect, tiles might overlap in destination space on the |
| + // 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
|
| + // tiles for error margin, tiles might overlap in destination space on the |
| // edges. |
| gfx::Rect last_geometry_rect = current_geometry_rect_; |
| - gfx::Rect content_rect = tiling_->tiling_data_.TileBounds(tile_i_, tile_j_); |
| - |
| - current_geometry_rect_ = |
| - gfx::ScaleToEnclosingRect(content_rect, 1 / dest_to_content_scale_); |
| + gfx::RectF texel_extent = tiling_->tiling_data_.TexelExtent(tile_i_, tile_j_); |
| + { |
| + // Adjust tile extent to accommodate numerical errors. |
| + // |
| + // For internal edges, allow the tile to overreach by 1/1024 texels to |
| + // 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
|
| + // that with bilinear filtering, the maximum error in color value |
| + // introduced by clamping error in both u/v axis can't exceed |
| + // 255 * (1 - (1 - 1/1024) * (1 - 1/1024)) ~= 0.498 |
| + // i.e. The color value can never flip over a rounding threshold. |
| + // |
| + // For external edges, extend tile bound by 1.5 texels. This is needed to |
| + // fully cover the dest space. The number 1.5 came from the fact that the |
| + // sample extent doesn't cover the last 0.5 texel to layer edge, and the |
| + // dest space can be rounded up for up to 1 pixel. This overhang will never |
| + // be sampled as the AA fragment shader clamps sample coordinate and apply |
| + // antialiasing itself. |
| + const TilingData& data = tiling_->tiling_data_; |
| + constexpr float epsilon = 1.f / 1024.f; |
| + 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
|
| + tile_j_ ? -epsilon : -1.5, |
| + (tile_i_ != data.num_tiles_x() - 1) ? -epsilon : -1.5, |
| + (tile_j_ != data.num_tiles_y() - 1) ? -epsilon : -1.5); |
| + } |
| + current_geometry_rect_ = gfx::ToEnclosedRect( |
| + gfx::ScaleRect(texel_extent, 1 / dest_to_content_scale_)); |
| current_geometry_rect_.Intersect(dest_rect_); |
| DCHECK(!current_geometry_rect_.IsEmpty()); |