Add iOS bots to 10% CQ experiment
[chromium-blink-merge.git] / cc / resources / tile_task_worker_pool_unittest.cc
blobd7cb155ef956c0cd06fd780e57df27916d05f77a
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 "cc/base/unique_notifier.h"
12 #include "cc/resources/bitmap_tile_task_worker_pool.h"
13 #include "cc/resources/gpu_rasterizer.h"
14 #include "cc/resources/gpu_tile_task_worker_pool.h"
15 #include "cc/resources/one_copy_tile_task_worker_pool.h"
16 #include "cc/resources/picture_pile.h"
17 #include "cc/resources/picture_pile_impl.h"
18 #include "cc/resources/pixel_buffer_tile_task_worker_pool.h"
19 #include "cc/resources/raster_buffer.h"
20 #include "cc/resources/resource_pool.h"
21 #include "cc/resources/resource_provider.h"
22 #include "cc/resources/scoped_resource.h"
23 #include "cc/resources/tile_task_runner.h"
24 #include "cc/resources/zero_copy_tile_task_worker_pool.h"
25 #include "cc/test/fake_output_surface.h"
26 #include "cc/test/fake_output_surface_client.h"
27 #include "cc/test/fake_picture_pile_impl.h"
28 #include "cc/test/test_gpu_memory_buffer_manager.h"
29 #include "cc/test/test_shared_bitmap_manager.h"
30 #include "cc/test/test_web_graphics_context_3d.h"
31 #include "testing/gtest/include/gtest/gtest.h"
33 namespace cc {
34 namespace {
36 const size_t kMaxTransferBufferUsageBytes = 10000U;
37 // A resource of this dimension^2 * 4 must be greater than the above transfer
38 // buffer constant.
39 const size_t kLargeResourceDimension = 1000U;
41 enum TileTaskWorkerPoolType {
42 TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER,
43 TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY,
44 TILE_TASK_WORKER_POOL_TYPE_ONE_COPY,
45 TILE_TASK_WORKER_POOL_TYPE_GPU,
46 TILE_TASK_WORKER_POOL_TYPE_BITMAP
49 class TestRasterTaskImpl : public RasterTask {
50 public:
51 typedef base::Callback<void(const RasterSource::SolidColorAnalysis& analysis,
52 bool was_canceled)> Reply;
54 TestRasterTaskImpl(const Resource* resource,
55 const Reply& reply,
56 ImageDecodeTask::Vector* dependencies)
57 : RasterTask(resource, dependencies),
58 reply_(reply),
59 picture_pile_(FakePicturePileImpl::CreateEmptyPile(gfx::Size(1, 1),
60 gfx::Size(1, 1))) {}
62 // Overridden from Task:
63 void RunOnWorkerThread() override {
64 raster_buffer_->Playback(picture_pile_.get(), gfx::Rect(0, 0, 1, 1), 1.0);
67 // Overridden from TileTask:
68 void ScheduleOnOriginThread(TileTaskClient* client) override {
69 raster_buffer_ = client->AcquireBufferForRaster(resource());
71 void CompleteOnOriginThread(TileTaskClient* client) override {
72 client->ReleaseBufferForRaster(raster_buffer_.Pass());
74 void RunReplyOnOriginThread() override {
75 reply_.Run(RasterSource::SolidColorAnalysis(), !HasFinishedRunning());
78 protected:
79 ~TestRasterTaskImpl() override {}
81 private:
82 const Reply reply_;
83 scoped_ptr<RasterBuffer> raster_buffer_;
84 scoped_refptr<PicturePileImpl> picture_pile_;
86 DISALLOW_COPY_AND_ASSIGN(TestRasterTaskImpl);
89 class BlockingTestRasterTaskImpl : public TestRasterTaskImpl {
90 public:
91 BlockingTestRasterTaskImpl(const Resource* resource,
92 const Reply& reply,
93 base::Lock* lock,
94 ImageDecodeTask::Vector* dependencies)
95 : TestRasterTaskImpl(resource, reply, dependencies), lock_(lock) {}
97 // Overridden from Task:
98 void RunOnWorkerThread() override {
99 base::AutoLock lock(*lock_);
100 TestRasterTaskImpl::RunOnWorkerThread();
103 // Overridden from TileTask:
104 void RunReplyOnOriginThread() override {}
106 protected:
107 ~BlockingTestRasterTaskImpl() override {}
109 private:
110 base::Lock* lock_;
112 DISALLOW_COPY_AND_ASSIGN(BlockingTestRasterTaskImpl);
115 class TileTaskWorkerPoolTest
116 : public testing::TestWithParam<TileTaskWorkerPoolType>,
117 public TileTaskRunnerClient {
118 public:
119 struct RasterTaskResult {
120 unsigned id;
121 bool canceled;
124 typedef std::vector<scoped_refptr<RasterTask>> RasterTaskVector;
126 enum NamedTaskSet { REQUIRED_FOR_ACTIVATION, REQUIRED_FOR_DRAW, ALL };
128 TileTaskWorkerPoolTest()
129 : context_provider_(TestContextProvider::Create()),
130 worker_context_provider_(TestContextProvider::Create()),
131 all_tile_tasks_finished_(
132 base::MessageLoopProxy::current().get(),
133 base::Bind(&TileTaskWorkerPoolTest::AllTileTasksFinished,
134 base::Unretained(this))),
135 timeout_seconds_(5),
136 timed_out_(false) {}
138 // Overridden from testing::Test:
139 void SetUp() override {
140 switch (GetParam()) {
141 case TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER:
142 Create3dOutputSurfaceAndResourceProvider();
143 tile_task_worker_pool_ = PixelBufferTileTaskWorkerPool::Create(
144 base::MessageLoopProxy::current().get(),
145 TileTaskWorkerPool::GetTaskGraphRunner(), context_provider_.get(),
146 resource_provider_.get(), kMaxTransferBufferUsageBytes);
147 break;
148 case TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY:
149 Create3dOutputSurfaceAndResourceProvider();
150 tile_task_worker_pool_ = ZeroCopyTileTaskWorkerPool::Create(
151 base::MessageLoopProxy::current().get(),
152 TileTaskWorkerPool::GetTaskGraphRunner(), resource_provider_.get());
153 break;
154 case TILE_TASK_WORKER_POOL_TYPE_ONE_COPY:
155 Create3dOutputSurfaceAndResourceProvider();
156 staging_resource_pool_ = ResourcePool::Create(resource_provider_.get(),
157 GL_TEXTURE_2D);
158 tile_task_worker_pool_ = OneCopyTileTaskWorkerPool::Create(
159 base::MessageLoopProxy::current().get(),
160 TileTaskWorkerPool::GetTaskGraphRunner(), context_provider_.get(),
161 resource_provider_.get(), staging_resource_pool_.get());
162 break;
163 case TILE_TASK_WORKER_POOL_TYPE_GPU:
164 Create3dOutputSurfaceAndResourceProvider();
165 rasterizer_ = GpuRasterizer::Create(
166 context_provider_.get(), resource_provider_.get(), false, false, 0);
167 tile_task_worker_pool_ = GpuTileTaskWorkerPool::Create(
168 base::MessageLoopProxy::current().get(),
169 TileTaskWorkerPool::GetTaskGraphRunner(),
170 static_cast<GpuRasterizer*>(rasterizer_.get()));
171 break;
172 case TILE_TASK_WORKER_POOL_TYPE_BITMAP:
173 CreateSoftwareOutputSurfaceAndResourceProvider();
174 tile_task_worker_pool_ = BitmapTileTaskWorkerPool::Create(
175 base::MessageLoopProxy::current().get(),
176 TileTaskWorkerPool::GetTaskGraphRunner(), resource_provider_.get());
177 break;
180 DCHECK(tile_task_worker_pool_);
181 tile_task_worker_pool_->AsTileTaskRunner()->SetClient(this);
184 void TearDown() override {
185 tile_task_worker_pool_->AsTileTaskRunner()->Shutdown();
186 tile_task_worker_pool_->AsTileTaskRunner()->CheckForCompletedTasks();
189 void AllTileTasksFinished() {
190 tile_task_worker_pool_->AsTileTaskRunner()->CheckForCompletedTasks();
191 base::MessageLoop::current()->Quit();
194 // Overriden from TileTaskWorkerPoolClient:
195 void DidFinishRunningTileTasks(TaskSet task_set) override {
196 EXPECT_FALSE(completed_task_sets_[task_set]);
197 completed_task_sets_[task_set] = true;
198 if (task_set == ALL) {
199 EXPECT_TRUE((~completed_task_sets_).none());
200 all_tile_tasks_finished_.Schedule();
204 TaskSetCollection TasksThatShouldBeForcedToComplete() const override {
205 return TaskSetCollection();
208 void RunMessageLoopUntilAllTasksHaveCompleted() {
209 if (timeout_seconds_) {
210 timeout_.Reset(base::Bind(&TileTaskWorkerPoolTest::OnTimeout,
211 base::Unretained(this)));
212 base::MessageLoopProxy::current()->PostDelayedTask(
213 FROM_HERE, timeout_.callback(),
214 base::TimeDelta::FromSeconds(timeout_seconds_));
217 base::MessageLoop::current()->Run();
219 timeout_.Cancel();
221 ASSERT_FALSE(timed_out_) << "Test timed out";
224 void ScheduleTasks() {
225 TileTaskQueue queue;
227 for (RasterTaskVector::const_iterator it = tasks_.begin();
228 it != tasks_.end(); ++it) {
229 TaskSetCollection task_sets;
230 task_sets[REQUIRED_FOR_ACTIVATION] = true;
231 task_sets[REQUIRED_FOR_DRAW] = true;
232 task_sets[ALL] = true;
233 queue.items.push_back(TileTaskQueue::Item(it->get(), task_sets));
236 completed_task_sets_.reset();
237 tile_task_worker_pool_->AsTileTaskRunner()->ScheduleTasks(&queue);
240 void AppendTask(unsigned id, const gfx::Size& size) {
241 scoped_ptr<ScopedResource> resource(
242 ScopedResource::Create(resource_provider_.get()));
243 resource->Allocate(size, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
244 RGBA_8888);
245 const Resource* const_resource = resource.get();
247 ImageDecodeTask::Vector empty;
248 tasks_.push_back(new TestRasterTaskImpl(
249 const_resource,
250 base::Bind(&TileTaskWorkerPoolTest::OnTaskCompleted,
251 base::Unretained(this), base::Passed(&resource), id),
252 &empty));
255 void AppendTask(unsigned id) { AppendTask(id, gfx::Size(1, 1)); }
257 void AppendBlockingTask(unsigned id, base::Lock* lock) {
258 const gfx::Size size(1, 1);
260 scoped_ptr<ScopedResource> resource(
261 ScopedResource::Create(resource_provider_.get()));
262 resource->Allocate(size, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
263 RGBA_8888);
264 const Resource* const_resource = resource.get();
266 ImageDecodeTask::Vector empty;
267 tasks_.push_back(new BlockingTestRasterTaskImpl(
268 const_resource,
269 base::Bind(&TileTaskWorkerPoolTest::OnTaskCompleted,
270 base::Unretained(this), base::Passed(&resource), id),
271 lock, &empty));
274 const std::vector<RasterTaskResult>& completed_tasks() const {
275 return completed_tasks_;
278 private:
279 void Create3dOutputSurfaceAndResourceProvider() {
280 output_surface_ = FakeOutputSurface::Create3d(
281 context_provider_, worker_context_provider_).Pass();
282 CHECK(output_surface_->BindToClient(&output_surface_client_));
283 TestWebGraphicsContext3D* context3d = context_provider_->TestContext3d();
284 context3d->set_support_sync_query(true);
285 resource_provider_ = ResourceProvider::Create(output_surface_.get(), NULL,
286 &gpu_memory_buffer_manager_,
287 NULL, 0, false, 1).Pass();
290 void CreateSoftwareOutputSurfaceAndResourceProvider() {
291 output_surface_ = FakeOutputSurface::CreateSoftware(
292 make_scoped_ptr(new SoftwareOutputDevice));
293 CHECK(output_surface_->BindToClient(&output_surface_client_));
294 resource_provider_ =
295 ResourceProvider::Create(output_surface_.get(), &shared_bitmap_manager_,
296 NULL, NULL, 0, false, 1).Pass();
299 void OnTaskCompleted(scoped_ptr<ScopedResource> resource,
300 unsigned id,
301 const RasterSource::SolidColorAnalysis& analysis,
302 bool was_canceled) {
303 RasterTaskResult result;
304 result.id = id;
305 result.canceled = was_canceled;
306 completed_tasks_.push_back(result);
309 void OnTimeout() {
310 timed_out_ = true;
311 base::MessageLoop::current()->Quit();
314 protected:
315 scoped_refptr<TestContextProvider> context_provider_;
316 scoped_refptr<TestContextProvider> worker_context_provider_;
317 scoped_ptr<Rasterizer> rasterizer_;
318 FakeOutputSurfaceClient output_surface_client_;
319 scoped_ptr<FakeOutputSurface> output_surface_;
320 scoped_ptr<ResourceProvider> resource_provider_;
321 scoped_ptr<ResourcePool> staging_resource_pool_;
322 scoped_ptr<TileTaskWorkerPool> tile_task_worker_pool_;
323 TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
324 TestSharedBitmapManager shared_bitmap_manager_;
325 base::CancelableClosure timeout_;
326 UniqueNotifier all_tile_tasks_finished_;
327 int timeout_seconds_;
328 bool timed_out_;
329 RasterTaskVector tasks_;
330 std::vector<RasterTaskResult> completed_tasks_;
331 TaskSetCollection completed_task_sets_;
334 TEST_P(TileTaskWorkerPoolTest, Basic) {
335 AppendTask(0u);
336 AppendTask(1u);
337 ScheduleTasks();
339 RunMessageLoopUntilAllTasksHaveCompleted();
341 ASSERT_EQ(2u, completed_tasks().size());
342 EXPECT_FALSE(completed_tasks()[0].canceled);
343 EXPECT_FALSE(completed_tasks()[1].canceled);
346 TEST_P(TileTaskWorkerPoolTest, FailedMapResource) {
347 if (GetParam() == TILE_TASK_WORKER_POOL_TYPE_BITMAP)
348 return;
350 TestWebGraphicsContext3D* context3d = context_provider_->TestContext3d();
351 context3d->set_times_map_buffer_chromium_succeeds(0);
352 AppendTask(0u);
353 ScheduleTasks();
355 RunMessageLoopUntilAllTasksHaveCompleted();
357 ASSERT_EQ(1u, completed_tasks().size());
358 EXPECT_FALSE(completed_tasks()[0].canceled);
361 // This test checks that replacing a pending raster task with another does
362 // not prevent the DidFinishRunningTileTasks notification from being sent.
363 TEST_P(TileTaskWorkerPoolTest, FalseThrottling) {
364 base::Lock lock;
366 // Schedule a task that is prevented from completing with a lock.
367 lock.Acquire();
368 AppendBlockingTask(0u, &lock);
369 ScheduleTasks();
371 // Schedule another task to replace the still-pending task. Because the old
372 // task is not a throttled task in the new task set, it should not prevent
373 // DidFinishRunningTileTasks from getting signaled.
374 RasterTaskVector tasks;
375 tasks.swap(tasks_);
376 AppendTask(1u);
377 ScheduleTasks();
379 // Unblock the first task to allow the second task to complete.
380 lock.Release();
382 RunMessageLoopUntilAllTasksHaveCompleted();
385 TEST_P(TileTaskWorkerPoolTest, LargeResources) {
386 gfx::Size size(kLargeResourceDimension, kLargeResourceDimension);
389 // Verify a resource of this size is larger than the transfer buffer.
390 scoped_ptr<ScopedResource> resource(
391 ScopedResource::Create(resource_provider_.get()));
392 resource->Allocate(size, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
393 RGBA_8888);
394 EXPECT_GE(resource->bytes(), kMaxTransferBufferUsageBytes);
397 AppendTask(0u, size);
398 AppendTask(1u, size);
399 AppendTask(2u, size);
400 ScheduleTasks();
402 // This will time out if a resource that is larger than the throttle limit
403 // never gets scheduled.
404 RunMessageLoopUntilAllTasksHaveCompleted();
407 INSTANTIATE_TEST_CASE_P(
408 TileTaskWorkerPoolTests,
409 TileTaskWorkerPoolTest,
410 ::testing::Values(TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER,
411 TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY,
412 TILE_TASK_WORKER_POOL_TYPE_ONE_COPY,
413 TILE_TASK_WORKER_POOL_TYPE_GPU,
414 TILE_TASK_WORKER_POOL_TYPE_BITMAP));
416 } // namespace
417 } // namespace cc