Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(33)

Side by Side Diff: cc/resources/tile_task_worker_pool_perftest.cc

Issue 1144693002: cc: Move files out of cc/resources/. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: resources: android Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « cc/resources/tile_task_worker_pool.cc ('k') | cc/resources/tile_task_worker_pool_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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/tile_task_worker_pool.h"
6
7 #include "base/test/test_simple_task_runner.h"
8 #include "base/time/time.h"
9 #include "cc/debug/lap_timer.h"
10 #include "cc/output/context_provider.h"
11 #include "cc/resources/bitmap_tile_task_worker_pool.h"
12 #include "cc/resources/gpu_rasterizer.h"
13 #include "cc/resources/gpu_tile_task_worker_pool.h"
14 #include "cc/resources/one_copy_tile_task_worker_pool.h"
15 #include "cc/resources/pixel_buffer_tile_task_worker_pool.h"
16 #include "cc/resources/raster_buffer.h"
17 #include "cc/resources/resource_pool.h"
18 #include "cc/resources/resource_provider.h"
19 #include "cc/resources/scoped_resource.h"
20 #include "cc/resources/tile_task_runner.h"
21 #include "cc/resources/zero_copy_tile_task_worker_pool.h"
22 #include "cc/test/fake_output_surface.h"
23 #include "cc/test/fake_output_surface_client.h"
24 #include "cc/test/test_context_support.h"
25 #include "cc/test/test_gpu_memory_buffer_manager.h"
26 #include "cc/test/test_shared_bitmap_manager.h"
27 #include "cc/test/test_web_graphics_context_3d.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 #include "testing/perf/perf_test.h"
30 #include "third_party/khronos/GLES2/gl2.h"
31 #include "third_party/skia/include/gpu/GrContext.h"
32 #include "third_party/skia/include/gpu/gl/GrGLInterface.h"
33
34 namespace cc {
35 namespace {
36
37 class PerfGLES2Interface : public gpu::gles2::GLES2InterfaceStub {
38 // Overridden from gpu::gles2::GLES2Interface:
39 GLuint CreateImageCHROMIUM(ClientBuffer buffer,
40 GLsizei width,
41 GLsizei height,
42 GLenum internalformat) override {
43 return 1u;
44 }
45 void GenBuffers(GLsizei n, GLuint* buffers) override {
46 for (GLsizei i = 0; i < n; ++i)
47 buffers[i] = 1u;
48 }
49 void GenTextures(GLsizei n, GLuint* textures) override {
50 for (GLsizei i = 0; i < n; ++i)
51 textures[i] = 1u;
52 }
53 void GetIntegerv(GLenum pname, GLint* params) override {
54 if (pname == GL_MAX_TEXTURE_SIZE)
55 *params = INT_MAX;
56 }
57 void GenQueriesEXT(GLsizei n, GLuint* queries) override {
58 for (GLsizei i = 0; i < n; ++i)
59 queries[i] = 1u;
60 }
61 void GetQueryObjectuivEXT(GLuint query,
62 GLenum pname,
63 GLuint* params) override {
64 if (pname == GL_QUERY_RESULT_AVAILABLE_EXT)
65 *params = 1;
66 }
67 };
68
69 class PerfContextProvider : public ContextProvider {
70 public:
71 PerfContextProvider() : context_gl_(new PerfGLES2Interface) {}
72
73 bool BindToCurrentThread() override { return true; }
74 Capabilities ContextCapabilities() override {
75 Capabilities capabilities;
76 capabilities.gpu.image = true;
77 capabilities.gpu.sync_query = true;
78 return capabilities;
79 }
80 gpu::gles2::GLES2Interface* ContextGL() override { return context_gl_.get(); }
81 gpu::ContextSupport* ContextSupport() override { return &support_; }
82 class GrContext* GrContext() override {
83 if (gr_context_)
84 return gr_context_.get();
85
86 skia::RefPtr<const GrGLInterface> null_interface =
87 skia::AdoptRef(GrGLCreateNullInterface());
88 gr_context_ = skia::AdoptRef(GrContext::Create(
89 kOpenGL_GrBackend,
90 reinterpret_cast<GrBackendContext>(null_interface.get())));
91 return gr_context_.get();
92 }
93 void InvalidateGrContext(uint32_t state) override {
94 if (gr_context_)
95 gr_context_.get()->resetContext(state);
96 }
97 void SetupLock() override {}
98 base::Lock* GetLock() override { return &context_lock_; }
99 bool IsContextLost() override { return false; }
100 void VerifyContexts() override {}
101 void DeleteCachedResources() override {}
102 bool DestroyedOnMainThread() override { return false; }
103 void SetLostContextCallback(const LostContextCallback& cb) override {}
104 void SetMemoryPolicyChangedCallback(
105 const MemoryPolicyChangedCallback& cb) override {}
106
107 private:
108 ~PerfContextProvider() override {}
109
110 scoped_ptr<PerfGLES2Interface> context_gl_;
111 skia::RefPtr<class GrContext> gr_context_;
112 TestContextSupport support_;
113 base::Lock context_lock_;
114 };
115
116 enum TileTaskWorkerPoolType {
117 TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER,
118 TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY,
119 TILE_TASK_WORKER_POOL_TYPE_ONE_COPY,
120 TILE_TASK_WORKER_POOL_TYPE_GPU,
121 TILE_TASK_WORKER_POOL_TYPE_BITMAP
122 };
123
124 static const int kTimeLimitMillis = 2000;
125 static const int kWarmupRuns = 5;
126 static const int kTimeCheckInterval = 10;
127
128 class PerfImageDecodeTaskImpl : public ImageDecodeTask {
129 public:
130 PerfImageDecodeTaskImpl() {}
131
132 // Overridden from Task:
133 void RunOnWorkerThread() override {}
134
135 // Overridden from TileTask:
136 void ScheduleOnOriginThread(TileTaskClient* client) override {}
137 void CompleteOnOriginThread(TileTaskClient* client) override {}
138 void RunReplyOnOriginThread() override { Reset(); }
139
140 void Reset() {
141 did_run_ = false;
142 did_complete_ = false;
143 }
144
145 protected:
146 ~PerfImageDecodeTaskImpl() override {}
147
148 private:
149 DISALLOW_COPY_AND_ASSIGN(PerfImageDecodeTaskImpl);
150 };
151
152 class PerfRasterTaskImpl : public RasterTask {
153 public:
154 PerfRasterTaskImpl(scoped_ptr<ScopedResource> resource,
155 ImageDecodeTask::Vector* dependencies)
156 : RasterTask(resource.get(), dependencies), resource_(resource.Pass()) {}
157
158 // Overridden from Task:
159 void RunOnWorkerThread() override {}
160
161 // Overridden from TileTask:
162 void ScheduleOnOriginThread(TileTaskClient* client) override {
163 raster_buffer_ = client->AcquireBufferForRaster(resource());
164 }
165 void CompleteOnOriginThread(TileTaskClient* client) override {
166 client->ReleaseBufferForRaster(raster_buffer_.Pass());
167 }
168 void RunReplyOnOriginThread() override { Reset(); }
169
170 void Reset() {
171 did_run_ = false;
172 did_complete_ = false;
173 }
174
175 protected:
176 ~PerfRasterTaskImpl() override {}
177
178 private:
179 scoped_ptr<ScopedResource> resource_;
180 scoped_ptr<RasterBuffer> raster_buffer_;
181
182 DISALLOW_COPY_AND_ASSIGN(PerfRasterTaskImpl);
183 };
184
185 class TileTaskWorkerPoolPerfTestBase {
186 public:
187 typedef std::vector<scoped_refptr<RasterTask>> RasterTaskVector;
188
189 enum NamedTaskSet { REQUIRED_FOR_ACTIVATION, REQUIRED_FOR_DRAW, ALL };
190
191 TileTaskWorkerPoolPerfTestBase()
192 : context_provider_(make_scoped_refptr(new PerfContextProvider)),
193 task_runner_(new base::TestSimpleTaskRunner),
194 task_graph_runner_(new TaskGraphRunner),
195 timer_(kWarmupRuns,
196 base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
197 kTimeCheckInterval) {}
198
199 void CreateImageDecodeTasks(unsigned num_image_decode_tasks,
200 ImageDecodeTask::Vector* image_decode_tasks) {
201 for (unsigned i = 0; i < num_image_decode_tasks; ++i)
202 image_decode_tasks->push_back(new PerfImageDecodeTaskImpl);
203 }
204
205 void CreateRasterTasks(unsigned num_raster_tasks,
206 const ImageDecodeTask::Vector& image_decode_tasks,
207 RasterTaskVector* raster_tasks) {
208 const gfx::Size size(1, 1);
209
210 for (unsigned i = 0; i < num_raster_tasks; ++i) {
211 scoped_ptr<ScopedResource> resource(
212 ScopedResource::Create(resource_provider_.get()));
213 resource->Allocate(size, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
214 RGBA_8888);
215
216 ImageDecodeTask::Vector dependencies = image_decode_tasks;
217 raster_tasks->push_back(
218 new PerfRasterTaskImpl(resource.Pass(), &dependencies));
219 }
220 }
221
222 void BuildTileTaskQueue(TileTaskQueue* queue,
223 const RasterTaskVector& raster_tasks) {
224 for (size_t i = 0u; i < raster_tasks.size(); ++i) {
225 bool required_for_activation = (i % 2) == 0;
226 TaskSetCollection task_set_collection;
227 task_set_collection[ALL] = true;
228 task_set_collection[REQUIRED_FOR_ACTIVATION] = required_for_activation;
229 queue->items.push_back(
230 TileTaskQueue::Item(raster_tasks[i].get(), task_set_collection));
231 }
232 }
233
234 protected:
235 scoped_refptr<ContextProvider> context_provider_;
236 FakeOutputSurfaceClient output_surface_client_;
237 scoped_ptr<FakeOutputSurface> output_surface_;
238 scoped_ptr<ResourceProvider> resource_provider_;
239 scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
240 scoped_ptr<TaskGraphRunner> task_graph_runner_;
241 LapTimer timer_;
242 };
243
244 class TileTaskWorkerPoolPerfTest
245 : public TileTaskWorkerPoolPerfTestBase,
246 public testing::TestWithParam<TileTaskWorkerPoolType>,
247 public TileTaskRunnerClient {
248 public:
249 // Overridden from testing::Test:
250 void SetUp() override {
251 switch (GetParam()) {
252 case TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER:
253 Create3dOutputSurfaceAndResourceProvider();
254 tile_task_worker_pool_ = PixelBufferTileTaskWorkerPool::Create(
255 task_runner_.get(), task_graph_runner_.get(),
256 context_provider_.get(), resource_provider_.get(),
257 std::numeric_limits<size_t>::max());
258 break;
259 case TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY:
260 Create3dOutputSurfaceAndResourceProvider();
261 tile_task_worker_pool_ = ZeroCopyTileTaskWorkerPool::Create(
262 task_runner_.get(), task_graph_runner_.get(),
263 resource_provider_.get());
264 break;
265 case TILE_TASK_WORKER_POOL_TYPE_ONE_COPY:
266 Create3dOutputSurfaceAndResourceProvider();
267 staging_resource_pool_ = ResourcePool::Create(resource_provider_.get(),
268 GL_TEXTURE_2D);
269 tile_task_worker_pool_ = OneCopyTileTaskWorkerPool::Create(
270 task_runner_.get(), task_graph_runner_.get(),
271 context_provider_.get(), resource_provider_.get(),
272 staging_resource_pool_.get());
273 break;
274 case TILE_TASK_WORKER_POOL_TYPE_GPU:
275 Create3dOutputSurfaceAndResourceProvider();
276 tile_task_worker_pool_ = GpuTileTaskWorkerPool::Create(
277 task_runner_.get(), task_graph_runner_.get(),
278 context_provider_.get(), resource_provider_.get(), false, 0);
279 break;
280 case TILE_TASK_WORKER_POOL_TYPE_BITMAP:
281 CreateSoftwareOutputSurfaceAndResourceProvider();
282 tile_task_worker_pool_ = BitmapTileTaskWorkerPool::Create(
283 task_runner_.get(), task_graph_runner_.get(),
284 resource_provider_.get());
285 break;
286 }
287
288 DCHECK(tile_task_worker_pool_);
289 tile_task_worker_pool_->AsTileTaskRunner()->SetClient(this);
290 }
291 void TearDown() override {
292 tile_task_worker_pool_->AsTileTaskRunner()->Shutdown();
293 tile_task_worker_pool_->AsTileTaskRunner()->CheckForCompletedTasks();
294 }
295
296 // Overriden from TileTaskRunnerClient:
297 void DidFinishRunningTileTasks(TaskSet task_set) override {
298 tile_task_worker_pool_->AsTileTaskRunner()->CheckForCompletedTasks();
299 }
300 TaskSetCollection TasksThatShouldBeForcedToComplete() const override {
301 return TaskSetCollection();
302 }
303
304 void RunMessageLoopUntilAllTasksHaveCompleted() {
305 task_graph_runner_->RunUntilIdle();
306 task_runner_->RunUntilIdle();
307 }
308
309 void RunScheduleTasksTest(const std::string& test_name,
310 unsigned num_raster_tasks,
311 unsigned num_image_decode_tasks) {
312 ImageDecodeTask::Vector image_decode_tasks;
313 RasterTaskVector raster_tasks;
314 CreateImageDecodeTasks(num_image_decode_tasks, &image_decode_tasks);
315 CreateRasterTasks(num_raster_tasks, image_decode_tasks, &raster_tasks);
316
317 // Avoid unnecessary heap allocations by reusing the same queue.
318 TileTaskQueue queue;
319
320 timer_.Reset();
321 do {
322 queue.Reset();
323 BuildTileTaskQueue(&queue, raster_tasks);
324 tile_task_worker_pool_->AsTileTaskRunner()->ScheduleTasks(&queue);
325 tile_task_worker_pool_->AsTileTaskRunner()->CheckForCompletedTasks();
326 timer_.NextLap();
327 } while (!timer_.HasTimeLimitExpired());
328
329 TileTaskQueue empty;
330 tile_task_worker_pool_->AsTileTaskRunner()->ScheduleTasks(&empty);
331 RunMessageLoopUntilAllTasksHaveCompleted();
332
333 perf_test::PrintResult("schedule_tasks", TestModifierString(), test_name,
334 timer_.LapsPerSecond(), "runs/s", true);
335 }
336
337 void RunScheduleAlternateTasksTest(const std::string& test_name,
338 unsigned num_raster_tasks,
339 unsigned num_image_decode_tasks) {
340 const size_t kNumVersions = 2;
341 ImageDecodeTask::Vector image_decode_tasks[kNumVersions];
342 RasterTaskVector raster_tasks[kNumVersions];
343 for (size_t i = 0; i < kNumVersions; ++i) {
344 CreateImageDecodeTasks(num_image_decode_tasks, &image_decode_tasks[i]);
345 CreateRasterTasks(num_raster_tasks, image_decode_tasks[i],
346 &raster_tasks[i]);
347 }
348
349 // Avoid unnecessary heap allocations by reusing the same queue.
350 TileTaskQueue queue;
351
352 size_t count = 0;
353 timer_.Reset();
354 do {
355 queue.Reset();
356 BuildTileTaskQueue(&queue, raster_tasks[count % kNumVersions]);
357 tile_task_worker_pool_->AsTileTaskRunner()->ScheduleTasks(&queue);
358 tile_task_worker_pool_->AsTileTaskRunner()->CheckForCompletedTasks();
359 ++count;
360 timer_.NextLap();
361 } while (!timer_.HasTimeLimitExpired());
362
363 TileTaskQueue empty;
364 tile_task_worker_pool_->AsTileTaskRunner()->ScheduleTasks(&empty);
365 RunMessageLoopUntilAllTasksHaveCompleted();
366
367 perf_test::PrintResult("schedule_alternate_tasks", TestModifierString(),
368 test_name, timer_.LapsPerSecond(), "runs/s", true);
369 }
370
371 void RunScheduleAndExecuteTasksTest(const std::string& test_name,
372 unsigned num_raster_tasks,
373 unsigned num_image_decode_tasks) {
374 ImageDecodeTask::Vector image_decode_tasks;
375 RasterTaskVector raster_tasks;
376 CreateImageDecodeTasks(num_image_decode_tasks, &image_decode_tasks);
377 CreateRasterTasks(num_raster_tasks, image_decode_tasks, &raster_tasks);
378
379 // Avoid unnecessary heap allocations by reusing the same queue.
380 TileTaskQueue queue;
381
382 timer_.Reset();
383 do {
384 queue.Reset();
385 BuildTileTaskQueue(&queue, raster_tasks);
386 tile_task_worker_pool_->AsTileTaskRunner()->ScheduleTasks(&queue);
387 RunMessageLoopUntilAllTasksHaveCompleted();
388 timer_.NextLap();
389 } while (!timer_.HasTimeLimitExpired());
390
391 TileTaskQueue empty;
392 tile_task_worker_pool_->AsTileTaskRunner()->ScheduleTasks(&empty);
393 RunMessageLoopUntilAllTasksHaveCompleted();
394
395 perf_test::PrintResult("schedule_and_execute_tasks", TestModifierString(),
396 test_name, timer_.LapsPerSecond(), "runs/s", true);
397 }
398
399 private:
400 void Create3dOutputSurfaceAndResourceProvider() {
401 output_surface_ = FakeOutputSurface::Create3d(context_provider_).Pass();
402 CHECK(output_surface_->BindToClient(&output_surface_client_));
403 resource_provider_ = ResourceProvider::Create(output_surface_.get(), NULL,
404 &gpu_memory_buffer_manager_,
405 NULL, 0, false, 1).Pass();
406 }
407
408 void CreateSoftwareOutputSurfaceAndResourceProvider() {
409 output_surface_ = FakeOutputSurface::CreateSoftware(
410 make_scoped_ptr(new SoftwareOutputDevice));
411 CHECK(output_surface_->BindToClient(&output_surface_client_));
412 resource_provider_ =
413 ResourceProvider::Create(output_surface_.get(), &shared_bitmap_manager_,
414 NULL, NULL, 0, false, 1).Pass();
415 }
416
417 std::string TestModifierString() const {
418 switch (GetParam()) {
419 case TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER:
420 return std::string("_pixel_tile_task_worker_pool");
421 case TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY:
422 return std::string("_zero_copy_tile_task_worker_pool");
423 case TILE_TASK_WORKER_POOL_TYPE_ONE_COPY:
424 return std::string("_one_copy_tile_task_worker_pool");
425 case TILE_TASK_WORKER_POOL_TYPE_GPU:
426 return std::string("_gpu_tile_task_worker_pool");
427 case TILE_TASK_WORKER_POOL_TYPE_BITMAP:
428 return std::string("_bitmap_tile_task_worker_pool");
429 }
430 NOTREACHED();
431 return std::string();
432 }
433
434 scoped_ptr<ResourcePool> staging_resource_pool_;
435 scoped_ptr<TileTaskWorkerPool> tile_task_worker_pool_;
436 TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
437 TestSharedBitmapManager shared_bitmap_manager_;
438 };
439
440 TEST_P(TileTaskWorkerPoolPerfTest, ScheduleTasks) {
441 RunScheduleTasksTest("1_0", 1, 0);
442 RunScheduleTasksTest("32_0", 32, 0);
443 RunScheduleTasksTest("1_1", 1, 1);
444 RunScheduleTasksTest("32_1", 32, 1);
445 RunScheduleTasksTest("1_4", 1, 4);
446 RunScheduleTasksTest("32_4", 32, 4);
447 }
448
449 TEST_P(TileTaskWorkerPoolPerfTest, ScheduleAlternateTasks) {
450 RunScheduleAlternateTasksTest("1_0", 1, 0);
451 RunScheduleAlternateTasksTest("32_0", 32, 0);
452 RunScheduleAlternateTasksTest("1_1", 1, 1);
453 RunScheduleAlternateTasksTest("32_1", 32, 1);
454 RunScheduleAlternateTasksTest("1_4", 1, 4);
455 RunScheduleAlternateTasksTest("32_4", 32, 4);
456 }
457
458 TEST_P(TileTaskWorkerPoolPerfTest, ScheduleAndExecuteTasks) {
459 RunScheduleAndExecuteTasksTest("1_0", 1, 0);
460 RunScheduleAndExecuteTasksTest("32_0", 32, 0);
461 RunScheduleAndExecuteTasksTest("1_1", 1, 1);
462 RunScheduleAndExecuteTasksTest("32_1", 32, 1);
463 RunScheduleAndExecuteTasksTest("1_4", 1, 4);
464 RunScheduleAndExecuteTasksTest("32_4", 32, 4);
465 }
466
467 INSTANTIATE_TEST_CASE_P(
468 TileTaskWorkerPoolPerfTests,
469 TileTaskWorkerPoolPerfTest,
470 ::testing::Values(TILE_TASK_WORKER_POOL_TYPE_PIXEL_BUFFER,
471 TILE_TASK_WORKER_POOL_TYPE_ZERO_COPY,
472 TILE_TASK_WORKER_POOL_TYPE_ONE_COPY,
473 TILE_TASK_WORKER_POOL_TYPE_GPU,
474 TILE_TASK_WORKER_POOL_TYPE_BITMAP));
475
476 class TileTaskWorkerPoolCommonPerfTest : public TileTaskWorkerPoolPerfTestBase,
477 public testing::Test {
478 public:
479 // Overridden from testing::Test:
480 void SetUp() override {
481 output_surface_ = FakeOutputSurface::Create3d(context_provider_).Pass();
482 CHECK(output_surface_->BindToClient(&output_surface_client_));
483 resource_provider_ =
484 ResourceProvider::Create(output_surface_.get(), NULL, NULL, NULL, 0,
485 false, 1).Pass();
486 }
487
488 void RunBuildTileTaskQueueTest(const std::string& test_name,
489 unsigned num_raster_tasks,
490 unsigned num_image_decode_tasks) {
491 ImageDecodeTask::Vector image_decode_tasks;
492 RasterTaskVector raster_tasks;
493 CreateImageDecodeTasks(num_image_decode_tasks, &image_decode_tasks);
494 CreateRasterTasks(num_raster_tasks, image_decode_tasks, &raster_tasks);
495
496 // Avoid unnecessary heap allocations by reusing the same queue.
497 TileTaskQueue queue;
498
499 timer_.Reset();
500 do {
501 queue.Reset();
502 BuildTileTaskQueue(&queue, raster_tasks);
503 timer_.NextLap();
504 } while (!timer_.HasTimeLimitExpired());
505
506 perf_test::PrintResult("build_raster_task_queue", "", test_name,
507 timer_.LapsPerSecond(), "runs/s", true);
508 }
509 };
510
511 TEST_F(TileTaskWorkerPoolCommonPerfTest, BuildTileTaskQueue) {
512 RunBuildTileTaskQueueTest("1_0", 1, 0);
513 RunBuildTileTaskQueueTest("32_0", 32, 0);
514 RunBuildTileTaskQueueTest("1_1", 1, 1);
515 RunBuildTileTaskQueueTest("32_1", 32, 1);
516 RunBuildTileTaskQueueTest("1_4", 1, 4);
517 RunBuildTileTaskQueueTest("32_4", 32, 4);
518 }
519
520 } // namespace
521 } // namespace cc
OLDNEW
« no previous file with comments | « cc/resources/tile_task_worker_pool.cc ('k') | cc/resources/tile_task_worker_pool_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698