Add ICU message format support
[chromium-blink-merge.git] / cc / raster / tile_task_worker_pool_unittest.cc
blob6038b00e89bdb1d543ca64f72643fa0f5fe6e0fa
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;
45 // A resource of this dimension^2 * 4 must be greater than the above transfer
46 // buffer constant.
47 const size_t kLargeResourceDimension = 1000U;
49 enum TileTaskWorkerPoolType {
50 TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER,
51 TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY,
52 TILE_TASK_WORKER_POOL_TYPE_ONE_COPY,
53 TILE_TASK_WORKER_POOL_TYPE_GPU,
54 TILE_TASK_WORKER_POOL_TYPE_BITMAP
57 class TestRasterTaskImpl : public RasterTask {
58 public:
59 typedef base::Callback<void(const RasterSource::SolidColorAnalysis& analysis,
60 bool was_canceled)> Reply;
62 TestRasterTaskImpl(const Resource* resource,
63 const Reply& reply,
64 ImageDecodeTask::Vector* dependencies)
65 : RasterTask(resource, dependencies),
66 reply_(reply),
67 picture_pile_(FakePicturePileImpl::CreateEmptyPile(gfx::Size(1, 1),
68 gfx::Size(1, 1))) {}
70 // Overridden from Task:
71 void RunOnWorkerThread() override {
72 uint64_t new_content_id = 0;
73 raster_buffer_->Playback(picture_pile_.get(), gfx::Rect(1, 1),
74 gfx::Rect(1, 1), new_content_id, 1.f, true);
77 // Overridden from TileTask:
78 void ScheduleOnOriginThread(TileTaskClient* client) override {
79 // The raster buffer has no tile ids associated with it for partial update,
80 // so doesn't need to provide a valid dirty rect.
81 raster_buffer_ = client->AcquireBufferForRaster(resource(), 0, 0);
83 void CompleteOnOriginThread(TileTaskClient* client) override {
84 client->ReleaseBufferForRaster(raster_buffer_.Pass());
86 void RunReplyOnOriginThread() override {
87 reply_.Run(RasterSource::SolidColorAnalysis(), !HasFinishedRunning());
90 protected:
91 ~TestRasterTaskImpl() override {}
93 private:
94 const Reply reply_;
95 scoped_ptr<RasterBuffer> raster_buffer_;
96 scoped_refptr<PicturePileImpl> picture_pile_;
98 DISALLOW_COPY_AND_ASSIGN(TestRasterTaskImpl);
101 class BlockingTestRasterTaskImpl : public TestRasterTaskImpl {
102 public:
103 BlockingTestRasterTaskImpl(const Resource* resource,
104 const Reply& reply,
105 base::Lock* lock,
106 ImageDecodeTask::Vector* dependencies)
107 : TestRasterTaskImpl(resource, reply, dependencies), lock_(lock) {}
109 // Overridden from Task:
110 void RunOnWorkerThread() override {
111 base::AutoLock lock(*lock_);
112 TestRasterTaskImpl::RunOnWorkerThread();
115 // Overridden from TileTask:
116 void RunReplyOnOriginThread() override {}
118 protected:
119 ~BlockingTestRasterTaskImpl() override {}
121 private:
122 base::Lock* lock_;
124 DISALLOW_COPY_AND_ASSIGN(BlockingTestRasterTaskImpl);
127 class TileTaskWorkerPoolTest
128 : public testing::TestWithParam<TileTaskWorkerPoolType>,
129 public TileTaskRunnerClient {
130 public:
131 struct RasterTaskResult {
132 unsigned id;
133 bool canceled;
136 typedef std::vector<scoped_refptr<RasterTask>> RasterTaskVector;
138 enum NamedTaskSet { REQUIRED_FOR_ACTIVATION, REQUIRED_FOR_DRAW, ALL };
140 TileTaskWorkerPoolTest()
141 : context_provider_(TestContextProvider::Create()),
142 worker_context_provider_(TestContextProvider::Create()),
143 all_tile_tasks_finished_(
144 base::ThreadTaskRunnerHandle::Get().get(),
145 base::Bind(&TileTaskWorkerPoolTest::AllTileTasksFinished,
146 base::Unretained(this))),
147 timeout_seconds_(5),
148 timed_out_(false) {}
150 // Overridden from testing::Test:
151 void SetUp() override {
152 switch (GetParam()) {
153 case TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER:
154 Create3dOutputSurfaceAndResourceProvider();
155 tile_task_worker_pool_ = PixelBufferTileTaskWorkerPool::Create(
156 base::ThreadTaskRunnerHandle::Get().get(), &task_graph_runner_,
157 context_provider_.get(), resource_provider_.get(),
158 kMaxTransferBufferUsageBytes);
159 break;
160 case TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY:
161 Create3dOutputSurfaceAndResourceProvider();
162 tile_task_worker_pool_ = ZeroCopyTileTaskWorkerPool::Create(
163 base::ThreadTaskRunnerHandle::Get().get(), &task_graph_runner_,
164 resource_provider_.get());
165 break;
166 case TILE_TASK_WORKER_POOL_TYPE_ONE_COPY:
167 Create3dOutputSurfaceAndResourceProvider();
168 staging_resource_pool_ = ResourcePool::Create(resource_provider_.get(),
169 GL_TEXTURE_2D);
170 tile_task_worker_pool_ = OneCopyTileTaskWorkerPool::Create(
171 base::ThreadTaskRunnerHandle::Get().get(), &task_graph_runner_,
172 context_provider_.get(), resource_provider_.get(),
173 staging_resource_pool_.get(), kMaxBytesPerCopyOperation, false);
174 break;
175 case TILE_TASK_WORKER_POOL_TYPE_GPU:
176 Create3dOutputSurfaceAndResourceProvider();
177 tile_task_worker_pool_ = GpuTileTaskWorkerPool::Create(
178 base::ThreadTaskRunnerHandle::Get().get(), &task_graph_runner_,
179 context_provider_.get(), resource_provider_.get(), false, 0);
180 break;
181 case TILE_TASK_WORKER_POOL_TYPE_BITMAP:
182 CreateSoftwareOutputSurfaceAndResourceProvider();
183 tile_task_worker_pool_ = BitmapTileTaskWorkerPool::Create(
184 base::ThreadTaskRunnerHandle::Get().get(), &task_graph_runner_,
185 resource_provider_.get());
186 break;
189 DCHECK(tile_task_worker_pool_);
190 tile_task_worker_pool_->AsTileTaskRunner()->SetClient(this);
193 void TearDown() override {
194 tile_task_worker_pool_->AsTileTaskRunner()->Shutdown();
195 tile_task_worker_pool_->AsTileTaskRunner()->CheckForCompletedTasks();
198 void AllTileTasksFinished() {
199 tile_task_worker_pool_->AsTileTaskRunner()->CheckForCompletedTasks();
200 base::MessageLoop::current()->Quit();
203 // Overriden from TileTaskWorkerPoolClient:
204 void DidFinishRunningTileTasks(TaskSet task_set) override {
205 EXPECT_FALSE(completed_task_sets_[task_set]);
206 completed_task_sets_[task_set] = true;
207 if (task_set == ALL) {
208 EXPECT_TRUE((~completed_task_sets_).none());
209 all_tile_tasks_finished_.Schedule();
213 TaskSetCollection TasksThatShouldBeForcedToComplete() const override {
214 return TaskSetCollection();
217 void RunMessageLoopUntilAllTasksHaveCompleted() {
218 if (timeout_seconds_) {
219 timeout_.Reset(base::Bind(&TileTaskWorkerPoolTest::OnTimeout,
220 base::Unretained(this)));
221 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
222 FROM_HERE, timeout_.callback(),
223 base::TimeDelta::FromSeconds(timeout_seconds_));
226 base::MessageLoop::current()->Run();
228 timeout_.Cancel();
230 ASSERT_FALSE(timed_out_) << "Test timed out";
233 void ScheduleTasks() {
234 TileTaskQueue queue;
236 for (RasterTaskVector::const_iterator it = tasks_.begin();
237 it != tasks_.end(); ++it) {
238 TaskSetCollection task_sets;
239 task_sets[REQUIRED_FOR_ACTIVATION] = true;
240 task_sets[REQUIRED_FOR_DRAW] = true;
241 task_sets[ALL] = true;
242 queue.items.push_back(TileTaskQueue::Item(it->get(), task_sets));
245 completed_task_sets_.reset();
246 tile_task_worker_pool_->AsTileTaskRunner()->ScheduleTasks(&queue);
249 void AppendTask(unsigned id, const gfx::Size& size) {
250 scoped_ptr<ScopedResource> resource(
251 ScopedResource::Create(resource_provider_.get()));
252 resource->Allocate(size, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
253 RGBA_8888);
254 const Resource* const_resource = resource.get();
256 ImageDecodeTask::Vector empty;
257 tasks_.push_back(new TestRasterTaskImpl(
258 const_resource,
259 base::Bind(&TileTaskWorkerPoolTest::OnTaskCompleted,
260 base::Unretained(this), base::Passed(&resource), id),
261 &empty));
264 void AppendTask(unsigned id) { AppendTask(id, gfx::Size(1, 1)); }
266 void AppendBlockingTask(unsigned id, base::Lock* lock) {
267 const gfx::Size size(1, 1);
269 scoped_ptr<ScopedResource> resource(
270 ScopedResource::Create(resource_provider_.get()));
271 resource->Allocate(size, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
272 RGBA_8888);
273 const Resource* const_resource = resource.get();
275 ImageDecodeTask::Vector empty;
276 tasks_.push_back(new BlockingTestRasterTaskImpl(
277 const_resource,
278 base::Bind(&TileTaskWorkerPoolTest::OnTaskCompleted,
279 base::Unretained(this), base::Passed(&resource), id),
280 lock, &empty));
283 const std::vector<RasterTaskResult>& completed_tasks() const {
284 return completed_tasks_;
287 void LoseContext(ContextProvider* context_provider) {
288 if (!context_provider)
289 return;
290 context_provider->ContextGL()->LoseContextCHROMIUM(
291 GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB);
292 context_provider->ContextGL()->Flush();
295 private:
296 void Create3dOutputSurfaceAndResourceProvider() {
297 output_surface_ = FakeOutputSurface::Create3d(context_provider_,
298 worker_context_provider_);
299 CHECK(output_surface_->BindToClient(&output_surface_client_));
300 TestWebGraphicsContext3D* context3d = context_provider_->TestContext3d();
301 context3d->set_support_sync_query(true);
302 resource_provider_ = FakeResourceProvider::Create(
303 output_surface_.get(), nullptr, &gpu_memory_buffer_manager_);
306 void CreateSoftwareOutputSurfaceAndResourceProvider() {
307 output_surface_ = FakeOutputSurface::CreateSoftware(
308 make_scoped_ptr(new SoftwareOutputDevice));
309 CHECK(output_surface_->BindToClient(&output_surface_client_));
310 resource_provider_ = FakeResourceProvider::Create(
311 output_surface_.get(), &shared_bitmap_manager_, nullptr);
314 void OnTaskCompleted(scoped_ptr<ScopedResource> resource,
315 unsigned id,
316 const RasterSource::SolidColorAnalysis& analysis,
317 bool was_canceled) {
318 RasterTaskResult result;
319 result.id = id;
320 result.canceled = was_canceled;
321 completed_tasks_.push_back(result);
324 void OnTimeout() {
325 timed_out_ = true;
326 base::MessageLoop::current()->Quit();
329 protected:
330 scoped_refptr<TestContextProvider> context_provider_;
331 scoped_refptr<TestContextProvider> worker_context_provider_;
332 FakeOutputSurfaceClient output_surface_client_;
333 scoped_ptr<FakeOutputSurface> output_surface_;
334 scoped_ptr<ResourceProvider> resource_provider_;
335 scoped_ptr<ResourcePool> staging_resource_pool_;
336 scoped_ptr<TileTaskWorkerPool> tile_task_worker_pool_;
337 TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
338 TestSharedBitmapManager shared_bitmap_manager_;
339 TestTaskGraphRunner task_graph_runner_;
340 base::CancelableClosure timeout_;
341 UniqueNotifier all_tile_tasks_finished_;
342 int timeout_seconds_;
343 bool timed_out_;
344 RasterTaskVector tasks_;
345 std::vector<RasterTaskResult> completed_tasks_;
346 TaskSetCollection completed_task_sets_;
349 TEST_P(TileTaskWorkerPoolTest, Basic) {
350 AppendTask(0u);
351 AppendTask(1u);
352 ScheduleTasks();
354 RunMessageLoopUntilAllTasksHaveCompleted();
356 ASSERT_EQ(2u, completed_tasks().size());
357 EXPECT_FALSE(completed_tasks()[0].canceled);
358 EXPECT_FALSE(completed_tasks()[1].canceled);
361 TEST_P(TileTaskWorkerPoolTest, FailedMapResource) {
362 if (GetParam() == TILE_TASK_WORKER_POOL_TYPE_BITMAP)
363 return;
365 TestWebGraphicsContext3D* context3d = context_provider_->TestContext3d();
366 context3d->set_times_map_buffer_chromium_succeeds(0);
367 AppendTask(0u);
368 ScheduleTasks();
370 RunMessageLoopUntilAllTasksHaveCompleted();
372 ASSERT_EQ(1u, completed_tasks().size());
373 EXPECT_FALSE(completed_tasks()[0].canceled);
376 // This test checks that replacing a pending raster task with another does
377 // not prevent the DidFinishRunningTileTasks notification from being sent.
378 TEST_P(TileTaskWorkerPoolTest, FalseThrottling) {
379 base::Lock lock;
381 // Schedule a task that is prevented from completing with a lock.
382 lock.Acquire();
383 AppendBlockingTask(0u, &lock);
384 ScheduleTasks();
386 // Schedule another task to replace the still-pending task. Because the old
387 // task is not a throttled task in the new task set, it should not prevent
388 // DidFinishRunningTileTasks from getting signaled.
389 RasterTaskVector tasks;
390 tasks.swap(tasks_);
391 AppendTask(1u);
392 ScheduleTasks();
394 // Unblock the first task to allow the second task to complete.
395 lock.Release();
397 RunMessageLoopUntilAllTasksHaveCompleted();
400 TEST_P(TileTaskWorkerPoolTest, LargeResources) {
401 gfx::Size size(kLargeResourceDimension, kLargeResourceDimension);
404 // Verify a resource of this size is larger than the transfer buffer.
405 scoped_ptr<ScopedResource> resource(
406 ScopedResource::Create(resource_provider_.get()));
407 resource->Allocate(size, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
408 RGBA_8888);
409 EXPECT_GE(ResourceUtil::UncheckedSizeInBytes<size_t>(resource->size(),
410 resource->format()),
411 kMaxTransferBufferUsageBytes);
414 AppendTask(0u, size);
415 AppendTask(1u, size);
416 AppendTask(2u, size);
417 ScheduleTasks();
419 // This will time out if a resource that is larger than the throttle limit
420 // never gets scheduled.
421 RunMessageLoopUntilAllTasksHaveCompleted();
424 TEST_P(TileTaskWorkerPoolTest, LostContext) {
425 LoseContext(output_surface_->context_provider());
426 LoseContext(output_surface_->worker_context_provider());
428 AppendTask(0u);
429 AppendTask(1u);
430 ScheduleTasks();
432 RunMessageLoopUntilAllTasksHaveCompleted();
434 ASSERT_EQ(2u, completed_tasks().size());
435 EXPECT_FALSE(completed_tasks()[0].canceled);
436 EXPECT_FALSE(completed_tasks()[1].canceled);
439 TEST_P(TileTaskWorkerPoolTest, ScheduleEmptyStillTriggersCallback) {
440 // Don't append any tasks, just call ScheduleTasks.
441 ScheduleTasks();
443 EXPECT_FALSE(completed_task_sets_[REQUIRED_FOR_ACTIVATION]);
444 EXPECT_FALSE(completed_task_sets_[REQUIRED_FOR_DRAW]);
445 EXPECT_FALSE(completed_task_sets_[ALL]);
447 RunMessageLoopUntilAllTasksHaveCompleted();
449 EXPECT_TRUE(completed_task_sets_[REQUIRED_FOR_ACTIVATION]);
450 EXPECT_TRUE(completed_task_sets_[REQUIRED_FOR_DRAW]);
451 EXPECT_TRUE(completed_task_sets_[ALL]);
454 INSTANTIATE_TEST_CASE_P(
455 TileTaskWorkerPoolTests,
456 TileTaskWorkerPoolTest,
457 ::testing::Values(TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER,
458 TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY,
459 TILE_TASK_WORKER_POOL_TYPE_ONE_COPY,
460 TILE_TASK_WORKER_POOL_TYPE_GPU,
461 TILE_TASK_WORKER_POOL_TYPE_BITMAP));
463 } // namespace
464 } // namespace cc