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