cc: Adding DidFinishImplFrame to LTHI.
[chromium-blink-merge.git] / cc / resources / tile_task_worker_pool_unittest.cc
blob34de309356a6556713b0ffc7c8be2d6514da75d6
1 // Copyright 2013 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.
5 #include "cc/resources/tile_task_worker_pool.h"
7 #include <limits>
8 #include <vector>
10 #include "base/cancelable_callback.h"
11 #include "base/location.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "cc/base/unique_notifier.h"
15 #include "cc/resources/bitmap_tile_task_worker_pool.h"
16 #include "cc/resources/gpu_rasterizer.h"
17 #include "cc/resources/gpu_tile_task_worker_pool.h"
18 #include "cc/resources/one_copy_tile_task_worker_pool.h"
19 #include "cc/resources/picture_pile.h"
20 #include "cc/resources/picture_pile_impl.h"
21 #include "cc/resources/pixel_buffer_tile_task_worker_pool.h"
22 #include "cc/resources/raster_buffer.h"
23 #include "cc/resources/resource_pool.h"
24 #include "cc/resources/resource_provider.h"
25 #include "cc/resources/scoped_resource.h"
26 #include "cc/resources/tile_task_runner.h"
27 #include "cc/resources/zero_copy_tile_task_worker_pool.h"
28 #include "cc/test/fake_output_surface.h"
29 #include "cc/test/fake_output_surface_client.h"
30 #include "cc/test/fake_picture_pile_impl.h"
31 #include "cc/test/test_gpu_memory_buffer_manager.h"
32 #include "cc/test/test_shared_bitmap_manager.h"
33 #include "cc/test/test_task_graph_runner.h"
34 #include "cc/test/test_web_graphics_context_3d.h"
35 #include "gpu/GLES2/gl2extchromium.h"
36 #include "testing/gtest/include/gtest/gtest.h"
38 namespace cc {
39 namespace {
41 const size_t kMaxTransferBufferUsageBytes = 10000U;
42 // A resource of this dimension^2 * 4 must be greater than the above transfer
43 // buffer constant.
44 const size_t kLargeResourceDimension = 1000U;
46 enum TileTaskWorkerPoolType {
47 TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER,
48 TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY,
49 TILE_TASK_WORKER_POOL_TYPE_ONE_COPY,
50 TILE_TASK_WORKER_POOL_TYPE_GPU,
51 TILE_TASK_WORKER_POOL_TYPE_BITMAP
54 class TestRasterTaskImpl : public RasterTask {
55 public:
56 typedef base::Callback<void(const RasterSource::SolidColorAnalysis& analysis,
57 bool was_canceled)> Reply;
59 TestRasterTaskImpl(const Resource* resource,
60 const Reply& reply,
61 ImageDecodeTask::Vector* dependencies)
62 : RasterTask(resource, dependencies),
63 reply_(reply),
64 picture_pile_(FakePicturePileImpl::CreateEmptyPile(gfx::Size(1, 1),
65 gfx::Size(1, 1))) {}
67 // Overridden from Task:
68 void RunOnWorkerThread() override {
69 raster_buffer_->Playback(picture_pile_.get(), gfx::Rect(0, 0, 1, 1), 1.0);
72 // Overridden from TileTask:
73 void ScheduleOnOriginThread(TileTaskClient* client) override {
74 raster_buffer_ = client->AcquireBufferForRaster(resource());
76 void CompleteOnOriginThread(TileTaskClient* client) override {
77 client->ReleaseBufferForRaster(raster_buffer_.Pass());
79 void RunReplyOnOriginThread() override {
80 reply_.Run(RasterSource::SolidColorAnalysis(), !HasFinishedRunning());
83 protected:
84 ~TestRasterTaskImpl() override {}
86 private:
87 const Reply reply_;
88 scoped_ptr<RasterBuffer> raster_buffer_;
89 scoped_refptr<PicturePileImpl> picture_pile_;
91 DISALLOW_COPY_AND_ASSIGN(TestRasterTaskImpl);
94 class BlockingTestRasterTaskImpl : public TestRasterTaskImpl {
95 public:
96 BlockingTestRasterTaskImpl(const Resource* resource,
97 const Reply& reply,
98 base::Lock* lock,
99 ImageDecodeTask::Vector* dependencies)
100 : TestRasterTaskImpl(resource, reply, dependencies), lock_(lock) {}
102 // Overridden from Task:
103 void RunOnWorkerThread() override {
104 base::AutoLock lock(*lock_);
105 TestRasterTaskImpl::RunOnWorkerThread();
108 // Overridden from TileTask:
109 void RunReplyOnOriginThread() override {}
111 protected:
112 ~BlockingTestRasterTaskImpl() override {}
114 private:
115 base::Lock* lock_;
117 DISALLOW_COPY_AND_ASSIGN(BlockingTestRasterTaskImpl);
120 class TileTaskWorkerPoolTest
121 : public testing::TestWithParam<TileTaskWorkerPoolType>,
122 public TileTaskRunnerClient {
123 public:
124 struct RasterTaskResult {
125 unsigned id;
126 bool canceled;
129 typedef std::vector<scoped_refptr<RasterTask>> RasterTaskVector;
131 enum NamedTaskSet { REQUIRED_FOR_ACTIVATION, REQUIRED_FOR_DRAW, ALL };
133 TileTaskWorkerPoolTest()
134 : context_provider_(TestContextProvider::Create()),
135 worker_context_provider_(TestContextProvider::Create()),
136 all_tile_tasks_finished_(
137 base::ThreadTaskRunnerHandle::Get().get(),
138 base::Bind(&TileTaskWorkerPoolTest::AllTileTasksFinished,
139 base::Unretained(this))),
140 timeout_seconds_(5),
141 timed_out_(false) {}
143 // Overridden from testing::Test:
144 void SetUp() override {
145 switch (GetParam()) {
146 case TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER:
147 Create3dOutputSurfaceAndResourceProvider();
148 tile_task_worker_pool_ = PixelBufferTileTaskWorkerPool::Create(
149 base::ThreadTaskRunnerHandle::Get().get(), &task_graph_runner_,
150 context_provider_.get(), resource_provider_.get(),
151 kMaxTransferBufferUsageBytes);
152 break;
153 case TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY:
154 Create3dOutputSurfaceAndResourceProvider();
155 tile_task_worker_pool_ = ZeroCopyTileTaskWorkerPool::Create(
156 base::ThreadTaskRunnerHandle::Get().get(), &task_graph_runner_,
157 resource_provider_.get());
158 break;
159 case TILE_TASK_WORKER_POOL_TYPE_ONE_COPY:
160 Create3dOutputSurfaceAndResourceProvider();
161 staging_resource_pool_ = ResourcePool::Create(resource_provider_.get(),
162 GL_TEXTURE_2D);
163 tile_task_worker_pool_ = OneCopyTileTaskWorkerPool::Create(
164 base::ThreadTaskRunnerHandle::Get().get(), &task_graph_runner_,
165 context_provider_.get(), resource_provider_.get(),
166 staging_resource_pool_.get());
167 break;
168 case TILE_TASK_WORKER_POOL_TYPE_GPU:
169 Create3dOutputSurfaceAndResourceProvider();
170 tile_task_worker_pool_ = GpuTileTaskWorkerPool::Create(
171 base::ThreadTaskRunnerHandle::Get().get(), &task_graph_runner_,
172 context_provider_.get(), resource_provider_.get(), false, 0);
173 break;
174 case TILE_TASK_WORKER_POOL_TYPE_BITMAP:
175 CreateSoftwareOutputSurfaceAndResourceProvider();
176 tile_task_worker_pool_ = BitmapTileTaskWorkerPool::Create(
177 base::ThreadTaskRunnerHandle::Get().get(), &task_graph_runner_,
178 resource_provider_.get());
179 break;
182 DCHECK(tile_task_worker_pool_);
183 tile_task_worker_pool_->AsTileTaskRunner()->SetClient(this);
186 void TearDown() override {
187 tile_task_worker_pool_->AsTileTaskRunner()->Shutdown();
188 tile_task_worker_pool_->AsTileTaskRunner()->CheckForCompletedTasks();
191 void AllTileTasksFinished() {
192 tile_task_worker_pool_->AsTileTaskRunner()->CheckForCompletedTasks();
193 base::MessageLoop::current()->Quit();
196 // Overriden from TileTaskWorkerPoolClient:
197 void DidFinishRunningTileTasks(TaskSet task_set) override {
198 EXPECT_FALSE(completed_task_sets_[task_set]);
199 completed_task_sets_[task_set] = true;
200 if (task_set == ALL) {
201 EXPECT_TRUE((~completed_task_sets_).none());
202 all_tile_tasks_finished_.Schedule();
206 TaskSetCollection TasksThatShouldBeForcedToComplete() const override {
207 return TaskSetCollection();
210 void RunMessageLoopUntilAllTasksHaveCompleted() {
211 if (timeout_seconds_) {
212 timeout_.Reset(base::Bind(&TileTaskWorkerPoolTest::OnTimeout,
213 base::Unretained(this)));
214 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
215 FROM_HERE, timeout_.callback(),
216 base::TimeDelta::FromSeconds(timeout_seconds_));
219 base::MessageLoop::current()->Run();
221 timeout_.Cancel();
223 ASSERT_FALSE(timed_out_) << "Test timed out";
226 void ScheduleTasks() {
227 TileTaskQueue queue;
229 for (RasterTaskVector::const_iterator it = tasks_.begin();
230 it != tasks_.end(); ++it) {
231 TaskSetCollection task_sets;
232 task_sets[REQUIRED_FOR_ACTIVATION] = true;
233 task_sets[REQUIRED_FOR_DRAW] = true;
234 task_sets[ALL] = true;
235 queue.items.push_back(TileTaskQueue::Item(it->get(), task_sets));
238 completed_task_sets_.reset();
239 tile_task_worker_pool_->AsTileTaskRunner()->ScheduleTasks(&queue);
242 void AppendTask(unsigned id, const gfx::Size& size) {
243 scoped_ptr<ScopedResource> resource(
244 ScopedResource::Create(resource_provider_.get()));
245 resource->Allocate(size, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
246 RGBA_8888);
247 const Resource* const_resource = resource.get();
249 ImageDecodeTask::Vector empty;
250 tasks_.push_back(new TestRasterTaskImpl(
251 const_resource,
252 base::Bind(&TileTaskWorkerPoolTest::OnTaskCompleted,
253 base::Unretained(this), base::Passed(&resource), id),
254 &empty));
257 void AppendTask(unsigned id) { AppendTask(id, gfx::Size(1, 1)); }
259 void AppendBlockingTask(unsigned id, base::Lock* lock) {
260 const gfx::Size size(1, 1);
262 scoped_ptr<ScopedResource> resource(
263 ScopedResource::Create(resource_provider_.get()));
264 resource->Allocate(size, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
265 RGBA_8888);
266 const Resource* const_resource = resource.get();
268 ImageDecodeTask::Vector empty;
269 tasks_.push_back(new BlockingTestRasterTaskImpl(
270 const_resource,
271 base::Bind(&TileTaskWorkerPoolTest::OnTaskCompleted,
272 base::Unretained(this), base::Passed(&resource), id),
273 lock, &empty));
276 const std::vector<RasterTaskResult>& completed_tasks() const {
277 return completed_tasks_;
280 void LoseContext(ContextProvider* context_provider) {
281 if (!context_provider)
282 return;
283 context_provider->ContextGL()->LoseContextCHROMIUM(
284 GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB);
285 context_provider->ContextGL()->Flush();
288 private:
289 void Create3dOutputSurfaceAndResourceProvider() {
290 output_surface_ = FakeOutputSurface::Create3d(
291 context_provider_, worker_context_provider_).Pass();
292 CHECK(output_surface_->BindToClient(&output_surface_client_));
293 TestWebGraphicsContext3D* context3d = context_provider_->TestContext3d();
294 context3d->set_support_sync_query(true);
295 resource_provider_ = ResourceProvider::Create(output_surface_.get(), NULL,
296 &gpu_memory_buffer_manager_,
297 NULL, 0, false, 1).Pass();
300 void CreateSoftwareOutputSurfaceAndResourceProvider() {
301 output_surface_ = FakeOutputSurface::CreateSoftware(
302 make_scoped_ptr(new SoftwareOutputDevice));
303 CHECK(output_surface_->BindToClient(&output_surface_client_));
304 resource_provider_ =
305 ResourceProvider::Create(output_surface_.get(), &shared_bitmap_manager_,
306 NULL, NULL, 0, false, 1).Pass();
309 void OnTaskCompleted(scoped_ptr<ScopedResource> resource,
310 unsigned id,
311 const RasterSource::SolidColorAnalysis& analysis,
312 bool was_canceled) {
313 RasterTaskResult result;
314 result.id = id;
315 result.canceled = was_canceled;
316 completed_tasks_.push_back(result);
319 void OnTimeout() {
320 timed_out_ = true;
321 base::MessageLoop::current()->Quit();
324 protected:
325 scoped_refptr<TestContextProvider> context_provider_;
326 scoped_refptr<TestContextProvider> worker_context_provider_;
327 FakeOutputSurfaceClient output_surface_client_;
328 scoped_ptr<FakeOutputSurface> output_surface_;
329 scoped_ptr<ResourceProvider> resource_provider_;
330 scoped_ptr<ResourcePool> staging_resource_pool_;
331 scoped_ptr<TileTaskWorkerPool> tile_task_worker_pool_;
332 TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
333 TestSharedBitmapManager shared_bitmap_manager_;
334 TestTaskGraphRunner task_graph_runner_;
335 base::CancelableClosure timeout_;
336 UniqueNotifier all_tile_tasks_finished_;
337 int timeout_seconds_;
338 bool timed_out_;
339 RasterTaskVector tasks_;
340 std::vector<RasterTaskResult> completed_tasks_;
341 TaskSetCollection completed_task_sets_;
344 TEST_P(TileTaskWorkerPoolTest, Basic) {
345 AppendTask(0u);
346 AppendTask(1u);
347 ScheduleTasks();
349 RunMessageLoopUntilAllTasksHaveCompleted();
351 ASSERT_EQ(2u, completed_tasks().size());
352 EXPECT_FALSE(completed_tasks()[0].canceled);
353 EXPECT_FALSE(completed_tasks()[1].canceled);
356 TEST_P(TileTaskWorkerPoolTest, FailedMapResource) {
357 if (GetParam() == TILE_TASK_WORKER_POOL_TYPE_BITMAP)
358 return;
360 TestWebGraphicsContext3D* context3d = context_provider_->TestContext3d();
361 context3d->set_times_map_buffer_chromium_succeeds(0);
362 AppendTask(0u);
363 ScheduleTasks();
365 RunMessageLoopUntilAllTasksHaveCompleted();
367 ASSERT_EQ(1u, completed_tasks().size());
368 EXPECT_FALSE(completed_tasks()[0].canceled);
371 // This test checks that replacing a pending raster task with another does
372 // not prevent the DidFinishRunningTileTasks notification from being sent.
373 TEST_P(TileTaskWorkerPoolTest, FalseThrottling) {
374 base::Lock lock;
376 // Schedule a task that is prevented from completing with a lock.
377 lock.Acquire();
378 AppendBlockingTask(0u, &lock);
379 ScheduleTasks();
381 // Schedule another task to replace the still-pending task. Because the old
382 // task is not a throttled task in the new task set, it should not prevent
383 // DidFinishRunningTileTasks from getting signaled.
384 RasterTaskVector tasks;
385 tasks.swap(tasks_);
386 AppendTask(1u);
387 ScheduleTasks();
389 // Unblock the first task to allow the second task to complete.
390 lock.Release();
392 RunMessageLoopUntilAllTasksHaveCompleted();
395 TEST_P(TileTaskWorkerPoolTest, LargeResources) {
396 gfx::Size size(kLargeResourceDimension, kLargeResourceDimension);
399 // Verify a resource of this size is larger than the transfer buffer.
400 scoped_ptr<ScopedResource> resource(
401 ScopedResource::Create(resource_provider_.get()));
402 resource->Allocate(size, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
403 RGBA_8888);
404 EXPECT_GE(resource->bytes(), kMaxTransferBufferUsageBytes);
407 AppendTask(0u, size);
408 AppendTask(1u, size);
409 AppendTask(2u, size);
410 ScheduleTasks();
412 // This will time out if a resource that is larger than the throttle limit
413 // never gets scheduled.
414 RunMessageLoopUntilAllTasksHaveCompleted();
417 TEST_P(TileTaskWorkerPoolTest, LostContext) {
418 LoseContext(output_surface_->context_provider());
419 LoseContext(output_surface_->worker_context_provider());
421 AppendTask(0u);
422 AppendTask(1u);
423 ScheduleTasks();
425 RunMessageLoopUntilAllTasksHaveCompleted();
427 ASSERT_EQ(2u, completed_tasks().size());
428 EXPECT_FALSE(completed_tasks()[0].canceled);
429 EXPECT_FALSE(completed_tasks()[1].canceled);
432 INSTANTIATE_TEST_CASE_P(
433 TileTaskWorkerPoolTests,
434 TileTaskWorkerPoolTest,
435 ::testing::Values(TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER,
436 TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY,
437 TILE_TASK_WORKER_POOL_TYPE_ONE_COPY,
438 TILE_TASK_WORKER_POOL_TYPE_GPU,
439 TILE_TASK_WORKER_POOL_TYPE_BITMAP));
441 } // namespace
442 } // namespace cc