Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / cc / output / software_renderer_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/output/software_renderer.h"
6
7 #include "base/run_loop.h"
8 #include "cc/output/compositor_frame_metadata.h"
9 #include "cc/output/copy_output_request.h"
10 #include "cc/output/copy_output_result.h"
11 #include "cc/output/software_output_device.h"
12 #include "cc/quads/render_pass.h"
13 #include "cc/quads/render_pass_draw_quad.h"
14 #include "cc/quads/solid_color_draw_quad.h"
15 #include "cc/quads/tile_draw_quad.h"
16 #include "cc/test/animation_test_common.h"
17 #include "cc/test/fake_output_surface.h"
18 #include "cc/test/fake_output_surface_client.h"
19 #include "cc/test/geometry_test_utils.h"
20 #include "cc/test/render_pass_test_common.h"
21 #include "cc/test/render_pass_test_utils.h"
22 #include "cc/test/test_shared_bitmap_manager.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "third_party/skia/include/core/SkCanvas.h"
26
27 namespace cc {
28 namespace {
29
30 class SoftwareRendererTest : public testing::Test, public RendererClient {
31  public:
32   void InitializeRenderer(
33       scoped_ptr<SoftwareOutputDevice> software_output_device) {
34     output_surface_ = FakeOutputSurface::CreateSoftware(
35         software_output_device.Pass());
36     CHECK(output_surface_->BindToClient(&output_surface_client_));
37
38     shared_bitmap_manager_.reset(new TestSharedBitmapManager());
39     resource_provider_ = ResourceProvider::Create(output_surface_.get(),
40                                                   shared_bitmap_manager_.get(),
41                                                   NULL,
42                                                   NULL,
43                                                   0,
44                                                   false,
45                                                   1);
46     renderer_ = SoftwareRenderer::Create(
47         this, &settings_, output_surface_.get(), resource_provider());
48   }
49
50   ResourceProvider* resource_provider() const {
51     return resource_provider_.get();
52   }
53
54   SoftwareRenderer* renderer() const { return renderer_.get(); }
55
56   // RendererClient implementation.
57   void SetFullRootLayerDamage() override {}
58
59   scoped_ptr<SkBitmap> DrawAndCopyOutput(RenderPassList* list,
60                                          float device_scale_factor,
61                                          gfx::Rect device_viewport_rect) {
62     scoped_ptr<SkBitmap> bitmap_result;
63     base::RunLoop loop;
64
65     list->back()->copy_requests.push_back(
66         CopyOutputRequest::CreateBitmapRequest(
67             base::Bind(&SoftwareRendererTest::SaveBitmapResult,
68                        base::Unretained(&bitmap_result),
69                        loop.QuitClosure())));
70
71     renderer()->DrawFrame(list,
72                           device_scale_factor,
73                           device_viewport_rect,
74                           device_viewport_rect,
75                           false);
76     loop.Run();
77     return bitmap_result.Pass();
78   }
79
80   static void SaveBitmapResult(scoped_ptr<SkBitmap>* bitmap_result,
81                                const base::Closure& quit_closure,
82                                scoped_ptr<CopyOutputResult> result) {
83     DCHECK(result->HasBitmap());
84     *bitmap_result = result->TakeBitmap();
85     quit_closure.Run();
86   }
87
88  protected:
89   LayerTreeSettings settings_;
90   FakeOutputSurfaceClient output_surface_client_;
91   scoped_ptr<FakeOutputSurface> output_surface_;
92   scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
93   scoped_ptr<ResourceProvider> resource_provider_;
94   scoped_ptr<SoftwareRenderer> renderer_;
95 };
96
97 TEST_F(SoftwareRendererTest, SolidColorQuad) {
98   gfx::Size outer_size(100, 100);
99   gfx::Size inner_size(98, 98);
100   gfx::Rect outer_rect(outer_size);
101   gfx::Rect inner_rect(gfx::Point(1, 1), inner_size);
102   gfx::Rect visible_rect(gfx::Point(1, 2), gfx::Size(98, 97));
103
104   InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
105
106   RenderPassId root_render_pass_id = RenderPassId(1, 1);
107   scoped_ptr<TestRenderPass> root_render_pass = TestRenderPass::Create();
108   root_render_pass->SetNew(
109       root_render_pass_id, outer_rect, outer_rect, gfx::Transform());
110   SharedQuadState* shared_quad_state =
111       root_render_pass->CreateAndAppendSharedQuadState();
112   shared_quad_state->SetAll(gfx::Transform(),
113                             outer_size,
114                             outer_rect,
115                             outer_rect,
116                             false,
117                             1.0,
118                             SkXfermode::kSrcOver_Mode,
119                             0);
120   SolidColorDrawQuad* inner_quad =
121       root_render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
122   inner_quad->SetNew(
123       shared_quad_state, inner_rect, inner_rect, SK_ColorCYAN, false);
124   inner_quad->visible_rect = visible_rect;
125   SolidColorDrawQuad* outer_quad =
126       root_render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
127   outer_quad->SetNew(
128       shared_quad_state, outer_rect, outer_rect, SK_ColorYELLOW, false);
129
130   RenderPassList list;
131   list.push_back(root_render_pass.Pass());
132
133   float device_scale_factor = 1.f;
134   gfx::Rect device_viewport_rect(outer_size);
135   scoped_ptr<SkBitmap> output =
136       DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
137   EXPECT_EQ(outer_rect.width(), output->info().fWidth);
138   EXPECT_EQ(outer_rect.width(), output->info().fHeight);
139
140   EXPECT_EQ(SK_ColorYELLOW, output->getColor(0, 0));
141   EXPECT_EQ(SK_ColorYELLOW,
142             output->getColor(outer_size.width() - 1, outer_size.height() - 1));
143   EXPECT_EQ(SK_ColorYELLOW, output->getColor(1, 1));
144   EXPECT_EQ(SK_ColorCYAN, output->getColor(1, 2));
145   EXPECT_EQ(SK_ColorCYAN,
146             output->getColor(inner_size.width() - 1, inner_size.height() - 1));
147 }
148
149 TEST_F(SoftwareRendererTest, TileQuad) {
150   gfx::Size outer_size(100, 100);
151   gfx::Size inner_size(98, 98);
152   gfx::Rect outer_rect(outer_size);
153   gfx::Rect inner_rect(gfx::Point(1, 1), inner_size);
154   InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
155
156   ResourceProvider::ResourceId resource_yellow =
157       resource_provider()->CreateResource(
158           outer_size,
159           GL_CLAMP_TO_EDGE,
160           ResourceProvider::TextureHintImmutable,
161           RGBA_8888);
162   ResourceProvider::ResourceId resource_cyan =
163       resource_provider()->CreateResource(
164           inner_size,
165           GL_CLAMP_TO_EDGE,
166           ResourceProvider::TextureHintImmutable,
167           RGBA_8888);
168
169   SkBitmap yellow_tile;
170   yellow_tile.allocN32Pixels(outer_size.width(), outer_size.height());
171   yellow_tile.eraseColor(SK_ColorYELLOW);
172
173   SkBitmap cyan_tile;
174   cyan_tile.allocN32Pixels(inner_size.width(), inner_size.height());
175   cyan_tile.eraseColor(SK_ColorCYAN);
176
177   resource_provider()->SetPixels(
178       resource_yellow,
179       static_cast<uint8_t*>(yellow_tile.getPixels()),
180       gfx::Rect(outer_size),
181       gfx::Rect(outer_size),
182       gfx::Vector2d());
183   resource_provider()->SetPixels(resource_cyan,
184                                  static_cast<uint8_t*>(cyan_tile.getPixels()),
185                                  gfx::Rect(inner_size),
186                                  gfx::Rect(inner_size),
187                                  gfx::Vector2d());
188
189   gfx::Rect root_rect = outer_rect;
190
191   RenderPassId root_render_pass_id = RenderPassId(1, 1);
192   scoped_ptr<TestRenderPass> root_render_pass = TestRenderPass::Create();
193   root_render_pass->SetNew(
194       root_render_pass_id, root_rect, root_rect, gfx::Transform());
195   SharedQuadState* shared_quad_state =
196       root_render_pass->CreateAndAppendSharedQuadState();
197   shared_quad_state->SetAll(gfx::Transform(),
198                             outer_size,
199                             outer_rect,
200                             outer_rect,
201                             false,
202                             1.0,
203                             SkXfermode::kSrcOver_Mode,
204                             0);
205   TileDrawQuad* inner_quad =
206       root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
207   inner_quad->SetNew(shared_quad_state,
208                      inner_rect,
209                      inner_rect,
210                      inner_rect,
211                      resource_cyan,
212                      gfx::RectF(inner_size),
213                      inner_size,
214                      false);
215   TileDrawQuad* outer_quad =
216       root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
217   outer_quad->SetNew(shared_quad_state,
218                      outer_rect,
219                      outer_rect,
220                      outer_rect,
221                      resource_yellow,
222                      gfx::RectF(outer_size),
223                      outer_size,
224                      false);
225
226   RenderPassList list;
227   list.push_back(root_render_pass.Pass());
228
229   float device_scale_factor = 1.f;
230   gfx::Rect device_viewport_rect(outer_size);
231   scoped_ptr<SkBitmap> output =
232       DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
233   EXPECT_EQ(outer_rect.width(), output->info().fWidth);
234   EXPECT_EQ(outer_rect.width(), output->info().fHeight);
235
236   EXPECT_EQ(SK_ColorYELLOW, output->getColor(0, 0));
237   EXPECT_EQ(SK_ColorYELLOW,
238             output->getColor(outer_size.width() - 1, outer_size.height() - 1));
239   EXPECT_EQ(SK_ColorCYAN, output->getColor(1, 1));
240   EXPECT_EQ(SK_ColorCYAN,
241             output->getColor(inner_size.width() - 1, inner_size.height() - 1));
242 }
243
244 TEST_F(SoftwareRendererTest, TileQuadVisibleRect) {
245   gfx::Size tile_size(100, 100);
246   gfx::Rect tile_rect(tile_size);
247   gfx::Rect visible_rect = tile_rect;
248   visible_rect.Inset(1, 2, 3, 4);
249   InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
250
251   ResourceProvider::ResourceId resource_cyan =
252       resource_provider()->CreateResource(
253           tile_size,
254           GL_CLAMP_TO_EDGE,
255           ResourceProvider::TextureHintImmutable,
256           RGBA_8888);
257
258   SkBitmap cyan_tile;  // The lowest five rows are yellow.
259   cyan_tile.allocN32Pixels(tile_size.width(), tile_size.height());
260   cyan_tile.eraseColor(SK_ColorCYAN);
261   cyan_tile.eraseArea(
262       SkIRect::MakeLTRB(
263           0, visible_rect.bottom() - 1, tile_rect.width(), tile_rect.bottom()),
264       SK_ColorYELLOW);
265
266   resource_provider()->SetPixels(resource_cyan,
267                                  static_cast<uint8_t*>(cyan_tile.getPixels()),
268                                  gfx::Rect(tile_size),
269                                  gfx::Rect(tile_size),
270                                  gfx::Vector2d());
271
272   gfx::Rect root_rect(tile_size);
273
274   RenderPassId root_render_pass_id = RenderPassId(1, 1);
275   scoped_ptr<TestRenderPass> root_render_pass = TestRenderPass::Create();
276   root_render_pass->SetNew(
277       root_render_pass_id, root_rect, root_rect, gfx::Transform());
278   SharedQuadState* shared_quad_state =
279       root_render_pass->CreateAndAppendSharedQuadState();
280   shared_quad_state->SetAll(gfx::Transform(),
281                             tile_size,
282                             tile_rect,
283                             tile_rect,
284                             false,
285                             1.0,
286                             SkXfermode::kSrcOver_Mode,
287                             0);
288   TileDrawQuad* quad =
289       root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
290   quad->SetNew(shared_quad_state,
291                tile_rect,
292                tile_rect,
293                tile_rect,
294                resource_cyan,
295                gfx::RectF(tile_size),
296                tile_size,
297                false);
298   quad->visible_rect = visible_rect;
299
300   RenderPassList list;
301   list.push_back(root_render_pass.Pass());
302
303   float device_scale_factor = 1.f;
304   gfx::Rect device_viewport_rect(tile_size);
305   scoped_ptr<SkBitmap> output =
306       DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
307   EXPECT_EQ(tile_rect.width(), output->info().fWidth);
308   EXPECT_EQ(tile_rect.width(), output->info().fHeight);
309
310   // Check portion of tile not in visible rect isn't drawn.
311   const unsigned int kTransparent = SK_ColorTRANSPARENT;
312   EXPECT_EQ(kTransparent, output->getColor(0, 0));
313   EXPECT_EQ(kTransparent,
314             output->getColor(tile_rect.width() - 1, tile_rect.height() - 1));
315   EXPECT_EQ(kTransparent,
316             output->getColor(visible_rect.x() - 1, visible_rect.y() - 1));
317   EXPECT_EQ(kTransparent,
318             output->getColor(visible_rect.right(), visible_rect.bottom()));
319   // Ensure visible part is drawn correctly.
320   EXPECT_EQ(SK_ColorCYAN, output->getColor(visible_rect.x(), visible_rect.y()));
321   EXPECT_EQ(
322       SK_ColorCYAN,
323       output->getColor(visible_rect.right() - 2, visible_rect.bottom() - 2));
324   // Ensure last visible line is correct.
325   EXPECT_EQ(
326       SK_ColorYELLOW,
327       output->getColor(visible_rect.right() - 1, visible_rect.bottom() - 1));
328 }
329
330 TEST_F(SoftwareRendererTest, ShouldClearRootRenderPass) {
331   float device_scale_factor = 1.f;
332   gfx::Rect device_viewport_rect(0, 0, 100, 100);
333
334   settings_.should_clear_root_render_pass = false;
335   InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
336
337   RenderPassList list;
338
339   // Draw a fullscreen green quad in a first frame.
340   RenderPassId root_clear_pass_id(1, 0);
341   TestRenderPass* root_clear_pass = AddRenderPass(
342       &list, root_clear_pass_id, device_viewport_rect, gfx::Transform());
343   AddQuad(root_clear_pass, device_viewport_rect, SK_ColorGREEN);
344
345   renderer()->DecideRenderPassAllocationsForFrame(list);
346
347   scoped_ptr<SkBitmap> output =
348       DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
349   EXPECT_EQ(device_viewport_rect.width(), output->info().fWidth);
350   EXPECT_EQ(device_viewport_rect.width(), output->info().fHeight);
351
352   EXPECT_EQ(SK_ColorGREEN, output->getColor(0, 0));
353   EXPECT_EQ(SK_ColorGREEN,
354             output->getColor(device_viewport_rect.width() - 1,
355                              device_viewport_rect.height() - 1));
356
357   list.clear();
358
359   // Draw a smaller magenta rect without filling the viewport in a separate
360   // frame.
361   gfx::Rect smaller_rect(20, 20, 60, 60);
362
363   RenderPassId root_smaller_pass_id(2, 0);
364   TestRenderPass* root_smaller_pass = AddRenderPass(
365       &list, root_smaller_pass_id, device_viewport_rect, gfx::Transform());
366   AddQuad(root_smaller_pass, smaller_rect, SK_ColorMAGENTA);
367
368   renderer()->DecideRenderPassAllocationsForFrame(list);
369
370   output = DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
371   EXPECT_EQ(device_viewport_rect.width(), output->info().fWidth);
372   EXPECT_EQ(device_viewport_rect.width(), output->info().fHeight);
373
374   // If we didn't clear, the borders should still be green.
375   EXPECT_EQ(SK_ColorGREEN, output->getColor(0, 0));
376   EXPECT_EQ(SK_ColorGREEN,
377             output->getColor(device_viewport_rect.width() - 1,
378                              device_viewport_rect.height() - 1));
379
380   EXPECT_EQ(SK_ColorMAGENTA,
381             output->getColor(smaller_rect.x(), smaller_rect.y()));
382   EXPECT_EQ(
383       SK_ColorMAGENTA,
384       output->getColor(smaller_rect.right() - 1, smaller_rect.bottom() - 1));
385 }
386
387 TEST_F(SoftwareRendererTest, RenderPassVisibleRect) {
388   float device_scale_factor = 1.f;
389   gfx::Rect device_viewport_rect(0, 0, 100, 100);
390   InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
391
392   RenderPassList list;
393
394   // Pass drawn as inner quad is magenta.
395   gfx::Rect smaller_rect(20, 20, 60, 60);
396   RenderPassId smaller_pass_id(2, 1);
397   TestRenderPass* smaller_pass =
398       AddRenderPass(&list, smaller_pass_id, smaller_rect, gfx::Transform());
399   AddQuad(smaller_pass, smaller_rect, SK_ColorMAGENTA);
400
401   // Root pass is green.
402   RenderPassId root_clear_pass_id(1, 0);
403   TestRenderPass* root_clear_pass = AddRenderPass(
404       &list, root_clear_pass_id, device_viewport_rect, gfx::Transform());
405   AddRenderPassQuad(root_clear_pass, smaller_pass);
406   AddQuad(root_clear_pass, device_viewport_rect, SK_ColorGREEN);
407
408   // Interior pass quad has smaller visible rect.
409   gfx::Rect interior_visible_rect(30, 30, 40, 40);
410   root_clear_pass->quad_list.front()->visible_rect = interior_visible_rect;
411
412   renderer()->DecideRenderPassAllocationsForFrame(list);
413
414   scoped_ptr<SkBitmap> output =
415       DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
416   EXPECT_EQ(device_viewport_rect.width(), output->info().fWidth);
417   EXPECT_EQ(device_viewport_rect.width(), output->info().fHeight);
418
419   EXPECT_EQ(SK_ColorGREEN, output->getColor(0, 0));
420   EXPECT_EQ(SK_ColorGREEN,
421             output->getColor(device_viewport_rect.width() - 1,
422                              device_viewport_rect.height() - 1));
423
424   // Part outside visible rect should remain green.
425   EXPECT_EQ(SK_ColorGREEN,
426             output->getColor(smaller_rect.x(), smaller_rect.y()));
427   EXPECT_EQ(
428       SK_ColorGREEN,
429       output->getColor(smaller_rect.right() - 1, smaller_rect.bottom() - 1));
430
431   EXPECT_EQ(
432       SK_ColorMAGENTA,
433       output->getColor(interior_visible_rect.x(), interior_visible_rect.y()));
434   EXPECT_EQ(SK_ColorMAGENTA,
435             output->getColor(interior_visible_rect.right() - 1,
436                              interior_visible_rect.bottom() - 1));
437 }
438
439 }  // namespace
440 }  // namespace cc