Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / cc / output / software_renderer_unittest.cc
blobf587718eb7026bacf096bb2490cf469e4748ce23
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/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/fake_resource_provider.h"
20 #include "cc/test/geometry_test_utils.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"
27 namespace cc {
28 namespace {
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_));
38 shared_bitmap_manager_.reset(new TestSharedBitmapManager());
39 resource_provider_ = FakeResourceProvider::Create(
40 output_surface_.get(), shared_bitmap_manager_.get());
41 renderer_ = SoftwareRenderer::Create(
42 this, &settings_, output_surface_.get(), resource_provider());
45 ResourceProvider* resource_provider() const {
46 return resource_provider_.get();
49 SoftwareRenderer* renderer() const { return renderer_.get(); }
51 // RendererClient implementation.
52 void SetFullRootLayerDamage() override {}
54 scoped_ptr<SkBitmap> DrawAndCopyOutput(RenderPassList* list,
55 float device_scale_factor,
56 gfx::Rect device_viewport_rect) {
57 scoped_ptr<SkBitmap> bitmap_result;
58 base::RunLoop loop;
60 list->back()->copy_requests.push_back(
61 CopyOutputRequest::CreateBitmapRequest(
62 base::Bind(&SoftwareRendererTest::SaveBitmapResult,
63 base::Unretained(&bitmap_result),
64 loop.QuitClosure())));
66 renderer()->DrawFrame(list,
67 device_scale_factor,
68 device_viewport_rect,
69 device_viewport_rect,
70 false);
71 loop.Run();
72 return bitmap_result.Pass();
75 static void SaveBitmapResult(scoped_ptr<SkBitmap>* bitmap_result,
76 const base::Closure& quit_closure,
77 scoped_ptr<CopyOutputResult> result) {
78 DCHECK(result->HasBitmap());
79 *bitmap_result = result->TakeBitmap();
80 quit_closure.Run();
83 protected:
84 RendererSettings settings_;
85 FakeOutputSurfaceClient output_surface_client_;
86 scoped_ptr<FakeOutputSurface> output_surface_;
87 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
88 scoped_ptr<ResourceProvider> resource_provider_;
89 scoped_ptr<SoftwareRenderer> renderer_;
92 TEST_F(SoftwareRendererTest, SolidColorQuad) {
93 gfx::Size outer_size(100, 100);
94 gfx::Size inner_size(98, 98);
95 gfx::Rect outer_rect(outer_size);
96 gfx::Rect inner_rect(gfx::Point(1, 1), inner_size);
97 gfx::Rect visible_rect(gfx::Point(1, 2), gfx::Size(98, 97));
99 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
101 RenderPassId root_render_pass_id = RenderPassId(1, 1);
102 scoped_ptr<RenderPass> root_render_pass = RenderPass::Create();
103 root_render_pass->SetNew(
104 root_render_pass_id, outer_rect, outer_rect, gfx::Transform());
105 SharedQuadState* shared_quad_state =
106 root_render_pass->CreateAndAppendSharedQuadState();
107 shared_quad_state->SetAll(gfx::Transform(),
108 outer_size,
109 outer_rect,
110 outer_rect,
111 false,
112 1.0,
113 SkXfermode::kSrcOver_Mode,
115 SolidColorDrawQuad* inner_quad =
116 root_render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
117 inner_quad->SetNew(
118 shared_quad_state, inner_rect, inner_rect, SK_ColorCYAN, false);
119 inner_quad->visible_rect = visible_rect;
120 SolidColorDrawQuad* outer_quad =
121 root_render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
122 outer_quad->SetNew(
123 shared_quad_state, outer_rect, outer_rect, SK_ColorYELLOW, false);
125 RenderPassList list;
126 list.push_back(root_render_pass.Pass());
128 float device_scale_factor = 1.f;
129 gfx::Rect device_viewport_rect(outer_size);
130 scoped_ptr<SkBitmap> output =
131 DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
132 EXPECT_EQ(outer_rect.width(), output->info().width());
133 EXPECT_EQ(outer_rect.height(), output->info().height());
135 EXPECT_EQ(SK_ColorYELLOW, output->getColor(0, 0));
136 EXPECT_EQ(SK_ColorYELLOW,
137 output->getColor(outer_size.width() - 1, outer_size.height() - 1));
138 EXPECT_EQ(SK_ColorYELLOW, output->getColor(1, 1));
139 EXPECT_EQ(SK_ColorCYAN, output->getColor(1, 2));
140 EXPECT_EQ(SK_ColorCYAN,
141 output->getColor(inner_size.width() - 1, inner_size.height() - 1));
144 TEST_F(SoftwareRendererTest, TileQuad) {
145 gfx::Size outer_size(100, 100);
146 gfx::Size inner_size(98, 98);
147 gfx::Rect outer_rect(outer_size);
148 gfx::Rect inner_rect(gfx::Point(1, 1), inner_size);
149 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
151 ResourceId resource_yellow = resource_provider()->CreateResource(
152 outer_size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
153 RGBA_8888);
154 ResourceId resource_cyan = resource_provider()->CreateResource(
155 inner_size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
156 RGBA_8888);
158 SkBitmap yellow_tile;
159 yellow_tile.allocN32Pixels(outer_size.width(), outer_size.height());
160 yellow_tile.eraseColor(SK_ColorYELLOW);
162 SkBitmap cyan_tile;
163 cyan_tile.allocN32Pixels(inner_size.width(), inner_size.height());
164 cyan_tile.eraseColor(SK_ColorCYAN);
166 resource_provider()->CopyToResource(
167 resource_yellow, static_cast<uint8_t*>(yellow_tile.getPixels()),
168 outer_size);
169 resource_provider()->CopyToResource(
170 resource_cyan, static_cast<uint8_t*>(cyan_tile.getPixels()), inner_size);
172 gfx::Rect root_rect = outer_rect;
174 RenderPassId root_render_pass_id = RenderPassId(1, 1);
175 scoped_ptr<RenderPass> root_render_pass = RenderPass::Create();
176 root_render_pass->SetNew(
177 root_render_pass_id, root_rect, root_rect, gfx::Transform());
178 SharedQuadState* shared_quad_state =
179 root_render_pass->CreateAndAppendSharedQuadState();
180 shared_quad_state->SetAll(gfx::Transform(),
181 outer_size,
182 outer_rect,
183 outer_rect,
184 false,
185 1.0,
186 SkXfermode::kSrcOver_Mode,
188 TileDrawQuad* inner_quad =
189 root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
190 inner_quad->SetNew(shared_quad_state,
191 inner_rect,
192 inner_rect,
193 inner_rect,
194 resource_cyan,
195 gfx::RectF(inner_size),
196 inner_size,
197 false,
198 false);
199 TileDrawQuad* outer_quad =
200 root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
201 outer_quad->SetNew(shared_quad_state,
202 outer_rect,
203 outer_rect,
204 outer_rect,
205 resource_yellow,
206 gfx::RectF(outer_size),
207 outer_size,
208 false,
209 false);
211 RenderPassList list;
212 list.push_back(root_render_pass.Pass());
214 float device_scale_factor = 1.f;
215 gfx::Rect device_viewport_rect(outer_size);
216 scoped_ptr<SkBitmap> output =
217 DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
218 EXPECT_EQ(outer_rect.width(), output->info().width());
219 EXPECT_EQ(outer_rect.height(), output->info().height());
221 EXPECT_EQ(SK_ColorYELLOW, output->getColor(0, 0));
222 EXPECT_EQ(SK_ColorYELLOW,
223 output->getColor(outer_size.width() - 1, outer_size.height() - 1));
224 EXPECT_EQ(SK_ColorCYAN, output->getColor(1, 1));
225 EXPECT_EQ(SK_ColorCYAN,
226 output->getColor(inner_size.width() - 1, inner_size.height() - 1));
229 TEST_F(SoftwareRendererTest, TileQuadVisibleRect) {
230 gfx::Size tile_size(100, 100);
231 gfx::Rect tile_rect(tile_size);
232 gfx::Rect visible_rect = tile_rect;
233 visible_rect.Inset(1, 2, 3, 4);
234 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
236 ResourceId resource_cyan = resource_provider()->CreateResource(
237 tile_size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
238 RGBA_8888);
240 SkBitmap cyan_tile; // The lowest five rows are yellow.
241 cyan_tile.allocN32Pixels(tile_size.width(), tile_size.height());
242 cyan_tile.eraseColor(SK_ColorCYAN);
243 cyan_tile.eraseArea(
244 SkIRect::MakeLTRB(
245 0, visible_rect.bottom() - 1, tile_rect.width(), tile_rect.bottom()),
246 SK_ColorYELLOW);
248 resource_provider()->CopyToResource(
249 resource_cyan, static_cast<uint8_t*>(cyan_tile.getPixels()), tile_size);
251 gfx::Rect root_rect(tile_size);
253 RenderPassId root_render_pass_id = RenderPassId(1, 1);
254 scoped_ptr<RenderPass> root_render_pass = RenderPass::Create();
255 root_render_pass->SetNew(
256 root_render_pass_id, root_rect, root_rect, gfx::Transform());
257 SharedQuadState* shared_quad_state =
258 root_render_pass->CreateAndAppendSharedQuadState();
259 shared_quad_state->SetAll(gfx::Transform(),
260 tile_size,
261 tile_rect,
262 tile_rect,
263 false,
264 1.0,
265 SkXfermode::kSrcOver_Mode,
267 TileDrawQuad* quad =
268 root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
269 quad->SetNew(shared_quad_state,
270 tile_rect,
271 tile_rect,
272 tile_rect,
273 resource_cyan,
274 gfx::RectF(tile_size),
275 tile_size,
276 false,
277 false);
278 quad->visible_rect = visible_rect;
280 RenderPassList list;
281 list.push_back(root_render_pass.Pass());
283 float device_scale_factor = 1.f;
284 gfx::Rect device_viewport_rect(tile_size);
285 scoped_ptr<SkBitmap> output =
286 DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
287 EXPECT_EQ(tile_rect.width(), output->info().width());
288 EXPECT_EQ(tile_rect.height(), output->info().height());
290 // Check portion of tile not in visible rect isn't drawn.
291 const unsigned int kTransparent = SK_ColorTRANSPARENT;
292 EXPECT_EQ(kTransparent, output->getColor(0, 0));
293 EXPECT_EQ(kTransparent,
294 output->getColor(tile_rect.width() - 1, tile_rect.height() - 1));
295 EXPECT_EQ(kTransparent,
296 output->getColor(visible_rect.x() - 1, visible_rect.y() - 1));
297 EXPECT_EQ(kTransparent,
298 output->getColor(visible_rect.right(), visible_rect.bottom()));
299 // Ensure visible part is drawn correctly.
300 EXPECT_EQ(SK_ColorCYAN, output->getColor(visible_rect.x(), visible_rect.y()));
301 EXPECT_EQ(
302 SK_ColorCYAN,
303 output->getColor(visible_rect.right() - 2, visible_rect.bottom() - 2));
304 // Ensure last visible line is correct.
305 EXPECT_EQ(
306 SK_ColorYELLOW,
307 output->getColor(visible_rect.right() - 1, visible_rect.bottom() - 1));
310 TEST_F(SoftwareRendererTest, ShouldClearRootRenderPass) {
311 float device_scale_factor = 1.f;
312 gfx::Rect device_viewport_rect(0, 0, 100, 100);
314 settings_.should_clear_root_render_pass = false;
315 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
317 RenderPassList list;
319 // Draw a fullscreen green quad in a first frame.
320 RenderPassId root_clear_pass_id(1, 0);
321 RenderPass* root_clear_pass = AddRenderPass(
322 &list, root_clear_pass_id, device_viewport_rect, gfx::Transform());
323 AddQuad(root_clear_pass, device_viewport_rect, SK_ColorGREEN);
325 renderer()->DecideRenderPassAllocationsForFrame(list);
327 scoped_ptr<SkBitmap> output =
328 DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
329 EXPECT_EQ(device_viewport_rect.width(), output->info().width());
330 EXPECT_EQ(device_viewport_rect.height(), output->info().height());
332 EXPECT_EQ(SK_ColorGREEN, output->getColor(0, 0));
333 EXPECT_EQ(SK_ColorGREEN,
334 output->getColor(device_viewport_rect.width() - 1,
335 device_viewport_rect.height() - 1));
337 list.clear();
339 // Draw a smaller magenta rect without filling the viewport in a separate
340 // frame.
341 gfx::Rect smaller_rect(20, 20, 60, 60);
343 RenderPassId root_smaller_pass_id(2, 0);
344 RenderPass* root_smaller_pass = AddRenderPass(
345 &list, root_smaller_pass_id, device_viewport_rect, gfx::Transform());
346 AddQuad(root_smaller_pass, smaller_rect, SK_ColorMAGENTA);
348 renderer()->DecideRenderPassAllocationsForFrame(list);
350 output = DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
351 EXPECT_EQ(device_viewport_rect.width(), output->info().width());
352 EXPECT_EQ(device_viewport_rect.height(), output->info().height());
354 // If we didn't clear, the borders should still be green.
355 EXPECT_EQ(SK_ColorGREEN, output->getColor(0, 0));
356 EXPECT_EQ(SK_ColorGREEN,
357 output->getColor(device_viewport_rect.width() - 1,
358 device_viewport_rect.height() - 1));
360 EXPECT_EQ(SK_ColorMAGENTA,
361 output->getColor(smaller_rect.x(), smaller_rect.y()));
362 EXPECT_EQ(
363 SK_ColorMAGENTA,
364 output->getColor(smaller_rect.right() - 1, smaller_rect.bottom() - 1));
367 TEST_F(SoftwareRendererTest, RenderPassVisibleRect) {
368 float device_scale_factor = 1.f;
369 gfx::Rect device_viewport_rect(0, 0, 100, 100);
370 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
372 RenderPassList list;
374 // Pass drawn as inner quad is magenta.
375 gfx::Rect smaller_rect(20, 20, 60, 60);
376 RenderPassId smaller_pass_id(2, 1);
377 RenderPass* smaller_pass =
378 AddRenderPass(&list, smaller_pass_id, smaller_rect, gfx::Transform());
379 AddQuad(smaller_pass, smaller_rect, SK_ColorMAGENTA);
381 // Root pass is green.
382 RenderPassId root_clear_pass_id(1, 0);
383 RenderPass* root_clear_pass = AddRenderPass(
384 &list, root_clear_pass_id, device_viewport_rect, gfx::Transform());
385 AddRenderPassQuad(root_clear_pass, smaller_pass);
386 AddQuad(root_clear_pass, device_viewport_rect, SK_ColorGREEN);
388 // Interior pass quad has smaller visible rect.
389 gfx::Rect interior_visible_rect(30, 30, 40, 40);
390 root_clear_pass->quad_list.front()->visible_rect = interior_visible_rect;
392 renderer()->DecideRenderPassAllocationsForFrame(list);
394 scoped_ptr<SkBitmap> output =
395 DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
396 EXPECT_EQ(device_viewport_rect.width(), output->info().width());
397 EXPECT_EQ(device_viewport_rect.height(), output->info().height());
399 EXPECT_EQ(SK_ColorGREEN, output->getColor(0, 0));
400 EXPECT_EQ(SK_ColorGREEN,
401 output->getColor(device_viewport_rect.width() - 1,
402 device_viewport_rect.height() - 1));
404 // Part outside visible rect should remain green.
405 EXPECT_EQ(SK_ColorGREEN,
406 output->getColor(smaller_rect.x(), smaller_rect.y()));
407 EXPECT_EQ(
408 SK_ColorGREEN,
409 output->getColor(smaller_rect.right() - 1, smaller_rect.bottom() - 1));
411 EXPECT_EQ(
412 SK_ColorMAGENTA,
413 output->getColor(interior_visible_rect.x(), interior_visible_rect.y()));
414 EXPECT_EQ(SK_ColorMAGENTA,
415 output->getColor(interior_visible_rect.right() - 1,
416 interior_visible_rect.bottom() - 1));
419 } // namespace
420 } // namespace cc