Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / cc / resources / raster_worker_pool_unittest.cc
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.
4
5 #include "cc/resources/raster_worker_pool.h"
6
7 #include <limits>
8 #include <vector>
9
10 #include "base/cancelable_callback.h"
11 #include "cc/resources/bitmap_raster_worker_pool.h"
12 #include "cc/resources/gpu_raster_worker_pool.h"
13 #include "cc/resources/one_copy_raster_worker_pool.h"
14 #include "cc/resources/picture_pile.h"
15 #include "cc/resources/picture_pile_impl.h"
16 #include "cc/resources/pixel_buffer_raster_worker_pool.h"
17 #include "cc/resources/raster_buffer.h"
18 #include "cc/resources/rasterizer.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/zero_copy_raster_worker_pool.h"
23 #include "cc/test/fake_output_surface.h"
24 #include "cc/test/fake_output_surface_client.h"
25 #include "cc/test/fake_picture_pile_impl.h"
26 #include "cc/test/test_gpu_memory_buffer_manager.h"
27 #include "cc/test/test_shared_bitmap_manager.h"
28 #include "cc/test/test_web_graphics_context_3d.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30
31 namespace cc {
32 namespace {
33
34 const size_t kMaxTransferBufferUsageBytes = 10000U;
35 // A resource of this dimension^2 * 4 must be greater than the above transfer
36 // buffer constant.
37 const size_t kLargeResourceDimension = 1000U;
38
39 enum RasterWorkerPoolType {
40   RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER,
41   RASTER_WORKER_POOL_TYPE_ZERO_COPY,
42   RASTER_WORKER_POOL_TYPE_ONE_COPY,
43   RASTER_WORKER_POOL_TYPE_GPU,
44   RASTER_WORKER_POOL_TYPE_BITMAP
45 };
46
47 class TestRasterTaskImpl : public RasterTask {
48  public:
49   typedef base::Callback<void(const RasterSource::SolidColorAnalysis& analysis,
50                               bool was_canceled)> Reply;
51
52   TestRasterTaskImpl(const Resource* resource,
53                      const Reply& reply,
54                      ImageDecodeTask::Vector* dependencies)
55       : RasterTask(resource, dependencies),
56         reply_(reply),
57         picture_pile_(FakePicturePileImpl::CreateEmptyPile(gfx::Size(1, 1),
58                                                            gfx::Size(1, 1))) {}
59
60   // Overridden from Task:
61   void RunOnWorkerThread() override {
62     raster_buffer_->Playback(picture_pile_.get(), gfx::Rect(0, 0, 1, 1), 1.0);
63   }
64
65   // Overridden from RasterizerTask:
66   void ScheduleOnOriginThread(RasterizerTaskClient* client) override {
67     raster_buffer_ = client->AcquireBufferForRaster(resource());
68   }
69   void CompleteOnOriginThread(RasterizerTaskClient* client) override {
70     client->ReleaseBufferForRaster(raster_buffer_.Pass());
71   }
72   void RunReplyOnOriginThread() override {
73     reply_.Run(RasterSource::SolidColorAnalysis(), !HasFinishedRunning());
74   }
75
76  protected:
77   ~TestRasterTaskImpl() override {}
78
79  private:
80   const Reply reply_;
81   scoped_ptr<RasterBuffer> raster_buffer_;
82   scoped_refptr<PicturePileImpl> picture_pile_;
83
84   DISALLOW_COPY_AND_ASSIGN(TestRasterTaskImpl);
85 };
86
87 class BlockingTestRasterTaskImpl : public TestRasterTaskImpl {
88  public:
89   BlockingTestRasterTaskImpl(const Resource* resource,
90                              const Reply& reply,
91                              base::Lock* lock,
92                              ImageDecodeTask::Vector* dependencies)
93       : TestRasterTaskImpl(resource, reply, dependencies), lock_(lock) {}
94
95   // Overridden from Task:
96   void RunOnWorkerThread() override {
97     base::AutoLock lock(*lock_);
98     TestRasterTaskImpl::RunOnWorkerThread();
99   }
100
101   // Overridden from RasterizerTask:
102   void RunReplyOnOriginThread() override {}
103
104  protected:
105   ~BlockingTestRasterTaskImpl() override {}
106
107  private:
108   base::Lock* lock_;
109
110   DISALLOW_COPY_AND_ASSIGN(BlockingTestRasterTaskImpl);
111 };
112
113 class RasterWorkerPoolTest
114     : public testing::TestWithParam<RasterWorkerPoolType>,
115       public RasterizerClient {
116  public:
117   struct RasterTaskResult {
118     unsigned id;
119     bool canceled;
120   };
121
122   typedef std::vector<scoped_refptr<RasterTask>> RasterTaskVector;
123
124   enum NamedTaskSet { REQUIRED_FOR_ACTIVATION = 0, ALL = 1 };
125
126   RasterWorkerPoolTest()
127       : context_provider_(TestContextProvider::Create()),
128         timeout_seconds_(5),
129         timed_out_(false) {}
130
131   // Overridden from testing::Test:
132   virtual void SetUp() override {
133     switch (GetParam()) {
134       case RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER:
135         Create3dOutputSurfaceAndResourceProvider();
136         raster_worker_pool_ = PixelBufferRasterWorkerPool::Create(
137             base::MessageLoopProxy::current().get(),
138             RasterWorkerPool::GetTaskGraphRunner(),
139             context_provider_.get(),
140             resource_provider_.get(),
141             kMaxTransferBufferUsageBytes);
142         break;
143       case RASTER_WORKER_POOL_TYPE_ZERO_COPY:
144         Create3dOutputSurfaceAndResourceProvider();
145         raster_worker_pool_ = ZeroCopyRasterWorkerPool::Create(
146             base::MessageLoopProxy::current().get(),
147             RasterWorkerPool::GetTaskGraphRunner(),
148             resource_provider_.get());
149         break;
150       case RASTER_WORKER_POOL_TYPE_ONE_COPY:
151         Create3dOutputSurfaceAndResourceProvider();
152         staging_resource_pool_ = ResourcePool::Create(
153             resource_provider_.get(), GL_TEXTURE_2D, RGBA_8888);
154         raster_worker_pool_ = OneCopyRasterWorkerPool::Create(
155             base::MessageLoopProxy::current().get(),
156             RasterWorkerPool::GetTaskGraphRunner(),
157             context_provider_.get(),
158             resource_provider_.get(),
159             staging_resource_pool_.get());
160         break;
161       case RASTER_WORKER_POOL_TYPE_GPU:
162         Create3dOutputSurfaceAndResourceProvider();
163         raster_worker_pool_ =
164             GpuRasterWorkerPool::Create(base::MessageLoopProxy::current().get(),
165                                         context_provider_.get(),
166                                         resource_provider_.get(),
167                                         false);
168         break;
169       case RASTER_WORKER_POOL_TYPE_BITMAP:
170         CreateSoftwareOutputSurfaceAndResourceProvider();
171         raster_worker_pool_ = BitmapRasterWorkerPool::Create(
172             base::MessageLoopProxy::current().get(),
173             RasterWorkerPool::GetTaskGraphRunner(),
174             resource_provider_.get());
175         break;
176     }
177
178     DCHECK(raster_worker_pool_);
179     raster_worker_pool_->AsRasterizer()->SetClient(this);
180   }
181
182   virtual void TearDown() override {
183     raster_worker_pool_->AsRasterizer()->Shutdown();
184     raster_worker_pool_->AsRasterizer()->CheckForCompletedTasks();
185   }
186
187   // Overriden from RasterWorkerPoolClient:
188   void DidFinishRunningTasks(TaskSet task_set) override {
189     if (task_set == ALL) {
190       raster_worker_pool_->AsRasterizer()->CheckForCompletedTasks();
191       base::MessageLoop::current()->Quit();
192     }
193   }
194   TaskSetCollection TasksThatShouldBeForcedToComplete() const override {
195     return TaskSetCollection();
196   }
197
198   void RunMessageLoopUntilAllTasksHaveCompleted() {
199     if (timeout_seconds_) {
200       timeout_.Reset(
201           base::Bind(&RasterWorkerPoolTest::OnTimeout, base::Unretained(this)));
202       base::MessageLoopProxy::current()->PostDelayedTask(
203           FROM_HERE,
204           timeout_.callback(),
205           base::TimeDelta::FromSeconds(timeout_seconds_));
206     }
207
208     base::MessageLoop::current()->Run();
209
210     timeout_.Cancel();
211
212     ASSERT_FALSE(timed_out_) << "Test timed out";
213   }
214
215   void ScheduleTasks() {
216     RasterTaskQueue queue;
217
218     for (RasterTaskVector::const_iterator it = tasks_.begin();
219          it != tasks_.end();
220          ++it) {
221       TaskSetCollection task_sets;
222       task_sets[ALL] = true;
223       queue.items.push_back(RasterTaskQueue::Item(it->get(), task_sets));
224     }
225
226     raster_worker_pool_->AsRasterizer()->ScheduleTasks(&queue);
227   }
228
229   void AppendTask(unsigned id, const gfx::Size& size) {
230     scoped_ptr<ScopedResource> resource(
231         ScopedResource::Create(resource_provider_.get()));
232     resource->Allocate(size, ResourceProvider::TextureHintImmutable, RGBA_8888);
233     const Resource* const_resource = resource.get();
234
235     ImageDecodeTask::Vector empty;
236     tasks_.push_back(new TestRasterTaskImpl(
237         const_resource,
238         base::Bind(&RasterWorkerPoolTest::OnTaskCompleted,
239                    base::Unretained(this),
240                    base::Passed(&resource),
241                    id),
242         &empty));
243   }
244
245   void AppendTask(unsigned id) { AppendTask(id, gfx::Size(1, 1)); }
246
247   void AppendBlockingTask(unsigned id, base::Lock* lock) {
248     const gfx::Size size(1, 1);
249
250     scoped_ptr<ScopedResource> resource(
251         ScopedResource::Create(resource_provider_.get()));
252     resource->Allocate(size, ResourceProvider::TextureHintImmutable, RGBA_8888);
253     const Resource* const_resource = resource.get();
254
255     ImageDecodeTask::Vector empty;
256     tasks_.push_back(new BlockingTestRasterTaskImpl(
257         const_resource,
258         base::Bind(&RasterWorkerPoolTest::OnTaskCompleted,
259                    base::Unretained(this),
260                    base::Passed(&resource),
261                    id),
262         lock,
263         &empty));
264   }
265
266   const std::vector<RasterTaskResult>& completed_tasks() const {
267     return completed_tasks_;
268   }
269
270  private:
271   void Create3dOutputSurfaceAndResourceProvider() {
272     output_surface_ = FakeOutputSurface::Create3d(context_provider_).Pass();
273     CHECK(output_surface_->BindToClient(&output_surface_client_));
274     TestWebGraphicsContext3D* context3d = context_provider_->TestContext3d();
275     context3d->set_support_sync_query(true);
276     resource_provider_ = ResourceProvider::Create(output_surface_.get(),
277                                                   NULL,
278                                                   &gpu_memory_buffer_manager_,
279                                                   NULL,
280                                                   0,
281                                                   false,
282                                                   1).Pass();
283   }
284
285   void CreateSoftwareOutputSurfaceAndResourceProvider() {
286     output_surface_ = FakeOutputSurface::CreateSoftware(
287         make_scoped_ptr(new SoftwareOutputDevice));
288     CHECK(output_surface_->BindToClient(&output_surface_client_));
289     resource_provider_ = ResourceProvider::Create(output_surface_.get(),
290                                                   &shared_bitmap_manager_,
291                                                   NULL,
292                                                   NULL,
293                                                   0,
294                                                   false,
295                                                   1).Pass();
296   }
297
298   void OnTaskCompleted(scoped_ptr<ScopedResource> resource,
299                        unsigned id,
300                        const RasterSource::SolidColorAnalysis& analysis,
301                        bool was_canceled) {
302     RasterTaskResult result;
303     result.id = id;
304     result.canceled = was_canceled;
305     completed_tasks_.push_back(result);
306   }
307
308   void OnTimeout() {
309     timed_out_ = true;
310     base::MessageLoop::current()->Quit();
311   }
312
313  protected:
314   scoped_refptr<TestContextProvider> context_provider_;
315   FakeOutputSurfaceClient output_surface_client_;
316   scoped_ptr<FakeOutputSurface> output_surface_;
317   scoped_ptr<ResourceProvider> resource_provider_;
318   scoped_ptr<ResourcePool> staging_resource_pool_;
319   scoped_ptr<RasterWorkerPool> raster_worker_pool_;
320   TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
321   TestSharedBitmapManager shared_bitmap_manager_;
322   base::CancelableClosure timeout_;
323   int timeout_seconds_;
324   bool timed_out_;
325   RasterTaskVector tasks_;
326   std::vector<RasterTaskResult> completed_tasks_;
327 };
328
329 TEST_P(RasterWorkerPoolTest, Basic) {
330   AppendTask(0u);
331   AppendTask(1u);
332   ScheduleTasks();
333
334   RunMessageLoopUntilAllTasksHaveCompleted();
335
336   ASSERT_EQ(2u, completed_tasks().size());
337   EXPECT_FALSE(completed_tasks()[0].canceled);
338   EXPECT_FALSE(completed_tasks()[1].canceled);
339 }
340
341 TEST_P(RasterWorkerPoolTest, FailedMapResource) {
342   if (GetParam() == RASTER_WORKER_POOL_TYPE_BITMAP)
343     return;
344
345   TestWebGraphicsContext3D* context3d = context_provider_->TestContext3d();
346   context3d->set_times_map_buffer_chromium_succeeds(0);
347   AppendTask(0u);
348   ScheduleTasks();
349
350   RunMessageLoopUntilAllTasksHaveCompleted();
351
352   ASSERT_EQ(1u, completed_tasks().size());
353   EXPECT_FALSE(completed_tasks()[0].canceled);
354 }
355
356 // This test checks that replacing a pending raster task with another does
357 // not prevent the DidFinishRunningTasks notification from being sent.
358 TEST_P(RasterWorkerPoolTest, FalseThrottling) {
359   base::Lock lock;
360
361   // Schedule a task that is prevented from completing with a lock.
362   lock.Acquire();
363   AppendBlockingTask(0u, &lock);
364   ScheduleTasks();
365
366   // Schedule another task to replace the still-pending task. Because the old
367   // task is not a throttled task in the new task set, it should not prevent
368   // DidFinishRunningTasks from getting signaled.
369   RasterTaskVector tasks;
370   tasks.swap(tasks_);
371   AppendTask(1u);
372   ScheduleTasks();
373
374   // Unblock the first task to allow the second task to complete.
375   lock.Release();
376
377   RunMessageLoopUntilAllTasksHaveCompleted();
378 }
379
380 TEST_P(RasterWorkerPoolTest, LargeResources) {
381   gfx::Size size(kLargeResourceDimension, kLargeResourceDimension);
382
383   {
384     // Verify a resource of this size is larger than the transfer buffer.
385     scoped_ptr<ScopedResource> resource(
386         ScopedResource::Create(resource_provider_.get()));
387     resource->Allocate(size, ResourceProvider::TextureHintImmutable, RGBA_8888);
388     EXPECT_GE(resource->bytes(), kMaxTransferBufferUsageBytes);
389   }
390
391   AppendTask(0u, size);
392   AppendTask(1u, size);
393   AppendTask(2u, size);
394   ScheduleTasks();
395
396   // This will time out if a resource that is larger than the throttle limit
397   // never gets scheduled.
398   RunMessageLoopUntilAllTasksHaveCompleted();
399 }
400
401 INSTANTIATE_TEST_CASE_P(RasterWorkerPoolTests,
402                         RasterWorkerPoolTest,
403                         ::testing::Values(RASTER_WORKER_POOL_TYPE_PIXEL_BUFFER,
404                                           RASTER_WORKER_POOL_TYPE_ZERO_COPY,
405                                           RASTER_WORKER_POOL_TYPE_ONE_COPY,
406                                           RASTER_WORKER_POOL_TYPE_GPU,
407                                           RASTER_WORKER_POOL_TYPE_BITMAP));
408
409 }  // namespace
410 }  // namespace cc