WebKit Roll 139512:139548
[chromium-blink-merge.git] / cc / resource_update_controller_unittest.cc
blob2da1460ade149f6f5d1c947f7082a272cbef81ae
1 // Copyright 2012 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/resource_update_controller.h"
7 #include "cc/prioritized_resource_manager.h"
8 #include "cc/single_thread_proxy.h" // For DebugScopedSetImplThread
9 #include "cc/test/fake_output_surface.h"
10 #include "cc/test/fake_proxy.h"
11 #include "cc/test/fake_web_graphics_context_3d.h"
12 #include "cc/test/scheduler_test_common.h"
13 #include "cc/test/tiled_layer_test_common.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "third_party/khronos/GLES2/gl2ext.h"
17 using namespace WebKit;
18 using testing::Test;
20 namespace cc {
21 namespace {
23 const int kFlushPeriodFull = 4;
24 const int kFlushPeriodPartial = kFlushPeriodFull;
26 class ResourceUpdateControllerTest;
28 class WebGraphicsContext3DForUploadTest : public FakeWebGraphicsContext3D {
29 public:
30 WebGraphicsContext3DForUploadTest(ResourceUpdateControllerTest *test)
31 : m_test(test)
32 , m_supportShallowFlush(true)
33 { }
35 virtual void flush(void);
36 virtual void shallowFlushCHROMIUM(void);
37 virtual void texSubImage2D(WGC3Denum target,
38 WGC3Dint level,
39 WGC3Dint xoffset,
40 WGC3Dint yoffset,
41 WGC3Dsizei width,
42 WGC3Dsizei height,
43 WGC3Denum format,
44 WGC3Denum type,
45 const void* pixels);
46 virtual GrGLInterface* onCreateGrGLInterface() { return 0; }
48 virtual WebString getString(WGC3Denum name)
50 if (m_supportShallowFlush)
51 return WebString("GL_CHROMIUM_shallow_flush");
52 return WebString("");
55 virtual void getQueryObjectuivEXT(WebGLId, WGC3Denum, WGC3Duint*);
57 private:
58 ResourceUpdateControllerTest* m_test;
59 bool m_supportShallowFlush;
63 class ResourceUpdateControllerTest : public Test {
64 public:
65 ResourceUpdateControllerTest()
66 : m_proxy(scoped_ptr<Thread>(NULL))
67 , m_queue(make_scoped_ptr(new ResourceUpdateQueue))
68 , m_resourceManager(PrioritizedResourceManager::create(&m_proxy))
69 , m_fullUploadCountExpected(0)
70 , m_partialCountExpected(0)
71 , m_totalUploadCountExpected(0)
72 , m_maxUploadCountPerUpdate(0)
73 , m_numConsecutiveFlushes(0)
74 , m_numDanglingUploads(0)
75 , m_numTotalUploads(0)
76 , m_numTotalFlushes(0)
77 , m_queryResultsAvailable(0)
81 ~ResourceUpdateControllerTest()
83 DebugScopedSetImplThreadAndMainThreadBlocked
84 implThreadAndMainThreadBlocked(&m_proxy);
85 m_resourceManager->clearAllMemory(m_resourceProvider.get());
88 public:
89 void onFlush()
91 // Check for back-to-back flushes.
92 EXPECT_EQ(0, m_numConsecutiveFlushes) << "Back-to-back flushes detected.";
94 m_numDanglingUploads = 0;
95 m_numConsecutiveFlushes++;
96 m_numTotalFlushes++;
99 void onUpload()
101 // Check for too many consecutive uploads
102 if (m_numTotalUploads < m_fullUploadCountExpected)
103 EXPECT_LT(m_numDanglingUploads, kFlushPeriodFull) << "Too many consecutive full uploads detected.";
104 else
105 EXPECT_LT(m_numDanglingUploads, kFlushPeriodPartial) << "Too many consecutive partial uploads detected.";
107 m_numConsecutiveFlushes = 0;
108 m_numDanglingUploads++;
109 m_numTotalUploads++;
112 bool isQueryResultAvailable()
114 if (!m_queryResultsAvailable)
115 return false;
117 m_queryResultsAvailable--;
118 return true;
121 protected:
122 virtual void SetUp()
124 m_outputSurface = FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new WebGraphicsContext3DForUploadTest(this)));
125 m_bitmap.setConfig(SkBitmap::kARGB_8888_Config, 300, 150);
126 m_bitmap.allocPixels();
128 for (int i = 0; i < 4; i++) {
129 m_textures[i] = PrioritizedResource::create(
130 m_resourceManager.get(), gfx::Size(300, 150), GL_RGBA);
131 m_textures[i]->setRequestPriority(
132 PriorityCalculator::visiblePriority(true));
134 m_resourceManager->prioritizeTextures();
136 m_resourceProvider = ResourceProvider::create(m_outputSurface.get());
140 void appendFullUploadsOfIndexedTextureToUpdateQueue(int count, int textureIndex)
142 m_fullUploadCountExpected += count;
143 m_totalUploadCountExpected += count;
145 const gfx::Rect rect(0, 0, 300, 150);
146 const ResourceUpdate upload = ResourceUpdate::Create(
147 m_textures[textureIndex].get(), &m_bitmap, rect, rect, gfx::Vector2d());
148 for (int i = 0; i < count; i++)
149 m_queue->appendFullUpload(upload);
152 void appendFullUploadsToUpdateQueue(int count)
154 appendFullUploadsOfIndexedTextureToUpdateQueue(count, 0);
157 void appendPartialUploadsOfIndexedTextureToUpdateQueue(int count, int textureIndex)
159 m_partialCountExpected += count;
160 m_totalUploadCountExpected += count;
162 const gfx::Rect rect(0, 0, 100, 100);
163 const ResourceUpdate upload = ResourceUpdate::Create(
164 m_textures[textureIndex].get(), &m_bitmap, rect, rect, gfx::Vector2d());
165 for (int i = 0; i < count; i++)
166 m_queue->appendPartialUpload(upload);
169 void appendPartialUploadsToUpdateQueue(int count)
171 appendPartialUploadsOfIndexedTextureToUpdateQueue(count, 0);
174 void setMaxUploadCountPerUpdate(int count)
176 m_maxUploadCountPerUpdate = count;
179 void updateTextures()
181 DebugScopedSetImplThreadAndMainThreadBlocked
182 implThreadAndMainThreadBlocked(&m_proxy);
183 scoped_ptr<ResourceUpdateController> updateController =
184 ResourceUpdateController::create(
185 NULL,
186 m_proxy.implThread(),
187 m_queue.Pass(),
188 m_resourceProvider.get(),
189 m_proxy.hasImplThread());
190 updateController->finalize();
193 void makeQueryResultAvailable()
195 m_queryResultsAvailable++;
198 protected:
199 // Classes required to interact and test the ResourceUpdateController
200 FakeProxy m_proxy;
201 scoped_ptr<OutputSurface> m_outputSurface;
202 scoped_ptr<ResourceProvider> m_resourceProvider;
203 scoped_ptr<ResourceUpdateQueue> m_queue;
204 scoped_ptr<PrioritizedResource> m_textures[4];
205 scoped_ptr<PrioritizedResourceManager> m_resourceManager;
206 SkBitmap m_bitmap;
207 int m_queryResultsAvailable;
209 // Properties / expectations of this test
210 int m_fullUploadCountExpected;
211 int m_partialCountExpected;
212 int m_totalUploadCountExpected;
213 int m_maxUploadCountPerUpdate;
215 // Dynamic properties of this test
216 int m_numConsecutiveFlushes;
217 int m_numDanglingUploads;
218 int m_numTotalUploads;
219 int m_numTotalFlushes;
222 void WebGraphicsContext3DForUploadTest::flush(void)
224 m_test->onFlush();
227 void WebGraphicsContext3DForUploadTest::shallowFlushCHROMIUM(void)
229 m_test->onFlush();
232 void WebGraphicsContext3DForUploadTest::texSubImage2D(WGC3Denum target,
233 WGC3Dint level,
234 WGC3Dint xoffset,
235 WGC3Dint yoffset,
236 WGC3Dsizei width,
237 WGC3Dsizei height,
238 WGC3Denum format,
239 WGC3Denum type,
240 const void* pixels)
242 m_test->onUpload();
245 void WebGraphicsContext3DForUploadTest::getQueryObjectuivEXT(
246 WebGLId,
247 WGC3Denum pname,
248 WGC3Duint* params) {
249 if (pname == GL_QUERY_RESULT_AVAILABLE_EXT)
250 *params = m_test->isQueryResultAvailable();
253 // ZERO UPLOADS TESTS
254 TEST_F(ResourceUpdateControllerTest, ZeroUploads)
256 appendFullUploadsToUpdateQueue(0);
257 appendPartialUploadsToUpdateQueue(0);
258 updateTextures();
260 EXPECT_EQ(0, m_numTotalFlushes);
261 EXPECT_EQ(0, m_numTotalUploads);
265 // ONE UPLOAD TESTS
266 TEST_F(ResourceUpdateControllerTest, OneFullUpload)
268 appendFullUploadsToUpdateQueue(1);
269 appendPartialUploadsToUpdateQueue(0);
270 updateTextures();
272 EXPECT_EQ(1, m_numTotalFlushes);
273 EXPECT_EQ(1, m_numTotalUploads);
274 EXPECT_EQ(0, m_numDanglingUploads) << "Last upload wasn't followed by a flush.";
277 TEST_F(ResourceUpdateControllerTest, OnePartialUpload)
279 appendFullUploadsToUpdateQueue(0);
280 appendPartialUploadsToUpdateQueue(1);
281 updateTextures();
283 EXPECT_EQ(1, m_numTotalFlushes);
284 EXPECT_EQ(1, m_numTotalUploads);
285 EXPECT_EQ(0, m_numDanglingUploads) << "Last upload wasn't followed by a flush.";
288 TEST_F(ResourceUpdateControllerTest, OneFullOnePartialUpload)
290 appendFullUploadsToUpdateQueue(1);
291 appendPartialUploadsToUpdateQueue(1);
292 updateTextures();
294 EXPECT_EQ(1, m_numTotalFlushes);
295 EXPECT_EQ(2, m_numTotalUploads);
296 EXPECT_EQ(0, m_numDanglingUploads) << "Last upload wasn't followed by a flush.";
300 // This class of tests upload a number of textures that is a multiple of the flush period.
301 const int fullUploadFlushMultipler = 7;
302 const int fullCount = fullUploadFlushMultipler * kFlushPeriodFull;
304 const int partialUploadFlushMultipler = 11;
305 const int partialCount = partialUploadFlushMultipler * kFlushPeriodPartial;
307 TEST_F(ResourceUpdateControllerTest, ManyFullUploads)
309 appendFullUploadsToUpdateQueue(fullCount);
310 appendPartialUploadsToUpdateQueue(0);
311 updateTextures();
313 EXPECT_EQ(fullUploadFlushMultipler, m_numTotalFlushes);
314 EXPECT_EQ(fullCount, m_numTotalUploads);
315 EXPECT_EQ(0, m_numDanglingUploads) << "Last upload wasn't followed by a flush.";
318 TEST_F(ResourceUpdateControllerTest, ManyPartialUploads)
320 appendFullUploadsToUpdateQueue(0);
321 appendPartialUploadsToUpdateQueue(partialCount);
322 updateTextures();
324 EXPECT_EQ(partialUploadFlushMultipler, m_numTotalFlushes);
325 EXPECT_EQ(partialCount, m_numTotalUploads);
326 EXPECT_EQ(0, m_numDanglingUploads) << "Last upload wasn't followed by a flush.";
329 TEST_F(ResourceUpdateControllerTest, ManyFullManyPartialUploads)
331 appendFullUploadsToUpdateQueue(fullCount);
332 appendPartialUploadsToUpdateQueue(partialCount);
333 updateTextures();
335 EXPECT_EQ(fullUploadFlushMultipler + partialUploadFlushMultipler, m_numTotalFlushes);
336 EXPECT_EQ(fullCount + partialCount, m_numTotalUploads);
337 EXPECT_EQ(0, m_numDanglingUploads) << "Last upload wasn't followed by a flush.";
340 class FakeResourceUpdateControllerClient : public cc::ResourceUpdateControllerClient {
341 public:
342 FakeResourceUpdateControllerClient() { reset(); }
343 void reset() { m_readyToFinalizeCalled = false; }
344 bool readyToFinalizeCalled() const { return m_readyToFinalizeCalled; }
346 virtual void readyToFinalizeTextureUpdates() OVERRIDE { m_readyToFinalizeCalled = true; }
348 protected:
349 bool m_readyToFinalizeCalled;
352 class FakeResourceUpdateController : public cc::ResourceUpdateController {
353 public:
354 static scoped_ptr<FakeResourceUpdateController> create(cc::ResourceUpdateControllerClient* client, cc::Thread* thread, scoped_ptr<ResourceUpdateQueue> queue, ResourceProvider* resourceProvider)
356 return make_scoped_ptr(new FakeResourceUpdateController(client, thread, queue.Pass(), resourceProvider));
359 void setNow(base::TimeTicks time) { m_now = time; }
360 virtual base::TimeTicks now() const OVERRIDE { return m_now; }
361 void setUpdateMoreTexturesTime(base::TimeDelta time) { m_updateMoreTexturesTime = time; }
362 virtual base::TimeDelta updateMoreTexturesTime() const OVERRIDE { return m_updateMoreTexturesTime; }
363 void setUpdateMoreTexturesSize(size_t size) { m_updateMoreTexturesSize = size; }
364 virtual size_t updateMoreTexturesSize() const OVERRIDE { return m_updateMoreTexturesSize; }
366 protected:
367 FakeResourceUpdateController(cc::ResourceUpdateControllerClient* client, cc::Thread* thread, scoped_ptr<ResourceUpdateQueue> queue, ResourceProvider* resourceProvider)
368 : cc::ResourceUpdateController(client, thread, queue.Pass(), resourceProvider, false)
369 , m_updateMoreTexturesSize(0) { }
371 base::TimeTicks m_now;
372 base::TimeDelta m_updateMoreTexturesTime;
373 size_t m_updateMoreTexturesSize;
376 static void runPendingTask(FakeThread* thread, FakeResourceUpdateController* controller)
378 EXPECT_TRUE(thread->hasPendingTask());
379 controller->setNow(controller->now() + base::TimeDelta::FromMilliseconds(thread->pendingDelayMs()));
380 thread->runPendingTask();
383 TEST_F(ResourceUpdateControllerTest, UpdateMoreTextures)
385 FakeResourceUpdateControllerClient client;
386 FakeThread thread;
388 setMaxUploadCountPerUpdate(1);
389 appendFullUploadsToUpdateQueue(3);
390 appendPartialUploadsToUpdateQueue(0);
392 DebugScopedSetImplThreadAndMainThreadBlocked
393 implThreadAndMainThreadBlocked(&m_proxy);
394 scoped_ptr<FakeResourceUpdateController> controller(FakeResourceUpdateController::create(&client, &thread, m_queue.Pass(), m_resourceProvider.get()));
396 controller->setNow(
397 controller->now() + base::TimeDelta::FromMilliseconds(1));
398 controller->setUpdateMoreTexturesTime(
399 base::TimeDelta::FromMilliseconds(100));
400 controller->setUpdateMoreTexturesSize(1);
401 // Not enough time for any updates.
402 controller->performMoreUpdates(
403 controller->now() + base::TimeDelta::FromMilliseconds(90));
404 EXPECT_FALSE(thread.hasPendingTask());
406 controller->setUpdateMoreTexturesTime(
407 base::TimeDelta::FromMilliseconds(100));
408 controller->setUpdateMoreTexturesSize(1);
409 // Only enough time for 1 update.
410 controller->performMoreUpdates(
411 controller->now() + base::TimeDelta::FromMilliseconds(120));
412 EXPECT_FALSE(thread.hasPendingTask());
413 EXPECT_EQ(1, m_numTotalUploads);
415 // Complete one upload.
416 makeQueryResultAvailable();
418 controller->setUpdateMoreTexturesTime(
419 base::TimeDelta::FromMilliseconds(100));
420 controller->setUpdateMoreTexturesSize(1);
421 // Enough time for 2 updates.
422 controller->performMoreUpdates(
423 controller->now() + base::TimeDelta::FromMilliseconds(220));
424 runPendingTask(&thread, controller.get());
425 EXPECT_FALSE(thread.hasPendingTask());
426 EXPECT_TRUE(client.readyToFinalizeCalled());
427 EXPECT_EQ(3, m_numTotalUploads);
430 TEST_F(ResourceUpdateControllerTest, NoMoreUpdates)
432 FakeResourceUpdateControllerClient client;
433 FakeThread thread;
435 setMaxUploadCountPerUpdate(1);
436 appendFullUploadsToUpdateQueue(2);
437 appendPartialUploadsToUpdateQueue(0);
439 DebugScopedSetImplThreadAndMainThreadBlocked
440 implThreadAndMainThreadBlocked(&m_proxy);
441 scoped_ptr<FakeResourceUpdateController> controller(FakeResourceUpdateController::create(&client, &thread, m_queue.Pass(), m_resourceProvider.get()));
443 controller->setNow(
444 controller->now() + base::TimeDelta::FromMilliseconds(1));
445 controller->setUpdateMoreTexturesTime(
446 base::TimeDelta::FromMilliseconds(100));
447 controller->setUpdateMoreTexturesSize(1);
448 // Enough time for 3 updates but only 2 necessary.
449 controller->performMoreUpdates(
450 controller->now() + base::TimeDelta::FromMilliseconds(310));
451 runPendingTask(&thread, controller.get());
452 EXPECT_FALSE(thread.hasPendingTask());
453 EXPECT_TRUE(client.readyToFinalizeCalled());
454 EXPECT_EQ(2, m_numTotalUploads);
456 controller->setUpdateMoreTexturesTime(
457 base::TimeDelta::FromMilliseconds(100));
458 controller->setUpdateMoreTexturesSize(1);
459 // Enough time for updates but no more updates left.
460 controller->performMoreUpdates(
461 controller->now() + base::TimeDelta::FromMilliseconds(310));
462 // 0-delay task used to call readyToFinalizeTextureUpdates().
463 runPendingTask(&thread, controller.get());
464 EXPECT_FALSE(thread.hasPendingTask());
465 EXPECT_TRUE(client.readyToFinalizeCalled());
466 EXPECT_EQ(2, m_numTotalUploads);
469 TEST_F(ResourceUpdateControllerTest, UpdatesCompleteInFiniteTime)
471 FakeResourceUpdateControllerClient client;
472 FakeThread thread;
474 setMaxUploadCountPerUpdate(1);
475 appendFullUploadsToUpdateQueue(2);
476 appendPartialUploadsToUpdateQueue(0);
478 DebugScopedSetImplThreadAndMainThreadBlocked
479 implThreadAndMainThreadBlocked(&m_proxy);
480 scoped_ptr<FakeResourceUpdateController> controller(FakeResourceUpdateController::create(&client, &thread, m_queue.Pass(), m_resourceProvider.get()));
482 controller->setNow(
483 controller->now() + base::TimeDelta::FromMilliseconds(1));
484 controller->setUpdateMoreTexturesTime(
485 base::TimeDelta::FromMilliseconds(500));
486 controller->setUpdateMoreTexturesSize(1);
488 for (int i = 0; i < 100; i++) {
489 if (client.readyToFinalizeCalled())
490 break;
492 // Not enough time for any updates.
493 controller->performMoreUpdates(
494 controller->now() + base::TimeDelta::FromMilliseconds(400));
496 if (thread.hasPendingTask())
497 runPendingTask(&thread, controller.get());
500 EXPECT_FALSE(thread.hasPendingTask());
501 EXPECT_TRUE(client.readyToFinalizeCalled());
502 EXPECT_EQ(2, m_numTotalUploads);
505 } // namespace
506 } // namespace cc