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