blob: 118fbff0189d0dfbaa67be56474c2ccf9757fd87 [file] [log] [blame]
[email protected]d993b602013-01-04 02:08:121// Copyright 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
avi02a4d172015-12-21 06:14:365#include <stddef.h>
6#include <stdint.h>
7
Sebastien Marchand6d0558fd2019-01-25 16:49:378#include "base/bind.h"
Avi Drissman0dd4e0e62018-12-25 23:20:469#include "base/stl_util.h"
Stephen McGruer25ddb1372018-01-18 19:10:1510#include "build/build_config.h"
[email protected]cc3cfaa2013-03-18 09:05:5211#include "cc/layers/heads_up_display_layer.h"
[email protected]cc3cfaa2013-03-18 09:05:5212#include "cc/layers/layer_impl.h"
[email protected]3a83478b2013-08-22 20:55:1713#include "cc/layers/painted_scrollbar_layer.h"
[email protected]cc3cfaa2013-03-18 09:05:5214#include "cc/layers/picture_layer.h"
[email protected]cc3cfaa2013-03-18 09:05:5215#include "cc/layers/texture_layer.h"
[email protected]4145d172013-05-10 16:54:3616#include "cc/layers/texture_layer_impl.h"
[email protected]cc3cfaa2013-03-18 09:05:5217#include "cc/layers/video_layer.h"
18#include "cc/layers/video_layer_impl.h"
Khushal7865b5be2017-11-22 03:12:0619#include "cc/paint/filter_operations.h"
enne34f6084c2017-02-02 22:39:0820#include "cc/paint/paint_flags.h"
khushalsagar8ec07402016-09-10 03:13:1921#include "cc/resources/ui_resource_manager.h"
[email protected]d993b602013-01-04 02:08:1222#include "cc/test/fake_content_layer_client.h"
[email protected]04049fc2013-05-01 03:13:2023#include "cc/test/fake_layer_tree_host_client.h"
[email protected]3a83478b2013-08-22 20:55:1724#include "cc/test/fake_painted_scrollbar_layer.h"
sohan.jyoti9d1e4202014-09-23 21:02:3325#include "cc/test/fake_picture_layer.h"
26#include "cc/test/fake_picture_layer_impl.h"
[email protected]c9280762013-08-01 06:28:5727#include "cc/test/fake_scoped_ui_resource.h"
[email protected]c28df4c12013-05-22 17:36:4928#include "cc/test/fake_scrollbar.h"
[email protected]d993b602013-01-04 02:08:1229#include "cc/test/fake_video_frame_provider.h"
[email protected]e216fef02013-03-20 22:56:1030#include "cc/test/layer_tree_test.h"
danakj7e605b662015-08-18 20:23:1231#include "cc/test/render_pass_test_utils.h"
Antoine Labour7f5179a2019-06-04 01:46:2932#include "cc/test/test_layer_tree_frame_sink.h"
danakj60bc3bc2016-04-09 00:24:4833#include "cc/trees/layer_tree_host.h"
[email protected]556fd292013-03-18 08:03:0434#include "cc/trees/layer_tree_host_impl.h"
35#include "cc/trees/layer_tree_impl.h"
36#include "cc/trees/single_thread_proxy.h"
danakj4b15f742018-05-30 22:52:2237#include "components/viz/client/client_resource_provider.h"
danakjf20f4502017-09-26 17:13:3138#include "components/viz/common/resources/single_release_callback.h"
danakjb90335d2018-06-07 23:42:2939#include "components/viz/test/fake_output_surface.h"
kylechardfe762f2018-02-26 17:00:0140#include "components/viz/test/test_context_provider.h"
Xu Xing1252efe2018-05-05 00:20:2541#include "components/viz/test/test_gles2_interface.h"
kylecharefc48452018-02-23 17:11:0042#include "components/viz/test/test_shared_bitmap_manager.h"
[email protected]7a6acd02013-01-19 04:16:1343#include "gpu/GLES2/gl2extchromium.h"
Victor Miura3a4ad4f82017-12-13 06:03:4544#include "gpu/command_buffer/client/raster_interface.h"
[email protected]d993b602013-01-04 02:08:1245#include "media/base/media.h"
46
47using media::VideoFrame;
[email protected]d993b602013-01-04 02:08:1248
49namespace cc {
50namespace {
51
Yuri Wiitalad0611762017-07-22 02:33:2152// Returns a fake TimeTicks based on the given microsecond offset.
53base::TimeTicks TicksFromMicroseconds(int64_t micros) {
54 return base::TimeTicks() + base::TimeDelta::FromMicroseconds(micros);
55}
56
[email protected]d993b602013-01-04 02:08:1257// These tests deal with losing the 3d graphics context.
[email protected]e216fef02013-03-20 22:56:1058class LayerTreeHostContextTest : public LayerTreeTest {
[email protected]d993b602013-01-04 02:08:1259 public:
60 LayerTreeHostContextTest()
[email protected]e216fef02013-03-20 22:56:1061 : LayerTreeTest(),
[email protected]d993b602013-01-04 02:08:1262 times_to_fail_create_(0),
[email protected]d993b602013-01-04 02:08:1263 times_to_lose_during_commit_(0),
[email protected]e01dddb12013-01-23 03:57:0864 times_to_lose_during_draw_(0),
65 times_to_fail_recreate_(0),
[email protected]04049fc2013-05-01 03:13:2066 times_to_expect_create_failed_(0),
67 times_create_failed_(0),
[email protected]04049fc2013-05-01 03:13:2068 committed_at_least_once_(false),
[email protected]ebc0e1df2013-08-01 02:46:2269 context_should_support_io_surface_(false),
enne2097cab2014-09-25 20:16:3170 fallback_context_works_(false),
danakjc7afae52017-06-20 21:12:4171 async_layer_tree_frame_sink_creation_(false) {
chcunninghamfd11b3c2015-06-09 02:09:4272 media::InitializeMediaLibrary();
[email protected]d993b602013-01-04 02:08:1273 }
74
75 void LoseContext() {
danakjc7afae52017-06-20 21:12:4176 // CreateDisplayLayerTreeFrameSink happens on a different thread, so lock
Xu Xing1252efe2018-05-05 00:20:2577 // gl_ to make sure we don't set it to null after recreating it
danakj1120f4c2016-09-15 02:05:3278 // there.
Xu Xing1252efe2018-05-05 00:20:2579 base::AutoLock lock(gl_lock_);
[email protected]aeeedad2014-08-22 18:16:2280 // For sanity-checking tests, they should only call this when the
81 // context is not lost.
Xu Xing1252efe2018-05-05 00:20:2582 CHECK(gl_);
83 gl_->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
84 GL_INNOCENT_CONTEXT_RESET_ARB);
85 gl_ = nullptr;
[email protected]d993b602013-01-04 02:08:1286 }
87
Antoine Labour7f5179a2019-06-04 01:46:2988 std::unique_ptr<TestLayerTreeFrameSink> CreateLayerTreeFrameSink(
Alex Zhangbcce8b132017-07-20 20:17:2489 const viz::RendererSettings& renderer_settings,
Alex Zhang903cb6a2017-06-12 20:31:3790 double refresh_rate,
Xu Xing32549162017-07-17 22:25:4391 scoped_refptr<viz::ContextProvider> compositor_context_provider,
Victor Miura29b7ea3d2017-12-19 20:23:5992 scoped_refptr<viz::RasterContextProvider> worker_context_provider)
93 override {
Xu Xing1252efe2018-05-05 00:20:2594 base::AutoLock lock(gl_lock_);
sunnypse9fd9522016-10-06 23:03:2795
Xu Xing0d4b2bf92018-05-17 00:20:1296 auto gl_owned = std::make_unique<viz::TestGLES2Interface>();
97 if (context_should_support_io_surface_) {
98 gl_owned->set_have_extension_io_surface(true);
99 gl_owned->set_have_extension_egl_image(true);
100 }
101
Xu Xing1252efe2018-05-05 00:20:25102 gl_ = gl_owned.get();
sunnypse9fd9522016-10-06 23:03:27103
Xu Xing1252efe2018-05-05 00:20:25104 auto provider = viz::TestContextProvider::Create(std::move(gl_owned));
[email protected]d993b602013-01-04 02:08:12105 if (times_to_fail_create_) {
106 --times_to_fail_create_;
[email protected]04049fc2013-05-01 03:13:20107 ExpectCreateToFail();
Xu Xing1252efe2018-05-05 00:20:25108 gl_->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
109 GL_INNOCENT_CONTEXT_RESET_ARB);
danakj014316e2016-08-04 18:40:26110 }
sunnypse9fd9522016-10-06 23:03:27111
Eric Karl8d678f892018-12-11 06:51:00112 sii_ = provider->SharedImageInterface();
113
danakjc7afae52017-06-20 21:12:41114 return LayerTreeTest::CreateLayerTreeFrameSink(
Xu Xing1252efe2018-05-05 00:20:25115 renderer_settings, refresh_rate, std::move(provider),
danakj014316e2016-08-04 18:40:26116 std::move(worker_context_provider));
117 }
118
dcheng716bedf2014-10-21 09:51:08119 DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
120 LayerTreeHostImpl::FrameData* frame,
121 DrawResult draw_result) override {
enne98f3a6c2014-10-09 20:09:44122 if (draw_result == DRAW_ABORTED_MISSING_HIGH_RES_CONTENT) {
danakj431a1202015-06-17 19:09:33123 // Only valid for single-threaded compositing, which activates
enne98f3a6c2014-10-09 20:09:44124 // immediately and will try to draw again when content has finished.
khushalsagarb64b360d2015-10-21 19:25:16125 DCHECK(!host_impl->task_runner_provider()->HasImplThread());
enne98f3a6c2014-10-09 20:09:44126 return draw_result;
127 }
[email protected]30d82142014-05-12 04:26:02128 EXPECT_EQ(DRAW_SUCCESS, draw_result);
[email protected]0a451722013-02-22 20:32:05129 if (!times_to_lose_during_draw_)
[email protected]7ddfe7e82014-01-30 07:22:11130 return draw_result;
[email protected]0a451722013-02-22 20:32:05131
132 --times_to_lose_during_draw_;
[email protected]c9addd12013-12-08 22:43:26133 LoseContext();
[email protected]0a451722013-02-22 20:32:05134
135 times_to_fail_create_ = times_to_fail_recreate_;
136 times_to_fail_recreate_ = 0;
[email protected]0a451722013-02-22 20:32:05137
[email protected]7ddfe7e82014-01-30 07:22:11138 return draw_result;
[email protected]0a451722013-02-22 20:32:05139 }
140
dcheng716bedf2014-10-21 09:51:08141 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
[email protected]0a451722013-02-22 20:32:05142 committed_at_least_once_ = true;
143
[email protected]d993b602013-01-04 02:08:12144 if (!times_to_lose_during_commit_)
145 return;
146 --times_to_lose_during_commit_;
147 LoseContext();
148
[email protected]d993b602013-01-04 02:08:12149 times_to_fail_create_ = times_to_fail_recreate_;
150 times_to_fail_recreate_ = 0;
[email protected]0a451722013-02-22 20:32:05151 }
152
danakjc7afae52017-06-20 21:12:41153 void DidFailToInitializeLayerTreeFrameSink() override {
danakj1120f4c2016-09-15 02:05:32154 ++times_create_failed_;
155 }
[email protected]0a451722013-02-22 20:32:05156
danakjaeb95062014-11-14 01:35:36157 void TearDown() override {
[email protected]e216fef02013-03-20 22:56:10158 LayerTreeTest::TearDown();
[email protected]04049fc2013-05-01 03:13:20159 EXPECT_EQ(times_to_expect_create_failed_, times_create_failed_);
[email protected]0a451722013-02-22 20:32:05160 }
161
[email protected]e7e7ebd2014-01-16 00:11:11162 void ExpectCreateToFail() { ++times_to_expect_create_failed_; }
[email protected]d993b602013-01-04 02:08:12163
164 protected:
Xu Xing1252efe2018-05-05 00:20:25165 // Protects use of gl_ so LoseContext and
danakjc7afae52017-06-20 21:12:41166 // CreateDisplayLayerTreeFrameSink can both use it on different threads.
Xu Xing1252efe2018-05-05 00:20:25167 base::Lock gl_lock_;
168 viz::TestGLES2Interface* gl_ = nullptr;
Eric Karl8d678f892018-12-11 06:51:00169 viz::TestSharedImageInterface* sii_ = nullptr;
danakj5d897112015-06-24 20:07:20170
[email protected]d993b602013-01-04 02:08:12171 int times_to_fail_create_;
[email protected]d993b602013-01-04 02:08:12172 int times_to_lose_during_commit_;
[email protected]e01dddb12013-01-23 03:57:08173 int times_to_lose_during_draw_;
[email protected]155399d2013-03-29 19:07:36174 int times_to_fail_recreate_;
[email protected]04049fc2013-05-01 03:13:20175 int times_to_expect_create_failed_;
176 int times_create_failed_;
[email protected]0a451722013-02-22 20:32:05177 bool committed_at_least_once_;
[email protected]04049fc2013-05-01 03:13:20178 bool context_should_support_io_surface_;
[email protected]ebc0e1df2013-08-01 02:46:22179 bool fallback_context_works_;
danakjc7afae52017-06-20 21:12:41180 bool async_layer_tree_frame_sink_creation_;
[email protected]d993b602013-01-04 02:08:12181};
182
[email protected]ca2902e92013-03-28 01:45:35183class LayerTreeHostContextTestLostContextSucceeds
184 : public LayerTreeHostContextTest {
[email protected]d993b602013-01-04 02:08:12185 public:
186 LayerTreeHostContextTestLostContextSucceeds()
187 : LayerTreeHostContextTest(),
188 test_case_(0),
[email protected]e01dddb12013-01-23 03:57:08189 num_losses_(0),
[email protected]c9addd12013-12-08 22:43:26190 num_losses_last_test_case_(-1),
[email protected]04049fc2013-05-01 03:13:20191 recovered_context_(true),
192 first_initialized_(false) {}
[email protected]d993b602013-01-04 02:08:12193
dcheng716bedf2014-10-21 09:51:08194 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
[email protected]d993b602013-01-04 02:08:12195
danakjc7afae52017-06-20 21:12:41196 void RequestNewLayerTreeFrameSink() override {
197 if (async_layer_tree_frame_sink_creation_) {
enne2097cab2014-09-25 20:16:31198 MainThreadTaskRunner()->PostTask(
tzik4604bb52017-04-13 21:50:22199 FROM_HERE,
200 base::BindOnce(&LayerTreeHostContextTestLostContextSucceeds::
danakjc7afae52017-06-20 21:12:41201 AsyncRequestNewLayerTreeFrameSink,
tzik4604bb52017-04-13 21:50:22202 base::Unretained(this)));
enne2097cab2014-09-25 20:16:31203 } else {
danakjc7afae52017-06-20 21:12:41204 AsyncRequestNewLayerTreeFrameSink();
enne2097cab2014-09-25 20:16:31205 }
206 }
207
danakjc7afae52017-06-20 21:12:41208 void AsyncRequestNewLayerTreeFrameSink() {
209 LayerTreeHostContextTest::RequestNewLayerTreeFrameSink();
enne2097cab2014-09-25 20:16:31210 }
211
danakjc7afae52017-06-20 21:12:41212 void DidInitializeLayerTreeFrameSink() override {
[email protected]04049fc2013-05-01 03:13:20213 if (first_initialized_)
214 ++num_losses_;
215 else
216 first_initialized_ = true;
217
[email protected]e01dddb12013-01-23 03:57:08218 recovered_context_ = true;
[email protected]d993b602013-01-04 02:08:12219 }
220
dcheng716bedf2014-10-21 09:51:08221 void AfterTest() override { EXPECT_EQ(11u, test_case_); }
[email protected]d993b602013-01-04 02:08:12222
dcheng716bedf2014-10-21 09:51:08223 void DidCommitAndDrawFrame() override {
[email protected]d993b602013-01-04 02:08:12224 // If the last frame had a context loss, then we'll commit again to
225 // recover.
[email protected]e01dddb12013-01-23 03:57:08226 if (!recovered_context_)
227 return;
228 if (times_to_lose_during_commit_)
229 return;
230 if (times_to_lose_during_draw_)
[email protected]d993b602013-01-04 02:08:12231 return;
232
[email protected]e01dddb12013-01-23 03:57:08233 recovered_context_ = false;
[email protected]d993b602013-01-04 02:08:12234 if (NextTestCase())
[email protected]e01dddb12013-01-23 03:57:08235 InvalidateAndSetNeedsCommit();
[email protected]d993b602013-01-04 02:08:12236 else
[email protected]e216fef02013-03-20 22:56:10237 EndTest();
[email protected]d993b602013-01-04 02:08:12238 }
239
[email protected]e01dddb12013-01-23 03:57:08240 virtual void InvalidateAndSetNeedsCommit() {
[email protected]e0341352013-04-06 05:01:20241 // Cause damage so we try to draw.
khushalsagarb69ba9452017-01-27 22:20:07242 layer_tree_host()->root_layer()->SetNeedsDisplay();
[email protected]3519b872013-07-30 07:17:50243 layer_tree_host()->SetNeedsCommit();
[email protected]e01dddb12013-01-23 03:57:08244 }
245
[email protected]d993b602013-01-04 02:08:12246 bool NextTestCase() {
247 static const TestCase kTests[] = {
[email protected]e7e7ebd2014-01-16 00:11:11248 // Losing the context and failing to recreate it (or losing it again
249 // immediately) a small number of times should succeed.
[email protected]174c6d42014-08-12 01:43:06250 {
danakj1120f4c2016-09-15 02:05:32251 1, // times_to_lose_during_commit
252 0, // times_to_lose_during_draw
253 0, // times_to_fail_recreate
254 false, // fallback_context_works
danakjc7afae52017-06-20 21:12:41255 false, // async_layer_tree_frame_sink_creation
[email protected]e7e7ebd2014-01-16 00:11:11256 },
[email protected]174c6d42014-08-12 01:43:06257 {
danakj1120f4c2016-09-15 02:05:32258 0, // times_to_lose_during_commit
259 1, // times_to_lose_during_draw
260 0, // times_to_fail_recreate
261 false, // fallback_context_works
danakjc7afae52017-06-20 21:12:41262 false, // async_layer_tree_frame_sink_creation
[email protected]e7e7ebd2014-01-16 00:11:11263 },
[email protected]174c6d42014-08-12 01:43:06264 {
danakj1120f4c2016-09-15 02:05:32265 1, // times_to_lose_during_commit
266 0, // times_to_lose_during_draw
267 3, // times_to_fail_recreate
268 false, // fallback_context_works
danakjc7afae52017-06-20 21:12:41269 false, // async_layer_tree_frame_sink_creation
[email protected]e7e7ebd2014-01-16 00:11:11270 },
[email protected]174c6d42014-08-12 01:43:06271 {
danakj1120f4c2016-09-15 02:05:32272 0, // times_to_lose_during_commit
273 1, // times_to_lose_during_draw
274 3, // times_to_fail_recreate
275 false, // fallback_context_works
danakjc7afae52017-06-20 21:12:41276 false, // async_layer_tree_frame_sink_creation
enne2097cab2014-09-25 20:16:31277 },
278 {
danakj1120f4c2016-09-15 02:05:32279 0, // times_to_lose_during_commit
280 1, // times_to_lose_during_draw
281 3, // times_to_fail_recreate
282 false, // fallback_context_works
danakjc7afae52017-06-20 21:12:41283 true, // async_layer_tree_frame_sink_creation
[email protected]e7e7ebd2014-01-16 00:11:11284 },
[email protected]e7e7ebd2014-01-16 00:11:11285 // Losing the context and recreating it any number of times should
286 // succeed.
[email protected]174c6d42014-08-12 01:43:06287 {
danakj1120f4c2016-09-15 02:05:32288 10, // times_to_lose_during_commit
289 0, // times_to_lose_during_draw
290 0, // times_to_fail_recreate
291 false, // fallback_context_works
danakjc7afae52017-06-20 21:12:41292 false, // async_layer_tree_frame_sink_creation
[email protected]e7e7ebd2014-01-16 00:11:11293 },
[email protected]174c6d42014-08-12 01:43:06294 {
danakj1120f4c2016-09-15 02:05:32295 0, // times_to_lose_during_commit
296 10, // times_to_lose_during_draw
297 0, // times_to_fail_recreate
298 false, // fallback_context_works
danakjc7afae52017-06-20 21:12:41299 false, // async_layer_tree_frame_sink_creation
enne2097cab2014-09-25 20:16:31300 },
301 {
danakj1120f4c2016-09-15 02:05:32302 10, // times_to_lose_during_commit
303 0, // times_to_lose_during_draw
304 0, // times_to_fail_recreate
305 false, // fallback_context_works
danakjc7afae52017-06-20 21:12:41306 true, // async_layer_tree_frame_sink_creation
enne2097cab2014-09-25 20:16:31307 },
308 {
danakj1120f4c2016-09-15 02:05:32309 0, // times_to_lose_during_commit
310 10, // times_to_lose_during_draw
311 0, // times_to_fail_recreate
312 false, // fallback_context_works
danakjc7afae52017-06-20 21:12:41313 true, // async_layer_tree_frame_sink_creation
[email protected]e7e7ebd2014-01-16 00:11:11314 },
315 // Losing the context, failing to reinitialize it, and making a fallback
316 // context should work.
[email protected]174c6d42014-08-12 01:43:06317 {
danakj1120f4c2016-09-15 02:05:32318 0, // times_to_lose_during_commit
319 1, // times_to_lose_during_draw
320 0, // times_to_fail_recreate
321 true, // fallback_context_works
danakjc7afae52017-06-20 21:12:41322 false, // async_layer_tree_frame_sink_creation
enne2097cab2014-09-25 20:16:31323 },
324 {
danakj1120f4c2016-09-15 02:05:32325 0, // times_to_lose_during_commit
326 1, // times_to_lose_during_draw
327 0, // times_to_fail_recreate
328 true, // fallback_context_works
danakjc7afae52017-06-20 21:12:41329 true, // async_layer_tree_frame_sink_creation
[email protected]174c6d42014-08-12 01:43:06330 },
331 };
[email protected]d993b602013-01-04 02:08:12332
Avi Drissman0dd4e0e62018-12-25 23:20:46333 if (test_case_ >= base::size(kTests))
[email protected]d993b602013-01-04 02:08:12334 return false;
[email protected]c9addd12013-12-08 22:43:26335 // Make sure that we lost our context at least once in the last test run so
336 // the test did something.
337 EXPECT_GT(num_losses_, num_losses_last_test_case_);
338 num_losses_last_test_case_ = num_losses_;
[email protected]d993b602013-01-04 02:08:12339
340 times_to_lose_during_commit_ =
341 kTests[test_case_].times_to_lose_during_commit;
[email protected]e7e7ebd2014-01-16 00:11:11342 times_to_lose_during_draw_ = kTests[test_case_].times_to_lose_during_draw;
[email protected]d993b602013-01-04 02:08:12343 times_to_fail_recreate_ = kTests[test_case_].times_to_fail_recreate;
[email protected]ebc0e1df2013-08-01 02:46:22344 fallback_context_works_ = kTests[test_case_].fallback_context_works;
danakjc7afae52017-06-20 21:12:41345 async_layer_tree_frame_sink_creation_ =
346 kTests[test_case_].async_layer_tree_frame_sink_creation;
[email protected]d993b602013-01-04 02:08:12347 ++test_case_;
348 return true;
349 }
350
351 struct TestCase {
352 int times_to_lose_during_commit;
[email protected]e01dddb12013-01-23 03:57:08353 int times_to_lose_during_draw;
[email protected]d993b602013-01-04 02:08:12354 int times_to_fail_recreate;
[email protected]ebc0e1df2013-08-01 02:46:22355 bool fallback_context_works;
danakjc7afae52017-06-20 21:12:41356 bool async_layer_tree_frame_sink_creation;
[email protected]d993b602013-01-04 02:08:12357 };
358
[email protected]0a451722013-02-22 20:32:05359 protected:
[email protected]d993b602013-01-04 02:08:12360 size_t test_case_;
361 int num_losses_;
[email protected]c9addd12013-12-08 22:43:26362 int num_losses_last_test_case_;
[email protected]e01dddb12013-01-23 03:57:08363 bool recovered_context_;
[email protected]04049fc2013-05-01 03:13:20364 bool first_initialized_;
[email protected]d993b602013-01-04 02:08:12365};
366
Xida Chen4731a332017-06-23 17:41:09367// Disabled because of crbug.com/736392
368// SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLostContextSucceeds);
[email protected]d993b602013-01-04 02:08:12369
danakjc7afae52017-06-20 21:12:41370class LayerTreeHostClientNotVisibleDoesNotCreateLayerTreeFrameSink
[email protected]e96e3432013-12-19 18:56:07371 : public LayerTreeHostContextTest {
372 public:
danakjc7afae52017-06-20 21:12:41373 LayerTreeHostClientNotVisibleDoesNotCreateLayerTreeFrameSink()
[email protected]e96e3432013-12-19 18:56:07374 : LayerTreeHostContextTest() {}
375
dcheng716bedf2014-10-21 09:51:08376 void WillBeginTest() override {
sievers71c62dd52015-10-07 01:44:39377 // Override to not become visible.
khushalsagarcebe4942016-09-07 23:27:01378 DCHECK(!layer_tree_host()->IsVisible());
[email protected]e96e3432013-12-19 18:56:07379 }
380
dcheng716bedf2014-10-21 09:51:08381 void BeginTest() override {
[email protected]e96e3432013-12-19 18:56:07382 PostSetNeedsCommitToMainThread();
383 EndTest();
384 }
385
danakjc7afae52017-06-20 21:12:41386 void RequestNewLayerTreeFrameSink() override {
387 ADD_FAILURE() << "RequestNewLayerTreeFrameSink() should not be called";
[email protected]e96e3432013-12-19 18:56:07388 }
389
danakjc7afae52017-06-20 21:12:41390 void DidInitializeLayerTreeFrameSink() override { EXPECT_TRUE(false); }
[email protected]e96e3432013-12-19 18:56:07391};
392
[email protected]aeeedad2014-08-22 18:16:22393SINGLE_AND_MULTI_THREAD_TEST_F(
danakjc7afae52017-06-20 21:12:41394 LayerTreeHostClientNotVisibleDoesNotCreateLayerTreeFrameSink);
[email protected]e96e3432013-12-19 18:56:07395
danakjc7afae52017-06-20 21:12:41396// This tests the LayerTreeFrameSink release logic in the following sequence.
397// SetUp LTH and create and init LayerTreeFrameSink.
sohan.jyoti3a33d872015-09-18 22:32:55398// LTH::SetVisible(false);
danakjc7afae52017-06-20 21:12:41399// LTH::ReleaseLayerTreeFrameSink();
sohan.jyoti3a33d872015-09-18 22:32:55400// ...
401// LTH::SetVisible(true);
danakjc7afae52017-06-20 21:12:41402// Create and init new LayerTreeFrameSink
403class LayerTreeHostClientTakeAwayLayerTreeFrameSink
sohan.jyoti3a33d872015-09-18 22:32:55404 : public LayerTreeHostContextTest {
405 public:
danakjc7afae52017-06-20 21:12:41406 LayerTreeHostClientTakeAwayLayerTreeFrameSink()
sohan.jyoti3a33d872015-09-18 22:32:55407 : LayerTreeHostContextTest(), setos_counter_(0) {}
408
409 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
410
danakjc7afae52017-06-20 21:12:41411 void RequestNewLayerTreeFrameSink() override {
khushalsagarcebe4942016-09-07 23:27:01412 if (layer_tree_host()->IsVisible()) {
danakj014316e2016-08-04 18:40:26413 setos_counter_++;
danakjc7afae52017-06-20 21:12:41414 LayerTreeHostContextTest::RequestNewLayerTreeFrameSink();
danakj014316e2016-08-04 18:40:26415 }
sohan.jyoti3a33d872015-09-18 22:32:55416 }
417
danakjc7afae52017-06-20 21:12:41418 void HideAndReleaseLayerTreeFrameSink() {
khushalsagarcebe4942016-09-07 23:27:01419 EXPECT_TRUE(layer_tree_host()->GetTaskRunnerProvider()->IsMainThread());
sohan.jyoti3a33d872015-09-18 22:32:55420 layer_tree_host()->SetVisible(false);
danakjc7afae52017-06-20 21:12:41421 std::unique_ptr<LayerTreeFrameSink> surface =
422 layer_tree_host()->ReleaseLayerTreeFrameSink();
sohan.jyoti3a33d872015-09-18 22:32:55423 CHECK(surface);
sohan.jyoti3a33d872015-09-18 22:32:55424 MainThreadTaskRunner()->PostTask(
425 FROM_HERE,
tzik4604bb52017-04-13 21:50:22426 base::BindOnce(
danakjc7afae52017-06-20 21:12:41427 &LayerTreeHostClientTakeAwayLayerTreeFrameSink::MakeVisible,
tzik4604bb52017-04-13 21:50:22428 base::Unretained(this)));
sohan.jyoti3a33d872015-09-18 22:32:55429 }
430
danakjc7afae52017-06-20 21:12:41431 void DidInitializeLayerTreeFrameSink() override {
khushalsagarcebe4942016-09-07 23:27:01432 EXPECT_TRUE(layer_tree_host()->IsVisible());
sohan.jyoti3a33d872015-09-18 22:32:55433 if (setos_counter_ == 1) {
434 MainThreadTaskRunner()->PostTask(
danakj1120f4c2016-09-15 02:05:32435 FROM_HERE,
danakjc7afae52017-06-20 21:12:41436 base::BindOnce(&LayerTreeHostClientTakeAwayLayerTreeFrameSink::
437 HideAndReleaseLayerTreeFrameSink,
tzik4604bb52017-04-13 21:50:22438 base::Unretained(this)));
sohan.jyoti3a33d872015-09-18 22:32:55439 } else {
440 EndTest();
441 }
442 }
443
444 void MakeVisible() {
khushalsagarcebe4942016-09-07 23:27:01445 EXPECT_TRUE(layer_tree_host()->GetTaskRunnerProvider()->IsMainThread());
sohan.jyoti3a33d872015-09-18 22:32:55446 layer_tree_host()->SetVisible(true);
447 }
448
sohan.jyoti3a33d872015-09-18 22:32:55449 int setos_counter_;
450};
451
danakjc7afae52017-06-20 21:12:41452SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostClientTakeAwayLayerTreeFrameSink);
sohan.jyoti3a33d872015-09-18 22:32:55453
danakjc7afae52017-06-20 21:12:41454class MultipleCompositeDoesNotCreateLayerTreeFrameSink
jbauman8ab0f9e2014-10-15 02:30:34455 : public LayerTreeHostContextTest {
456 public:
danakjc7afae52017-06-20 21:12:41457 MultipleCompositeDoesNotCreateLayerTreeFrameSink()
jbauman8ab0f9e2014-10-15 02:30:34458 : LayerTreeHostContextTest(), request_count_(0) {}
459
dcheng716bedf2014-10-21 09:51:08460 void InitializeSettings(LayerTreeSettings* settings) override {
jbauman8ab0f9e2014-10-15 02:30:34461 settings->single_thread_proxy_scheduler = false;
danakj16e072d2015-05-21 00:31:16462 settings->use_zero_copy = true;
jbauman8ab0f9e2014-10-15 02:30:34463 }
464
danakjc7afae52017-06-20 21:12:41465 void RequestNewLayerTreeFrameSink() override {
jbauman8ab0f9e2014-10-15 02:30:34466 EXPECT_GE(1, ++request_count_);
467 EndTest();
468 }
469
dcheng716bedf2014-10-21 09:51:08470 void BeginTest() override {
Khushal4b6c41882018-02-16 09:02:10471 layer_tree_host()->Composite(TicksFromMicroseconds(1), false);
472 layer_tree_host()->Composite(TicksFromMicroseconds(2), false);
jbauman8ab0f9e2014-10-15 02:30:34473 }
474
danakjc7afae52017-06-20 21:12:41475 void DidInitializeLayerTreeFrameSink() override { EXPECT_TRUE(false); }
jbauman8ab0f9e2014-10-15 02:30:34476
jbauman8ab0f9e2014-10-15 02:30:34477 int request_count_;
478};
479
Dana Jansensab277762015-06-12 23:52:55480// This test uses Composite() which only exists for single thread.
danakjc7afae52017-06-20 21:12:41481SINGLE_THREAD_TEST_F(MultipleCompositeDoesNotCreateLayerTreeFrameSink);
jbauman8ab0f9e2014-10-15 02:30:34482
enne5232fbb2015-01-27 21:22:41483// This test makes sure that once a SingleThreadProxy issues a
danakjc7afae52017-06-20 21:12:41484// DidFailToInitializeLayerTreeFrameSink, that future Composite calls will not
enne5232fbb2015-01-27 21:22:41485// trigger additional requests for output surfaces.
danakjc7afae52017-06-20 21:12:41486class FailedCreateDoesNotCreateExtraLayerTreeFrameSink
jbauman8ab0f9e2014-10-15 02:30:34487 : public LayerTreeHostContextTest {
488 public:
danakjc7afae52017-06-20 21:12:41489 FailedCreateDoesNotCreateExtraLayerTreeFrameSink()
sunnypse9fd9522016-10-06 23:03:27490 : LayerTreeHostContextTest(), num_requests_(0), has_failed_(false) {
491 times_to_fail_create_ = 1;
492 }
jbauman8ab0f9e2014-10-15 02:30:34493
dcheng716bedf2014-10-21 09:51:08494 void InitializeSettings(LayerTreeSettings* settings) override {
jbauman8ab0f9e2014-10-15 02:30:34495 settings->single_thread_proxy_scheduler = false;
danakj16e072d2015-05-21 00:31:16496 settings->use_zero_copy = true;
jbauman8ab0f9e2014-10-15 02:30:34497 }
498
danakjc7afae52017-06-20 21:12:41499 void RequestNewLayerTreeFrameSink() override {
enne5232fbb2015-01-27 21:22:41500 num_requests_++;
501 // There should be one initial request and then one request from
danakjc7afae52017-06-20 21:12:41502 // the LayerTreeTest test hooks DidFailToInitializeLayerTreeFrameSink
danakj1120f4c2016-09-15 02:05:32503 // (which is hard to skip). This second request is just ignored and is test
504 // cruft.
enne5232fbb2015-01-27 21:22:41505 EXPECT_LE(num_requests_, 2);
506 if (num_requests_ > 1)
507 return;
danakjc7afae52017-06-20 21:12:41508 LayerTreeHostContextTest::RequestNewLayerTreeFrameSink();
danakj014316e2016-08-04 18:40:26509 }
510
dcheng716bedf2014-10-21 09:51:08511 void BeginTest() override {
enne5232fbb2015-01-27 21:22:41512 // First composite tries to create a surface.
Khushal4b6c41882018-02-16 09:02:10513 layer_tree_host()->Composite(TicksFromMicroseconds(1), false);
enne5232fbb2015-01-27 21:22:41514 EXPECT_EQ(num_requests_, 2);
515 EXPECT_TRUE(has_failed_);
516
517 // Second composite should not request or fail.
Khushal4b6c41882018-02-16 09:02:10518 layer_tree_host()->Composite(TicksFromMicroseconds(2), false);
enne5232fbb2015-01-27 21:22:41519 EXPECT_EQ(num_requests_, 2);
520 EndTest();
jbauman8ab0f9e2014-10-15 02:30:34521 }
522
danakjc7afae52017-06-20 21:12:41523 void DidInitializeLayerTreeFrameSink() override { EXPECT_TRUE(false); }
jbauman8ab0f9e2014-10-15 02:30:34524
danakjc7afae52017-06-20 21:12:41525 void DidFailToInitializeLayerTreeFrameSink() override {
526 LayerTreeHostContextTest::DidFailToInitializeLayerTreeFrameSink();
enne5232fbb2015-01-27 21:22:41527 EXPECT_FALSE(has_failed_);
528 has_failed_ = true;
enne7f8fdde2014-12-10 21:32:09529 }
530
enne5232fbb2015-01-27 21:22:41531 int num_requests_;
532 bool has_failed_;
jbauman8ab0f9e2014-10-15 02:30:34533};
534
Dana Jansensab277762015-06-12 23:52:55535// This test uses Composite() which only exists for single thread.
danakjc7afae52017-06-20 21:12:41536SINGLE_THREAD_TEST_F(FailedCreateDoesNotCreateExtraLayerTreeFrameSink);
jbauman399aec1a2014-10-25 02:33:32537
danakjc7afae52017-06-20 21:12:41538class LayerTreeHostContextTestCommitAfterDelayedLayerTreeFrameSink
jbauman399aec1a2014-10-25 02:33:32539 : public LayerTreeHostContextTest {
540 public:
danakjc7afae52017-06-20 21:12:41541 LayerTreeHostContextTestCommitAfterDelayedLayerTreeFrameSink()
jbauman399aec1a2014-10-25 02:33:32542 : LayerTreeHostContextTest(), creating_output_(false) {}
543
544 void InitializeSettings(LayerTreeSettings* settings) override {
545 settings->single_thread_proxy_scheduler = false;
danakj16e072d2015-05-21 00:31:16546 settings->use_zero_copy = true;
jbauman399aec1a2014-10-25 02:33:32547 }
548
danakjc7afae52017-06-20 21:12:41549 void RequestNewLayerTreeFrameSink() override {
jbauman399aec1a2014-10-25 02:33:32550 MainThreadTaskRunner()->PostTask(
551 FROM_HERE,
tzik4604bb52017-04-13 21:50:22552 base::BindOnce(
danakjc7afae52017-06-20 21:12:41553 &LayerTreeHostContextTestCommitAfterDelayedLayerTreeFrameSink::
554 CreateAndSetLayerTreeFrameSink,
danakj1120f4c2016-09-15 02:05:32555 base::Unretained(this)));
jbauman399aec1a2014-10-25 02:33:32556 }
557
danakjc7afae52017-06-20 21:12:41558 void CreateAndSetLayerTreeFrameSink() {
jbauman399aec1a2014-10-25 02:33:32559 creating_output_ = true;
danakjc7afae52017-06-20 21:12:41560 LayerTreeHostContextTest::RequestNewLayerTreeFrameSink();
jbauman399aec1a2014-10-25 02:33:32561 }
562
mithro0bdb49d2015-05-27 13:08:01563 void BeginTest() override {
Khushal4b6c41882018-02-16 09:02:10564 layer_tree_host()->Composite(TicksFromMicroseconds(1), false);
mithro0bdb49d2015-05-27 13:08:01565 }
jbauman399aec1a2014-10-25 02:33:32566
567 void ScheduleComposite() override {
568 if (creating_output_)
569 EndTest();
570 }
571
jbauman399aec1a2014-10-25 02:33:32572 bool creating_output_;
573};
574
Dana Jansensab277762015-06-12 23:52:55575// This test uses Composite() which only exists for single thread.
danakj1120f4c2016-09-15 02:05:32576SINGLE_THREAD_TEST_F(
danakjc7afae52017-06-20 21:12:41577 LayerTreeHostContextTestCommitAfterDelayedLayerTreeFrameSink);
jbauman399aec1a2014-10-25 02:33:32578
579class LayerTreeHostContextTestAvoidUnnecessaryComposite
580 : public LayerTreeHostContextTest {
581 public:
582 LayerTreeHostContextTestAvoidUnnecessaryComposite()
583 : LayerTreeHostContextTest(), in_composite_(false) {}
584
585 void InitializeSettings(LayerTreeSettings* settings) override {
586 settings->single_thread_proxy_scheduler = false;
danakj16e072d2015-05-21 00:31:16587 settings->use_zero_copy = true;
jbauman399aec1a2014-10-25 02:33:32588 }
589
danakjc7afae52017-06-20 21:12:41590 void RequestNewLayerTreeFrameSink() override {
591 LayerTreeHostContextTest::RequestNewLayerTreeFrameSink();
jbauman399aec1a2014-10-25 02:33:32592 EndTest();
593 }
594
595 void BeginTest() override {
596 in_composite_ = true;
Khushal4b6c41882018-02-16 09:02:10597 layer_tree_host()->Composite(TicksFromMicroseconds(1), false);
jbauman399aec1a2014-10-25 02:33:32598 in_composite_ = false;
599 }
600
601 void ScheduleComposite() override { EXPECT_FALSE(in_composite_); }
602
jbauman399aec1a2014-10-25 02:33:32603 bool in_composite_;
604};
605
Dana Jansensab277762015-06-12 23:52:55606// This test uses Composite() which only exists for single thread.
607SINGLE_THREAD_TEST_F(LayerTreeHostContextTestAvoidUnnecessaryComposite);
jbauman8ab0f9e2014-10-15 02:30:34608
Dana Jansensab277762015-06-12 23:52:55609// This test uses PictureLayer to check for a working context.
[email protected]ca2902e92013-03-28 01:45:35610class LayerTreeHostContextTestLostContextSucceedsWithContent
611 : public LayerTreeHostContextTestLostContextSucceeds {
[email protected]d993b602013-01-04 02:08:12612 public:
dcheng716bedf2014-10-21 09:51:08613 void SetupTree() override {
loyso0940d412016-03-14 01:30:31614 root_ = Layer::Create();
[email protected]7aba6662013-03-12 10:17:34615 root_->SetBounds(gfx::Size(10, 10));
[email protected]7aba6662013-03-12 10:17:34616 root_->SetIsDrawable(true);
[email protected]d993b602013-01-04 02:08:12617
sohan.jyoti9d1e4202014-09-23 21:02:33618 // Paint non-solid color.
ennebb7c4bcf2017-02-07 17:59:49619 PaintFlags flags;
620 flags.setColor(SkColorSetARGB(100, 80, 200, 200));
621 client_.add_draw_rect(gfx::Rect(5, 5), flags);
[email protected]e01dddb12013-01-23 03:57:08622
loyso0940d412016-03-14 01:30:31623 layer_ = FakePictureLayer::Create(&client_);
sohan.jyoti9d1e4202014-09-23 21:02:33624 layer_->SetBounds(gfx::Size(10, 10));
625 layer_->SetIsDrawable(true);
626
627 root_->AddChild(layer_);
[email protected]d993b602013-01-04 02:08:12628
khushalsagarb69ba9452017-01-27 22:20:07629 layer_tree_host()->SetRootLayer(root_);
[email protected]e216fef02013-03-20 22:56:10630 LayerTreeHostContextTest::SetupTree();
chrishtr01539b802015-11-24 08:11:32631 client_.set_bounds(root_->bounds());
[email protected]d993b602013-01-04 02:08:12632 }
633
dcheng716bedf2014-10-21 09:51:08634 void InvalidateAndSetNeedsCommit() override {
[email protected]e01dddb12013-01-23 03:57:08635 // Invalidate the render surface so we don't try to use a cached copy of the
636 // surface. We want to make sure to test the drawing paths for drawing to
637 // a child surface.
sohan.jyoti9d1e4202014-09-23 21:02:33638 layer_->SetNeedsDisplay();
[email protected]e01dddb12013-01-23 03:57:08639 LayerTreeHostContextTestLostContextSucceeds::InvalidateAndSetNeedsCommit();
640 }
641
dcheng716bedf2014-10-21 09:51:08642 void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
danakjeed856b62015-06-10 21:31:03643 FakePictureLayerImpl* picture_impl = static_cast<FakePictureLayerImpl*>(
sunxd1ae6803f2016-04-21 20:15:12644 host_impl->active_tree()->LayerById(layer_->id()));
danakjeed856b62015-06-10 21:31:03645 EXPECT_TRUE(picture_impl->HighResTiling()
646 ->TileAt(0, 0)
647 ->draw_info()
648 .IsReadyToDraw());
[email protected]d993b602013-01-04 02:08:12649 }
650
651 protected:
[email protected]d993b602013-01-04 02:08:12652 FakeContentLayerClient client_;
653 scoped_refptr<Layer> root_;
sohan.jyoti9d1e4202014-09-23 21:02:33654 scoped_refptr<Layer> layer_;
[email protected]d993b602013-01-04 02:08:12655};
656
Dana Jansensab277762015-06-12 23:52:55657SINGLE_AND_MULTI_THREAD_TEST_F(
[email protected]c2cc8bb2014-04-24 01:17:52658 LayerTreeHostContextTestLostContextSucceedsWithContent);
[email protected]2a61ad52013-05-13 14:01:29659
danakjc7afae52017-06-20 21:12:41660class LayerTreeHostContextTestCreateLayerTreeFrameSinkFailsOnce
[email protected]e96e3432013-12-19 18:56:07661 : public LayerTreeHostContextTest {
662 public:
danakjc7afae52017-06-20 21:12:41663 LayerTreeHostContextTestCreateLayerTreeFrameSinkFailsOnce()
enne7f8fdde2014-12-10 21:32:09664 : times_to_fail_(1), times_initialized_(0) {
[email protected]aeeedad2014-08-22 18:16:22665 times_to_fail_create_ = times_to_fail_;
666 }
[email protected]e96e3432013-12-19 18:56:07667
dcheng716bedf2014-10-21 09:51:08668 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
[email protected]e96e3432013-12-19 18:56:07669
danakjc7afae52017-06-20 21:12:41670 void DidInitializeLayerTreeFrameSink() override { times_initialized_++; }
[email protected]e96e3432013-12-19 18:56:07671
dcheng716bedf2014-10-21 09:51:08672 void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override { EndTest(); }
[email protected]e96e3432013-12-19 18:56:07673
dcheng716bedf2014-10-21 09:51:08674 void AfterTest() override {
[email protected]e96e3432013-12-19 18:56:07675 EXPECT_EQ(times_to_fail_, times_create_failed_);
[email protected]da8e3b72b2014-04-25 02:33:45676 EXPECT_NE(0, times_initialized_);
[email protected]e96e3432013-12-19 18:56:07677 }
678
679 private:
680 int times_to_fail_;
[email protected]e96e3432013-12-19 18:56:07681 int times_initialized_;
682};
683
[email protected]e96e3432013-12-19 18:56:07684SINGLE_AND_MULTI_THREAD_TEST_F(
danakjc7afae52017-06-20 21:12:41685 LayerTreeHostContextTestCreateLayerTreeFrameSinkFailsOnce);
[email protected]e96e3432013-12-19 18:56:07686
[email protected]ca2902e92013-03-28 01:45:35687class LayerTreeHostContextTestLostContextAndEvictTextures
688 : public LayerTreeHostContextTest {
[email protected]d993b602013-01-04 02:08:12689 public:
690 LayerTreeHostContextTestLostContextAndEvictTextures()
691 : LayerTreeHostContextTest(),
Ivan Kotenkov05d57542017-10-25 06:47:00692 impl_host_(nullptr),
sohan.jyoti9d1e4202014-09-23 21:02:33693 num_commits_(0),
694 lost_context_(false) {}
[email protected]d993b602013-01-04 02:08:12695
dcheng716bedf2014-10-21 09:51:08696 void SetupTree() override {
sohan.jyoti9d1e4202014-09-23 21:02:33697 // Paint non-solid color.
ennebb7c4bcf2017-02-07 17:59:49698 PaintFlags flags;
699 flags.setColor(SkColorSetARGB(100, 80, 200, 200));
700 client_.add_draw_rect(gfx::Rect(5, 5), flags);
sohan.jyoti9d1e4202014-09-23 21:02:33701
danakjeed856b62015-06-10 21:31:03702 scoped_refptr<FakePictureLayer> picture_layer =
loyso0940d412016-03-14 01:30:31703 FakePictureLayer::Create(&client_);
danakjeed856b62015-06-10 21:31:03704 picture_layer->SetBounds(gfx::Size(10, 20));
chrishtr01539b802015-11-24 08:11:32705 client_.set_bounds(picture_layer->bounds());
khushalsagarb69ba9452017-01-27 22:20:07706 layer_tree_host()->SetRootLayer(picture_layer);
sohan.jyoti9d1e4202014-09-23 21:02:33707
[email protected]e216fef02013-03-20 22:56:10708 LayerTreeHostContextTest::SetupTree();
[email protected]d993b602013-01-04 02:08:12709 }
710
dcheng716bedf2014-10-21 09:51:08711 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
[email protected]d993b602013-01-04 02:08:12712
713 void PostEvictTextures() {
[email protected]810d40b72013-06-20 18:26:15714 if (HasImplThread()) {
715 ImplThreadTaskRunner()->PostTask(
716 FROM_HERE,
tzik4604bb52017-04-13 21:50:22717 base::BindOnce(&LayerTreeHostContextTestLostContextAndEvictTextures::
718 EvictTexturesOnImplThread,
719 base::Unretained(this)));
[email protected]d993b602013-01-04 02:08:12720 } else {
khushalsagarb7db1fe2015-11-12 00:51:27721 DebugScopedSetImplThread impl(task_runner_provider());
[email protected]d993b602013-01-04 02:08:12722 EvictTexturesOnImplThread();
723 }
724 }
725
726 void EvictTexturesOnImplThread() {
[email protected]0309ba5e02013-06-26 04:11:08727 impl_host_->EvictTexturesForTesting();
sohan.jyoti9d1e4202014-09-23 21:02:33728
729 if (lose_after_evict_) {
[email protected]d993b602013-01-04 02:08:12730 LoseContext();
sohan.jyoti9d1e4202014-09-23 21:02:33731 lost_context_ = true;
732 }
[email protected]d993b602013-01-04 02:08:12733 }
734
dcheng716bedf2014-10-21 09:51:08735 void DidCommitAndDrawFrame() override {
[email protected]d993b602013-01-04 02:08:12736 if (num_commits_ > 1)
737 return;
[email protected]d993b602013-01-04 02:08:12738 PostEvictTextures();
739 }
740
dcheng716bedf2014-10-21 09:51:08741 void CommitCompleteOnThread(LayerTreeHostImpl* impl) override {
Dirk Pranke035a7942014-09-17 18:56:14742 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
743 if (num_commits_ > 1)
744 return;
745 ++num_commits_;
sohan.jyoti9d1e4202014-09-23 21:02:33746 if (!lose_after_evict_) {
Dirk Pranke035a7942014-09-17 18:56:14747 LoseContext();
sohan.jyoti9d1e4202014-09-23 21:02:33748 lost_context_ = true;
749 }
[email protected]d993b602013-01-04 02:08:12750 }
751
dcheng716bedf2014-10-21 09:51:08752 void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
Xianzhu Wang66e13e02019-09-18 20:39:12753 FakePictureLayerImpl* picture_impl =
754 static_cast<FakePictureLayerImpl*>(impl->active_tree()->root_layer());
danakjeed856b62015-06-10 21:31:03755 EXPECT_TRUE(picture_impl->HighResTiling()
756 ->TileAt(0, 0)
757 ->draw_info()
758 .IsReadyToDraw());
sohan.jyoti9d1e4202014-09-23 21:02:33759
760 impl_host_ = impl;
761 if (lost_context_)
762 EndTest();
763 }
764
danakjc7afae52017-06-20 21:12:41765 void DidInitializeLayerTreeFrameSink() override {}
[email protected]d993b602013-01-04 02:08:12766
[email protected]d993b602013-01-04 02:08:12767 protected:
768 bool lose_after_evict_;
769 FakeContentLayerClient client_;
[email protected]d993b602013-01-04 02:08:12770 LayerTreeHostImpl* impl_host_;
771 int num_commits_;
sohan.jyoti9d1e4202014-09-23 21:02:33772 bool lost_context_;
[email protected]d993b602013-01-04 02:08:12773};
774
Olga Sharonovae8994682017-11-22 12:05:22775TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
776 LoseAfterEvict_SingleThread) {
777 lose_after_evict_ = true;
778 RunTest(CompositorMode::SINGLE_THREADED);
779}
[email protected]d993b602013-01-04 02:08:12780
Olga Sharonovae8994682017-11-22 12:05:22781TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
782 LoseAfterEvict_MultiThread) {
783 lose_after_evict_ = true;
784 RunTest(CompositorMode::THREADED);
785}
[email protected]4145d172013-05-10 16:54:36786
Olga Sharonovae8994682017-11-22 12:05:22787TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
788 LoseBeforeEvict_SingleThread) {
789 lose_after_evict_ = false;
790 RunTest(CompositorMode::SINGLE_THREADED);
791}
[email protected]4145d172013-05-10 16:54:36792
Olga Sharonovae8994682017-11-22 12:05:22793TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
794 LoseBeforeEvict_MultiThread) {
795 lose_after_evict_ = false;
796 RunTest(CompositorMode::THREADED);
797}
[email protected]d993b602013-01-04 02:08:12798
[email protected]e7e7ebd2014-01-16 00:11:11799class LayerTreeHostContextTestLayersNotified : public LayerTreeHostContextTest {
[email protected]d993b602013-01-04 02:08:12800 public:
801 LayerTreeHostContextTestLayersNotified()
[email protected]e7e7ebd2014-01-16 00:11:11802 : LayerTreeHostContextTest(), num_commits_(0) {}
[email protected]d993b602013-01-04 02:08:12803
dcheng716bedf2014-10-21 09:51:08804 void SetupTree() override {
loyso0940d412016-03-14 01:30:31805 root_ = FakePictureLayer::Create(&client_);
806 child_ = FakePictureLayer::Create(&client_);
807 grandchild_ = FakePictureLayer::Create(&client_);
[email protected]d993b602013-01-04 02:08:12808
[email protected]7aba6662013-03-12 10:17:34809 root_->AddChild(child_);
810 child_->AddChild(grandchild_);
[email protected]d993b602013-01-04 02:08:12811
[email protected]e216fef02013-03-20 22:56:10812 LayerTreeHostContextTest::SetupTree();
chrishtr01539b802015-11-24 08:11:32813 client_.set_bounds(root_->bounds());
[email protected]d993b602013-01-04 02:08:12814 }
815
dcheng716bedf2014-10-21 09:51:08816 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
[email protected]d993b602013-01-04 02:08:12817
Adrienne Walker91d9347932018-11-07 02:11:17818 void AttachTree() { layer_tree_host()->SetRootLayer(root_); }
819
dcheng716bedf2014-10-21 09:51:08820 void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
[email protected]94bf75c2013-06-12 13:20:04821 LayerTreeHostContextTest::DidActivateTreeOnThread(host_impl);
[email protected]0a451722013-02-22 20:32:05822
Sunny Sachanandani0c193dc2018-11-10 01:14:02823 ++num_commits_;
824
Ivan Kotenkov05d57542017-10-25 06:47:00825 FakePictureLayerImpl* root_picture = nullptr;
826 FakePictureLayerImpl* child_picture = nullptr;
827 FakePictureLayerImpl* grandchild_picture = nullptr;
Sunny Sachanandani0c193dc2018-11-10 01:14:02828 // Root layer isn't attached on first activation so the static_cast will
829 // fail before second activation.
830 if (num_commits_ >= 2) {
831 root_picture = static_cast<FakePictureLayerImpl*>(
Xianzhu Wang66e13e02019-09-18 20:39:12832 host_impl->active_tree()->root_layer());
Sunny Sachanandani0c193dc2018-11-10 01:14:02833 child_picture = static_cast<FakePictureLayerImpl*>(
834 host_impl->active_tree()->LayerById(child_->id()));
835 grandchild_picture = static_cast<FakePictureLayerImpl*>(
836 host_impl->active_tree()->LayerById(grandchild_->id()));
837 }
[email protected]d993b602013-01-04 02:08:12838 switch (num_commits_) {
839 case 1:
Adrienne Walker91d9347932018-11-07 02:11:17840 // Because setting the colorspace on the first activation releases
841 // resources, don't attach the layers until the first activation.
842 // Because of single thread vs multi thread differences (i.e.
843 // commit to active tree), if this delay is not done, then the
844 // active tree layers will have a different number of resource
845 // releasing.
846 MainThreadTaskRunner()->PostTask(
847 FROM_HERE,
848 base::BindOnce(&LayerTreeHostContextTestLayersNotified::AttachTree,
849 base::Unretained(this)));
850 break;
851 case 2:
danakjeed856b62015-06-10 21:31:03852 EXPECT_EQ(0u, root_picture->release_resources_count());
853 EXPECT_EQ(0u, child_picture->release_resources_count());
854 EXPECT_EQ(0u, grandchild_picture->release_resources_count());
sohan.jyoti9d1e4202014-09-23 21:02:33855
[email protected]d993b602013-01-04 02:08:12856 // Lose the context and struggle to recreate it.
857 LoseContext();
858 times_to_fail_create_ = 1;
859 break;
Adrienne Walker91d9347932018-11-07 02:11:17860 case 3:
danakjeed856b62015-06-10 21:31:03861 EXPECT_TRUE(root_picture->release_resources_count());
862 EXPECT_TRUE(child_picture->release_resources_count());
863 EXPECT_TRUE(grandchild_picture->release_resources_count());
sohan.jyoti9d1e4202014-09-23 21:02:33864
[email protected]e216fef02013-03-20 22:56:10865 EndTest();
[email protected]d993b602013-01-04 02:08:12866 break;
867 default:
868 NOTREACHED();
869 }
870 }
871
[email protected]d993b602013-01-04 02:08:12872 private:
873 int num_commits_;
874
875 FakeContentLayerClient client_;
sohan.jyoti9d1e4202014-09-23 21:02:33876 scoped_refptr<Layer> root_;
877 scoped_refptr<Layer> child_;
878 scoped_refptr<Layer> grandchild_;
[email protected]d993b602013-01-04 02:08:12879};
880
[email protected]75ea789f2013-03-27 18:06:10881SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLayersNotified);
[email protected]d993b602013-01-04 02:08:12882
[email protected]ca2902e92013-03-28 01:45:35883class LayerTreeHostContextTestDontUseLostResources
884 : public LayerTreeHostContextTest {
[email protected]d993b602013-01-04 02:08:12885 public:
[email protected]e7e7ebd2014-01-16 00:11:11886 LayerTreeHostContextTestDontUseLostResources() : lost_context_(false) {
[email protected]796e18f2013-09-26 18:38:34887 context_should_support_io_surface_ = true;
[email protected]50008cd2013-10-20 08:20:27888
kylechardfe762f2018-02-26 17:00:01889 child_context_provider_ = viz::TestContextProvider::Create();
danakj45cfd232017-10-18 19:31:31890 auto result = child_context_provider_->BindToCurrentThread();
891 CHECK_EQ(result, gpu::ContextResult::kSuccess);
kylecharefc48452018-02-23 17:11:00892 shared_bitmap_manager_ = std::make_unique<viz::TestSharedBitmapManager>();
Xu Xingb57edf32017-08-22 04:18:47893 child_resource_provider_ =
danakj4b15f742018-05-30 22:52:22894 std::make_unique<viz::ClientResourceProvider>(true);
[email protected]796e18f2013-09-26 18:38:34895 }
896
dyencc16ed4d2015-11-03 20:03:04897 static void EmptyReleaseCallback(const gpu::SyncToken& sync_token,
898 bool lost) {}
[email protected]50008cd2013-10-20 08:20:27899
dcheng716bedf2014-10-21 09:51:08900 void SetupTree() override {
danakj1120f4c2016-09-15 02:05:32901 gpu::gles2::GLES2Interface* gl = child_context_provider_->ContextGL();
[email protected]d993b602013-01-04 02:08:12902
Antoine Labour3a776dc12018-06-13 00:07:48903 gpu::Mailbox mailbox = gpu::Mailbox::Generate();
dyen0f072272016-01-08 01:16:15904
dyen0f072272016-01-08 01:16:15905 gpu::SyncToken sync_token;
Sunny Sachanandanic94b8de2017-12-16 03:30:30906 gl->GenSyncTokenCHROMIUM(sync_token.GetData());
[email protected]50008cd2013-10-20 08:20:27907
loyso0940d412016-03-14 01:30:31908 scoped_refptr<Layer> root = Layer::Create();
[email protected]50008cd2013-10-20 08:20:27909 root->SetBounds(gfx::Size(10, 10));
[email protected]50008cd2013-10-20 08:20:27910 root->SetIsDrawable(true);
911
loyso0940d412016-03-14 01:30:31912 scoped_refptr<PictureLayer> layer = PictureLayer::Create(&client_);
sohan.jyoti9d1e4202014-09-23 21:02:33913 layer->SetBounds(gfx::Size(10, 10));
914 layer->SetIsDrawable(true);
915 root->AddChild(layer);
[email protected]d993b602013-01-04 02:08:12916
Ivan Kotenkov05d57542017-10-25 06:47:00917 scoped_refptr<TextureLayer> texture =
918 TextureLayer::CreateForMailbox(nullptr);
[email protected]796e18f2013-09-26 18:38:34919 texture->SetBounds(gfx::Size(10, 10));
[email protected]796e18f2013-09-26 18:38:34920 texture->SetIsDrawable(true);
Saman Sami51c0a3e2019-05-02 13:43:38921 constexpr gfx::Size size(64, 64);
danakj5df8257f2017-11-20 22:16:58922 auto resource = viz::TransferableResource::MakeGL(
Saman Sami51c0a3e2019-05-02 13:43:38923 mailbox, GL_LINEAR, GL_TEXTURE_2D, sync_token, size,
924 false /* is_overlay_candidate */);
danakj5df8257f2017-11-20 22:16:58925 texture->SetTransferableResource(
kylechar3ef69ec2019-01-16 21:07:15926 resource, viz::SingleReleaseCallback::Create(base::BindOnce(
927 &LayerTreeHostContextTestDontUseLostResources::
928 EmptyReleaseCallback)));
[email protected]796e18f2013-09-26 18:38:34929 root->AddChild(texture);
[email protected]d993b602013-01-04 02:08:12930
loyso0940d412016-03-14 01:30:31931 scoped_refptr<PictureLayer> mask = PictureLayer::Create(&client_);
[email protected]796e18f2013-09-26 18:38:34932 mask->SetBounds(gfx::Size(10, 10));
chrishtr01539b802015-11-24 08:11:32933 client_.set_bounds(mask->bounds());
[email protected]d993b602013-01-04 02:08:12934
danakjeed856b62015-06-10 21:31:03935 scoped_refptr<PictureLayer> layer_with_mask =
loyso0940d412016-03-14 01:30:31936 PictureLayer::Create(&client_);
sohan.jyoti9d1e4202014-09-23 21:02:33937 layer_with_mask->SetBounds(gfx::Size(10, 10));
938 layer_with_mask->SetIsDrawable(true);
Xianzhu Wang15557bb2f2019-08-30 22:33:01939 layer_with_mask->SetMaskLayer(mask);
sohan.jyoti9d1e4202014-09-23 21:02:33940 root->AddChild(layer_with_mask);
[email protected]d993b602013-01-04 02:08:12941
loyso0940d412016-03-14 01:30:31942 scoped_refptr<VideoLayer> video_color =
943 VideoLayer::Create(&color_frame_provider_, media::VIDEO_ROTATION_0);
[email protected]796e18f2013-09-26 18:38:34944 video_color->SetBounds(gfx::Size(10, 10));
[email protected]796e18f2013-09-26 18:38:34945 video_color->SetIsDrawable(true);
946 root->AddChild(video_color);
[email protected]d993b602013-01-04 02:08:12947
loyso0940d412016-03-14 01:30:31948 scoped_refptr<VideoLayer> video_hw =
949 VideoLayer::Create(&hw_frame_provider_, media::VIDEO_ROTATION_0);
[email protected]796e18f2013-09-26 18:38:34950 video_hw->SetBounds(gfx::Size(10, 10));
[email protected]796e18f2013-09-26 18:38:34951 video_hw->SetIsDrawable(true);
952 root->AddChild(video_hw);
[email protected]d993b602013-01-04 02:08:12953
loyso0940d412016-03-14 01:30:31954 scoped_refptr<VideoLayer> video_scaled_hw =
955 VideoLayer::Create(&scaled_hw_frame_provider_, media::VIDEO_ROTATION_0);
[email protected]796e18f2013-09-26 18:38:34956 video_scaled_hw->SetBounds(gfx::Size(10, 10));
[email protected]796e18f2013-09-26 18:38:34957 video_scaled_hw->SetIsDrawable(true);
958 root->AddChild(video_scaled_hw);
[email protected]d993b602013-01-04 02:08:12959
[email protected]50008cd2013-10-20 08:20:27960 color_video_frame_ = VideoFrame::CreateColorFrame(
961 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
emircan8428d412016-01-15 08:59:27962 ASSERT_TRUE(color_video_frame_);
jbaumanb97bf4cf2016-05-12 00:20:18963 gpu::MailboxHolder holders[media::VideoFrame::kMaxPlanes] = {
964 gpu::MailboxHolder(mailbox, sync_token, GL_TEXTURE_2D)};
965 hw_video_frame_ = VideoFrame::WrapNativeTextures(
966 media::PIXEL_FORMAT_ARGB, holders,
achaulk91d8e7f2015-01-29 22:16:05967 media::VideoFrame::ReleaseMailboxCB(), gfx::Size(4, 4),
mcasas4337a742015-06-11 00:11:39968 gfx::Rect(0, 0, 4, 4), gfx::Size(4, 4), base::TimeDelta());
emircan8428d412016-01-15 08:59:27969 ASSERT_TRUE(hw_video_frame_);
jbaumanb97bf4cf2016-05-12 00:20:18970 scaled_hw_video_frame_ = VideoFrame::WrapNativeTextures(
971 media::PIXEL_FORMAT_ARGB, holders,
achaulk91d8e7f2015-01-29 22:16:05972 media::VideoFrame::ReleaseMailboxCB(), gfx::Size(4, 4),
mcasas4337a742015-06-11 00:11:39973 gfx::Rect(0, 0, 3, 2), gfx::Size(4, 4), base::TimeDelta());
emircan8428d412016-01-15 08:59:27974 ASSERT_TRUE(scaled_hw_video_frame_);
[email protected]50008cd2013-10-20 08:20:27975
976 color_frame_provider_.set_frame(color_video_frame_);
977 hw_frame_provider_.set_frame(hw_video_frame_);
978 scaled_hw_frame_provider_.set_frame(scaled_hw_video_frame_);
979
[email protected]d993b602013-01-04 02:08:12980 // Enable the hud.
981 LayerTreeDebugState debug_state;
[email protected]846f455b2013-03-18 19:07:41982 debug_state.show_property_changed_rects = true;
[email protected]e216fef02013-03-20 22:56:10983 layer_tree_host()->SetDebugState(debug_state);
[email protected]d993b602013-01-04 02:08:12984
[email protected]796e18f2013-09-26 18:38:34985 scoped_refptr<PaintedScrollbarLayer> scrollbar =
Xianzhu Wang5e6254e2019-10-30 17:58:49986 PaintedScrollbarLayer::Create(base::MakeRefCounted<FakeScrollbar>());
Xianzhu Wang42e5f4772019-10-04 00:10:22987 scrollbar->SetScrollElementId(layer->element_id());
[email protected]796e18f2013-09-26 18:38:34988 scrollbar->SetBounds(gfx::Size(10, 10));
[email protected]796e18f2013-09-26 18:38:34989 scrollbar->SetIsDrawable(true);
990 root->AddChild(scrollbar);
[email protected]d993b602013-01-04 02:08:12991
khushalsagarb69ba9452017-01-27 22:20:07992 layer_tree_host()->SetRootLayer(root);
[email protected]e216fef02013-03-20 22:56:10993 LayerTreeHostContextTest::SetupTree();
[email protected]d993b602013-01-04 02:08:12994 }
995
dcheng716bedf2014-10-21 09:51:08996 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
[email protected]d993b602013-01-04 02:08:12997
dcheng716bedf2014-10-21 09:51:08998 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
[email protected]e216fef02013-03-20 22:56:10999 LayerTreeHostContextTest::CommitCompleteOnThread(host_impl);
[email protected]0a451722013-02-22 20:32:051000
[email protected]c1bb5af2013-03-13 19:06:271001 if (host_impl->active_tree()->source_frame_number() == 3) {
[email protected]d993b602013-01-04 02:08:121002 // On the third commit we're recovering from context loss. Hardware
1003 // video frames should not be reused by the VideoFrameProvider, but
1004 // software frames can be.
Ivan Kotenkov05d57542017-10-25 06:47:001005 hw_frame_provider_.set_frame(nullptr);
1006 scaled_hw_frame_provider_.set_frame(nullptr);
[email protected]d993b602013-01-04 02:08:121007 }
1008 }
1009
dcheng716bedf2014-10-21 09:51:081010 DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
1011 LayerTreeHostImpl::FrameData* frame,
1012 DrawResult draw_result) override {
sohan5f348032017-07-22 01:33:281013 if (host_impl->active_tree()->source_frame_number() == 2) {
1014 // Lose the context after draw on the second commit. This will cause
1015 // a third commit to recover.
Xu Xing1252efe2018-05-05 00:20:251016 gl_->set_times_bind_texture_succeeds(0);
sohan5f348032017-07-22 01:33:281017 }
[email protected]7ddfe7e82014-01-30 07:22:111018 return draw_result;
[email protected]d993b602013-01-04 02:08:121019 }
1020
danakjc7afae52017-06-20 21:12:411021 void RequestNewLayerTreeFrameSink() override {
[email protected]e96e3432013-12-19 18:56:071022 // This will get called twice:
danakjc7afae52017-06-20 21:12:411023 // First when we create the initial LayerTreeFrameSink...
khushalsagarcebe4942016-09-07 23:27:011024 if (layer_tree_host()->SourceFrameNumber() > 0) {
[email protected]0c7a5612014-03-12 21:58:221025 // ... and then again after we forced the context to be lost.
[email protected]5b9e9bc2013-10-05 05:08:321026 lost_context_ = true;
[email protected]5b9e9bc2013-10-05 05:08:321027 }
danakjc7afae52017-06-20 21:12:411028 LayerTreeHostContextTest::RequestNewLayerTreeFrameSink();
[email protected]796e18f2013-09-26 18:38:341029 }
1030
dcheng716bedf2014-10-21 09:51:081031 void DidCommitAndDrawFrame() override {
khushalsagarb69ba9452017-01-27 22:20:071032 ASSERT_TRUE(layer_tree_host()->hud_layer());
[email protected]d993b602013-01-04 02:08:121033 // End the test once we know the 3nd frame drew.
khushalsagarcebe4942016-09-07 23:27:011034 if (layer_tree_host()->SourceFrameNumber() < 5) {
khushalsagarb69ba9452017-01-27 22:20:071035 layer_tree_host()->root_layer()->SetNeedsDisplay();
[email protected]5b9e9bc2013-10-05 05:08:321036 layer_tree_host()->SetNeedsCommit();
1037 } else {
[email protected]796e18f2013-09-26 18:38:341038 EndTest();
[email protected]5b9e9bc2013-10-05 05:08:321039 }
[email protected]d993b602013-01-04 02:08:121040 }
1041
dcheng716bedf2014-10-21 09:51:081042 void AfterTest() override { EXPECT_TRUE(lost_context_); }
[email protected]d993b602013-01-04 02:08:121043
1044 private:
1045 FakeContentLayerClient client_;
[email protected]5b9e9bc2013-10-05 05:08:321046 bool lost_context_;
[email protected]d993b602013-01-04 02:08:121047
kylechardfe762f2018-02-26 17:00:011048 scoped_refptr<viz::TestContextProvider> child_context_provider_;
Fady Samuel4b5f9862017-07-11 05:27:201049 std::unique_ptr<viz::SharedBitmapManager> shared_bitmap_manager_;
danakj57baa772018-05-29 15:59:141050 std::unique_ptr<viz::ClientResourceProvider> child_resource_provider_;
[email protected]50008cd2013-10-20 08:20:271051
[email protected]568285b2013-01-07 23:19:191052 scoped_refptr<VideoFrame> color_video_frame_;
1053 scoped_refptr<VideoFrame> hw_video_frame_;
1054 scoped_refptr<VideoFrame> scaled_hw_video_frame_;
[email protected]d993b602013-01-04 02:08:121055
1056 FakeVideoFrameProvider color_frame_provider_;
1057 FakeVideoFrameProvider hw_frame_provider_;
1058 FakeVideoFrameProvider scaled_hw_frame_provider_;
1059};
1060
[email protected]75ea789f2013-03-27 18:06:101061SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestDontUseLostResources);
[email protected]d993b602013-01-04 02:08:121062
[email protected]ca2902e92013-03-28 01:45:351063class LayerTreeHostContextTestImplSidePainting
danakjeed856b62015-06-10 21:31:031064 : public LayerTreeHostContextTest {
[email protected]45c4b1e2013-01-16 02:19:401065 public:
dcheng716bedf2014-10-21 09:51:081066 void SetupTree() override {
loyso0940d412016-03-14 01:30:311067 scoped_refptr<Layer> root = Layer::Create();
[email protected]7aba6662013-03-12 10:17:341068 root->SetBounds(gfx::Size(10, 10));
[email protected]7aba6662013-03-12 10:17:341069 root->SetIsDrawable(true);
[email protected]45c4b1e2013-01-16 02:19:401070
loyso0940d412016-03-14 01:30:311071 scoped_refptr<PictureLayer> picture = PictureLayer::Create(&client_);
[email protected]7aba6662013-03-12 10:17:341072 picture->SetBounds(gfx::Size(10, 10));
chrishtr01539b802015-11-24 08:11:321073 client_.set_bounds(picture->bounds());
[email protected]7aba6662013-03-12 10:17:341074 picture->SetIsDrawable(true);
1075 root->AddChild(picture);
[email protected]45c4b1e2013-01-16 02:19:401076
khushalsagarb69ba9452017-01-27 22:20:071077 layer_tree_host()->SetRootLayer(root);
[email protected]e216fef02013-03-20 22:56:101078 LayerTreeHostContextTest::SetupTree();
[email protected]45c4b1e2013-01-16 02:19:401079 }
1080
dcheng716bedf2014-10-21 09:51:081081 void BeginTest() override {
[email protected]45c4b1e2013-01-16 02:19:401082 times_to_lose_during_commit_ = 1;
[email protected]e216fef02013-03-20 22:56:101083 PostSetNeedsCommitToMainThread();
[email protected]45c4b1e2013-01-16 02:19:401084 }
1085
danakjc7afae52017-06-20 21:12:411086 void DidInitializeLayerTreeFrameSink() override { EndTest(); }
[email protected]45c4b1e2013-01-16 02:19:401087
1088 private:
1089 FakeContentLayerClient client_;
1090};
1091
Dana Jansensab277762015-06-12 23:52:551092SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestImplSidePainting);
[email protected]45c4b1e2013-01-16 02:19:401093
[email protected]7a6acd02013-01-19 04:16:131094class ScrollbarLayerLostContext : public LayerTreeHostContextTest {
1095 public:
1096 ScrollbarLayerLostContext() : commits_(0) {}
1097
dcheng716bedf2014-10-21 09:51:081098 void BeginTest() override {
loyso0940d412016-03-14 01:30:311099 scoped_refptr<Layer> scroll_layer = Layer::Create();
pdrfaf2ee222017-04-19 03:11:041100 scrollbar_layer_ = FakePaintedScrollbarLayer::Create(
pdr75a6cc52017-04-20 19:21:141101 false, true, scroll_layer->element_id());
[email protected]7aba6662013-03-12 10:17:341102 scrollbar_layer_->SetBounds(gfx::Size(10, 100));
khushalsagarb69ba9452017-01-27 22:20:071103 layer_tree_host()->root_layer()->AddChild(scrollbar_layer_);
1104 layer_tree_host()->root_layer()->AddChild(scroll_layer);
[email protected]e216fef02013-03-20 22:56:101105 PostSetNeedsCommitToMainThread();
[email protected]7a6acd02013-01-19 04:16:131106 }
1107
dcheng716bedf2014-10-21 09:51:081108 void CommitCompleteOnThread(LayerTreeHostImpl* impl) override {
[email protected]e216fef02013-03-20 22:56:101109 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
[email protected]0a451722013-02-22 20:32:051110
[email protected]7a6acd02013-01-19 04:16:131111 ++commits_;
[email protected]ca2902e92013-03-28 01:45:351112 switch (commits_) {
[email protected]7a6acd02013-01-19 04:16:131113 case 1:
1114 // First (regular) update, we should upload 2 resources (thumb, and
1115 // backtrack).
1116 EXPECT_EQ(1, scrollbar_layer_->update_count());
[email protected]7a6acd02013-01-19 04:16:131117 LoseContext();
1118 break;
1119 case 2:
1120 // Second update, after the lost context, we should still upload 2
1121 // resources even if the contents haven't changed.
1122 EXPECT_EQ(2, scrollbar_layer_->update_count());
[email protected]e216fef02013-03-20 22:56:101123 EndTest();
[email protected]7a6acd02013-01-19 04:16:131124 break;
1125 default:
1126 NOTREACHED();
1127 }
1128 }
1129
1130 private:
1131 int commits_;
[email protected]3a83478b2013-08-22 20:55:171132 scoped_refptr<FakePaintedScrollbarLayer> scrollbar_layer_;
[email protected]7a6acd02013-01-19 04:16:131133};
1134
[email protected]75ea789f2013-03-27 18:06:101135SINGLE_AND_MULTI_THREAD_TEST_F(ScrollbarLayerLostContext);
[email protected]7a6acd02013-01-19 04:16:131136
[email protected]c9280762013-08-01 06:28:571137class UIResourceLostTest : public LayerTreeHostContextTest {
1138 public:
1139 UIResourceLostTest() : time_step_(0) {}
dcheng716bedf2014-10-21 09:51:081140 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
[email protected]c9280762013-08-01 06:28:571141
[email protected]e11fceee2013-09-09 23:49:491142 // This is called on the main thread after each commit and
1143 // DidActivateTreeOnThread, with the value of time_step_ at the time
1144 // of the call to DidActivateTreeOnThread. Similar tests will do
1145 // work on the main thread in DidCommit but that is unsuitable because
1146 // the main thread work for these tests must happen after
1147 // DidActivateTreeOnThread, which happens after DidCommit with impl-side
1148 // painting.
1149 virtual void StepCompleteOnMainThread(int time_step) = 0;
1150
1151 // Called after DidActivateTreeOnThread. If this is done during the commit,
1152 // the call to StepCompleteOnMainThread will not occur until after
1153 // the commit completes, because the main thread is blocked.
1154 void PostStepCompleteToMainThread() {
khushalsagarb7db1fe2015-11-12 00:51:271155 task_runner_provider()->MainThreadTaskRunner()->PostTask(
[email protected]e11fceee2013-09-09 23:49:491156 FROM_HERE,
tzik4604bb52017-04-13 21:50:221157 base::BindOnce(&UIResourceLostTest::StepCompleteOnMainThreadInternal,
1158 base::Unretained(this), time_step_));
[email protected]e11fceee2013-09-09 23:49:491159 }
1160
1161 void PostLoseContextToImplThread() {
khushalsagarcebe4942016-09-07 23:27:011162 EXPECT_TRUE(layer_tree_host()->GetTaskRunnerProvider()->IsMainThread());
[email protected]aeeedad2014-08-22 18:16:221163 ImplThreadTaskRunner()->PostTask(
tzik4604bb52017-04-13 21:50:221164 FROM_HERE, base::BindOnce(&LayerTreeHostContextTest::LoseContext,
1165 base::Unretained(this)));
[email protected]e11fceee2013-09-09 23:49:491166 }
1167
[email protected]c9280762013-08-01 06:28:571168 protected:
1169 int time_step_;
danakj60bc3bc2016-04-09 00:24:481170 std::unique_ptr<FakeScopedUIResource> ui_resource_;
[email protected]e11fceee2013-09-09 23:49:491171
1172 private:
1173 void StepCompleteOnMainThreadInternal(int step) {
khushalsagarcebe4942016-09-07 23:27:011174 EXPECT_TRUE(layer_tree_host()->GetTaskRunnerProvider()->IsMainThread());
[email protected]e11fceee2013-09-09 23:49:491175 StepCompleteOnMainThread(step);
1176 }
1177};
1178
1179class UIResourceLostTestSimple : public UIResourceLostTest {
1180 public:
danakj431a1202015-06-17 19:09:331181 // This is called when the new layer tree has been activated.
[email protected]e11fceee2013-09-09 23:49:491182 virtual void StepCompleteOnImplThread(LayerTreeHostImpl* impl) = 0;
1183
dcheng716bedf2014-10-21 09:51:081184 void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override {
danakj431a1202015-06-17 19:09:331185 StepCompleteOnImplThread(impl);
1186 PostStepCompleteToMainThread();
1187 ++time_step_;
[email protected]e11fceee2013-09-09 23:49:491188 }
[email protected]c9280762013-08-01 06:28:571189};
1190
1191// Losing context after an UI resource has been created.
[email protected]e11fceee2013-09-09 23:49:491192class UIResourceLostAfterCommit : public UIResourceLostTestSimple {
[email protected]c9280762013-08-01 06:28:571193 public:
dcheng716bedf2014-10-21 09:51:081194 void StepCompleteOnMainThread(int step) override {
khushalsagarcebe4942016-09-07 23:27:011195 EXPECT_TRUE(layer_tree_host()->GetTaskRunnerProvider()->IsMainThread());
[email protected]e11fceee2013-09-09 23:49:491196 switch (step) {
[email protected]c9280762013-08-01 06:28:571197 case 0:
khushalsagar8ec07402016-09-10 03:13:191198 ui_resource_ = FakeScopedUIResource::Create(
1199 layer_tree_host()->GetUIResourceManager());
[email protected]c9280762013-08-01 06:28:571200 // Expects a valid UIResourceId.
1201 EXPECT_NE(0, ui_resource_->id());
1202 PostSetNeedsCommitToMainThread();
1203 break;
[email protected]e11fceee2013-09-09 23:49:491204 case 4:
1205 // Release resource before ending the test.
danakjf446a072014-09-27 21:55:481206 ui_resource_ = nullptr;
[email protected]e11fceee2013-09-09 23:49:491207 EndTest();
1208 break;
1209 case 5:
[email protected]2decdd782014-08-13 22:36:061210 NOTREACHED();
[email protected]aeeedad2014-08-22 18:16:221211 break;
[email protected]e11fceee2013-09-09 23:49:491212 }
1213 }
1214
dcheng716bedf2014-10-21 09:51:081215 void StepCompleteOnImplThread(LayerTreeHostImpl* impl) override {
[email protected]e11fceee2013-09-09 23:49:491216 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1217 switch (time_step_) {
[email protected]c9280762013-08-01 06:28:571218 case 1:
1219 // The resource should have been created on LTHI after the commit.
[email protected]e11fceee2013-09-09 23:49:491220 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
[email protected]c9280762013-08-01 06:28:571221 PostSetNeedsCommitToMainThread();
1222 break;
1223 case 2:
1224 LoseContext();
1225 break;
1226 case 3:
1227 // The resources should have been recreated. The bitmap callback should
1228 // have been called once with the resource_lost flag set to true.
1229 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1230 // Resource Id on the impl-side have been recreated as well. Note
1231 // that the same UIResourceId persists after the context lost.
[email protected]e11fceee2013-09-09 23:49:491232 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
[email protected]c9280762013-08-01 06:28:571233 PostSetNeedsCommitToMainThread();
1234 break;
[email protected]c9280762013-08-01 06:28:571235 }
1236 }
[email protected]c9280762013-08-01 06:28:571237};
1238
1239SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostAfterCommit);
1240
1241// Losing context before UI resource requests can be commited. Three sequences
1242// of creation/deletion are considered:
1243// 1. Create one resource -> Context Lost => Expect the resource to have been
1244// created.
sievers8afa2d42016-08-26 19:45:151245// 2. Delete an existing resource (test_id0_) -> create a second resource
[email protected]c9280762013-08-01 06:28:571246// (test_id1_) -> Context Lost => Expect the test_id0_ to be removed and
1247// test_id1_ to have been created.
1248// 3. Create one resource -> Delete that same resource -> Context Lost => Expect
1249// the resource to not exist in the manager.
[email protected]e11fceee2013-09-09 23:49:491250class UIResourceLostBeforeCommit : public UIResourceLostTestSimple {
[email protected]c9280762013-08-01 06:28:571251 public:
[email protected]e7e7ebd2014-01-16 00:11:111252 UIResourceLostBeforeCommit() : test_id0_(0), test_id1_(0) {}
[email protected]c9280762013-08-01 06:28:571253
dcheng716bedf2014-10-21 09:51:081254 void StepCompleteOnMainThread(int step) override {
[email protected]e11fceee2013-09-09 23:49:491255 switch (step) {
[email protected]c9280762013-08-01 06:28:571256 case 0:
khushalsagar8ec07402016-09-10 03:13:191257 ui_resource_ = FakeScopedUIResource::Create(
1258 layer_tree_host()->GetUIResourceManager());
[email protected]e11fceee2013-09-09 23:49:491259 // Lose the context on the impl thread before the commit.
1260 PostLoseContextToImplThread();
[email protected]c9280762013-08-01 06:28:571261 break;
1262 case 2:
1263 // Sequence 2:
1264 // Currently one resource has been created.
1265 test_id0_ = ui_resource_->id();
1266 // Delete this resource.
danakjf446a072014-09-27 21:55:481267 ui_resource_ = nullptr;
[email protected]c9280762013-08-01 06:28:571268 // Create another resource.
khushalsagar8ec07402016-09-10 03:13:191269 ui_resource_ = FakeScopedUIResource::Create(
1270 layer_tree_host()->GetUIResourceManager());
[email protected]c9280762013-08-01 06:28:571271 test_id1_ = ui_resource_->id();
1272 // Sanity check that two resource creations return different ids.
1273 EXPECT_NE(test_id0_, test_id1_);
[email protected]e11fceee2013-09-09 23:49:491274 // Lose the context on the impl thread before the commit.
1275 PostLoseContextToImplThread();
[email protected]c9280762013-08-01 06:28:571276 break;
1277 case 3:
[email protected]c9280762013-08-01 06:28:571278 // Clear the manager of resources.
danakjf446a072014-09-27 21:55:481279 ui_resource_ = nullptr;
[email protected]c9280762013-08-01 06:28:571280 PostSetNeedsCommitToMainThread();
1281 break;
1282 case 4:
1283 // Sequence 3:
khushalsagar8ec07402016-09-10 03:13:191284 ui_resource_ = FakeScopedUIResource::Create(
1285 layer_tree_host()->GetUIResourceManager());
[email protected]c9280762013-08-01 06:28:571286 test_id0_ = ui_resource_->id();
1287 // Sanity check the UIResourceId should not be 0.
1288 EXPECT_NE(0, test_id0_);
1289 // Usually ScopedUIResource are deleted from the manager in their
danakjf446a072014-09-27 21:55:481290 // destructor (so usually ui_resource_ = nullptr). But here we need
[email protected]c9280762013-08-01 06:28:571291 // ui_resource_ for the next step, so call DeleteUIResource directly.
khushalsagar8ec07402016-09-10 03:13:191292 layer_tree_host()->GetUIResourceManager()->DeleteUIResource(test_id0_);
[email protected]e11fceee2013-09-09 23:49:491293 // Delete the resouce and then lose the context.
1294 PostLoseContextToImplThread();
[email protected]c9280762013-08-01 06:28:571295 break;
1296 case 5:
[email protected]e11fceee2013-09-09 23:49:491297 // Release resource before ending the test.
danakjf446a072014-09-27 21:55:481298 ui_resource_ = nullptr;
[email protected]e11fceee2013-09-09 23:49:491299 EndTest();
1300 break;
1301 case 6:
[email protected]2decdd782014-08-13 22:36:061302 NOTREACHED();
[email protected]aeeedad2014-08-22 18:16:221303 break;
[email protected]e11fceee2013-09-09 23:49:491304 }
1305 }
1306
dcheng716bedf2014-10-21 09:51:081307 void StepCompleteOnImplThread(LayerTreeHostImpl* impl) override {
[email protected]e11fceee2013-09-09 23:49:491308 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1309 switch (time_step_) {
1310 case 1:
1311 // Sequence 1 (continued):
[email protected]127bdc1a2013-09-11 01:44:481312 // The first context lost happens before the resources were created,
1313 // and because it resulted in no resources being destroyed, it does not
1314 // trigger resource re-creation.
1315 EXPECT_EQ(1, ui_resource_->resource_create_count);
1316 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1317 // Resource Id on the impl-side has been created.
[email protected]e11fceee2013-09-09 23:49:491318 PostSetNeedsCommitToMainThread();
1319 break;
1320 case 3:
1321 // Sequence 2 (continued):
1322 // The previous resource should have been deleted.
1323 EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_));
[email protected]aeeedad2014-08-22 18:16:221324 // The second resource should have been created.
1325 EXPECT_NE(0u, impl->ResourceIdForUIResource(test_id1_));
sievers8afa2d42016-08-26 19:45:151326 // The second resource was not actually uploaded before the context
1327 // was lost, so it only got created once.
1328 EXPECT_EQ(1, ui_resource_->resource_create_count);
1329 EXPECT_EQ(0, ui_resource_->lost_resource_count);
[email protected]e11fceee2013-09-09 23:49:491330 break;
1331 case 5:
1332 // Sequence 3 (continued):
[email protected]c9280762013-08-01 06:28:571333 // Expect the resource callback to have been called once.
1334 EXPECT_EQ(1, ui_resource_->resource_create_count);
1335 // No "resource lost" callbacks.
1336 EXPECT_EQ(0, ui_resource_->lost_resource_count);
[email protected]e11fceee2013-09-09 23:49:491337 // The UI resource id should not be valid
1338 EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_));
[email protected]c9280762013-08-01 06:28:571339 break;
1340 }
1341 }
1342
[email protected]c9280762013-08-01 06:28:571343 private:
1344 UIResourceId test_id0_;
1345 UIResourceId test_id1_;
1346};
1347
Sahel Sharifyd9857642018-04-30 15:06:401348// http://crbug.com/803532 : Flaky on Win 7 (dbg) and linux tsan
1349#if (defined(NDEBUG) || !defined(OS_WIN)) && \
1350 (!defined(THREAD_SANITIZER) || !defined(OS_LINUX))
Stephen McGruer25ddb1372018-01-18 19:10:151351SINGLE_THREAD_TEST_F(UIResourceLostBeforeCommit);
1352#endif
1353MULTI_THREAD_TEST_F(UIResourceLostBeforeCommit);
[email protected]c9280762013-08-01 06:28:571354
1355// Losing UI resource before the pending trees is activated but after the
1356// commit. Impl-side-painting only.
1357class UIResourceLostBeforeActivateTree : public UIResourceLostTest {
dcheng716bedf2014-10-21 09:51:081358 void StepCompleteOnMainThread(int step) override {
khushalsagarcebe4942016-09-07 23:27:011359 EXPECT_TRUE(layer_tree_host()->GetTaskRunnerProvider()->IsMainThread());
[email protected]e11fceee2013-09-09 23:49:491360 switch (step) {
[email protected]c9280762013-08-01 06:28:571361 case 0:
khushalsagar8ec07402016-09-10 03:13:191362 ui_resource_ = FakeScopedUIResource::Create(
1363 layer_tree_host()->GetUIResourceManager());
[email protected]c9280762013-08-01 06:28:571364 PostSetNeedsCommitToMainThread();
1365 break;
[email protected]c9280762013-08-01 06:28:571366 case 3:
1367 test_id_ = ui_resource_->id();
danakjf446a072014-09-27 21:55:481368 ui_resource_ = nullptr;
[email protected]c9280762013-08-01 06:28:571369 PostSetNeedsCommitToMainThread();
1370 break;
[email protected]e11fceee2013-09-09 23:49:491371 case 5:
1372 // Release resource before ending the test.
danakjf446a072014-09-27 21:55:481373 ui_resource_ = nullptr;
[email protected]e11fceee2013-09-09 23:49:491374 EndTest();
1375 break;
1376 case 6:
1377 // Make sure no extra commits happened.
1378 NOTREACHED();
1379 }
1380 }
1381
dcheng716bedf2014-10-21 09:51:081382 void CommitCompleteOnThread(LayerTreeHostImpl* impl) override {
[email protected]e11fceee2013-09-09 23:49:491383 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1384 switch (time_step_) {
1385 case 2:
[email protected]c9280762013-08-01 06:28:571386 PostSetNeedsCommitToMainThread();
1387 break;
[email protected]e11fceee2013-09-09 23:49:491388 case 4:
1389 PostSetNeedsCommitToMainThread();
[email protected]c9280762013-08-01 06:28:571390 break;
1391 }
1392 }
1393
dcheng716bedf2014-10-21 09:51:081394 void WillActivateTreeOnThread(LayerTreeHostImpl* impl) override {
[email protected]c9280762013-08-01 06:28:571395 switch (time_step_) {
[email protected]c9280762013-08-01 06:28:571396 case 1:
1397 // The resource creation callback has been called.
1398 EXPECT_EQ(1, ui_resource_->resource_create_count);
1399 // The resource is not yet lost (sanity check).
1400 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1401 // The resource should not have been created yet on the impl-side.
1402 EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1403 LoseContext();
1404 break;
1405 case 3:
1406 LoseContext();
1407 break;
1408 }
1409 }
1410
dcheng716bedf2014-10-21 09:51:081411 void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override {
[email protected]c9280762013-08-01 06:28:571412 LayerTreeHostContextTest::DidActivateTreeOnThread(impl);
1413 switch (time_step_) {
1414 case 1:
sievers68dc75d2016-09-23 22:31:311415 // The pending requests on the impl-side should not have been processed
1416 // since the context was lost. But we should have marked the resource as
1417 // evicted instead.
1418 EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1419 EXPECT_TRUE(impl->EvictedUIResourcesExist());
[email protected]c9280762013-08-01 06:28:571420 break;
1421 case 2:
sievers68dc75d2016-09-23 22:31:311422 // The "lost resource" callback should have been called once and it
1423 // should have gotten recreated now and shouldn't be marked as evicted
1424 // anymore.
[email protected]c9280762013-08-01 06:28:571425 EXPECT_EQ(1, ui_resource_->lost_resource_count);
sievers68dc75d2016-09-23 22:31:311426 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1427 EXPECT_FALSE(impl->EvictedUIResourcesExist());
[email protected]c9280762013-08-01 06:28:571428 break;
1429 case 4:
1430 // The resource is deleted and should not be in the manager. Use
1431 // test_id_ since ui_resource_ has been deleted.
1432 EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id_));
1433 break;
1434 }
[email protected]e11fceee2013-09-09 23:49:491435
1436 PostStepCompleteToMainThread();
[email protected]c9280762013-08-01 06:28:571437 ++time_step_;
1438 }
1439
1440 private:
1441 UIResourceId test_id_;
1442};
1443
Dana Jansensab277762015-06-12 23:52:551444SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostBeforeActivateTree);
[email protected]c9280762013-08-01 06:28:571445
[email protected]127bdc1a2013-09-11 01:44:481446// Resources evicted explicitly and by visibility changes.
1447class UIResourceLostEviction : public UIResourceLostTestSimple {
1448 public:
dcheng716bedf2014-10-21 09:51:081449 void StepCompleteOnMainThread(int step) override {
khushalsagarcebe4942016-09-07 23:27:011450 EXPECT_TRUE(layer_tree_host()->GetTaskRunnerProvider()->IsMainThread());
[email protected]127bdc1a2013-09-11 01:44:481451 switch (step) {
1452 case 0:
khushalsagar8ec07402016-09-10 03:13:191453 ui_resource_ = FakeScopedUIResource::Create(
1454 layer_tree_host()->GetUIResourceManager());
1455 ui_resource2_ = FakeScopedUIResource::Create(
1456 layer_tree_host()->GetUIResourceManager());
[email protected]127bdc1a2013-09-11 01:44:481457 EXPECT_NE(0, ui_resource_->id());
sievers8afa2d42016-08-26 19:45:151458 EXPECT_NE(0, ui_resource2_->id());
[email protected]127bdc1a2013-09-11 01:44:481459 PostSetNeedsCommitToMainThread();
1460 break;
1461 case 2:
1462 // Make the tree not visible.
1463 PostSetVisibleToMainThread(false);
sievers8afa2d42016-08-26 19:45:151464 ui_resource2_->DeleteResource();
khushalsagar8ec07402016-09-10 03:13:191465 ui_resource3_ = FakeScopedUIResource::Create(
1466 layer_tree_host()->GetUIResourceManager());
[email protected]127bdc1a2013-09-11 01:44:481467 break;
1468 case 3:
sievers8afa2d42016-08-26 19:45:151469 // Release resources before ending the test.
danakjf446a072014-09-27 21:55:481470 ui_resource_ = nullptr;
sievers8afa2d42016-08-26 19:45:151471 ui_resource2_ = nullptr;
1472 ui_resource3_ = nullptr;
[email protected]127bdc1a2013-09-11 01:44:481473 EndTest();
1474 break;
1475 case 4:
1476 NOTREACHED();
1477 }
1478 }
1479
dcheng716bedf2014-10-21 09:51:081480 void DidSetVisibleOnImplTree(LayerTreeHostImpl* impl, bool visible) override {
[email protected]127bdc1a2013-09-11 01:44:481481 if (!visible) {
1482 // All resources should have been evicted.
Eric Karl8d678f892018-12-11 06:51:001483 ASSERT_EQ(0u, sii_->shared_image_count());
[email protected]127bdc1a2013-09-11 01:44:481484 EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
sievers8afa2d42016-08-26 19:45:151485 EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource2_->id()));
1486 EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource3_->id()));
[email protected]127bdc1a2013-09-11 01:44:481487 EXPECT_EQ(2, ui_resource_->resource_create_count);
1488 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1489 // Drawing is disabled both because of the evicted resources and
1490 // because the renderer is not visible.
1491 EXPECT_FALSE(impl->CanDraw());
1492 // Make the renderer visible again.
1493 PostSetVisibleToMainThread(true);
1494 }
1495 }
1496
dcheng716bedf2014-10-21 09:51:081497 void StepCompleteOnImplThread(LayerTreeHostImpl* impl) override {
[email protected]127bdc1a2013-09-11 01:44:481498 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1499 switch (time_step_) {
1500 case 1:
sievers8afa2d42016-08-26 19:45:151501 // The first two resources should have been created on LTHI after the
1502 // commit.
Eric Karl8d678f892018-12-11 06:51:001503 ASSERT_EQ(2u, sii_->shared_image_count());
[email protected]127bdc1a2013-09-11 01:44:481504 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
sievers8afa2d42016-08-26 19:45:151505 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource2_->id()));
[email protected]127bdc1a2013-09-11 01:44:481506 EXPECT_EQ(1, ui_resource_->resource_create_count);
1507 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1508 EXPECT_TRUE(impl->CanDraw());
1509 // Evict all UI resources. This will trigger a commit.
1510 impl->EvictAllUIResources();
Eric Karl8d678f892018-12-11 06:51:001511 ASSERT_EQ(0u, sii_->shared_image_count());
[email protected]127bdc1a2013-09-11 01:44:481512 EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
sievers8afa2d42016-08-26 19:45:151513 EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource2_->id()));
[email protected]127bdc1a2013-09-11 01:44:481514 EXPECT_EQ(1, ui_resource_->resource_create_count);
1515 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1516 EXPECT_FALSE(impl->CanDraw());
1517 break;
1518 case 2:
sievers8afa2d42016-08-26 19:45:151519 // The first two resources should have been recreated.
Eric Karl8d678f892018-12-11 06:51:001520 ASSERT_EQ(2u, sii_->shared_image_count());
[email protected]127bdc1a2013-09-11 01:44:481521 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1522 EXPECT_EQ(2, ui_resource_->resource_create_count);
1523 EXPECT_EQ(1, ui_resource_->lost_resource_count);
sievers8afa2d42016-08-26 19:45:151524 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource2_->id()));
1525 EXPECT_EQ(2, ui_resource2_->resource_create_count);
1526 EXPECT_EQ(1, ui_resource2_->lost_resource_count);
[email protected]127bdc1a2013-09-11 01:44:481527 EXPECT_TRUE(impl->CanDraw());
1528 break;
1529 case 3:
sievers8afa2d42016-08-26 19:45:151530 // The first resource should have been recreated after visibility was
[email protected]127bdc1a2013-09-11 01:44:481531 // restored.
Eric Karl8d678f892018-12-11 06:51:001532 ASSERT_EQ(2u, sii_->shared_image_count());
[email protected]127bdc1a2013-09-11 01:44:481533 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1534 EXPECT_EQ(3, ui_resource_->resource_create_count);
1535 EXPECT_EQ(2, ui_resource_->lost_resource_count);
sievers8afa2d42016-08-26 19:45:151536
1537 // This resource was deleted.
1538 EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource2_->id()));
1539 EXPECT_EQ(2, ui_resource2_->resource_create_count);
1540 EXPECT_EQ(1, ui_resource2_->lost_resource_count);
1541
1542 // This resource should have been created now.
1543 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource3_->id()));
1544 EXPECT_EQ(1, ui_resource3_->resource_create_count);
1545 EXPECT_EQ(0, ui_resource3_->lost_resource_count);
[email protected]127bdc1a2013-09-11 01:44:481546 EXPECT_TRUE(impl->CanDraw());
1547 break;
1548 }
1549 }
sievers8afa2d42016-08-26 19:45:151550
1551 private:
1552 std::unique_ptr<FakeScopedUIResource> ui_resource2_;
1553 std::unique_ptr<FakeScopedUIResource> ui_resource3_;
[email protected]127bdc1a2013-09-11 01:44:481554};
1555
1556SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostEviction);
1557
danakjb90335d2018-06-07 23:42:291558class UIResourceFreedIfLostWhileExported : public LayerTreeHostContextTest {
1559 protected:
1560 void BeginTest() override {
1561 // Make 1 UIResource, post it to the compositor thread, where it will be
1562 // uploaded.
1563 ui_resource_ =
1564 FakeScopedUIResource::Create(layer_tree_host()->GetUIResourceManager());
1565 EXPECT_NE(0, ui_resource_->id());
1566 PostSetNeedsCommitToMainThread();
1567 }
1568
1569 void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override {
1570 switch (impl->active_tree()->source_frame_number()) {
1571 case 0:
1572 // The UIResource has been created and a gpu resource made for it.
1573 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
Eric Karl8d678f892018-12-11 06:51:001574 EXPECT_EQ(1u, sii_->shared_image_count());
danakjb90335d2018-06-07 23:42:291575 // Lose the LayerTreeFrameSink connection. The UI resource should
1576 // be replaced and the old texture should be destroyed.
1577 impl->DidLoseLayerTreeFrameSink();
1578 break;
1579 case 1:
1580 // The UIResource has been recreated, the old texture is not kept
1581 // around.
1582 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
Eric Karl8d678f892018-12-11 06:51:001583 EXPECT_EQ(1u, sii_->shared_image_count());
danakjb90335d2018-06-07 23:42:291584 MainThreadTaskRunner()->PostTask(
1585 FROM_HERE,
1586 base::BindOnce(
1587 &UIResourceFreedIfLostWhileExported::DeleteAndEndTest,
1588 base::Unretained(this)));
1589 }
1590 }
1591
1592 void DeleteAndEndTest() {
1593 ui_resource_->DeleteResource();
1594 EndTest();
1595 }
1596
danakjb90335d2018-06-07 23:42:291597 std::unique_ptr<FakeScopedUIResource> ui_resource_;
1598};
1599
1600SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceFreedIfLostWhileExported);
1601
1602class TileResourceFreedIfLostWhileExported : public LayerTreeHostContextTest {
1603 protected:
1604 void SetupTree() override {
1605 PaintFlags flags;
1606 client_.set_fill_with_nonsolid_color(true);
1607
1608 scoped_refptr<FakePictureLayer> picture_layer =
1609 FakePictureLayer::Create(&client_);
1610 picture_layer->SetBounds(gfx::Size(10, 20));
1611 client_.set_bounds(picture_layer->bounds());
1612 layer_tree_host()->SetRootLayer(std::move(picture_layer));
1613
1614 LayerTreeTest::SetupTree();
1615 }
1616
1617 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1618
1619 void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
Antoine Labour7a950ebc2018-11-08 21:59:491620 auto* context_provider = static_cast<viz::TestContextProvider*>(
1621 impl->layer_tree_frame_sink()->worker_context_provider());
1622 viz::TestSharedImageInterface* sii =
1623 context_provider->SharedImageInterface();
danakjb90335d2018-06-07 23:42:291624 switch (impl->active_tree()->source_frame_number()) {
1625 case 0:
1626 // The PicturLayer has a texture for a tile, that has been exported to
1627 // the display compositor now.
1628 EXPECT_EQ(1u, impl->resource_provider()->num_resources_for_testing());
1629 EXPECT_EQ(1u, impl->resource_pool()->resource_count());
Antoine Labour7a950ebc2018-11-08 21:59:491630 // Shows that the tile texture is allocated with the current worker
1631 // context.
1632 num_textures_ = sii->shared_image_count();
danakjb90335d2018-06-07 23:42:291633 EXPECT_GT(num_textures_, 0u);
1634
1635 // Lose the LayerTreeFrameSink connection. The tile resource should
1636 // be replaced and the old texture should be destroyed.
1637 LoseContext();
1638 break;
1639 case 1:
1640 // The tile has been recreated, the old texture is not kept around in
1641 // the pool indefinitely. It can be dropped as soon as the context is
1642 // known to be lost.
1643 EXPECT_EQ(1u, impl->resource_provider()->num_resources_for_testing());
1644 EXPECT_EQ(1u, impl->resource_pool()->resource_count());
1645 // Shows that the replacement tile texture is re-allocated with the
Antoine Labour7a950ebc2018-11-08 21:59:491646 // current worker context, not just the previous one.
1647 EXPECT_EQ(num_textures_, sii->shared_image_count());
danakjb90335d2018-06-07 23:42:291648 EndTest();
1649 }
1650 }
1651
danakjb90335d2018-06-07 23:42:291652 FakeContentLayerClient client_;
1653 size_t num_textures_ = 0;
1654};
1655
1656SINGLE_AND_MULTI_THREAD_TEST_F(TileResourceFreedIfLostWhileExported);
1657
1658class SoftwareTileResourceFreedIfLostWhileExported : public LayerTreeTest {
1659 protected:
Antoine Labour7f5179a2019-06-04 01:46:291660 std::unique_ptr<TestLayerTreeFrameSink> CreateLayerTreeFrameSink(
danakjb90335d2018-06-07 23:42:291661 const viz::RendererSettings& renderer_settings,
1662 double refresh_rate,
1663 scoped_refptr<viz::ContextProvider> compositor_context_provider,
1664 scoped_refptr<viz::RasterContextProvider> worker_context_provider)
1665 override {
1666 // Induce software compositing in cc.
1667 return LayerTreeTest::CreateLayerTreeFrameSink(
1668 renderer_settings, refresh_rate, nullptr, nullptr);
1669 }
1670
1671 std::unique_ptr<viz::OutputSurface> CreateDisplayOutputSurfaceOnThread(
1672 scoped_refptr<viz::ContextProvider> compositor_context_provider)
1673 override {
1674 // Induce software compositing in the display compositor.
1675 return viz::FakeOutputSurface::CreateSoftware(
1676 std::make_unique<viz::SoftwareOutputDevice>());
1677 }
1678
1679 void SetupTree() override {
1680 PaintFlags flags;
1681 client_.set_fill_with_nonsolid_color(true);
1682
1683 scoped_refptr<FakePictureLayer> picture_layer =
1684 FakePictureLayer::Create(&client_);
1685 picture_layer->SetBounds(gfx::Size(10, 20));
1686 client_.set_bounds(picture_layer->bounds());
1687 layer_tree_host()->SetRootLayer(std::move(picture_layer));
1688
1689 LayerTreeTest::SetupTree();
1690 }
1691
1692 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1693
1694 void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
1695 switch (impl->active_tree()->source_frame_number()) {
1696 case 0: {
1697 // The PicturLayer has a bitmap for a tile, that has been exported to
1698 // the display compositor now.
1699 EXPECT_EQ(1u, impl->resource_provider()->num_resources_for_testing());
1700 EXPECT_EQ(1u, impl->resource_pool()->resource_count());
1701
1702 impl->DidLoseLayerTreeFrameSink();
1703 break;
1704 }
1705 case 1: {
1706 // The tile did not need to be recreated, the same bitmap/resource
1707 // should be used for it.
1708 EXPECT_EQ(1u, impl->resource_provider()->num_resources_for_testing());
1709 EXPECT_EQ(1u, impl->resource_pool()->resource_count());
1710
1711 // TODO(danakj): It'd be possible to not destroy and recreate the
1712 // software bitmap, however for simplicity we do the same for software
1713 // and for gpu paths. If we didn't destroy it we could see the same
1714 // bitmap on PictureLayerImpl's tile.
1715
1716 EndTest();
1717 }
1718 }
1719 }
1720
danakjb90335d2018-06-07 23:42:291721 FakeContentLayerClient client_;
1722 viz::ResourceId exported_resource_id_ = 0;
1723};
1724
1725SINGLE_AND_MULTI_THREAD_TEST_F(SoftwareTileResourceFreedIfLostWhileExported);
1726
[email protected]922186942014-06-11 16:30:351727class LayerTreeHostContextTestLoseAfterSendingBeginMainFrame
1728 : public LayerTreeHostContextTest {
1729 protected:
sunnypse9fd9522016-10-06 23:03:271730 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
[email protected]922186942014-06-11 16:30:351731
danakj94b7e4f2016-07-20 01:49:381732 void WillBeginMainFrame() override {
1733 // Don't begin a frame with a lost surface.
danakjbe9c59ee2016-08-26 18:24:561734 EXPECT_FALSE(lost_);
danakj94b7e4f2016-07-20 01:49:381735
[email protected]922186942014-06-11 16:30:351736 if (deferred_)
1737 return;
1738 deferred_ = true;
1739
Stephen Chenney6d3f5ce2018-11-14 02:08:051740 // TODO(schenney): This should switch back to defer_commits_ because there
1741 // is no way in the real code to start deferring main frame updates when
1742 // inside WillBeginMainFrame. Defer commits before the BeginFrame completes,
1743 // causing it to be delayed.
1744 scoped_defer_main_frame_update_ = layer_tree_host()->DeferMainFrameUpdate();
1745 // Meanwhile, lose the context while we are in defer BeginMainFrame.
[email protected]922186942014-06-11 16:30:351746 ImplThreadTaskRunner()->PostTask(
1747 FROM_HERE,
tzik4604bb52017-04-13 21:50:221748 base::BindOnce(&LayerTreeHostContextTestLoseAfterSendingBeginMainFrame::
1749 LoseContextOnImplThread,
1750 base::Unretained(this)));
danakjbe9c59ee2016-08-26 18:24:561751
1752 // After the first frame, we will lose the context and then not start
Stephen Chenney6d3f5ce2018-11-14 02:08:051753 // lifecycle updates and commits until that happens. The 2nd frame should
1754 // not happen before DidInitializeLayerTreeFrameSink occurs.
danakjbe9c59ee2016-08-26 18:24:561755 lost_ = true;
1756 }
1757
danakjc7afae52017-06-20 21:12:411758 void DidInitializeLayerTreeFrameSink() override {
danakjbe9c59ee2016-08-26 18:24:561759 EXPECT_TRUE(lost_);
1760 lost_ = false;
[email protected]922186942014-06-11 16:30:351761 }
1762
1763 void LoseContextOnImplThread() {
1764 LoseContext();
1765
Stephen Chenney6d3f5ce2018-11-14 02:08:051766 // TODO(schenney): This should switch back to defer_commits_ to match the
1767 // change above.
[email protected]922186942014-06-11 16:30:351768 // After losing the context, stop deferring commits.
Stephen Chenney6d3f5ce2018-11-14 02:08:051769 PostReturnDeferMainFrameUpdateToMainThread(
1770 std::move(scoped_defer_main_frame_update_));
[email protected]922186942014-06-11 16:30:351771 }
1772
dcheng716bedf2014-10-21 09:51:081773 void DidCommitAndDrawFrame() override { EndTest(); }
[email protected]922186942014-06-11 16:30:351774
Stephen Chenney6d3f5ce2018-11-14 02:08:051775 std::unique_ptr<ScopedDeferMainFrameUpdate> scoped_defer_main_frame_update_;
danakjbe9c59ee2016-08-26 18:24:561776 bool deferred_ = false;
1777 bool lost_ = true;
[email protected]922186942014-06-11 16:30:351778};
1779
[email protected]aeeedad2014-08-22 18:16:221780SINGLE_AND_MULTI_THREAD_TEST_F(
1781 LayerTreeHostContextTestLoseAfterSendingBeginMainFrame);
[email protected]922186942014-06-11 16:30:351782
Sunny Sachanandani158d26d2017-12-12 19:44:101783class LayerTreeHostContextTestWorkerContextLostRecovery : public LayerTreeTest {
sunnypse9fd9522016-10-06 23:03:271784 protected:
1785 void SetupTree() override {
ennebb7c4bcf2017-02-07 17:59:491786 PaintFlags flags;
sunnypse9fd9522016-10-06 23:03:271787 client_.set_fill_with_nonsolid_color(true);
ennebb7c4bcf2017-02-07 17:59:491788 client_.add_draw_rect(gfx::Rect(5, 5), flags);
sunnypse9fd9522016-10-06 23:03:271789
1790 scoped_refptr<FakePictureLayer> picture_layer =
1791 FakePictureLayer::Create(&client_);
1792 picture_layer->SetBounds(gfx::Size(10, 20));
1793 client_.set_bounds(picture_layer->bounds());
khushalsagarb69ba9452017-01-27 22:20:071794 layer_tree_host()->SetRootLayer(picture_layer);
sunnypse9fd9522016-10-06 23:03:271795
1796 LayerTreeTest::SetupTree();
1797 }
1798
1799 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1800
1801 void WillPrepareTilesOnThread(LayerTreeHostImpl* host_impl) override {
Sunny Sachanandani158d26d2017-12-12 19:44:101802 if (did_lose_context)
1803 return;
1804 did_lose_context = true;
Victor Miura29b7ea3d2017-12-19 20:23:591805 viz::RasterContextProvider::ScopedRasterContextLock scoped_context(
danakjc7afae52017-06-20 21:12:411806 host_impl->layer_tree_frame_sink()->worker_context_provider());
Victor Miura29b7ea3d2017-12-19 20:23:591807 gpu::raster::RasterInterface* ri = scoped_context.RasterInterface();
Victor Miura3a4ad4f82017-12-13 06:03:451808 ri->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
sunnypse9fd9522016-10-06 23:03:271809 GL_INNOCENT_CONTEXT_RESET_ARB);
1810 }
1811
Sunny Sachanandani158d26d2017-12-12 19:44:101812 void DidInitializeLayerTreeFrameSink() override { num_frame_sinks_++; }
sunnypse9fd9522016-10-06 23:03:271813
1814 void DidCommitAndDrawFrame() override { EndTest(); }
1815
Sunny Sachanandani158d26d2017-12-12 19:44:101816 void AfterTest() override {
1817 EXPECT_TRUE(did_lose_context);
1818 EXPECT_EQ(num_frame_sinks_, 2);
1819 }
sunnypse9fd9522016-10-06 23:03:271820
1821 FakeContentLayerClient client_;
Sunny Sachanandani158d26d2017-12-12 19:44:101822 bool did_lose_context = false;
1823 int num_frame_sinks_ = 0;
sunnypse9fd9522016-10-06 23:03:271824};
1825
Sunny Sachanandani158d26d2017-12-12 19:44:101826MULTI_THREAD_TEST_F(LayerTreeHostContextTestWorkerContextLostRecovery);
sunnypse9fd9522016-10-06 23:03:271827
[email protected]d993b602013-01-04 02:08:121828} // namespace
1829} // namespace cc