Index: cc/layers/picture_layer_impl.cc |
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc |
index 44b594f8a42db1ed7b372dd88d7454cc65eaecad..5cd14b3f6532ac463414485372914ed03ab4bfb2 100644 |
--- a/cc/layers/picture_layer_impl.cc |
+++ b/cc/layers/picture_layer_impl.cc |
@@ -109,6 +109,7 @@ PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, |
only_used_low_res_last_append_quads_(false), |
mask_type_(mask_type), |
nearest_neighbor_(false), |
+ use_transformed_rasterization_(false), |
is_directly_composited_image_(false) { |
layer_tree_impl()->RegisterPictureLayerImpl(this); |
} |
@@ -145,6 +146,7 @@ void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) { |
layer_impl->twin_layer_ = this; |
layer_impl->SetNearestNeighbor(nearest_neighbor_); |
+ layer_impl->SetUseTransformedRasterization(use_transformed_rasterization_); |
// Solid color layers have no tilings. |
DCHECK(!raster_source_->IsSolidColor() || tilings_->num_tilings() == 0); |
@@ -275,7 +277,7 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass, |
} else if (iter.resolution() == LOW_RESOLUTION) { |
color = DebugColors::LowResTileBorderColor(); |
width = DebugColors::LowResTileBorderWidth(device_scale_factor); |
- } else if (iter->contents_scale() > max_contents_scale) { |
+ } else if (iter->contents_scale_key() > max_contents_scale) { |
color = DebugColors::ExtraHighResTileBorderColor(); |
width = DebugColors::ExtraHighResTileBorderWidth(device_scale_factor); |
} else { |
@@ -343,8 +345,8 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass, |
// complete. But if a tile is ideal scale, we don't want to consider |
// it incomplete and trying to replace it with a tile at a worse |
// scale. |
- if (iter->contents_scale() != raster_contents_scale_ && |
- iter->contents_scale() != ideal_contents_scale_ && |
+ if (iter->contents_scale_key() != raster_contents_scale_ && |
+ iter->contents_scale_key() != ideal_contents_scale_ && |
geometry_rect.Intersects(scaled_viewport_for_tile_priority)) { |
append_quads_data->num_incomplete_tiles++; |
} |
@@ -644,19 +646,22 @@ bool PictureLayerImpl::RasterSourceUsesLCDText() const { |
} |
void PictureLayerImpl::NotifyTileStateChanged(const Tile* tile) { |
- if (layer_tree_impl()->IsActiveTree()) { |
- gfx::Rect layer_damage_rect = gfx::ScaleToEnclosingRect( |
- tile->content_rect(), 1.f / tile->contents_scale()); |
- AddDamageRect(layer_damage_rect); |
- } |
+ if (layer_tree_impl()->IsActiveTree()) |
+ AddDamageRect(tile->enclosing_layer_rect()); |
if (tile->draw_info().NeedsRaster()) { |
PictureLayerTiling* tiling = |
- tilings_->FindTilingWithScaleKey(tile->contents_scale()); |
+ tilings_->FindTilingWithScaleKey(tile->contents_scale_key()); |
if (tiling) |
tiling->set_all_tiles_done(false); |
} |
} |
+SimpleEnclosedRegion PictureLayerImpl::VisibleOpaqueRegion() const { |
+ if (use_transformed_rasterization_) |
+ return SimpleEnclosedRegion(); |
+ return LayerImpl::VisibleOpaqueRegion(); |
+} |
+ |
void PictureLayerImpl::DidBeginTracing() { |
raster_source_->DidBeginTracing(); |
} |
@@ -724,7 +729,13 @@ const PictureLayerTiling* PictureLayerImpl::GetPendingOrActiveTwinTiling( |
PictureLayerImpl* twin_layer = GetPendingOrActiveTwinLayer(); |
if (!twin_layer) |
return nullptr; |
- return twin_layer->tilings_->FindTilingWithScaleKey(tiling->contents_scale()); |
+ const PictureLayerTiling* twin_tiling = |
+ twin_layer->tilings_->FindTilingWithScaleKey( |
+ tiling->contents_scale_key()); |
+ if (twin_tiling && |
+ twin_tiling->raster_transform() == tiling->raster_transform()) |
+ return twin_tiling; |
+ return nullptr; |
} |
bool PictureLayerImpl::RequiresHighResToDraw() const { |
@@ -872,12 +883,21 @@ void PictureLayerImpl::SetNearestNeighbor(bool nearest_neighbor) { |
NoteLayerPropertyChanged(); |
} |
-PictureLayerTiling* PictureLayerImpl::AddTiling(float contents_scale) { |
+void PictureLayerImpl::SetUseTransformedRasterization(bool use) { |
+ if (use_transformed_rasterization_ == use) |
+ return; |
+ |
+ use_transformed_rasterization_ = use; |
+ NoteLayerPropertyChanged(); |
+} |
+ |
+PictureLayerTiling* PictureLayerImpl::AddTiling( |
+ const ScaleTranslate2d& contents_transform) { |
DCHECK(CanHaveTilings()); |
- DCHECK_GE(contents_scale, MinimumContentsScale()); |
- DCHECK_LE(contents_scale, MaximumContentsScale()); |
+ DCHECK_GE(contents_transform.scale(), MinimumContentsScale()); |
+ DCHECK_LE(contents_transform.scale(), MaximumContentsScale()); |
DCHECK(raster_source_->HasRecordings()); |
- return tilings_->AddTiling(contents_scale, raster_source_); |
+ return tilings_->AddTiling(contents_transform, raster_source_); |
} |
void PictureLayerImpl::RemoveAllTilings() { |
@@ -893,9 +913,17 @@ void PictureLayerImpl::AddTilingsForRasterScale() { |
PictureLayerTiling* high_res = |
tilings_->FindTilingWithScaleKey(raster_contents_scale_); |
+ gfx::Vector2dF raster_translation = |
+ CalculateRasterTranslation(raster_contents_scale_); |
+ if (high_res && |
+ high_res->raster_transform().translation() != raster_translation) { |
+ tilings_->Remove(high_res); |
+ high_res = nullptr; |
+ } |
if (!high_res) { |
// We always need a high res tiling, so create one if it doesn't exist. |
- high_res = AddTiling(raster_contents_scale_); |
+ high_res = |
+ AddTiling(ScaleTranslate2d(raster_contents_scale_, raster_translation)); |
} else if (high_res->may_contain_low_resolution_tiles()) { |
// If the tiling we find here was LOW_RESOLUTION previously, it may not be |
// fully rastered, so destroy the old tiles. |
@@ -992,7 +1020,8 @@ void PictureLayerImpl::AddLowResolutionTilingIfNeeded() { |
bool is_animating = draw_properties().screen_space_transform_is_animating; |
if (!is_pinching && !is_animating) { |
if (!low_res) |
- low_res = AddTiling(low_res_raster_contents_scale_); |
+ low_res = AddTiling( |
+ ScaleTranslate2d(low_res_raster_contents_scale_, gfx::Vector2dF())); |
low_res->set_resolution(LOW_RESOLUTION); |
} |
} |
@@ -1158,6 +1187,34 @@ void PictureLayerImpl::CleanUpTilingsOnActiveLayer( |
SanityCheckTilingState(); |
} |
+gfx::Vector2dF PictureLayerImpl::CalculateRasterTranslation( |
+ float raster_scale) { |
+ if (!use_transformed_rasterization_) |
+ return gfx::Vector2dF(); |
+ |
+ DCHECK(!draw_properties().screen_space_transform_is_animating); |
+ gfx::Transform draw_transform = DrawTransform(); |
+ DCHECK(draw_transform.IsScaleOrTranslation()); |
+ |
+ // It is only useful to align the content space to the target space if their |
+ // relative pixel ratio is some small rational number. Currently we only |
+ // align if the relative pixel ratio is 1:1. |
+ // Good match if the maximum alignment error on a layer of size 10000px |
+ // does not exceed 0.001px. |
+ static constexpr float kErrorThreshold = 0.0000001f; |
+ if (std::abs(draw_transform.matrix().getFloat(0, 0) - raster_scale) > |
+ kErrorThreshold || |
+ std::abs(draw_transform.matrix().getFloat(1, 1) - raster_scale) > |
+ kErrorThreshold) |
+ return gfx::Vector2dF(); |
+ |
+ // Extract the fractional part of layer origin in the target space. |
+ float origin_x = draw_transform.matrix().getFloat(0, 3); |
+ float origin_y = draw_transform.matrix().getFloat(1, 3); |
+ return gfx::Vector2dF(origin_x - floorf(origin_x), |
+ origin_y - floorf(origin_y)); |
+} |
+ |
float PictureLayerImpl::MinimumContentsScale() const { |
float setting_min = layer_tree_impl()->settings().minimum_contents_scale; |