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