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/raster_worker_pool.h"
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"
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
37 class TestRasterTaskImpl
: public RasterTask
{
39 typedef base::Callback
<
40 void(const PicturePileImpl::Analysis
& analysis
, bool was_canceled
)> Reply
;
42 TestRasterTaskImpl(const Resource
* resource
,
44 ImageDecodeTask::Vector
* dependencies
)
45 : RasterTask(resource
, dependencies
), reply_(reply
) {}
47 // Overridden from Task:
48 virtual void RunOnWorkerThread() OVERRIDE
{}
50 // Overridden from RasterizerTask:
51 virtual void ScheduleOnOriginThread(RasterizerTaskClient
* client
) OVERRIDE
{
52 client
->AcquireCanvasForRaster(this);
54 virtual void CompleteOnOriginThread(RasterizerTaskClient
* client
) OVERRIDE
{
55 client
->ReleaseCanvasForRaster(this);
57 virtual void RunReplyOnOriginThread() OVERRIDE
{
58 reply_
.Run(PicturePileImpl::Analysis(), !HasFinishedRunning());
62 virtual ~TestRasterTaskImpl() {}
67 DISALLOW_COPY_AND_ASSIGN(TestRasterTaskImpl
);
70 class BlockingTestRasterTaskImpl
: public TestRasterTaskImpl
{
72 BlockingTestRasterTaskImpl(const Resource
* resource
,
75 ImageDecodeTask::Vector
* dependencies
)
76 : TestRasterTaskImpl(resource
, reply
, dependencies
), lock_(lock
) {}
78 // Overridden from Task:
79 virtual void RunOnWorkerThread() OVERRIDE
{
80 base::AutoLock
lock(*lock_
);
81 TestRasterTaskImpl::RunOnWorkerThread();
84 // Overridden from RasterizerTask:
85 virtual void RunReplyOnOriginThread() OVERRIDE
{}
88 virtual ~BlockingTestRasterTaskImpl() {}
93 DISALLOW_COPY_AND_ASSIGN(BlockingTestRasterTaskImpl
);
96 class RasterWorkerPoolTest
97 : public testing::TestWithParam
<RasterWorkerPoolType
>,
98 public RasterizerClient
{
100 struct RasterTaskResult
{
105 typedef std::vector
<scoped_refptr
<RasterTask
> > RasterTaskVector
;
107 RasterWorkerPoolTest()
108 : context_provider_(TestContextProvider::Create()),
111 output_surface_
= FakeOutputSurface::Create3d(context_provider_
).Pass();
112 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
114 shared_bitmap_manager_
.reset(new TestSharedBitmapManager());
116 ResourceProvider::Create(
117 output_surface_
.get(), shared_bitmap_manager_
.get(), 0, false, 1,
119 staging_resource_pool_
= ResourcePool::Create(
120 resource_provider_
.get(), GL_TEXTURE_2D
, RGBA_8888
);
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());
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());
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());
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());
151 DCHECK(raster_worker_pool_
);
152 raster_worker_pool_
->AsRasterizer()->SetClient(this);
154 virtual ~RasterWorkerPoolTest() {
155 staging_resource_pool_
.reset();
156 resource_provider_
.reset();
159 // Overridden from testing::Test:
160 virtual void TearDown() OVERRIDE
{
161 raster_worker_pool_
->AsRasterizer()->Shutdown();
162 raster_worker_pool_
->AsRasterizer()->CheckForCompletedTasks();
165 // Overriden from RasterWorkerPoolClient:
166 virtual bool ShouldForceTasksRequiredForActivationToComplete() const
170 virtual void DidFinishRunningTasks() OVERRIDE
{
171 raster_worker_pool_
->AsRasterizer()->CheckForCompletedTasks();
172 base::MessageLoop::current()->Quit();
174 virtual void DidFinishRunningTasksRequiredForActivation() OVERRIDE
{}
176 void RunMessageLoopUntilAllTasksHaveCompleted() {
177 if (timeout_seconds_
) {
179 base::Bind(&RasterWorkerPoolTest::OnTimeout
, base::Unretained(this)));
180 base::MessageLoopProxy::current()->PostDelayedTask(
183 base::TimeDelta::FromSeconds(timeout_seconds_
));
186 base::MessageLoop::current()->Run();
190 ASSERT_FALSE(timed_out_
) << "Test timed out";
193 void ScheduleTasks() {
194 RasterTaskQueue queue
;
196 for (RasterTaskVector::const_iterator it
= tasks_
.begin();
199 queue
.items
.push_back(RasterTaskQueue::Item(*it
, false));
201 raster_worker_pool_
->AsRasterizer()->ScheduleTasks(&queue
);
204 void AppendTask(unsigned id
) {
205 const gfx::Size
size(1, 1);
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();
212 ImageDecodeTask::Vector empty
;
213 tasks_
.push_back(new TestRasterTaskImpl(
215 base::Bind(&RasterWorkerPoolTest::OnTaskCompleted
,
216 base::Unretained(this),
217 base::Passed(&resource
),
222 void AppendBlockingTask(unsigned id
, base::Lock
* lock
) {
223 const gfx::Size
size(1, 1);
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();
230 ImageDecodeTask::Vector empty
;
231 tasks_
.push_back(new BlockingTestRasterTaskImpl(
233 base::Bind(&RasterWorkerPoolTest::OnTaskCompleted
,
234 base::Unretained(this),
235 base::Passed(&resource
),
241 const std::vector
<RasterTaskResult
>& completed_tasks() const {
242 return completed_tasks_
;
246 void OnTaskCompleted(scoped_ptr
<ScopedResource
> resource
,
248 const PicturePileImpl::Analysis
& analysis
,
250 RasterTaskResult result
;
252 result
.canceled
= was_canceled
;
253 completed_tasks_
.push_back(result
);
258 base::MessageLoop::current()->Quit();
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_
;
272 RasterTaskVector tasks_
;
273 std::vector
<RasterTaskResult
> completed_tasks_
;
276 TEST_P(RasterWorkerPoolTest
, Basic
) {
281 RunMessageLoopUntilAllTasksHaveCompleted();
283 ASSERT_EQ(2u, completed_tasks().size());
284 EXPECT_FALSE(completed_tasks()[0].canceled
);
285 EXPECT_FALSE(completed_tasks()[1].canceled
);
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);
295 RunMessageLoopUntilAllTasksHaveCompleted();
297 ASSERT_EQ(1u, completed_tasks().size());
298 EXPECT_FALSE(completed_tasks()[0].canceled
);
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
) {
306 // Schedule a task that is prevented from completing with a lock.
308 AppendBlockingTask(0u, &lock
);
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
;
319 // Unblock the first task to allow the second task to complete.
322 RunMessageLoopUntilAllTasksHaveCompleted();
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
));