Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / cc / resources / tile_task_worker_pool_unittest.cc
blobc581e974d0e3333259316a2f1f2fa4ea0327038a
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_task_graph_runner.h"
31 #include "cc/test/test_web_graphics_context_3d.h"
32 #include "gpu/GLES2/gl2extchromium.h"
33 #include "testing/gtest/include/gtest/gtest.h"
35 namespace cc {
36 namespace {
38 const size_t kMaxTransferBufferUsageBytes = 10000U;
39 // A resource of this dimension^2 * 4 must be greater than the above transfer
40 // buffer constant.
41 const size_t kLargeResourceDimension = 1000U;
43 enum TileTaskWorkerPoolType {
44 TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER,
45 TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY,
46 TILE_TASK_WORKER_POOL_TYPE_ONE_COPY,
47 TILE_TASK_WORKER_POOL_TYPE_GPU,
48 TILE_TASK_WORKER_POOL_TYPE_BITMAP
51 class TestRasterTaskImpl : public RasterTask {
52 public:
53 typedef base::Callback<void(const RasterSource::SolidColorAnalysis& analysis,
54 bool was_canceled)> Reply;
56 TestRasterTaskImpl(const Resource* resource,
57 const Reply& reply,
58 ImageDecodeTask::Vector* dependencies)
59 : RasterTask(resource, dependencies),
60 reply_(reply),
61 picture_pile_(FakePicturePileImpl::CreateEmptyPile(gfx::Size(1, 1),
62 gfx::Size(1, 1))) {}
64 // Overridden from Task:
65 void RunOnWorkerThread() override {
66 raster_buffer_->Playback(picture_pile_.get(), gfx::Rect(0, 0, 1, 1), 1.0);
69 // Overridden from TileTask:
70 void ScheduleOnOriginThread(TileTaskClient* client) override {
71 raster_buffer_ = client->AcquireBufferForRaster(resource());
73 void CompleteOnOriginThread(TileTaskClient* client) override {
74 client->ReleaseBufferForRaster(raster_buffer_.Pass());
76 void RunReplyOnOriginThread() override {
77 reply_.Run(RasterSource::SolidColorAnalysis(), !HasFinishedRunning());
80 protected:
81 ~TestRasterTaskImpl() override {}
83 private:
84 const Reply reply_;
85 scoped_ptr<RasterBuffer> raster_buffer_;
86 scoped_refptr<PicturePileImpl> picture_pile_;
88 DISALLOW_COPY_AND_ASSIGN(TestRasterTaskImpl);
91 class BlockingTestRasterTaskImpl : public TestRasterTaskImpl {
92 public:
93 BlockingTestRasterTaskImpl(const Resource* resource,
94 const Reply& reply,
95 base::Lock* lock,
96 ImageDecodeTask::Vector* dependencies)
97 : TestRasterTaskImpl(resource, reply, dependencies), lock_(lock) {}
99 // Overridden from Task:
100 void RunOnWorkerThread() override {
101 base::AutoLock lock(*lock_);
102 TestRasterTaskImpl::RunOnWorkerThread();
105 // Overridden from TileTask:
106 void RunReplyOnOriginThread() override {}
108 protected:
109 ~BlockingTestRasterTaskImpl() override {}
111 private:
112 base::Lock* lock_;
114 DISALLOW_COPY_AND_ASSIGN(BlockingTestRasterTaskImpl);
117 class TileTaskWorkerPoolTest
118 : public testing::TestWithParam<TileTaskWorkerPoolType>,
119 public TileTaskRunnerClient {
120 public:
121 struct RasterTaskResult {
122 unsigned id;
123 bool canceled;
126 typedef std::vector<scoped_refptr<RasterTask>> RasterTaskVector;
128 enum NamedTaskSet { REQUIRED_FOR_ACTIVATION, REQUIRED_FOR_DRAW, ALL };
130 TileTaskWorkerPoolTest()
131 : context_provider_(TestContextProvider::Create()),
132 worker_context_provider_(TestContextProvider::Create()),
133 all_tile_tasks_finished_(
134 base::MessageLoopProxy::current().get(),
135 base::Bind(&TileTaskWorkerPoolTest::AllTileTasksFinished,
136 base::Unretained(this))),
137 timeout_seconds_(5),
138 timed_out_(false) {}
140 // Overridden from testing::Test:
141 void SetUp() override {
142 switch (GetParam()) {
143 case TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER:
144 Create3dOutputSurfaceAndResourceProvider();
145 tile_task_worker_pool_ = PixelBufferTileTaskWorkerPool::Create(
146 base::MessageLoopProxy::current().get(), &task_graph_runner_,
147 context_provider_.get(), resource_provider_.get(),
148 kMaxTransferBufferUsageBytes);
149 break;
150 case TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY:
151 Create3dOutputSurfaceAndResourceProvider();
152 tile_task_worker_pool_ = ZeroCopyTileTaskWorkerPool::Create(
153 base::MessageLoopProxy::current().get(), &task_graph_runner_,
154 resource_provider_.get());
155 break;
156 case TILE_TASK_WORKER_POOL_TYPE_ONE_COPY:
157 Create3dOutputSurfaceAndResourceProvider();
158 staging_resource_pool_ = ResourcePool::Create(resource_provider_.get(),
159 GL_TEXTURE_2D);
160 tile_task_worker_pool_ = OneCopyTileTaskWorkerPool::Create(
161 base::MessageLoopProxy::current().get(), &task_graph_runner_,
162 context_provider_.get(), resource_provider_.get(),
163 staging_resource_pool_.get());
164 break;
165 case TILE_TASK_WORKER_POOL_TYPE_GPU:
166 Create3dOutputSurfaceAndResourceProvider();
167 tile_task_worker_pool_ = GpuTileTaskWorkerPool::Create(
168 base::MessageLoopProxy::current().get(), &task_graph_runner_,
169 context_provider_.get(), resource_provider_.get(), false, 0);
170 break;
171 case TILE_TASK_WORKER_POOL_TYPE_BITMAP:
172 CreateSoftwareOutputSurfaceAndResourceProvider();
173 tile_task_worker_pool_ = BitmapTileTaskWorkerPool::Create(
174 base::MessageLoopProxy::current().get(), &task_graph_runner_,
175 resource_provider_.get());
176 break;
179 DCHECK(tile_task_worker_pool_);
180 tile_task_worker_pool_->AsTileTaskRunner()->SetClient(this);
183 void TearDown() override {
184 tile_task_worker_pool_->AsTileTaskRunner()->Shutdown();
185 tile_task_worker_pool_->AsTileTaskRunner()->CheckForCompletedTasks();
188 void AllTileTasksFinished() {
189 tile_task_worker_pool_->AsTileTaskRunner()->CheckForCompletedTasks();
190 base::MessageLoop::current()->Quit();
193 // Overriden from TileTaskWorkerPoolClient:
194 void DidFinishRunningTileTasks(TaskSet task_set) override {
195 EXPECT_FALSE(completed_task_sets_[task_set]);
196 completed_task_sets_[task_set] = true;
197 if (task_set == ALL) {
198 EXPECT_TRUE((~completed_task_sets_).none());
199 all_tile_tasks_finished_.Schedule();
203 TaskSetCollection TasksThatShouldBeForcedToComplete() const override {
204 return TaskSetCollection();
207 void RunMessageLoopUntilAllTasksHaveCompleted() {
208 if (timeout_seconds_) {
209 timeout_.Reset(base::Bind(&TileTaskWorkerPoolTest::OnTimeout,
210 base::Unretained(this)));
211 base::MessageLoopProxy::current()->PostDelayedTask(
212 FROM_HERE, timeout_.callback(),
213 base::TimeDelta::FromSeconds(timeout_seconds_));
216 base::MessageLoop::current()->Run();
218 timeout_.Cancel();
220 ASSERT_FALSE(timed_out_) << "Test timed out";
223 void ScheduleTasks() {
224 TileTaskQueue queue;
226 for (RasterTaskVector::const_iterator it = tasks_.begin();
227 it != tasks_.end(); ++it) {
228 TaskSetCollection task_sets;
229 task_sets[REQUIRED_FOR_ACTIVATION] = true;
230 task_sets[REQUIRED_FOR_DRAW] = true;
231 task_sets[ALL] = true;
232 queue.items.push_back(TileTaskQueue::Item(it->get(), task_sets));
235 completed_task_sets_.reset();
236 tile_task_worker_pool_->AsTileTaskRunner()->ScheduleTasks(&queue);
239 void AppendTask(unsigned id, const gfx::Size& size) {
240 scoped_ptr<ScopedResource> resource(
241 ScopedResource::Create(resource_provider_.get()));
242 resource->Allocate(size, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
243 RGBA_8888);
244 const Resource* const_resource = resource.get();
246 ImageDecodeTask::Vector empty;
247 tasks_.push_back(new TestRasterTaskImpl(
248 const_resource,
249 base::Bind(&TileTaskWorkerPoolTest::OnTaskCompleted,
250 base::Unretained(this), base::Passed(&resource), id),
251 &empty));
254 void AppendTask(unsigned id) { AppendTask(id, gfx::Size(1, 1)); }
256 void AppendBlockingTask(unsigned id, base::Lock* lock) {
257 const gfx::Size size(1, 1);
259 scoped_ptr<ScopedResource> resource(
260 ScopedResource::Create(resource_provider_.get()));
261 resource->Allocate(size, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
262 RGBA_8888);
263 const Resource* const_resource = resource.get();
265 ImageDecodeTask::Vector empty;
266 tasks_.push_back(new BlockingTestRasterTaskImpl(
267 const_resource,
268 base::Bind(&TileTaskWorkerPoolTest::OnTaskCompleted,
269 base::Unretained(this), base::Passed(&resource), id),
270 lock, &empty));
273 const std::vector<RasterTaskResult>& completed_tasks() const {
274 return completed_tasks_;
277 void LoseContext(ContextProvider* context_provider) {
278 if (!context_provider)
279 return;
280 context_provider->ContextGL()->LoseContextCHROMIUM(
281 GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB);
282 context_provider->ContextGL()->Flush();
285 private:
286 void Create3dOutputSurfaceAndResourceProvider() {
287 output_surface_ = FakeOutputSurface::Create3d(
288 context_provider_, worker_context_provider_).Pass();
289 CHECK(output_surface_->BindToClient(&output_surface_client_));
290 TestWebGraphicsContext3D* context3d = context_provider_->TestContext3d();
291 context3d->set_support_sync_query(true);
292 resource_provider_ = ResourceProvider::Create(output_surface_.get(), NULL,
293 &gpu_memory_buffer_manager_,
294 NULL, 0, false, 1).Pass();
297 void CreateSoftwareOutputSurfaceAndResourceProvider() {
298 output_surface_ = FakeOutputSurface::CreateSoftware(
299 make_scoped_ptr(new SoftwareOutputDevice));
300 CHECK(output_surface_->BindToClient(&output_surface_client_));
301 resource_provider_ =
302 ResourceProvider::Create(output_surface_.get(), &shared_bitmap_manager_,
303 NULL, NULL, 0, false, 1).Pass();
306 void OnTaskCompleted(scoped_ptr<ScopedResource> resource,
307 unsigned id,
308 const RasterSource::SolidColorAnalysis& analysis,
309 bool was_canceled) {
310 RasterTaskResult result;
311 result.id = id;
312 result.canceled = was_canceled;
313 completed_tasks_.push_back(result);
316 void OnTimeout() {
317 timed_out_ = true;
318 base::MessageLoop::current()->Quit();
321 protected:
322 scoped_refptr<TestContextProvider> context_provider_;
323 scoped_refptr<TestContextProvider> worker_context_provider_;
324 FakeOutputSurfaceClient output_surface_client_;
325 scoped_ptr<FakeOutputSurface> output_surface_;
326 scoped_ptr<ResourceProvider> resource_provider_;
327 scoped_ptr<ResourcePool> staging_resource_pool_;
328 scoped_ptr<TileTaskWorkerPool> tile_task_worker_pool_;
329 TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
330 TestSharedBitmapManager shared_bitmap_manager_;
331 TestTaskGraphRunner task_graph_runner_;
332 base::CancelableClosure timeout_;
333 UniqueNotifier all_tile_tasks_finished_;
334 int timeout_seconds_;
335 bool timed_out_;
336 RasterTaskVector tasks_;
337 std::vector<RasterTaskResult> completed_tasks_;
338 TaskSetCollection completed_task_sets_;
341 TEST_P(TileTaskWorkerPoolTest, Basic) {
342 AppendTask(0u);
343 AppendTask(1u);
344 ScheduleTasks();
346 RunMessageLoopUntilAllTasksHaveCompleted();
348 ASSERT_EQ(2u, completed_tasks().size());
349 EXPECT_FALSE(completed_tasks()[0].canceled);
350 EXPECT_FALSE(completed_tasks()[1].canceled);
353 TEST_P(TileTaskWorkerPoolTest, FailedMapResource) {
354 if (GetParam() == TILE_TASK_WORKER_POOL_TYPE_BITMAP)
355 return;
357 TestWebGraphicsContext3D* context3d = context_provider_->TestContext3d();
358 context3d->set_times_map_buffer_chromium_succeeds(0);
359 AppendTask(0u);
360 ScheduleTasks();
362 RunMessageLoopUntilAllTasksHaveCompleted();
364 ASSERT_EQ(1u, completed_tasks().size());
365 EXPECT_FALSE(completed_tasks()[0].canceled);
368 // This test checks that replacing a pending raster task with another does
369 // not prevent the DidFinishRunningTileTasks notification from being sent.
370 TEST_P(TileTaskWorkerPoolTest, FalseThrottling) {
371 base::Lock lock;
373 // Schedule a task that is prevented from completing with a lock.
374 lock.Acquire();
375 AppendBlockingTask(0u, &lock);
376 ScheduleTasks();
378 // Schedule another task to replace the still-pending task. Because the old
379 // task is not a throttled task in the new task set, it should not prevent
380 // DidFinishRunningTileTasks from getting signaled.
381 RasterTaskVector tasks;
382 tasks.swap(tasks_);
383 AppendTask(1u);
384 ScheduleTasks();
386 // Unblock the first task to allow the second task to complete.
387 lock.Release();
389 RunMessageLoopUntilAllTasksHaveCompleted();
392 TEST_P(TileTaskWorkerPoolTest, LargeResources) {
393 gfx::Size size(kLargeResourceDimension, kLargeResourceDimension);
396 // Verify a resource of this size is larger than the transfer buffer.
397 scoped_ptr<ScopedResource> resource(
398 ScopedResource::Create(resource_provider_.get()));
399 resource->Allocate(size, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
400 RGBA_8888);
401 EXPECT_GE(resource->bytes(), kMaxTransferBufferUsageBytes);
404 AppendTask(0u, size);
405 AppendTask(1u, size);
406 AppendTask(2u, size);
407 ScheduleTasks();
409 // This will time out if a resource that is larger than the throttle limit
410 // never gets scheduled.
411 RunMessageLoopUntilAllTasksHaveCompleted();
414 TEST_P(TileTaskWorkerPoolTest, LostContext) {
415 LoseContext(output_surface_->context_provider());
416 LoseContext(output_surface_->worker_context_provider());
418 AppendTask(0u);
419 AppendTask(1u);
420 ScheduleTasks();
422 RunMessageLoopUntilAllTasksHaveCompleted();
424 ASSERT_EQ(2u, completed_tasks().size());
425 EXPECT_FALSE(completed_tasks()[0].canceled);
426 EXPECT_FALSE(completed_tasks()[1].canceled);
429 INSTANTIATE_TEST_CASE_P(
430 TileTaskWorkerPoolTests,
431 TileTaskWorkerPoolTest,
432 ::testing::Values(TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER,
433 TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY,
434 TILE_TASK_WORKER_POOL_TYPE_ONE_COPY,
435 TILE_TASK_WORKER_POOL_TYPE_GPU,
436 TILE_TASK_WORKER_POOL_TYPE_BITMAP));
438 } // namespace
439 } // namespace cc