IndexedDB: fsync after transactions.
[chromium-blink-merge.git] / cc / output / software_renderer_unittest.cc
blobfc1c7070cb404131a0fc4d49f93f57541762b327
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.
5 #include "cc/output/software_renderer.h"
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"
25 namespace cc {
26 namespace {
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_));
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());
42 ResourceProvider* resource_provider() const {
43 return resource_provider_.get();
46 SoftwareRenderer* renderer() const { return renderer_.get(); }
48 // RendererClient implementation.
49 virtual void SetFullRootLayerDamage() OVERRIDE {}
51 protected:
52 LayerTreeSettings settings_;
53 FakeOutputSurfaceClient output_surface_client_;
54 scoped_ptr<FakeOutputSurface> output_surface_;
55 scoped_ptr<ResourceProvider> resource_provider_;
56 scoped_ptr<SoftwareRenderer> renderer_;
59 TEST_F(SoftwareRendererTest, SolidColorQuad) {
60 gfx::Size outer_size(100, 100);
61 gfx::Size inner_size(98, 98);
62 gfx::Rect outer_rect(outer_size);
63 gfx::Rect inner_rect(gfx::Point(1, 1), inner_size);
64 gfx::Rect visible_rect(gfx::Point(1, 2), gfx::Size(98, 97));
66 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
68 scoped_ptr<SharedQuadState> shared_quad_state = SharedQuadState::Create();
69 shared_quad_state->SetAll(gfx::Transform(),
70 outer_size,
71 outer_rect,
72 outer_rect,
73 false,
74 1.0,
75 SkXfermode::kSrcOver_Mode);
76 RenderPass::Id root_render_pass_id = RenderPass::Id(1, 1);
77 scoped_ptr<TestRenderPass> root_render_pass = TestRenderPass::Create();
78 root_render_pass->SetNew(
79 root_render_pass_id, outer_rect, outer_rect, gfx::Transform());
80 scoped_ptr<SolidColorDrawQuad> outer_quad = SolidColorDrawQuad::Create();
81 outer_quad->SetNew(
82 shared_quad_state.get(), outer_rect, SK_ColorYELLOW, false);
83 scoped_ptr<SolidColorDrawQuad> inner_quad = SolidColorDrawQuad::Create();
84 inner_quad->SetNew(shared_quad_state.get(), inner_rect, SK_ColorCYAN, false);
85 inner_quad->visible_rect = visible_rect;
86 root_render_pass->AppendQuad(inner_quad.PassAs<DrawQuad>());
87 root_render_pass->AppendQuad(outer_quad.PassAs<DrawQuad>());
89 RenderPassList list;
90 list.push_back(root_render_pass.PassAs<RenderPass>());
92 float device_scale_factor = 1.f;
93 gfx::Rect device_viewport_rect(outer_size);
94 renderer()->DrawFrame(&list,
95 NULL,
96 device_scale_factor,
97 device_viewport_rect,
98 device_viewport_rect,
99 true,
100 false);
102 SkBitmap output;
103 output.setConfig(
104 SkBitmap::kARGB_8888_Config, outer_rect.width(), outer_rect.height());
105 output.allocPixels();
106 renderer()->GetFramebufferPixels(output.getPixels(), outer_rect);
108 EXPECT_EQ(SK_ColorYELLOW, output.getColor(0, 0));
109 EXPECT_EQ(SK_ColorYELLOW,
110 output.getColor(outer_size.width() - 1, outer_size.height() - 1));
111 EXPECT_EQ(SK_ColorYELLOW, output.getColor(1, 1));
112 EXPECT_EQ(SK_ColorCYAN, output.getColor(1, 2));
113 EXPECT_EQ(SK_ColorCYAN,
114 output.getColor(inner_size.width() - 1, inner_size.height() - 1));
117 TEST_F(SoftwareRendererTest, TileQuad) {
118 gfx::Size outer_size(100, 100);
119 gfx::Size inner_size(98, 98);
120 gfx::Rect outer_rect(outer_size);
121 gfx::Rect inner_rect(gfx::Point(1, 1), inner_size);
122 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
124 ResourceProvider::ResourceId resource_yellow =
125 resource_provider()->CreateResource(outer_size,
126 GL_CLAMP_TO_EDGE,
127 ResourceProvider::TextureUsageAny,
128 RGBA_8888);
129 ResourceProvider::ResourceId resource_cyan =
130 resource_provider()->CreateResource(inner_size,
131 GL_CLAMP_TO_EDGE,
132 ResourceProvider::TextureUsageAny,
133 RGBA_8888);
135 SkBitmap yellow_tile;
136 yellow_tile.setConfig(
137 SkBitmap::kARGB_8888_Config, outer_size.width(), outer_size.height());
138 yellow_tile.allocPixels();
139 yellow_tile.eraseColor(SK_ColorYELLOW);
141 SkBitmap cyan_tile;
142 cyan_tile.setConfig(
143 SkBitmap::kARGB_8888_Config, inner_size.width(), inner_size.height());
144 cyan_tile.allocPixels();
145 cyan_tile.eraseColor(SK_ColorCYAN);
147 resource_provider()->SetPixels(
148 resource_yellow,
149 static_cast<uint8_t*>(yellow_tile.getPixels()),
150 gfx::Rect(outer_size),
151 gfx::Rect(outer_size),
152 gfx::Vector2d());
153 resource_provider()->SetPixels(resource_cyan,
154 static_cast<uint8_t*>(cyan_tile.getPixels()),
155 gfx::Rect(inner_size),
156 gfx::Rect(inner_size),
157 gfx::Vector2d());
159 gfx::Rect root_rect = outer_rect;
161 scoped_ptr<SharedQuadState> shared_quad_state = SharedQuadState::Create();
162 shared_quad_state->SetAll(gfx::Transform(),
163 outer_size,
164 outer_rect,
165 outer_rect,
166 false,
167 1.0,
168 SkXfermode::kSrcOver_Mode);
169 RenderPass::Id root_render_pass_id = RenderPass::Id(1, 1);
170 scoped_ptr<TestRenderPass> root_render_pass = TestRenderPass::Create();
171 root_render_pass->SetNew(
172 root_render_pass_id, root_rect, root_rect, gfx::Transform());
173 scoped_ptr<TileDrawQuad> outer_quad = TileDrawQuad::Create();
174 outer_quad->SetNew(shared_quad_state.get(),
175 outer_rect,
176 outer_rect,
177 resource_yellow,
178 gfx::RectF(outer_size),
179 outer_size,
180 false);
181 scoped_ptr<TileDrawQuad> inner_quad = TileDrawQuad::Create();
182 inner_quad->SetNew(shared_quad_state.get(),
183 inner_rect,
184 inner_rect,
185 resource_cyan,
186 gfx::RectF(inner_size),
187 inner_size,
188 false);
189 root_render_pass->AppendQuad(inner_quad.PassAs<DrawQuad>());
190 root_render_pass->AppendQuad(outer_quad.PassAs<DrawQuad>());
192 RenderPassList list;
193 list.push_back(root_render_pass.PassAs<RenderPass>());
195 float device_scale_factor = 1.f;
196 gfx::Rect device_viewport_rect(outer_size);
197 renderer()->DrawFrame(&list,
198 NULL,
199 device_scale_factor,
200 device_viewport_rect,
201 device_viewport_rect,
202 true,
203 false);
205 SkBitmap output;
206 output.setConfig(
207 SkBitmap::kARGB_8888_Config, outer_size.width(), outer_size.height());
208 output.allocPixels();
209 renderer()->GetFramebufferPixels(output.getPixels(), outer_rect);
211 EXPECT_EQ(SK_ColorYELLOW, output.getColor(0, 0));
212 EXPECT_EQ(SK_ColorYELLOW,
213 output.getColor(outer_size.width() - 1, outer_size.height() - 1));
214 EXPECT_EQ(SK_ColorCYAN, output.getColor(1, 1));
215 EXPECT_EQ(SK_ColorCYAN,
216 output.getColor(inner_size.width() - 1, inner_size.height() - 1));
219 TEST_F(SoftwareRendererTest, TileQuadVisibleRect) {
220 gfx::Size tile_size(100, 100);
221 gfx::Rect tile_rect(tile_size);
222 gfx::Rect visible_rect = tile_rect;
223 visible_rect.Inset(1, 2, 3, 4);
224 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
226 ResourceProvider::ResourceId resource_cyan =
227 resource_provider()->CreateResource(tile_size,
228 GL_CLAMP_TO_EDGE,
229 ResourceProvider::TextureUsageAny,
230 RGBA_8888);
232 SkBitmap cyan_tile; // The lowest five rows are yellow.
233 cyan_tile.setConfig(
234 SkBitmap::kARGB_8888_Config, tile_size.width(), tile_size.height());
235 cyan_tile.allocPixels();
236 cyan_tile.eraseColor(SK_ColorCYAN);
237 cyan_tile.eraseArea(
238 SkIRect::MakeLTRB(
239 0, visible_rect.bottom() - 1, tile_rect.width(), tile_rect.bottom()),
240 SK_ColorYELLOW);
242 resource_provider()->SetPixels(resource_cyan,
243 static_cast<uint8_t*>(cyan_tile.getPixels()),
244 gfx::Rect(tile_size),
245 gfx::Rect(tile_size),
246 gfx::Vector2d());
248 gfx::Rect root_rect(tile_size);
250 scoped_ptr<SharedQuadState> shared_quad_state = SharedQuadState::Create();
251 shared_quad_state->SetAll(gfx::Transform(),
252 tile_size,
253 tile_rect,
254 tile_rect,
255 false,
256 1.0,
257 SkXfermode::kSrcOver_Mode);
258 RenderPass::Id root_render_pass_id = RenderPass::Id(1, 1);
259 scoped_ptr<TestRenderPass> root_render_pass = TestRenderPass::Create();
260 root_render_pass->SetNew(
261 root_render_pass_id, root_rect, root_rect, gfx::Transform());
262 scoped_ptr<TileDrawQuad> quad = TileDrawQuad::Create();
263 quad->SetNew(shared_quad_state.get(),
264 tile_rect,
265 tile_rect,
266 resource_cyan,
267 gfx::RectF(tile_size),
268 tile_size,
269 false);
270 quad->visible_rect = visible_rect;
271 root_render_pass->AppendQuad(quad.PassAs<DrawQuad>());
273 RenderPassList list;
274 list.push_back(root_render_pass.PassAs<RenderPass>());
276 float device_scale_factor = 1.f;
277 gfx::Rect device_viewport_rect(tile_size);
278 renderer()->DrawFrame(&list,
279 NULL,
280 device_scale_factor,
281 device_viewport_rect,
282 device_viewport_rect,
283 true,
284 false);
286 SkBitmap output;
287 output.setConfig(
288 SkBitmap::kARGB_8888_Config, tile_size.width(), tile_size.height());
289 output.allocPixels();
290 renderer()->GetFramebufferPixels(output.getPixels(), tile_rect);
292 // Check portion of tile not in visible rect isn't drawn.
293 const unsigned int kTransparent = SK_ColorTRANSPARENT;
294 EXPECT_EQ(kTransparent, output.getColor(0, 0));
295 EXPECT_EQ(kTransparent,
296 output.getColor(tile_rect.width() - 1, tile_rect.height() - 1));
297 EXPECT_EQ(kTransparent,
298 output.getColor(visible_rect.x() - 1, visible_rect.y() - 1));
299 EXPECT_EQ(kTransparent,
300 output.getColor(visible_rect.right(), visible_rect.bottom()));
301 // Ensure visible part is drawn correctly.
302 EXPECT_EQ(SK_ColorCYAN, output.getColor(visible_rect.x(), visible_rect.y()));
303 EXPECT_EQ(
304 SK_ColorCYAN,
305 output.getColor(visible_rect.right() - 2, visible_rect.bottom() - 2));
306 // Ensure last visible line is correct.
307 EXPECT_EQ(
308 SK_ColorYELLOW,
309 output.getColor(visible_rect.right() - 1, visible_rect.bottom() - 1));
312 TEST_F(SoftwareRendererTest, ShouldClearRootRenderPass) {
313 float device_scale_factor = 1.f;
314 gfx::Rect viewport_rect(0, 0, 100, 100);
316 settings_.should_clear_root_render_pass = false;
317 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
319 RenderPassList list;
321 SkBitmap output;
322 output.setConfig(SkBitmap::kARGB_8888_Config,
323 viewport_rect.width(),
324 viewport_rect.height());
325 output.allocPixels();
327 // Draw a fullscreen green quad in a first frame.
328 RenderPass::Id root_clear_pass_id(1, 0);
329 TestRenderPass* root_clear_pass = AddRenderPass(
330 &list, root_clear_pass_id, viewport_rect, gfx::Transform());
331 AddQuad(root_clear_pass, viewport_rect, SK_ColorGREEN);
333 renderer()->DecideRenderPassAllocationsForFrame(list);
334 renderer()->DrawFrame(&list,
335 NULL,
336 device_scale_factor,
337 viewport_rect,
338 viewport_rect,
339 true,
340 false);
341 renderer()->GetFramebufferPixels(output.getPixels(), viewport_rect);
343 EXPECT_EQ(SK_ColorGREEN, output.getColor(0, 0));
344 EXPECT_EQ(SK_ColorGREEN,
345 output.getColor(viewport_rect.width() - 1, viewport_rect.height() - 1));
347 list.clear();
349 // Draw a smaller magenta rect without filling the viewport in a separate
350 // frame.
351 gfx::Rect smaller_rect(20, 20, 60, 60);
353 RenderPass::Id root_smaller_pass_id(2, 0);
354 TestRenderPass* root_smaller_pass = AddRenderPass(
355 &list, root_smaller_pass_id, viewport_rect, gfx::Transform());
356 AddQuad(root_smaller_pass, smaller_rect, SK_ColorMAGENTA);
358 renderer()->DecideRenderPassAllocationsForFrame(list);
359 renderer()->DrawFrame(&list,
360 NULL,
361 device_scale_factor,
362 viewport_rect,
363 viewport_rect,
364 true,
365 false);
366 renderer()->GetFramebufferPixels(output.getPixels(), viewport_rect);
368 // If we didn't clear, the borders should still be green.
369 EXPECT_EQ(SK_ColorGREEN, output.getColor(0, 0));
370 EXPECT_EQ(SK_ColorGREEN,
371 output.getColor(viewport_rect.width() - 1, viewport_rect.height() - 1));
373 EXPECT_EQ(SK_ColorMAGENTA,
374 output.getColor(smaller_rect.x(), smaller_rect.y()));
375 EXPECT_EQ(SK_ColorMAGENTA,
376 output.getColor(smaller_rect.right() - 1, smaller_rect.bottom() - 1));
379 TEST_F(SoftwareRendererTest, RenderPassVisibleRect) {
380 float device_scale_factor = 1.f;
381 gfx::Rect viewport_rect(0, 0, 100, 100);
382 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
384 RenderPassList list;
386 SkBitmap output;
387 output.setConfig(SkBitmap::kARGB_8888_Config,
388 viewport_rect.width(),
389 viewport_rect.height());
390 output.allocPixels();
392 // Pass drawn as inner quad is magenta.
393 gfx::Rect smaller_rect(20, 20, 60, 60);
394 RenderPass::Id smaller_pass_id(2, 1);
395 TestRenderPass* smaller_pass =
396 AddRenderPass(&list, smaller_pass_id, smaller_rect, gfx::Transform());
397 AddQuad(smaller_pass, smaller_rect, SK_ColorMAGENTA);
399 // Root pass is green.
400 RenderPass::Id root_clear_pass_id(1, 0);
401 TestRenderPass* root_clear_pass =
402 AddRenderPass(&list, root_clear_pass_id, viewport_rect, gfx::Transform());
403 AddRenderPassQuad(root_clear_pass, smaller_pass);
404 AddQuad(root_clear_pass, viewport_rect, SK_ColorGREEN);
406 // Interior pass quad has smaller visible rect.
407 gfx::Rect interior_visible_rect(30, 30, 40, 40);
408 root_clear_pass->quad_list[0]->visible_rect = interior_visible_rect;
410 renderer()->DecideRenderPassAllocationsForFrame(list);
411 renderer()->DrawFrame(&list,
412 NULL,
413 device_scale_factor,
414 viewport_rect,
415 viewport_rect,
416 true,
417 false);
418 renderer()->GetFramebufferPixels(output.getPixels(), viewport_rect);
420 EXPECT_EQ(SK_ColorGREEN, output.getColor(0, 0));
421 EXPECT_EQ(
422 SK_ColorGREEN,
423 output.getColor(viewport_rect.width() - 1, viewport_rect.height() - 1));
425 // Part outside visible rect should remain green.
426 EXPECT_EQ(SK_ColorGREEN, 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));
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));
439 } // namespace
440 } // namespace cc