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