diff --git a/cc/tiles/picture_layer_tiling.cc b/cc/tiles/picture_layer_tiling.cc index 52840a57b5ff17..c0bbd317bcb0d6 100644 --- a/cc/tiles/picture_layer_tiling.cc +++ b/cc/tiles/picture_layer_tiling.cc @@ -379,42 +379,27 @@ bool PictureLayerTiling::TilingMatchesTileIndices( twin->tiling_data_.max_texture_size(); } -PictureLayerTiling::CoverageIterator::CoverageIterator() - : tiling_(NULL), - current_tile_(NULL), - tile_i_(0), - tile_j_(0), - left_(0), - top_(0), - right_(-1), - bottom_(-1) { -} +PictureLayerTiling::CoverageIterator::CoverageIterator() = default; PictureLayerTiling::CoverageIterator::CoverageIterator( const PictureLayerTiling* tiling, - float dest_scale, - const gfx::Rect& dest_rect) - : tiling_(tiling), - dest_rect_(dest_rect), - dest_to_content_scale_(0), - current_tile_(NULL), - tile_i_(0), - tile_j_(0), - left_(0), - top_(0), - right_(-1), - bottom_(-1) { + float coverage_scale, + const gfx::Rect& coverage_rect) + : tiling_(tiling), coverage_rect_(coverage_rect) { DCHECK(tiling_); - DCHECK_GE(dest_scale, tiling_->contents_scale_); - - // Clamp dest_rect_ to the bounds of the layer. - dest_layer_bounds_ = - gfx::ScaleToCeiledSize(tiling->raster_source_->GetSize(), dest_scale); - dest_rect_.Intersect(gfx::Rect(dest_layer_bounds_)); - if (dest_rect_.IsEmpty()) + // In order to avoid artifacts in geometry_rect scaling and clamping to ints, + // the |coverage_scale| should always be at least as big as the tiling's + // contents scale. + DCHECK_GE(coverage_scale, tiling_->contents_scale_); + + // Clamp |coverage_rect| to the bounds of this tiling's raster source. + coverage_rect_max_bounds_ = + gfx::ScaleToCeiledSize(tiling->raster_source_->GetSize(), coverage_scale); + coverage_rect_.Intersect(gfx::Rect(coverage_rect_max_bounds_)); + if (coverage_rect_.IsEmpty()) return; - dest_to_content_scale_ = tiling_->contents_scale_ / dest_scale; + coverage_to_content_scale_ = tiling_->contents_scale_ / coverage_scale; // Find the indices of the texel samples that enclose the rect we want to // cover. @@ -433,7 +418,7 @@ PictureLayerTiling::CoverageIterator::CoverageIterator( // Or in integer index: // wanted_texels(integer index) = (l:99, t:189, r:280, b:371) gfx::RectF content_rect = - gfx::ScaleRect(gfx::RectF(dest_rect_), dest_to_content_scale_); + gfx::ScaleRect(gfx::RectF(coverage_rect_), coverage_to_content_scale_); content_rect.Offset(-0.5f, -0.5f); gfx::Rect wanted_texels = gfx::ToEnclosingRect(content_rect); @@ -492,29 +477,33 @@ PictureLayerTiling::CoverageIterator::operator++() { texel_extent.Inset(-epsilon, -epsilon); } + // Convert texel_extent to coverage scale, which is what we have to report + // geometry_rect in. current_geometry_rect_ = gfx::ToEnclosedRect( - gfx::ScaleRect(texel_extent, 1 / dest_to_content_scale_)); + gfx::ScaleRect(texel_extent, 1.f / coverage_to_content_scale_)); { // Adjust external edges to cover the whole layer in dest space. // // For external edges, extend the tile to scaled layer bounds. This is - // needed to fully cover the dest space because the sample extent doesn't - // cover the last 0.5 texel to layer edge, and also 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 antialiasing itself. + // needed to fully cover the coverage space because the sample extent + // doesn't cover the last 0.5 texel to layer edge, and also the coverage + // 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 + // antialiasing itself. const TilingData& data = tiling_->tiling_data_; - current_geometry_rect_.Inset( - tile_i_ ? 0 : -current_geometry_rect_.x(), - tile_j_ ? 0 : -current_geometry_rect_.y(), - (tile_i_ != data.num_tiles_x() - 1) - ? 0 - : current_geometry_rect_.right() - dest_layer_bounds_.width(), - (tile_j_ != data.num_tiles_y() - 1) - ? 0 - : current_geometry_rect_.bottom() - dest_layer_bounds_.height()); + current_geometry_rect_.Inset(tile_i_ ? 0 : -current_geometry_rect_.x(), + tile_j_ ? 0 : -current_geometry_rect_.y(), + (tile_i_ != data.num_tiles_x() - 1) + ? 0 + : current_geometry_rect_.right() - + coverage_rect_max_bounds_.width(), + (tile_j_ != data.num_tiles_y() - 1) + ? 0 + : current_geometry_rect_.bottom() - + coverage_rect_max_bounds_.height()); } - current_geometry_rect_.Intersect(dest_rect_); + current_geometry_rect_.Intersect(coverage_rect_); DCHECK(!current_geometry_rect_.IsEmpty()); if (first_time) @@ -526,7 +515,7 @@ PictureLayerTiling::CoverageIterator::operator++() { int min_left; int min_top; if (new_row) { - min_left = dest_rect_.x(); + min_left = coverage_rect_.x(); min_top = last_geometry_rect.bottom(); } else { min_left = last_geometry_rect.right(); @@ -556,8 +545,7 @@ gfx::RectF PictureLayerTiling::CoverageIterator::texture_rect() const { // Convert from dest space => content space => texture space. gfx::RectF texture_rect(current_geometry_rect_); - texture_rect.Scale(dest_to_content_scale_, - dest_to_content_scale_); + texture_rect.Scale(coverage_to_content_scale_); texture_rect.Intersect(gfx::RectF(gfx::SizeF(tiling_->tiling_size()))); if (texture_rect.IsEmpty()) return texture_rect; diff --git a/cc/tiles/picture_layer_tiling.h b/cc/tiles/picture_layer_tiling.h index 2768344a96b6ff..301974f11f4bff 100644 --- a/cc/tiles/picture_layer_tiling.h +++ b/cc/tiles/picture_layer_tiling.h @@ -190,12 +190,14 @@ class CC_EXPORT PictureLayerTiling { class CC_EXPORT CoverageIterator { public: CoverageIterator(); + // This requests an iterator that produces a coverage of the + // |coverage_rect|, which is specified at |coverage_scale|. CoverageIterator(const PictureLayerTiling* tiling, - float dest_scale, - const gfx::Rect& rect); + float coverage_scale, + const gfx::Rect& coverage_rect); ~CoverageIterator(); - // Visible rect (no borders), always in the space of content_rect, + // Visible rect (no borders), always in the space of |coverage_rect|, // regardless of the contents scale of the tiling. gfx::Rect geometry_rect() const; // Texture rect (in texels) for geometry_rect @@ -211,19 +213,19 @@ class CC_EXPORT PictureLayerTiling { int j() const { return tile_j_; } private: - const PictureLayerTiling* tiling_; - gfx::Size dest_layer_bounds_; - gfx::Rect dest_rect_; - float dest_to_content_scale_; + const PictureLayerTiling* tiling_ = nullptr; + gfx::Size coverage_rect_max_bounds_; + gfx::Rect coverage_rect_; + float coverage_to_content_scale_ = 0.f; - Tile* current_tile_; + Tile* current_tile_ = nullptr; gfx::Rect current_geometry_rect_; - int tile_i_; - int tile_j_; - int left_; - int top_; - int right_; - int bottom_; + int tile_i_ = 0; + int tile_j_ = 0; + int left_ = 0; + int top_ = 0; + int right_ = -1; + int bottom_ = -1; friend class PictureLayerTiling; }; diff --git a/cc/tiles/picture_layer_tiling_set.cc b/cc/tiles/picture_layer_tiling_set.cc index 0136b89d5bd7f9..76087fe4ce091f 100644 --- a/cc/tiles/picture_layer_tiling_set.cc +++ b/cc/tiles/picture_layer_tiling_set.cc @@ -547,25 +547,28 @@ void PictureLayerTilingSet::GetAllPrioritizedTilesForTracing( PictureLayerTilingSet::CoverageIterator::CoverageIterator( const PictureLayerTilingSet* set, - float contents_scale, - const gfx::Rect& content_rect, + float coverage_scale, + const gfx::Rect& coverage_rect, float ideal_contents_scale) : set_(set), - contents_scale_(contents_scale), - ideal_contents_scale_(ideal_contents_scale), + coverage_scale_(coverage_scale), current_tiling_(std::numeric_limits::max()) { - missing_region_.Union(content_rect); + missing_region_.Union(coverage_rect); + // Determine the smallest content_scale tiling which a scale higher than the + // ideal (or the first tiling if all tilings have a scale less than ideal). size_t tilings_size = set_->tilings_.size(); for (ideal_tiling_ = 0; ideal_tiling_ < tilings_size; ++ideal_tiling_) { PictureLayerTiling* tiling = set_->tilings_[ideal_tiling_].get(); - if (tiling->contents_scale() < ideal_contents_scale_) { + if (tiling->contents_scale() < ideal_contents_scale) { if (ideal_tiling_ > 0) ideal_tiling_--; break; } } + // If all tilings have a scale larger than the ideal, then use the smallest + // scale (which is the last one). if (ideal_tiling_ == tilings_size && ideal_tiling_ > 0) ideal_tiling_--; @@ -576,6 +579,8 @@ PictureLayerTilingSet::CoverageIterator::~CoverageIterator() { } gfx::Rect PictureLayerTilingSet::CoverageIterator::geometry_rect() const { + // If we don't have any more tilings to process, then return the region + // iterator rect that we need to fill, so that the caller can checkerboard it. if (!tiling_iter_) { if (!region_iter_.has_rect()) return gfx::Rect(); @@ -585,6 +590,7 @@ gfx::Rect PictureLayerTilingSet::CoverageIterator::geometry_rect() const { } gfx::RectF PictureLayerTilingSet::CoverageIterator::texture_rect() const { + // Texture rects are only valid if we have a tiling. if (!tiling_iter_) return gfx::RectF(); return tiling_iter_.texture_rect(); @@ -645,11 +651,15 @@ PictureLayerTilingSet::CoverageIterator::operator++() { // Loop until we find a valid place to stop. while (true) { + // While we don't have a ready to draw tile, accumulate the geometry rects + // back into the missing region, which will be iterated after this tiling is + // processed. while (tiling_iter_ && (!*tiling_iter_ || !tiling_iter_->draw_info().IsReadyToDraw())) { missing_region_.Union(tiling_iter_.geometry_rect()); ++tiling_iter_; } + // We found a ready tile, yield it! if (tiling_iter_) return *this; @@ -685,7 +695,7 @@ PictureLayerTilingSet::CoverageIterator::operator++() { // Construct a new iterator for the next tiling, but we need to loop // again until we get to a valid one. tiling_iter_ = PictureLayerTiling::CoverageIterator( - set_->tilings_[current_tiling_].get(), contents_scale_, last_rect); + set_->tilings_[current_tiling_].get(), coverage_scale_, last_rect); } return *this; diff --git a/cc/tiles/picture_layer_tiling_set.h b/cc/tiles/picture_layer_tiling_set.h index 20e7a76ef57e17..7bf3f7fec1f29c 100644 --- a/cc/tiles/picture_layer_tiling_set.h +++ b/cc/tiles/picture_layer_tiling_set.h @@ -134,16 +134,24 @@ class CC_EXPORT PictureLayerTilingSet { // exactly fill rect with no overlap. class CC_EXPORT CoverageIterator { public: + // |coverage_scale| is the scale at which we want to produce the coverage. + // This is the scale at which |coverage_rect| is specified (relative to + // identity). + // |coverage_rect| is a rect that we want to cover during this iteration. + // |ideal_contents_scale| is the ideal scale that we want, which determines + // the order in which tilings are processed to get the best ("crispest") + // coverage. CoverageIterator(const PictureLayerTilingSet* set, - float contents_scale, - const gfx::Rect& content_rect, - float ideal_contents_scale); + float coverage_scale, + const gfx::Rect& coverage_rect, + float ideal_contents_scale); ~CoverageIterator(); - // Visible rect (no borders), always in the space of rect, - // regardless of the relative contents scale of the tiling. + // Visible rect (no borders), in the space of |coverage_rect| (ie at + // |coverage_scale| from identity). This is clipped to the coverage_rect. gfx::Rect geometry_rect() const; - // Texture rect (in texels) for geometry_rect + // A geometry_rect scaled to the tiling's contents scale, which represents + // the texture rect in texels. gfx::RectF texture_rect() const; Tile* operator->() const; @@ -159,8 +167,7 @@ class CC_EXPORT PictureLayerTilingSet { size_t NextTiling() const; const PictureLayerTilingSet* set_; - float contents_scale_; - float ideal_contents_scale_; + float coverage_scale_; PictureLayerTiling::CoverageIterator tiling_iter_; size_t current_tiling_; size_t ideal_tiling_;