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