Commit 8ab29f09 authored by Xianzhu Wang's avatar Xianzhu Wang Committed by Commit Bot

[SPv175+] Don't invalidate chunk for tiny transform changes

This ignores the computation error introduced when mapping to and from
the common planar of the layer and the chunk while the relative
transform between the layer and the chunk doesn't actually change.

Bug: 814711
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.linux:linux_layout_tests_slimming_paint_v2
Change-Id: Ie97b425eb3de601107328513b611b3f8676afa73
Reviewed-on: https://chromium-review.googlesource.com/1040537Reviewed-by: default avatarChris Harrelson <chrishtr@chromium.org>
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#555820}
parent ab89dd3a
......@@ -45,6 +45,15 @@ size_t CompositedLayerRasterInvalidator::MatchNewChunkToOldChunk(
return kNotFound;
}
static bool ApproximatelyEqual(const SkMatrix& a, const SkMatrix& b) {
static constexpr float kTolerance = 1e-5f;
for (int i = 0; i < 9; i++) {
if (std::abs(a[i] - b[i]) > kTolerance)
return false;
}
return true;
}
PaintInvalidationReason
CompositedLayerRasterInvalidator::ChunkPropertiesChanged(
const RefCountedPropertyTreeState& new_chunk_state,
......@@ -55,7 +64,8 @@ CompositedLayerRasterInvalidator::ChunkPropertiesChanged(
// transform nodes when no raster invalidation is needed. For example, when
// a composited layer previously not transformed now gets transformed.
// Check for real accumulated transform change instead.
if (new_chunk.chunk_to_layer_transform != old_chunk.chunk_to_layer_transform)
if (!ApproximatelyEqual(new_chunk.chunk_to_layer_transform,
old_chunk.chunk_to_layer_transform))
return PaintInvalidationReason::kPaintProperty;
// Treat the chunk property as changed if the effect node pointer is
......@@ -111,7 +121,7 @@ void CompositedLayerRasterInvalidator::GenerateRasterInvalidations(
size_t max_matched_old_index = 0;
for (const auto& new_chunk : new_chunks) {
mapper.SwitchToChunk(new_chunk);
const auto& new_chunk_info =
auto& new_chunk_info =
new_chunks_info.emplace_back(*this, mapper, new_chunk);
if (!new_chunk.is_cacheable) {
......@@ -150,6 +160,13 @@ void CompositedLayerRasterInvalidator::GenerateRasterInvalidations(
// Ignore the display item raster invalidations because we have fully
// invalidated the chunk.
} else {
// We may have ignored tiny changes of transform, in which case we should
// use the old chunk_to_layer_transform for later comparison to correctly
// invalidate animating transform in tiny increments when the accumulated
// change exceeds the tolerance.
new_chunk_info.chunk_to_layer_transform =
old_chunk_info.chunk_to_layer_transform;
if (reason == PaintInvalidationReason::kIncremental)
IncrementallyInvalidateChunk(old_chunk_info, new_chunk_info);
......
......@@ -629,4 +629,54 @@ TEST_F(CompositedLayerRasterInvalidatorTest, TransformPropertyChange) {
invalidator.SetTracksRasterInvalidations(false);
}
TEST_F(CompositedLayerRasterInvalidatorTest, TransformPropertyTinyChange) {
CompositedLayerRasterInvalidator invalidator(kNoopRasterInvalidation);
auto layer_transform = CreateTransform(TransformPaintPropertyNode::Root(),
TransformationMatrix().Scale(5));
auto chunk_transform = CreateTransform(
layer_transform, TransformationMatrix().Translate(10, 20));
PropertyTreeState layer_state(layer_transform.get(),
ClipPaintPropertyNode::Root(),
EffectPaintPropertyNode::Root());
auto artifact = Chunk(0).Properties(chunk_transform.get()).Build();
GeometryMapperTransformCache::ClearCache();
invalidator.SetTracksRasterInvalidations(true);
invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
// Change chunk_transform by tiny difference, which should be ignored.
chunk_transform->Update(layer_state.Transform(),
TransformPaintPropertyNode::State{
TransformationMatrix(chunk_transform->Matrix())
.Translate(0.0000001, -0.0000001)
.Scale(1.0000001)
.Rotate(0.0000001)});
auto new_artifact = Chunk(0).Properties(chunk_transform.get()).Build();
GeometryMapperTransformCache::ClearCache();
invalidator.Generate(new_artifact, kDefaultLayerBounds, layer_state);
EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
// Tiny differences should accumulate and cause invalidation when the
// accumulation is large enough.
bool invalidated = false;
for (int i = 0; i < 100 && !invalidated; i++) {
chunk_transform->Update(layer_state.Transform(),
TransformPaintPropertyNode::State{
TransformationMatrix(chunk_transform->Matrix())
.Translate(0.0000001, -0.0000001)
.Scale(1.0000001)
.Rotate(0.0000001)});
auto new_artifact = Chunk(0).Properties(chunk_transform.get()).Build();
GeometryMapperTransformCache::ClearCache();
invalidator.Generate(new_artifact, kDefaultLayerBounds, layer_state);
invalidated = !TrackedRasterInvalidations(invalidator).IsEmpty();
}
EXPECT_TRUE(invalidated);
}
} // namespace blink
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment