1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
cc / trees / throttle_decider_unittest.cc [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif
#include "cc/trees/throttle_decider.h"
#include "components/viz/common/quads/compositor_render_pass_draw_quad.h"
#include "components/viz/common/quads/surface_draw_quad.h"
#include "components/viz/common/surfaces/local_surface_id.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cc {
class ThrottleDeciderTest : public ::testing::Test {
protected:
void RunThrottleDecider(const viz::CompositorRenderPassList& render_passes) {
throttle_decider_.Prepare();
for (auto& render_pass : render_passes) {
throttle_decider_.ProcessRenderPass(*render_pass.get());
}
}
const base::flat_set<viz::FrameSinkId>& GetFrameSinksToThrottle() const {
return throttle_decider_.ids();
}
ThrottleDecider throttle_decider_;
};
TEST_F(ThrottleDeciderTest, BackdropFilter) {
// Create two render passes. The first render pass has a blur backdrop filter.
// The second render pass has two quads: a RPDQ referencing the first render
// pass and a surface quad.
viz::CompositorRenderPassList render_passes;
render_passes.push_back(viz::CompositorRenderPass::Create());
render_passes.push_back(viz::CompositorRenderPass::Create());
gfx::Rect render_pass_rect(0, 0, 100, 100);
gfx::Rect quad_rect(0, 0, 100, 100);
viz::CompositorRenderPassId id1{1u};
viz::CompositorRenderPassId id2{2u};
render_passes[0]->SetNew(id1, render_pass_rect, gfx::Rect(),
gfx::Transform());
render_passes[0]->backdrop_filters.Append(
FilterOperation::CreateBlurFilter(5.0));
render_passes[1]->SetNew(id2, render_pass_rect, gfx::Rect(),
gfx::Transform());
auto* rpdq =
render_passes[1]
->CreateAndAppendDrawQuad<viz::CompositorRenderPassDrawQuad>();
rpdq->material = viz::DrawQuad::Material::kCompositorRenderPass;
rpdq->render_pass_id = id1;
viz::SharedQuadState sqs1;
rpdq->shared_quad_state = &sqs1;
rpdq->rect = quad_rect;
viz::FrameSinkId frame_sink_id{10, 10};
auto* surface_quad =
render_passes[1]->CreateAndAppendDrawQuad<viz::SurfaceDrawQuad>();
viz::SharedQuadState sqs2;
surface_quad->shared_quad_state = &sqs2;
surface_quad->material = viz::DrawQuad::Material::kSurfaceContent;
surface_quad->surface_range = viz::SurfaceRange(
std::nullopt,
viz::SurfaceId(frame_sink_id, viz::LocalSurfaceId(
1u, base::UnguessableToken::Create())));
surface_quad->rect = quad_rect;
surface_quad->visible_rect = quad_rect;
base::flat_set<viz::FrameSinkId> expected_frame_sinks{frame_sink_id};
// The surface quad (0,0 100x100) is entirely behind the backdrop filter on
// the rpdq (0,0 100x100) so it can be throttled.
RunThrottleDecider(render_passes);
EXPECT_EQ(GetFrameSinksToThrottle(), expected_frame_sinks);
// Put the backdrop filter within bounds (0,10 50x50).
render_passes[0]->backdrop_filter_bounds =
std::optional<gfx::RRectF>(gfx::RRectF(0.0f, 10.0f, 50.0f, 50.0f, 1.0f));
// The surface quad (0,0 100x100) is partially behind the backdrop filter on
// the rpdq (0,10 50x50) so it should not be throttled.
RunThrottleDecider(render_passes);
EXPECT_TRUE(GetFrameSinksToThrottle().empty());
// Transform the surface quad to (0,10 50x50).
gfx::Transform transform;
transform.Translate(0, 10);
transform.Scale(0.5f, 0.5f);
sqs2.quad_to_target_transform = transform;
// The surface quad (0,10 50x50) is entirely behind the backdrop filter on the
// rpdq (0,10 50x50) so it can be throttled.
RunThrottleDecider(render_passes);
EXPECT_EQ(GetFrameSinksToThrottle(), expected_frame_sinks);
// Add a mask to the backdrop filter.
rpdq->resource_id = viz::ResourceId::FromUnsafeValue(1u);
// As the mask would make the backdrop filter to be ignored, the surface
// should not be throttled.
RunThrottleDecider(render_passes);
EXPECT_TRUE(GetFrameSinksToThrottle().empty());
// Add a foreground filter to the second render pass.
render_passes[1]->filters.Append(FilterOperation::CreateBlurFilter(5.0f));
// The surface quad is being blurred by the foreground filter so it can be
// throttled.
RunThrottleDecider(render_passes);
EXPECT_EQ(GetFrameSinksToThrottle(), expected_frame_sinks);
}
} // namespace cc