Revert of Linux MSan: enable swarming/sharding for browser_tests. (patchset #1 id...
[chromium-blink-merge.git] / cc / resources / tile_task_worker_pool_unittest.cc
blob68758f63f728bca259d0517a665d82181ccbb0e0
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_tile_task_worker_pool.h"
14 #include "cc/resources/one_copy_tile_task_worker_pool.h"
15 #include "cc/resources/picture_pile.h"
16 #include "cc/resources/picture_pile_impl.h"
17 #include "cc/resources/pixel_buffer_tile_task_worker_pool.h"
18 #include "cc/resources/raster_buffer.h"
19 #include "cc/resources/resource_pool.h"
20 #include "cc/resources/resource_provider.h"
21 #include "cc/resources/scoped_resource.h"
22 #include "cc/resources/tile_task_runner.h"
23 #include "cc/resources/zero_copy_tile_task_worker_pool.h"
24 #include "cc/test/fake_output_surface.h"
25 #include "cc/test/fake_output_surface_client.h"
26 #include "cc/test/fake_picture_pile_impl.h"
27 #include "cc/test/test_gpu_memory_buffer_manager.h"
28 #include "cc/test/test_shared_bitmap_manager.h"
29 #include "cc/test/test_web_graphics_context_3d.h"
30 #include "testing/gtest/include/gtest/gtest.h"
32 namespace cc {
33 namespace {
35 const size_t kMaxTransferBufferUsageBytes = 10000U;
36 // A resource of this dimension^2 * 4 must be greater than the above transfer
37 // buffer constant.
38 const size_t kLargeResourceDimension = 1000U;
40 enum TileTaskWorkerPoolType {
41 TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER,
42 TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY,
43 TILE_TASK_WORKER_POOL_TYPE_ONE_COPY,
44 TILE_TASK_WORKER_POOL_TYPE_GPU,
45 TILE_TASK_WORKER_POOL_TYPE_BITMAP
48 class TestRasterTaskImpl : public RasterTask {
49 public:
50 typedef base::Callback<void(const RasterSource::SolidColorAnalysis& analysis,
51 bool was_canceled)> Reply;
53 TestRasterTaskImpl(const Resource* resource,
54 const Reply& reply,
55 ImageDecodeTask::Vector* dependencies)
56 : RasterTask(resource, dependencies),
57 reply_(reply),
58 picture_pile_(FakePicturePileImpl::CreateEmptyPile(gfx::Size(1, 1),
59 gfx::Size(1, 1))) {}
61 // Overridden from Task:
62 void RunOnWorkerThread() override {
63 raster_buffer_->Playback(picture_pile_.get(), gfx::Rect(0, 0, 1, 1), 1.0);
66 // Overridden from TileTask:
67 void ScheduleOnOriginThread(TileTaskClient* client) override {
68 raster_buffer_ = client->AcquireBufferForRaster(resource());
70 void CompleteOnOriginThread(TileTaskClient* client) override {
71 client->ReleaseBufferForRaster(raster_buffer_.Pass());
73 void RunReplyOnOriginThread() override {
74 reply_.Run(RasterSource::SolidColorAnalysis(), !HasFinishedRunning());
77 protected:
78 ~TestRasterTaskImpl() override {}
80 private:
81 const Reply reply_;
82 scoped_ptr<RasterBuffer> raster_buffer_;
83 scoped_refptr<PicturePileImpl> picture_pile_;
85 DISALLOW_COPY_AND_ASSIGN(TestRasterTaskImpl);
88 class BlockingTestRasterTaskImpl : public TestRasterTaskImpl {
89 public:
90 BlockingTestRasterTaskImpl(const Resource* resource,
91 const Reply& reply,
92 base::Lock* lock,
93 ImageDecodeTask::Vector* dependencies)
94 : TestRasterTaskImpl(resource, reply, dependencies), lock_(lock) {}
96 // Overridden from Task:
97 void RunOnWorkerThread() override {
98 base::AutoLock lock(*lock_);
99 TestRasterTaskImpl::RunOnWorkerThread();
102 // Overridden from TileTask:
103 void RunReplyOnOriginThread() override {}
105 protected:
106 ~BlockingTestRasterTaskImpl() override {}
108 private:
109 base::Lock* lock_;
111 DISALLOW_COPY_AND_ASSIGN(BlockingTestRasterTaskImpl);
114 class TileTaskWorkerPoolTest
115 : public testing::TestWithParam<TileTaskWorkerPoolType>,
116 public TileTaskRunnerClient {
117 public:
118 struct RasterTaskResult {
119 unsigned id;
120 bool canceled;
123 typedef std::vector<scoped_refptr<RasterTask>> RasterTaskVector;
125 enum NamedTaskSet { REQUIRED_FOR_ACTIVATION, REQUIRED_FOR_DRAW, ALL };
127 TileTaskWorkerPoolTest()
128 : context_provider_(TestContextProvider::Create()),
129 all_tile_tasks_finished_(
130 base::MessageLoopProxy::current().get(),
131 base::Bind(&TileTaskWorkerPoolTest::AllTileTasksFinished,
132 base::Unretained(this))),
133 timeout_seconds_(5),
134 timed_out_(false) {}
136 // Overridden from testing::Test:
137 void SetUp() override {
138 switch (GetParam()) {
139 case TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER:
140 Create3dOutputSurfaceAndResourceProvider();
141 tile_task_worker_pool_ = PixelBufferTileTaskWorkerPool::Create(
142 base::MessageLoopProxy::current().get(),
143 TileTaskWorkerPool::GetTaskGraphRunner(), context_provider_.get(),
144 resource_provider_.get(), kMaxTransferBufferUsageBytes);
145 break;
146 case TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY:
147 Create3dOutputSurfaceAndResourceProvider();
148 tile_task_worker_pool_ = ZeroCopyTileTaskWorkerPool::Create(
149 base::MessageLoopProxy::current().get(),
150 TileTaskWorkerPool::GetTaskGraphRunner(), resource_provider_.get());
151 break;
152 case TILE_TASK_WORKER_POOL_TYPE_ONE_COPY:
153 Create3dOutputSurfaceAndResourceProvider();
154 staging_resource_pool_ = ResourcePool::Create(resource_provider_.get(),
155 GL_TEXTURE_2D);
156 tile_task_worker_pool_ = OneCopyTileTaskWorkerPool::Create(
157 base::MessageLoopProxy::current().get(),
158 TileTaskWorkerPool::GetTaskGraphRunner(), context_provider_.get(),
159 resource_provider_.get(), staging_resource_pool_.get());
160 break;
161 case TILE_TASK_WORKER_POOL_TYPE_GPU:
162 Create3dOutputSurfaceAndResourceProvider();
163 tile_task_worker_pool_ = GpuTileTaskWorkerPool::Create(
164 base::MessageLoopProxy::current().get(),
165 TileTaskWorkerPool::GetTaskGraphRunner(),
166 resource_provider_.get());
167 break;
168 case TILE_TASK_WORKER_POOL_TYPE_BITMAP:
169 CreateSoftwareOutputSurfaceAndResourceProvider();
170 tile_task_worker_pool_ = BitmapTileTaskWorkerPool::Create(
171 base::MessageLoopProxy::current().get(),
172 TileTaskWorkerPool::GetTaskGraphRunner(), resource_provider_.get());
173 break;
176 DCHECK(tile_task_worker_pool_);
177 tile_task_worker_pool_->AsTileTaskRunner()->SetClient(this);
180 void TearDown() override {
181 tile_task_worker_pool_->AsTileTaskRunner()->Shutdown();
182 tile_task_worker_pool_->AsTileTaskRunner()->CheckForCompletedTasks();
185 void AllTileTasksFinished() {
186 tile_task_worker_pool_->AsTileTaskRunner()->CheckForCompletedTasks();
187 base::MessageLoop::current()->Quit();
190 // Overriden from TileTaskWorkerPoolClient:
191 void DidFinishRunningTileTasks(TaskSet task_set) override {
192 EXPECT_FALSE(completed_task_sets_[task_set]);
193 completed_task_sets_[task_set] = true;
194 if (task_set == ALL) {
195 EXPECT_TRUE((~completed_task_sets_).none());
196 all_tile_tasks_finished_.Schedule();
200 TaskSetCollection TasksThatShouldBeForcedToComplete() const override {
201 return TaskSetCollection();
204 void RunMessageLoopUntilAllTasksHaveCompleted() {
205 if (timeout_seconds_) {
206 timeout_.Reset(base::Bind(&TileTaskWorkerPoolTest::OnTimeout,
207 base::Unretained(this)));
208 base::MessageLoopProxy::current()->PostDelayedTask(
209 FROM_HERE, timeout_.callback(),
210 base::TimeDelta::FromSeconds(timeout_seconds_));
213 base::MessageLoop::current()->Run();
215 timeout_.Cancel();
217 ASSERT_FALSE(timed_out_) << "Test timed out";
220 void ScheduleTasks() {
221 TileTaskQueue queue;
223 for (RasterTaskVector::const_iterator it = tasks_.begin();
224 it != tasks_.end(); ++it) {
225 TaskSetCollection task_sets;
226 task_sets[REQUIRED_FOR_ACTIVATION] = true;
227 task_sets[REQUIRED_FOR_DRAW] = true;
228 task_sets[ALL] = true;
229 queue.items.push_back(TileTaskQueue::Item(it->get(), task_sets));
232 completed_task_sets_.reset();
233 tile_task_worker_pool_->AsTileTaskRunner()->ScheduleTasks(&queue);
236 void AppendTask(unsigned id, const gfx::Size& size) {
237 scoped_ptr<ScopedResource> resource(
238 ScopedResource::Create(resource_provider_.get()));
239 resource->Allocate(size, ResourceProvider::TextureHintImmutable, RGBA_8888);
240 const Resource* const_resource = resource.get();
242 ImageDecodeTask::Vector empty;
243 tasks_.push_back(new TestRasterTaskImpl(
244 const_resource,
245 base::Bind(&TileTaskWorkerPoolTest::OnTaskCompleted,
246 base::Unretained(this), base::Passed(&resource), id),
247 &empty));
250 void AppendTask(unsigned id) { AppendTask(id, gfx::Size(1, 1)); }
252 void AppendBlockingTask(unsigned id, base::Lock* lock) {
253 const gfx::Size size(1, 1);
255 scoped_ptr<ScopedResource> resource(
256 ScopedResource::Create(resource_provider_.get()));
257 resource->Allocate(size, ResourceProvider::TextureHintImmutable, RGBA_8888);
258 const Resource* const_resource = resource.get();
260 ImageDecodeTask::Vector empty;
261 tasks_.push_back(new BlockingTestRasterTaskImpl(
262 const_resource,
263 base::Bind(&TileTaskWorkerPoolTest::OnTaskCompleted,
264 base::Unretained(this), base::Passed(&resource), id),
265 lock, &empty));
268 const std::vector<RasterTaskResult>& completed_tasks() const {
269 return completed_tasks_;
272 private:
273 void Create3dOutputSurfaceAndResourceProvider() {
274 output_surface_ = FakeOutputSurface::Create3d(context_provider_).Pass();
275 CHECK(output_surface_->BindToClient(&output_surface_client_));
276 TestWebGraphicsContext3D* context3d = context_provider_->TestContext3d();
277 context3d->set_support_sync_query(true);
278 resource_provider_ = ResourceProvider::Create(output_surface_.get(), NULL,
279 &gpu_memory_buffer_manager_,
280 NULL, 0, false, 1).Pass();
283 void CreateSoftwareOutputSurfaceAndResourceProvider() {
284 output_surface_ = FakeOutputSurface::CreateSoftware(
285 make_scoped_ptr(new SoftwareOutputDevice));
286 CHECK(output_surface_->BindToClient(&output_surface_client_));
287 resource_provider_ =
288 ResourceProvider::Create(output_surface_.get(), &shared_bitmap_manager_,
289 NULL, NULL, 0, false, 1).Pass();
292 void OnTaskCompleted(scoped_ptr<ScopedResource> resource,
293 unsigned id,
294 const RasterSource::SolidColorAnalysis& analysis,
295 bool was_canceled) {
296 RasterTaskResult result;
297 result.id = id;
298 result.canceled = was_canceled;
299 completed_tasks_.push_back(result);
302 void OnTimeout() {
303 timed_out_ = true;
304 base::MessageLoop::current()->Quit();
307 protected:
308 scoped_refptr<TestContextProvider> context_provider_;
309 FakeOutputSurfaceClient output_surface_client_;
310 scoped_ptr<FakeOutputSurface> output_surface_;
311 scoped_ptr<ResourceProvider> resource_provider_;
312 scoped_ptr<ResourcePool> staging_resource_pool_;
313 scoped_ptr<TileTaskWorkerPool> tile_task_worker_pool_;
314 TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
315 TestSharedBitmapManager shared_bitmap_manager_;
316 base::CancelableClosure timeout_;
317 UniqueNotifier all_tile_tasks_finished_;
318 int timeout_seconds_;
319 bool timed_out_;
320 RasterTaskVector tasks_;
321 std::vector<RasterTaskResult> completed_tasks_;
322 TaskSetCollection completed_task_sets_;
325 TEST_P(TileTaskWorkerPoolTest, Basic) {
326 AppendTask(0u);
327 AppendTask(1u);
328 ScheduleTasks();
330 RunMessageLoopUntilAllTasksHaveCompleted();
332 ASSERT_EQ(2u, completed_tasks().size());
333 EXPECT_FALSE(completed_tasks()[0].canceled);
334 EXPECT_FALSE(completed_tasks()[1].canceled);
337 TEST_P(TileTaskWorkerPoolTest, FailedMapResource) {
338 if (GetParam() == TILE_TASK_WORKER_POOL_TYPE_BITMAP)
339 return;
341 TestWebGraphicsContext3D* context3d = context_provider_->TestContext3d();
342 context3d->set_times_map_buffer_chromium_succeeds(0);
343 AppendTask(0u);
344 ScheduleTasks();
346 RunMessageLoopUntilAllTasksHaveCompleted();
348 ASSERT_EQ(1u, completed_tasks().size());
349 EXPECT_FALSE(completed_tasks()[0].canceled);
352 // This test checks that replacing a pending raster task with another does
353 // not prevent the DidFinishRunningTileTasks notification from being sent.
354 TEST_P(TileTaskWorkerPoolTest, FalseThrottling) {
355 base::Lock lock;
357 // Schedule a task that is prevented from completing with a lock.
358 lock.Acquire();
359 AppendBlockingTask(0u, &lock);
360 ScheduleTasks();
362 // Schedule another task to replace the still-pending task. Because the old
363 // task is not a throttled task in the new task set, it should not prevent
364 // DidFinishRunningTileTasks from getting signaled.
365 RasterTaskVector tasks;
366 tasks.swap(tasks_);
367 AppendTask(1u);
368 ScheduleTasks();
370 // Unblock the first task to allow the second task to complete.
371 lock.Release();
373 RunMessageLoopUntilAllTasksHaveCompleted();
376 TEST_P(TileTaskWorkerPoolTest, LargeResources) {
377 gfx::Size size(kLargeResourceDimension, kLargeResourceDimension);
380 // Verify a resource of this size is larger than the transfer buffer.
381 scoped_ptr<ScopedResource> resource(
382 ScopedResource::Create(resource_provider_.get()));
383 resource->Allocate(size, ResourceProvider::TextureHintImmutable, RGBA_8888);
384 EXPECT_GE(resource->bytes(), kMaxTransferBufferUsageBytes);
387 AppendTask(0u, size);
388 AppendTask(1u, size);
389 AppendTask(2u, size);
390 ScheduleTasks();
392 // This will time out if a resource that is larger than the throttle limit
393 // never gets scheduled.
394 RunMessageLoopUntilAllTasksHaveCompleted();
397 INSTANTIATE_TEST_CASE_P(
398 TileTaskWorkerPoolTests,
399 TileTaskWorkerPoolTest,
400 ::testing::Values(TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER,
401 TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY,
402 TILE_TASK_WORKER_POOL_TYPE_ONE_COPY,
403 TILE_TASK_WORKER_POOL_TYPE_GPU,
404 TILE_TASK_WORKER_POOL_TYPE_BITMAP));
406 } // namespace
407 } // namespace cc