[Android] Implement 3-way sensor fallback for Device Orientation.
[chromium-blink-merge.git] / cc / raster / tile_task_worker_pool_unittest.cc
blobbf2a82a374704a74a84f782fce92ef280b209345
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/raster/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/playback/picture_pile.h"
16 #include "cc/playback/picture_pile_impl.h"
17 #include "cc/raster/bitmap_tile_task_worker_pool.h"
18 #include "cc/raster/gpu_rasterizer.h"
19 #include "cc/raster/gpu_tile_task_worker_pool.h"
20 #include "cc/raster/one_copy_tile_task_worker_pool.h"
21 #include "cc/raster/pixel_buffer_tile_task_worker_pool.h"
22 #include "cc/raster/raster_buffer.h"
23 #include "cc/raster/tile_task_runner.h"
24 #include "cc/raster/zero_copy_tile_task_worker_pool.h"
25 #include "cc/resources/resource_pool.h"
26 #include "cc/resources/resource_provider.h"
27 #include "cc/resources/scoped_resource.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/fake_resource_provider.h"
32 #include "cc/test/test_gpu_memory_buffer_manager.h"
33 #include "cc/test/test_shared_bitmap_manager.h"
34 #include "cc/test/test_task_graph_runner.h"
35 #include "cc/test/test_web_graphics_context_3d.h"
36 #include "gpu/GLES2/gl2extchromium.h"
37 #include "testing/gtest/include/gtest/gtest.h"
39 namespace cc {
40 namespace {
42 const size_t kMaxTransferBufferUsageBytes = 10000U;
43 const size_t kMaxBytesPerCopyOperation = 1000U;
44 const size_t kMaxStagingBuffers = 32U;
46 // A resource of this dimension^2 * 4 must be greater than the above transfer
47 // buffer constant.
48 const size_t kLargeResourceDimension = 1000U;
50 enum TileTaskWorkerPoolType {
51 TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER,
52 TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY,
53 TILE_TASK_WORKER_POOL_TYPE_ONE_COPY,
54 TILE_TASK_WORKER_POOL_TYPE_GPU,
55 TILE_TASK_WORKER_POOL_TYPE_BITMAP
58 class TestRasterTaskImpl : public RasterTask {
59 public:
60 typedef base::Callback<void(const RasterSource::SolidColorAnalysis& analysis,
61 bool was_canceled)> Reply;
63 TestRasterTaskImpl(const Resource* resource,
64 const Reply& reply,
65 ImageDecodeTask::Vector* dependencies)
66 : RasterTask(resource, dependencies),
67 reply_(reply),
68 picture_pile_(FakePicturePileImpl::CreateEmptyPile(gfx::Size(1, 1),
69 gfx::Size(1, 1))) {}
71 // Overridden from Task:
72 void RunOnWorkerThread() override {
73 uint64_t new_content_id = 0;
74 raster_buffer_->Playback(picture_pile_.get(), gfx::Rect(1, 1),
75 gfx::Rect(1, 1), new_content_id, 1.f, true);
78 // Overridden from TileTask:
79 void ScheduleOnOriginThread(TileTaskClient* client) override {
80 // The raster buffer has no tile ids associated with it for partial update,
81 // so doesn't need to provide a valid dirty rect.
82 raster_buffer_ = client->AcquireBufferForRaster(resource(), 0, 0);
84 void CompleteOnOriginThread(TileTaskClient* client) override {
85 client->ReleaseBufferForRaster(raster_buffer_.Pass());
87 void RunReplyOnOriginThread() override {
88 reply_.Run(RasterSource::SolidColorAnalysis(), !HasFinishedRunning());
91 protected:
92 ~TestRasterTaskImpl() override {}
94 private:
95 const Reply reply_;
96 scoped_ptr<RasterBuffer> raster_buffer_;
97 scoped_refptr<PicturePileImpl> picture_pile_;
99 DISALLOW_COPY_AND_ASSIGN(TestRasterTaskImpl);
102 class BlockingTestRasterTaskImpl : public TestRasterTaskImpl {
103 public:
104 BlockingTestRasterTaskImpl(const Resource* resource,
105 const Reply& reply,
106 base::Lock* lock,
107 ImageDecodeTask::Vector* dependencies)
108 : TestRasterTaskImpl(resource, reply, dependencies), lock_(lock) {}
110 // Overridden from Task:
111 void RunOnWorkerThread() override {
112 base::AutoLock lock(*lock_);
113 TestRasterTaskImpl::RunOnWorkerThread();
116 // Overridden from TileTask:
117 void RunReplyOnOriginThread() override {}
119 protected:
120 ~BlockingTestRasterTaskImpl() override {}
122 private:
123 base::Lock* lock_;
125 DISALLOW_COPY_AND_ASSIGN(BlockingTestRasterTaskImpl);
128 class TileTaskWorkerPoolTest
129 : public testing::TestWithParam<TileTaskWorkerPoolType>,
130 public TileTaskRunnerClient {
131 public:
132 struct RasterTaskResult {
133 unsigned id;
134 bool canceled;
137 typedef std::vector<scoped_refptr<RasterTask>> RasterTaskVector;
139 enum NamedTaskSet { REQUIRED_FOR_ACTIVATION, REQUIRED_FOR_DRAW, ALL };
141 TileTaskWorkerPoolTest()
142 : context_provider_(TestContextProvider::Create()),
143 worker_context_provider_(TestContextProvider::Create()),
144 all_tile_tasks_finished_(
145 base::ThreadTaskRunnerHandle::Get().get(),
146 base::Bind(&TileTaskWorkerPoolTest::AllTileTasksFinished,
147 base::Unretained(this))),
148 timeout_seconds_(5),
149 timed_out_(false) {}
151 // Overridden from testing::Test:
152 void SetUp() override {
153 switch (GetParam()) {
154 case TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER:
155 Create3dOutputSurfaceAndResourceProvider();
156 tile_task_worker_pool_ = PixelBufferTileTaskWorkerPool::Create(
157 base::ThreadTaskRunnerHandle::Get().get(), &task_graph_runner_,
158 context_provider_.get(), resource_provider_.get(),
159 kMaxTransferBufferUsageBytes);
160 break;
161 case TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY:
162 Create3dOutputSurfaceAndResourceProvider();
163 tile_task_worker_pool_ = ZeroCopyTileTaskWorkerPool::Create(
164 base::ThreadTaskRunnerHandle::Get().get(), &task_graph_runner_,
165 resource_provider_.get());
166 break;
167 case TILE_TASK_WORKER_POOL_TYPE_ONE_COPY:
168 Create3dOutputSurfaceAndResourceProvider();
169 tile_task_worker_pool_ = OneCopyTileTaskWorkerPool::Create(
170 base::ThreadTaskRunnerHandle::Get().get(), &task_graph_runner_,
171 context_provider_.get(), resource_provider_.get(),
172 kMaxBytesPerCopyOperation, false, kMaxStagingBuffers);
173 break;
174 case TILE_TASK_WORKER_POOL_TYPE_GPU:
175 Create3dOutputSurfaceAndResourceProvider();
176 tile_task_worker_pool_ = GpuTileTaskWorkerPool::Create(
177 base::ThreadTaskRunnerHandle::Get().get(), &task_graph_runner_,
178 context_provider_.get(), resource_provider_.get(), false, 0);
179 break;
180 case TILE_TASK_WORKER_POOL_TYPE_BITMAP:
181 CreateSoftwareOutputSurfaceAndResourceProvider();
182 tile_task_worker_pool_ = BitmapTileTaskWorkerPool::Create(
183 base::ThreadTaskRunnerHandle::Get().get(), &task_graph_runner_,
184 resource_provider_.get());
185 break;
188 DCHECK(tile_task_worker_pool_);
189 tile_task_worker_pool_->AsTileTaskRunner()->SetClient(this);
192 void TearDown() override {
193 tile_task_worker_pool_->AsTileTaskRunner()->Shutdown();
194 tile_task_worker_pool_->AsTileTaskRunner()->CheckForCompletedTasks();
197 void AllTileTasksFinished() {
198 tile_task_worker_pool_->AsTileTaskRunner()->CheckForCompletedTasks();
199 base::MessageLoop::current()->Quit();
202 // Overriden from TileTaskWorkerPoolClient:
203 void DidFinishRunningTileTasks(TaskSet task_set) override {
204 EXPECT_FALSE(completed_task_sets_[task_set]);
205 completed_task_sets_[task_set] = true;
206 if (task_set == ALL) {
207 EXPECT_TRUE((~completed_task_sets_).none());
208 all_tile_tasks_finished_.Schedule();
212 TaskSetCollection TasksThatShouldBeForcedToComplete() const override {
213 return TaskSetCollection();
216 void RunMessageLoopUntilAllTasksHaveCompleted() {
217 if (timeout_seconds_) {
218 timeout_.Reset(base::Bind(&TileTaskWorkerPoolTest::OnTimeout,
219 base::Unretained(this)));
220 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
221 FROM_HERE, timeout_.callback(),
222 base::TimeDelta::FromSeconds(timeout_seconds_));
225 base::MessageLoop::current()->Run();
227 timeout_.Cancel();
229 ASSERT_FALSE(timed_out_) << "Test timed out";
232 void ScheduleTasks() {
233 TileTaskQueue queue;
235 for (RasterTaskVector::const_iterator it = tasks_.begin();
236 it != tasks_.end(); ++it) {
237 TaskSetCollection task_sets;
238 task_sets[REQUIRED_FOR_ACTIVATION] = true;
239 task_sets[REQUIRED_FOR_DRAW] = true;
240 task_sets[ALL] = true;
241 queue.items.push_back(TileTaskQueue::Item(it->get(), task_sets));
244 completed_task_sets_.reset();
245 tile_task_worker_pool_->AsTileTaskRunner()->ScheduleTasks(&queue);
248 void AppendTask(unsigned id, const gfx::Size& size) {
249 scoped_ptr<ScopedResource> resource(
250 ScopedResource::Create(resource_provider_.get()));
251 resource->Allocate(size, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
252 RGBA_8888);
253 const Resource* const_resource = resource.get();
255 ImageDecodeTask::Vector empty;
256 tasks_.push_back(new TestRasterTaskImpl(
257 const_resource,
258 base::Bind(&TileTaskWorkerPoolTest::OnTaskCompleted,
259 base::Unretained(this), base::Passed(&resource), id),
260 &empty));
263 void AppendTask(unsigned id) { AppendTask(id, gfx::Size(1, 1)); }
265 void AppendBlockingTask(unsigned id, base::Lock* lock) {
266 const gfx::Size size(1, 1);
268 scoped_ptr<ScopedResource> resource(
269 ScopedResource::Create(resource_provider_.get()));
270 resource->Allocate(size, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
271 RGBA_8888);
272 const Resource* const_resource = resource.get();
274 ImageDecodeTask::Vector empty;
275 tasks_.push_back(new BlockingTestRasterTaskImpl(
276 const_resource,
277 base::Bind(&TileTaskWorkerPoolTest::OnTaskCompleted,
278 base::Unretained(this), base::Passed(&resource), id),
279 lock, &empty));
282 const std::vector<RasterTaskResult>& completed_tasks() const {
283 return completed_tasks_;
286 void LoseContext(ContextProvider* context_provider) {
287 if (!context_provider)
288 return;
289 context_provider->ContextGL()->LoseContextCHROMIUM(
290 GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB);
291 context_provider->ContextGL()->Flush();
294 private:
295 void Create3dOutputSurfaceAndResourceProvider() {
296 output_surface_ = FakeOutputSurface::Create3d(context_provider_,
297 worker_context_provider_);
298 CHECK(output_surface_->BindToClient(&output_surface_client_));
299 TestWebGraphicsContext3D* context3d = context_provider_->TestContext3d();
300 context3d->set_support_sync_query(true);
301 resource_provider_ = FakeResourceProvider::Create(
302 output_surface_.get(), nullptr, &gpu_memory_buffer_manager_);
305 void CreateSoftwareOutputSurfaceAndResourceProvider() {
306 output_surface_ = FakeOutputSurface::CreateSoftware(
307 make_scoped_ptr(new SoftwareOutputDevice));
308 CHECK(output_surface_->BindToClient(&output_surface_client_));
309 resource_provider_ = FakeResourceProvider::Create(
310 output_surface_.get(), &shared_bitmap_manager_, nullptr);
313 void OnTaskCompleted(scoped_ptr<ScopedResource> resource,
314 unsigned id,
315 const RasterSource::SolidColorAnalysis& analysis,
316 bool was_canceled) {
317 RasterTaskResult result;
318 result.id = id;
319 result.canceled = was_canceled;
320 completed_tasks_.push_back(result);
323 void OnTimeout() {
324 timed_out_ = true;
325 base::MessageLoop::current()->Quit();
328 protected:
329 scoped_refptr<TestContextProvider> context_provider_;
330 scoped_refptr<TestContextProvider> worker_context_provider_;
331 FakeOutputSurfaceClient output_surface_client_;
332 scoped_ptr<FakeOutputSurface> output_surface_;
333 scoped_ptr<ResourceProvider> resource_provider_;
334 scoped_ptr<TileTaskWorkerPool> tile_task_worker_pool_;
335 TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
336 TestSharedBitmapManager shared_bitmap_manager_;
337 TestTaskGraphRunner task_graph_runner_;
338 base::CancelableClosure timeout_;
339 UniqueNotifier all_tile_tasks_finished_;
340 int timeout_seconds_;
341 bool timed_out_;
342 RasterTaskVector tasks_;
343 std::vector<RasterTaskResult> completed_tasks_;
344 TaskSetCollection completed_task_sets_;
347 TEST_P(TileTaskWorkerPoolTest, Basic) {
348 AppendTask(0u);
349 AppendTask(1u);
350 ScheduleTasks();
352 RunMessageLoopUntilAllTasksHaveCompleted();
354 ASSERT_EQ(2u, completed_tasks().size());
355 EXPECT_FALSE(completed_tasks()[0].canceled);
356 EXPECT_FALSE(completed_tasks()[1].canceled);
359 TEST_P(TileTaskWorkerPoolTest, FailedMapResource) {
360 if (GetParam() == TILE_TASK_WORKER_POOL_TYPE_BITMAP)
361 return;
363 TestWebGraphicsContext3D* context3d = context_provider_->TestContext3d();
364 context3d->set_times_map_buffer_chromium_succeeds(0);
365 AppendTask(0u);
366 ScheduleTasks();
368 RunMessageLoopUntilAllTasksHaveCompleted();
370 ASSERT_EQ(1u, completed_tasks().size());
371 EXPECT_FALSE(completed_tasks()[0].canceled);
374 // This test checks that replacing a pending raster task with another does
375 // not prevent the DidFinishRunningTileTasks notification from being sent.
376 TEST_P(TileTaskWorkerPoolTest, FalseThrottling) {
377 base::Lock lock;
379 // Schedule a task that is prevented from completing with a lock.
380 lock.Acquire();
381 AppendBlockingTask(0u, &lock);
382 ScheduleTasks();
384 // Schedule another task to replace the still-pending task. Because the old
385 // task is not a throttled task in the new task set, it should not prevent
386 // DidFinishRunningTileTasks from getting signaled.
387 RasterTaskVector tasks;
388 tasks.swap(tasks_);
389 AppendTask(1u);
390 ScheduleTasks();
392 // Unblock the first task to allow the second task to complete.
393 lock.Release();
395 RunMessageLoopUntilAllTasksHaveCompleted();
398 TEST_P(TileTaskWorkerPoolTest, LargeResources) {
399 gfx::Size size(kLargeResourceDimension, kLargeResourceDimension);
402 // Verify a resource of this size is larger than the transfer buffer.
403 scoped_ptr<ScopedResource> resource(
404 ScopedResource::Create(resource_provider_.get()));
405 resource->Allocate(size, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
406 RGBA_8888);
407 EXPECT_GE(ResourceUtil::UncheckedSizeInBytes<size_t>(resource->size(),
408 resource->format()),
409 kMaxTransferBufferUsageBytes);
412 AppendTask(0u, size);
413 AppendTask(1u, size);
414 AppendTask(2u, size);
415 ScheduleTasks();
417 // This will time out if a resource that is larger than the throttle limit
418 // never gets scheduled.
419 RunMessageLoopUntilAllTasksHaveCompleted();
422 TEST_P(TileTaskWorkerPoolTest, LostContext) {
423 LoseContext(output_surface_->context_provider());
424 LoseContext(output_surface_->worker_context_provider());
426 AppendTask(0u);
427 AppendTask(1u);
428 ScheduleTasks();
430 RunMessageLoopUntilAllTasksHaveCompleted();
432 ASSERT_EQ(2u, completed_tasks().size());
433 EXPECT_FALSE(completed_tasks()[0].canceled);
434 EXPECT_FALSE(completed_tasks()[1].canceled);
437 TEST_P(TileTaskWorkerPoolTest, ScheduleEmptyStillTriggersCallback) {
438 // Don't append any tasks, just call ScheduleTasks.
439 ScheduleTasks();
441 EXPECT_FALSE(completed_task_sets_[REQUIRED_FOR_ACTIVATION]);
442 EXPECT_FALSE(completed_task_sets_[REQUIRED_FOR_DRAW]);
443 EXPECT_FALSE(completed_task_sets_[ALL]);
445 RunMessageLoopUntilAllTasksHaveCompleted();
447 EXPECT_TRUE(completed_task_sets_[REQUIRED_FOR_ACTIVATION]);
448 EXPECT_TRUE(completed_task_sets_[REQUIRED_FOR_DRAW]);
449 EXPECT_TRUE(completed_task_sets_[ALL]);
452 INSTANTIATE_TEST_CASE_P(
453 TileTaskWorkerPoolTests,
454 TileTaskWorkerPoolTest,
455 ::testing::Values(TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER,
456 TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY,
457 TILE_TASK_WORKER_POOL_TYPE_ONE_COPY,
458 TILE_TASK_WORKER_POOL_TYPE_GPU,
459 TILE_TASK_WORKER_POOL_TYPE_BITMAP));
461 } // namespace
462 } // namespace cc