Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / cc / resources / resource_update_controller_unittest.cc
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.
4
5 #include "cc/resources/resource_update_controller.h"
6
7 #include "base/test/test_simple_task_runner.h"
8 #include "cc/resources/prioritized_resource_manager.h"
9 #include "cc/test/fake_output_surface.h"
10 #include "cc/test/fake_output_surface_client.h"
11 #include "cc/test/fake_proxy.h"
12 #include "cc/test/scheduler_test_common.h"
13 #include "cc/test/test_shared_bitmap_manager.h"
14 #include "cc/test/test_web_graphics_context_3d.h"
15 #include "cc/test/tiled_layer_test_common.h"
16 #include "cc/trees/single_thread_proxy.h"  // For DebugScopedSetImplThread
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "third_party/khronos/GLES2/gl2ext.h"
19
20 using testing::Test;
21
22 namespace cc {
23 namespace {
24
25 const int kFlushPeriodFull = 4;
26 const int kFlushPeriodPartial = kFlushPeriodFull;
27
28 class ResourceUpdateControllerTest;
29
30 class WebGraphicsContext3DForUploadTest : public TestWebGraphicsContext3D {
31  public:
32   explicit WebGraphicsContext3DForUploadTest(ResourceUpdateControllerTest* test)
33       : test_(test) {}
34
35   virtual void flush() OVERRIDE;
36   virtual void shallowFlushCHROMIUM() OVERRIDE;
37   virtual void texSubImage2D(GLenum target,
38                              GLint level,
39                              GLint xoffset,
40                              GLint yoffset,
41                              GLsizei width,
42                              GLsizei height,
43                              GLenum format,
44                              GLenum type,
45                              const void* pixels) OVERRIDE;
46
47   virtual void getQueryObjectuivEXT(GLuint id, GLenum pname, GLuint* value)
48       OVERRIDE;
49
50  private:
51   ResourceUpdateControllerTest* test_;
52 };
53
54 class ResourceUpdateControllerTest : public Test {
55  public:
56   ResourceUpdateControllerTest()
57       : proxy_(),
58         queue_(make_scoped_ptr(new ResourceUpdateQueue)),
59         resource_manager_(PrioritizedResourceManager::Create(&proxy_)),
60         query_results_available_(0),
61         full_upload_count_expected_(0),
62         partial_count_expected_(0),
63         total_upload_count_expected_(0),
64         max_upload_count_per_update_(0),
65         num_consecutive_flushes_(0),
66         num_dangling_uploads_(0),
67         num_total_uploads_(0),
68         num_total_flushes_(0) {}
69
70   virtual ~ResourceUpdateControllerTest() {
71     DebugScopedSetImplThreadAndMainThreadBlocked
72     impl_thread_and_main_thread_blocked(&proxy_);
73     resource_manager_->ClearAllMemory(resource_provider_.get());
74   }
75
76  public:
77   void OnFlush() {
78     // Check for back-to-back flushes.
79     EXPECT_EQ(0, num_consecutive_flushes_) << "Back-to-back flushes detected.";
80
81     num_dangling_uploads_ = 0;
82     num_consecutive_flushes_++;
83     num_total_flushes_++;
84   }
85
86   void OnUpload() {
87     // Check for too many consecutive uploads
88     if (num_total_uploads_ < full_upload_count_expected_) {
89       EXPECT_LT(num_dangling_uploads_, kFlushPeriodFull)
90           << "Too many consecutive full uploads detected.";
91     } else {
92       EXPECT_LT(num_dangling_uploads_, kFlushPeriodPartial)
93           << "Too many consecutive partial uploads detected.";
94     }
95
96     num_consecutive_flushes_ = 0;
97     num_dangling_uploads_++;
98     num_total_uploads_++;
99   }
100
101   bool IsQueryResultAvailable() {
102     if (!query_results_available_)
103       return false;
104
105     query_results_available_--;
106     return true;
107   }
108
109  protected:
110   virtual void SetUp() {
111     bitmap_.allocN32Pixels(300, 150);
112
113     for (int i = 0; i < 4; i++) {
114       textures_[i] = PrioritizedResource::Create(resource_manager_.get(),
115                                                  gfx::Size(300, 150),
116                                                  RGBA_8888);
117       textures_[i]->
118           set_request_priority(PriorityCalculator::VisiblePriority(true));
119     }
120     resource_manager_->PrioritizeTextures();
121
122     output_surface_ = FakeOutputSurface::Create3d(
123         scoped_ptr<TestWebGraphicsContext3D>(
124             new WebGraphicsContext3DForUploadTest(this)));
125     CHECK(output_surface_->BindToClient(&output_surface_client_));
126
127     shared_bitmap_manager_.reset(new TestSharedBitmapManager());
128     resource_provider_ = ResourceProvider::Create(
129         output_surface_.get(), shared_bitmap_manager_.get(), 0, false, 1,
130         false);
131   }
132
133   void AppendFullUploadsOfIndexedTextureToUpdateQueue(int count,
134                                                       int texture_index) {
135     full_upload_count_expected_ += count;
136     total_upload_count_expected_ += count;
137
138     const gfx::Rect rect(0, 0, 300, 150);
139     const ResourceUpdate upload = ResourceUpdate::Create(
140         textures_[texture_index].get(), &bitmap_, rect, rect, gfx::Vector2d());
141     for (int i = 0; i < count; i++)
142       queue_->AppendFullUpload(upload);
143   }
144
145   void AppendFullUploadsToUpdateQueue(int count) {
146     AppendFullUploadsOfIndexedTextureToUpdateQueue(count, 0);
147   }
148
149   void AppendPartialUploadsOfIndexedTextureToUpdateQueue(int count,
150                                                          int texture_index) {
151     partial_count_expected_ += count;
152     total_upload_count_expected_ += count;
153
154     const gfx::Rect rect(0, 0, 100, 100);
155     const ResourceUpdate upload = ResourceUpdate::Create(
156         textures_[texture_index].get(), &bitmap_, rect, rect, gfx::Vector2d());
157     for (int i = 0; i < count; i++)
158       queue_->AppendPartialUpload(upload);
159   }
160
161   void AppendPartialUploadsToUpdateQueue(int count) {
162     AppendPartialUploadsOfIndexedTextureToUpdateQueue(count, 0);
163   }
164
165   void SetMaxUploadCountPerUpdate(int count) {
166     max_upload_count_per_update_ = count;
167   }
168
169   void UpdateTextures() {
170     DebugScopedSetImplThreadAndMainThreadBlocked
171     impl_thread_and_main_thread_blocked(&proxy_);
172     scoped_ptr<ResourceUpdateController> update_controller =
173         ResourceUpdateController::Create(NULL,
174                                          proxy_.ImplThreadTaskRunner(),
175                                          queue_.Pass(),
176                                          resource_provider_.get());
177     update_controller->Finalize();
178   }
179
180   void MakeQueryResultAvailable() { query_results_available_++; }
181
182  protected:
183   // Classes required to interact and test the ResourceUpdateController
184   FakeProxy proxy_;
185   FakeOutputSurfaceClient output_surface_client_;
186   scoped_ptr<OutputSurface> output_surface_;
187   scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
188   scoped_ptr<ResourceProvider> resource_provider_;
189   scoped_ptr<ResourceUpdateQueue> queue_;
190   scoped_ptr<PrioritizedResource> textures_[4];
191   scoped_ptr<PrioritizedResourceManager> resource_manager_;
192   SkBitmap bitmap_;
193   int query_results_available_;
194
195   // Properties / expectations of this test
196   int full_upload_count_expected_;
197   int partial_count_expected_;
198   int total_upload_count_expected_;
199   int max_upload_count_per_update_;
200
201   // Dynamic properties of this test
202   int num_consecutive_flushes_;
203   int num_dangling_uploads_;
204   int num_total_uploads_;
205   int num_total_flushes_;
206 };
207
208 void WebGraphicsContext3DForUploadTest::flush() { test_->OnFlush(); }
209
210 void WebGraphicsContext3DForUploadTest::shallowFlushCHROMIUM() {
211   test_->OnFlush();
212 }
213
214 void WebGraphicsContext3DForUploadTest::texSubImage2D(GLenum target,
215                                                       GLint level,
216                                                       GLint xoffset,
217                                                       GLint yoffset,
218                                                       GLsizei width,
219                                                       GLsizei height,
220                                                       GLenum format,
221                                                       GLenum type,
222                                                       const void* pixels) {
223   test_->OnUpload();
224 }
225
226 void WebGraphicsContext3DForUploadTest::getQueryObjectuivEXT(GLuint id,
227                                                              GLenum pname,
228                                                              GLuint* params) {
229   if (pname == GL_QUERY_RESULT_AVAILABLE_EXT)
230     *params = test_->IsQueryResultAvailable();
231 }
232
233 // ZERO UPLOADS TESTS
234 TEST_F(ResourceUpdateControllerTest, ZeroUploads) {
235   AppendFullUploadsToUpdateQueue(0);
236   AppendPartialUploadsToUpdateQueue(0);
237   UpdateTextures();
238
239   EXPECT_EQ(0, num_total_flushes_);
240   EXPECT_EQ(0, num_total_uploads_);
241 }
242
243 // ONE UPLOAD TESTS
244 TEST_F(ResourceUpdateControllerTest, OneFullUpload) {
245   AppendFullUploadsToUpdateQueue(1);
246   AppendPartialUploadsToUpdateQueue(0);
247   UpdateTextures();
248
249   EXPECT_EQ(1, num_total_flushes_);
250   EXPECT_EQ(1, num_total_uploads_);
251   EXPECT_EQ(0, num_dangling_uploads_)
252       << "Last upload wasn't followed by a flush.";
253 }
254
255 TEST_F(ResourceUpdateControllerTest, OnePartialUpload) {
256   AppendFullUploadsToUpdateQueue(0);
257   AppendPartialUploadsToUpdateQueue(1);
258   UpdateTextures();
259
260   EXPECT_EQ(1, num_total_flushes_);
261   EXPECT_EQ(1, num_total_uploads_);
262   EXPECT_EQ(0, num_dangling_uploads_)
263       << "Last upload wasn't followed by a flush.";
264 }
265
266 TEST_F(ResourceUpdateControllerTest, OneFullOnePartialUpload) {
267   AppendFullUploadsToUpdateQueue(1);
268   AppendPartialUploadsToUpdateQueue(1);
269   UpdateTextures();
270
271   EXPECT_EQ(1, num_total_flushes_);
272   EXPECT_EQ(2, num_total_uploads_);
273   EXPECT_EQ(0, num_dangling_uploads_)
274       << "Last upload wasn't followed by a flush.";
275 }
276
277 // This class of tests upload a number of textures that is a multiple
278 // of the flush period.
279 const int full_upload_flush_multipler = 7;
280 const int full_count = full_upload_flush_multipler * kFlushPeriodFull;
281
282 const int partial_upload_flush_multipler = 11;
283 const int partial_count =
284     partial_upload_flush_multipler * kFlushPeriodPartial;
285
286 TEST_F(ResourceUpdateControllerTest, ManyFullUploads) {
287   AppendFullUploadsToUpdateQueue(full_count);
288   AppendPartialUploadsToUpdateQueue(0);
289   UpdateTextures();
290
291   EXPECT_EQ(full_upload_flush_multipler, num_total_flushes_);
292   EXPECT_EQ(full_count, num_total_uploads_);
293   EXPECT_EQ(0, num_dangling_uploads_)
294       << "Last upload wasn't followed by a flush.";
295 }
296
297 TEST_F(ResourceUpdateControllerTest, ManyPartialUploads) {
298   AppendFullUploadsToUpdateQueue(0);
299   AppendPartialUploadsToUpdateQueue(partial_count);
300   UpdateTextures();
301
302   EXPECT_EQ(partial_upload_flush_multipler, num_total_flushes_);
303   EXPECT_EQ(partial_count, num_total_uploads_);
304   EXPECT_EQ(0, num_dangling_uploads_)
305       << "Last upload wasn't followed by a flush.";
306 }
307
308 TEST_F(ResourceUpdateControllerTest, ManyFullManyPartialUploads) {
309   AppendFullUploadsToUpdateQueue(full_count);
310   AppendPartialUploadsToUpdateQueue(partial_count);
311   UpdateTextures();
312
313   EXPECT_EQ(full_upload_flush_multipler + partial_upload_flush_multipler,
314             num_total_flushes_);
315   EXPECT_EQ(full_count + partial_count, num_total_uploads_);
316   EXPECT_EQ(0, num_dangling_uploads_)
317       << "Last upload wasn't followed by a flush.";
318 }
319
320 class FakeResourceUpdateControllerClient
321     : public ResourceUpdateControllerClient {
322  public:
323   FakeResourceUpdateControllerClient() { Reset(); }
324   void Reset() { ready_to_finalize_called_ = false; }
325   bool ReadyToFinalizeCalled() const { return ready_to_finalize_called_; }
326
327   virtual void ReadyToFinalizeTextureUpdates() OVERRIDE {
328     ready_to_finalize_called_ = true;
329   }
330
331  protected:
332   bool ready_to_finalize_called_;
333 };
334
335 class FakeResourceUpdateController : public ResourceUpdateController {
336  public:
337   static scoped_ptr<FakeResourceUpdateController> Create(
338       ResourceUpdateControllerClient* client,
339       base::TestSimpleTaskRunner* task_runner,
340       scoped_ptr<ResourceUpdateQueue> queue,
341       ResourceProvider* resource_provider) {
342     return make_scoped_ptr(new FakeResourceUpdateController(
343         client, task_runner, queue.Pass(), resource_provider));
344   }
345
346   void SetNow(base::TimeTicks time) { now_ = time; }
347   base::TimeTicks Now() const { return now_; }
348   void SetUpdateTextureTime(base::TimeDelta time) {
349     update_textures_time_ = time;
350   }
351   virtual base::TimeTicks UpdateMoreTexturesCompletionTime() OVERRIDE {
352     size_t total_updates =
353         resource_provider_->NumBlockingUploads() + update_more_textures_size_;
354     return now_ + total_updates * update_textures_time_;
355   }
356   void SetUpdateMoreTexturesSize(size_t size) {
357     update_more_textures_size_ = size;
358   }
359   virtual size_t UpdateMoreTexturesSize() const OVERRIDE {
360     return update_more_textures_size_;
361   }
362
363  protected:
364   FakeResourceUpdateController(ResourceUpdateControllerClient* client,
365                                base::TestSimpleTaskRunner* task_runner,
366                                scoped_ptr<ResourceUpdateQueue> queue,
367                                ResourceProvider* resource_provider)
368       : ResourceUpdateController(
369           client, task_runner, queue.Pass(), resource_provider),
370         resource_provider_(resource_provider),
371         update_more_textures_size_(0) {}
372
373   ResourceProvider* resource_provider_;
374   base::TimeTicks now_;
375   base::TimeDelta update_textures_time_;
376   size_t update_more_textures_size_;
377 };
378
379 static void RunPendingTask(base::TestSimpleTaskRunner* task_runner,
380                            FakeResourceUpdateController* controller) {
381   EXPECT_TRUE(task_runner->HasPendingTask());
382   controller->SetNow(controller->Now() + task_runner->NextPendingTaskDelay());
383   task_runner->RunPendingTasks();
384 }
385
386 TEST_F(ResourceUpdateControllerTest, UpdateMoreTextures) {
387   FakeResourceUpdateControllerClient client;
388   scoped_refptr<base::TestSimpleTaskRunner> task_runner =
389       new base::TestSimpleTaskRunner;
390
391   SetMaxUploadCountPerUpdate(1);
392   AppendFullUploadsToUpdateQueue(3);
393   AppendPartialUploadsToUpdateQueue(0);
394
395   DebugScopedSetImplThreadAndMainThreadBlocked
396   impl_thread_and_main_thread_blocked(&proxy_);
397   scoped_ptr<FakeResourceUpdateController> controller(
398       FakeResourceUpdateController::Create(&client,
399                                            task_runner.get(),
400                                            queue_.Pass(),
401                                            resource_provider_.get()));
402
403   controller->SetNow(controller->Now() + base::TimeDelta::FromMilliseconds(1));
404   controller->SetUpdateTextureTime(base::TimeDelta::FromMilliseconds(100));
405   controller->SetUpdateMoreTexturesSize(1);
406   // Not enough time for any updates.
407   controller->PerformMoreUpdates(controller->Now() +
408                                  base::TimeDelta::FromMilliseconds(90));
409   EXPECT_FALSE(task_runner->HasPendingTask());
410
411   controller->SetUpdateTextureTime(base::TimeDelta::FromMilliseconds(100));
412   controller->SetUpdateMoreTexturesSize(1);
413   // Only enough time for 1 update.
414   controller->PerformMoreUpdates(controller->Now() +
415                                  base::TimeDelta::FromMilliseconds(120));
416   EXPECT_FALSE(task_runner->HasPendingTask());
417   EXPECT_EQ(1, num_total_uploads_);
418
419   // Complete one upload.
420   MakeQueryResultAvailable();
421
422   controller->SetUpdateTextureTime(base::TimeDelta::FromMilliseconds(100));
423   controller->SetUpdateMoreTexturesSize(1);
424   // Enough time for 2 updates.
425   controller->PerformMoreUpdates(controller->Now() +
426                                  base::TimeDelta::FromMilliseconds(220));
427   RunPendingTask(task_runner.get(), controller.get());
428   EXPECT_FALSE(task_runner->HasPendingTask());
429   EXPECT_TRUE(client.ReadyToFinalizeCalled());
430   EXPECT_EQ(3, num_total_uploads_);
431 }
432
433 TEST_F(ResourceUpdateControllerTest, NoMoreUpdates) {
434   FakeResourceUpdateControllerClient client;
435   scoped_refptr<base::TestSimpleTaskRunner> task_runner =
436       new base::TestSimpleTaskRunner;
437
438   SetMaxUploadCountPerUpdate(1);
439   AppendFullUploadsToUpdateQueue(2);
440   AppendPartialUploadsToUpdateQueue(0);
441
442   DebugScopedSetImplThreadAndMainThreadBlocked
443   impl_thread_and_main_thread_blocked(&proxy_);
444   scoped_ptr<FakeResourceUpdateController> controller(
445       FakeResourceUpdateController::Create(&client,
446                                            task_runner.get(),
447                                            queue_.Pass(),
448                                            resource_provider_.get()));
449
450   controller->SetNow(controller->Now() + base::TimeDelta::FromMilliseconds(1));
451   controller->SetUpdateTextureTime(base::TimeDelta::FromMilliseconds(100));
452   controller->SetUpdateMoreTexturesSize(1);
453   // Enough time for 3 updates but only 2 necessary.
454   controller->PerformMoreUpdates(controller->Now() +
455                                  base::TimeDelta::FromMilliseconds(310));
456   RunPendingTask(task_runner.get(), controller.get());
457   EXPECT_FALSE(task_runner->HasPendingTask());
458   EXPECT_TRUE(client.ReadyToFinalizeCalled());
459   EXPECT_EQ(2, num_total_uploads_);
460
461   client.Reset();
462   controller->SetUpdateTextureTime(base::TimeDelta::FromMilliseconds(100));
463   controller->SetUpdateMoreTexturesSize(1);
464   // Enough time for updates but no more updates left.
465   controller->PerformMoreUpdates(controller->Now() +
466                                  base::TimeDelta::FromMilliseconds(310));
467
468   // ReadyToFinalizeTextureUpdates should only be called once.
469   EXPECT_FALSE(task_runner->HasPendingTask());
470   EXPECT_FALSE(client.ReadyToFinalizeCalled());
471   EXPECT_EQ(2, num_total_uploads_);
472 }
473
474 TEST_F(ResourceUpdateControllerTest, UpdatesCompleteInFiniteTime) {
475   FakeResourceUpdateControllerClient client;
476   scoped_refptr<base::TestSimpleTaskRunner> task_runner =
477       new base::TestSimpleTaskRunner;
478
479   SetMaxUploadCountPerUpdate(1);
480   AppendFullUploadsToUpdateQueue(2);
481   AppendPartialUploadsToUpdateQueue(0);
482
483   DebugScopedSetImplThreadAndMainThreadBlocked
484   impl_thread_and_main_thread_blocked(&proxy_);
485   scoped_ptr<FakeResourceUpdateController> controller(
486       FakeResourceUpdateController::Create(&client,
487                                            task_runner.get(),
488                                            queue_.Pass(),
489                                            resource_provider_.get()));
490
491   controller->SetNow(controller->Now() + base::TimeDelta::FromMilliseconds(1));
492   controller->SetUpdateTextureTime(base::TimeDelta::FromMilliseconds(500));
493   controller->SetUpdateMoreTexturesSize(1);
494
495   for (int i = 0; i < 100; i++) {
496     if (client.ReadyToFinalizeCalled())
497       break;
498
499     // Not enough time for any updates.
500     controller->PerformMoreUpdates(controller->Now() +
501                                    base::TimeDelta::FromMilliseconds(400));
502
503     if (task_runner->HasPendingTask())
504       RunPendingTask(task_runner.get(), controller.get());
505   }
506
507   EXPECT_FALSE(task_runner->HasPendingTask());
508   EXPECT_TRUE(client.ReadyToFinalizeCalled());
509   EXPECT_EQ(2, num_total_uploads_);
510 }
511
512 }  // namespace
513 }  // namespace cc