Abstract GoogleURLTracker & google_util Profile dependencies
[chromium-blink-merge.git] / cc / output / software_renderer_unittest.cc
blobee5af29f991b7169dbdd4a8f2c1b5ec7592c1358
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 "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"
28 namespace cc {
29 namespace {
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_));
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());
47 ResourceProvider* resource_provider() const {
48 return resource_provider_.get();
51 SoftwareRenderer* renderer() const { return renderer_.get(); }
53 // RendererClient implementation.
54 virtual void SetFullRootLayerDamage() OVERRIDE {}
56 scoped_ptr<SkBitmap> DrawAndCopyOutput(RenderPassList* list,
57 float device_scale_factor,
58 gfx::Rect device_viewport_rect) {
59 scoped_ptr<SkBitmap> bitmap_result;
60 base::RunLoop loop;
62 list->back()->copy_requests.push_back(
63 CopyOutputRequest::CreateBitmapRequest(
64 base::Bind(&SoftwareRendererTest::SaveBitmapResult,
65 base::Unretained(&bitmap_result),
66 loop.QuitClosure())));
68 renderer()->DrawFrame(list,
69 device_scale_factor,
70 device_viewport_rect,
71 device_viewport_rect,
72 false);
73 loop.Run();
74 return bitmap_result.Pass();
77 static void SaveBitmapResult(scoped_ptr<SkBitmap>* bitmap_result,
78 const base::Closure& quit_closure,
79 scoped_ptr<CopyOutputResult> result) {
80 DCHECK(result->HasBitmap());
81 *bitmap_result = result->TakeBitmap();
82 quit_closure.Run();
85 protected:
86 LayerTreeSettings settings_;
87 FakeOutputSurfaceClient output_surface_client_;
88 scoped_ptr<FakeOutputSurface> output_surface_;
89 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
90 scoped_ptr<ResourceProvider> resource_provider_;
91 scoped_ptr<SoftwareRenderer> renderer_;
94 TEST_F(SoftwareRendererTest, SolidColorQuad) {
95 gfx::Size outer_size(100, 100);
96 gfx::Size inner_size(98, 98);
97 gfx::Rect outer_rect(outer_size);
98 gfx::Rect inner_rect(gfx::Point(1, 1), inner_size);
99 gfx::Rect visible_rect(gfx::Point(1, 2), gfx::Size(98, 97));
101 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
103 RenderPass::Id root_render_pass_id = RenderPass::Id(1, 1);
104 scoped_ptr<TestRenderPass> root_render_pass = TestRenderPass::Create();
105 root_render_pass->SetNew(
106 root_render_pass_id, outer_rect, outer_rect, gfx::Transform());
107 SharedQuadState* shared_quad_state =
108 root_render_pass->CreateAndAppendSharedQuadState();
109 shared_quad_state->SetAll(gfx::Transform(),
110 outer_size,
111 outer_rect,
112 outer_rect,
113 false,
114 1.0,
115 SkXfermode::kSrcOver_Mode);
116 scoped_ptr<SolidColorDrawQuad> outer_quad = SolidColorDrawQuad::Create();
117 outer_quad->SetNew(
118 shared_quad_state, outer_rect, outer_rect, SK_ColorYELLOW, false);
119 scoped_ptr<SolidColorDrawQuad> inner_quad = SolidColorDrawQuad::Create();
120 inner_quad->SetNew(
121 shared_quad_state, inner_rect, inner_rect, SK_ColorCYAN, false);
122 inner_quad->visible_rect = visible_rect;
123 root_render_pass->AppendQuad(inner_quad.PassAs<DrawQuad>());
124 root_render_pass->AppendQuad(outer_quad.PassAs<DrawQuad>());
126 RenderPassList list;
127 list.push_back(root_render_pass.PassAs<RenderPass>());
129 float device_scale_factor = 1.f;
130 gfx::Rect device_viewport_rect(outer_size);
131 scoped_ptr<SkBitmap> output =
132 DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
133 EXPECT_EQ(outer_rect.width(), output->info().fWidth);
134 EXPECT_EQ(outer_rect.width(), output->info().fHeight);
136 EXPECT_EQ(SK_ColorYELLOW, output->getColor(0, 0));
137 EXPECT_EQ(SK_ColorYELLOW,
138 output->getColor(outer_size.width() - 1, outer_size.height() - 1));
139 EXPECT_EQ(SK_ColorYELLOW, output->getColor(1, 1));
140 EXPECT_EQ(SK_ColorCYAN, output->getColor(1, 2));
141 EXPECT_EQ(SK_ColorCYAN,
142 output->getColor(inner_size.width() - 1, inner_size.height() - 1));
145 TEST_F(SoftwareRendererTest, TileQuad) {
146 gfx::Size outer_size(100, 100);
147 gfx::Size inner_size(98, 98);
148 gfx::Rect outer_rect(outer_size);
149 gfx::Rect inner_rect(gfx::Point(1, 1), inner_size);
150 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
152 ResourceProvider::ResourceId resource_yellow =
153 resource_provider()->CreateResource(outer_size,
154 GL_CLAMP_TO_EDGE,
155 ResourceProvider::TextureUsageAny,
156 RGBA_8888);
157 ResourceProvider::ResourceId resource_cyan =
158 resource_provider()->CreateResource(inner_size,
159 GL_CLAMP_TO_EDGE,
160 ResourceProvider::TextureUsageAny,
161 RGBA_8888);
163 SkBitmap yellow_tile;
164 yellow_tile.setConfig(
165 SkBitmap::kARGB_8888_Config, outer_size.width(), outer_size.height());
166 yellow_tile.allocPixels();
167 yellow_tile.eraseColor(SK_ColorYELLOW);
169 SkBitmap cyan_tile;
170 cyan_tile.setConfig(
171 SkBitmap::kARGB_8888_Config, inner_size.width(), inner_size.height());
172 cyan_tile.allocPixels();
173 cyan_tile.eraseColor(SK_ColorCYAN);
175 resource_provider()->SetPixels(
176 resource_yellow,
177 static_cast<uint8_t*>(yellow_tile.getPixels()),
178 gfx::Rect(outer_size),
179 gfx::Rect(outer_size),
180 gfx::Vector2d());
181 resource_provider()->SetPixels(resource_cyan,
182 static_cast<uint8_t*>(cyan_tile.getPixels()),
183 gfx::Rect(inner_size),
184 gfx::Rect(inner_size),
185 gfx::Vector2d());
187 gfx::Rect root_rect = outer_rect;
189 RenderPass::Id root_render_pass_id = RenderPass::Id(1, 1);
190 scoped_ptr<TestRenderPass> root_render_pass = TestRenderPass::Create();
191 root_render_pass->SetNew(
192 root_render_pass_id, root_rect, root_rect, gfx::Transform());
193 SharedQuadState* shared_quad_state =
194 root_render_pass->CreateAndAppendSharedQuadState();
195 shared_quad_state->SetAll(gfx::Transform(),
196 outer_size,
197 outer_rect,
198 outer_rect,
199 false,
200 1.0,
201 SkXfermode::kSrcOver_Mode);
202 scoped_ptr<TileDrawQuad> outer_quad = TileDrawQuad::Create();
203 outer_quad->SetNew(shared_quad_state,
204 outer_rect,
205 outer_rect,
206 outer_rect,
207 resource_yellow,
208 gfx::RectF(outer_size),
209 outer_size,
210 false);
211 scoped_ptr<TileDrawQuad> inner_quad = TileDrawQuad::Create();
212 inner_quad->SetNew(shared_quad_state,
213 inner_rect,
214 inner_rect,
215 inner_rect,
216 resource_cyan,
217 gfx::RectF(inner_size),
218 inner_size,
219 false);
220 root_render_pass->AppendQuad(inner_quad.PassAs<DrawQuad>());
221 root_render_pass->AppendQuad(outer_quad.PassAs<DrawQuad>());
223 RenderPassList list;
224 list.push_back(root_render_pass.PassAs<RenderPass>());
226 float device_scale_factor = 1.f;
227 gfx::Rect device_viewport_rect(outer_size);
228 scoped_ptr<SkBitmap> output =
229 DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
230 EXPECT_EQ(outer_rect.width(), output->info().fWidth);
231 EXPECT_EQ(outer_rect.width(), output->info().fHeight);
233 EXPECT_EQ(SK_ColorYELLOW, output->getColor(0, 0));
234 EXPECT_EQ(SK_ColorYELLOW,
235 output->getColor(outer_size.width() - 1, outer_size.height() - 1));
236 EXPECT_EQ(SK_ColorCYAN, output->getColor(1, 1));
237 EXPECT_EQ(SK_ColorCYAN,
238 output->getColor(inner_size.width() - 1, inner_size.height() - 1));
241 TEST_F(SoftwareRendererTest, TileQuadVisibleRect) {
242 gfx::Size tile_size(100, 100);
243 gfx::Rect tile_rect(tile_size);
244 gfx::Rect visible_rect = tile_rect;
245 visible_rect.Inset(1, 2, 3, 4);
246 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
248 ResourceProvider::ResourceId resource_cyan =
249 resource_provider()->CreateResource(tile_size,
250 GL_CLAMP_TO_EDGE,
251 ResourceProvider::TextureUsageAny,
252 RGBA_8888);
254 SkBitmap cyan_tile; // The lowest five rows are yellow.
255 cyan_tile.setConfig(
256 SkBitmap::kARGB_8888_Config, tile_size.width(), tile_size.height());
257 cyan_tile.allocPixels();
258 cyan_tile.eraseColor(SK_ColorCYAN);
259 cyan_tile.eraseArea(
260 SkIRect::MakeLTRB(
261 0, visible_rect.bottom() - 1, tile_rect.width(), tile_rect.bottom()),
262 SK_ColorYELLOW);
264 resource_provider()->SetPixels(resource_cyan,
265 static_cast<uint8_t*>(cyan_tile.getPixels()),
266 gfx::Rect(tile_size),
267 gfx::Rect(tile_size),
268 gfx::Vector2d());
270 gfx::Rect root_rect(tile_size);
272 RenderPass::Id root_render_pass_id = RenderPass::Id(1, 1);
273 scoped_ptr<TestRenderPass> root_render_pass = TestRenderPass::Create();
274 root_render_pass->SetNew(
275 root_render_pass_id, root_rect, root_rect, gfx::Transform());
276 SharedQuadState* shared_quad_state =
277 root_render_pass->CreateAndAppendSharedQuadState();
278 shared_quad_state->SetAll(gfx::Transform(),
279 tile_size,
280 tile_rect,
281 tile_rect,
282 false,
283 1.0,
284 SkXfermode::kSrcOver_Mode);
285 scoped_ptr<TileDrawQuad> quad = TileDrawQuad::Create();
286 quad->SetNew(shared_quad_state,
287 tile_rect,
288 tile_rect,
289 tile_rect,
290 resource_cyan,
291 gfx::RectF(tile_size),
292 tile_size,
293 false);
294 quad->visible_rect = visible_rect;
295 root_render_pass->AppendQuad(quad.PassAs<DrawQuad>());
297 RenderPassList list;
298 list.push_back(root_render_pass.PassAs<RenderPass>());
300 float device_scale_factor = 1.f;
301 gfx::Rect device_viewport_rect(tile_size);
302 scoped_ptr<SkBitmap> output =
303 DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
304 EXPECT_EQ(tile_rect.width(), output->info().fWidth);
305 EXPECT_EQ(tile_rect.width(), output->info().fHeight);
307 // Check portion of tile not in visible rect isn't drawn.
308 const unsigned int kTransparent = SK_ColorTRANSPARENT;
309 EXPECT_EQ(kTransparent, output->getColor(0, 0));
310 EXPECT_EQ(kTransparent,
311 output->getColor(tile_rect.width() - 1, tile_rect.height() - 1));
312 EXPECT_EQ(kTransparent,
313 output->getColor(visible_rect.x() - 1, visible_rect.y() - 1));
314 EXPECT_EQ(kTransparent,
315 output->getColor(visible_rect.right(), visible_rect.bottom()));
316 // Ensure visible part is drawn correctly.
317 EXPECT_EQ(SK_ColorCYAN, output->getColor(visible_rect.x(), visible_rect.y()));
318 EXPECT_EQ(
319 SK_ColorCYAN,
320 output->getColor(visible_rect.right() - 2, visible_rect.bottom() - 2));
321 // Ensure last visible line is correct.
322 EXPECT_EQ(
323 SK_ColorYELLOW,
324 output->getColor(visible_rect.right() - 1, visible_rect.bottom() - 1));
327 TEST_F(SoftwareRendererTest, ShouldClearRootRenderPass) {
328 float device_scale_factor = 1.f;
329 gfx::Rect device_viewport_rect(0, 0, 100, 100);
331 settings_.should_clear_root_render_pass = false;
332 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
334 RenderPassList list;
336 // Draw a fullscreen green quad in a first frame.
337 RenderPass::Id root_clear_pass_id(1, 0);
338 TestRenderPass* root_clear_pass = AddRenderPass(
339 &list, root_clear_pass_id, device_viewport_rect, gfx::Transform());
340 AddQuad(root_clear_pass, device_viewport_rect, SK_ColorGREEN);
342 renderer()->DecideRenderPassAllocationsForFrame(list);
344 scoped_ptr<SkBitmap> output =
345 DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
346 EXPECT_EQ(device_viewport_rect.width(), output->info().fWidth);
347 EXPECT_EQ(device_viewport_rect.width(), output->info().fHeight);
349 EXPECT_EQ(SK_ColorGREEN, output->getColor(0, 0));
350 EXPECT_EQ(SK_ColorGREEN,
351 output->getColor(device_viewport_rect.width() - 1,
352 device_viewport_rect.height() - 1));
354 list.clear();
356 // Draw a smaller magenta rect without filling the viewport in a separate
357 // frame.
358 gfx::Rect smaller_rect(20, 20, 60, 60);
360 RenderPass::Id root_smaller_pass_id(2, 0);
361 TestRenderPass* root_smaller_pass = AddRenderPass(
362 &list, root_smaller_pass_id, device_viewport_rect, gfx::Transform());
363 AddQuad(root_smaller_pass, smaller_rect, SK_ColorMAGENTA);
365 renderer()->DecideRenderPassAllocationsForFrame(list);
367 output = DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
368 EXPECT_EQ(device_viewport_rect.width(), output->info().fWidth);
369 EXPECT_EQ(device_viewport_rect.width(), output->info().fHeight);
371 // If we didn't clear, the borders should still be green.
372 EXPECT_EQ(SK_ColorGREEN, output->getColor(0, 0));
373 EXPECT_EQ(SK_ColorGREEN,
374 output->getColor(device_viewport_rect.width() - 1,
375 device_viewport_rect.height() - 1));
377 EXPECT_EQ(SK_ColorMAGENTA,
378 output->getColor(smaller_rect.x(), smaller_rect.y()));
379 EXPECT_EQ(
380 SK_ColorMAGENTA,
381 output->getColor(smaller_rect.right() - 1, smaller_rect.bottom() - 1));
384 TEST_F(SoftwareRendererTest, RenderPassVisibleRect) {
385 float device_scale_factor = 1.f;
386 gfx::Rect device_viewport_rect(0, 0, 100, 100);
387 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
389 RenderPassList list;
391 // Pass drawn as inner quad is magenta.
392 gfx::Rect smaller_rect(20, 20, 60, 60);
393 RenderPass::Id smaller_pass_id(2, 1);
394 TestRenderPass* smaller_pass =
395 AddRenderPass(&list, smaller_pass_id, smaller_rect, gfx::Transform());
396 AddQuad(smaller_pass, smaller_rect, SK_ColorMAGENTA);
398 // Root pass is green.
399 RenderPass::Id root_clear_pass_id(1, 0);
400 TestRenderPass* root_clear_pass = AddRenderPass(
401 &list, root_clear_pass_id, device_viewport_rect, gfx::Transform());
402 AddRenderPassQuad(root_clear_pass, smaller_pass);
403 AddQuad(root_clear_pass, device_viewport_rect, SK_ColorGREEN);
405 // Interior pass quad has smaller visible rect.
406 gfx::Rect interior_visible_rect(30, 30, 40, 40);
407 root_clear_pass->quad_list[0]->visible_rect = interior_visible_rect;
409 renderer()->DecideRenderPassAllocationsForFrame(list);
411 scoped_ptr<SkBitmap> output =
412 DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
413 EXPECT_EQ(device_viewport_rect.width(), output->info().fWidth);
414 EXPECT_EQ(device_viewport_rect.width(), output->info().fHeight);
416 EXPECT_EQ(SK_ColorGREEN, output->getColor(0, 0));
417 EXPECT_EQ(SK_ColorGREEN,
418 output->getColor(device_viewport_rect.width() - 1,
419 device_viewport_rect.height() - 1));
421 // Part outside visible rect should remain green.
422 EXPECT_EQ(SK_ColorGREEN,
423 output->getColor(smaller_rect.x(), smaller_rect.y()));
424 EXPECT_EQ(
425 SK_ColorGREEN,
426 output->getColor(smaller_rect.right() - 1, smaller_rect.bottom() - 1));
428 EXPECT_EQ(
429 SK_ColorMAGENTA,
430 output->getColor(interior_visible_rect.x(), interior_visible_rect.y()));
431 EXPECT_EQ(SK_ColorMAGENTA,
432 output->getColor(interior_visible_rect.right() - 1,
433 interior_visible_rect.bottom() - 1));
436 } // namespace
437 } // namespace cc