Adds initial key systems support for Chromecast.
[chromium-blink-merge.git] / cc / output / software_renderer_unittest.cc
blobad88709a71b76f6545346917cc4b23ed69406502
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/geometry_test_utils.h"
20 #include "cc/test/render_pass_test_common.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_ = ResourceProvider::Create(output_surface_.get(),
40 shared_bitmap_manager_.get(),
41 NULL,
43 false,
45 false);
46 renderer_ = SoftwareRenderer::Create(
47 this, &settings_, output_surface_.get(), resource_provider());
50 ResourceProvider* resource_provider() const {
51 return resource_provider_.get();
54 SoftwareRenderer* renderer() const { return renderer_.get(); }
56 // RendererClient implementation.
57 virtual void SetFullRootLayerDamage() OVERRIDE {}
59 scoped_ptr<SkBitmap> DrawAndCopyOutput(RenderPassList* list,
60 float device_scale_factor,
61 gfx::Rect device_viewport_rect) {
62 scoped_ptr<SkBitmap> bitmap_result;
63 base::RunLoop loop;
65 list->back()->copy_requests.push_back(
66 CopyOutputRequest::CreateBitmapRequest(
67 base::Bind(&SoftwareRendererTest::SaveBitmapResult,
68 base::Unretained(&bitmap_result),
69 loop.QuitClosure())));
71 renderer()->DrawFrame(list,
72 device_scale_factor,
73 device_viewport_rect,
74 device_viewport_rect,
75 false);
76 loop.Run();
77 return bitmap_result.Pass();
80 static void SaveBitmapResult(scoped_ptr<SkBitmap>* bitmap_result,
81 const base::Closure& quit_closure,
82 scoped_ptr<CopyOutputResult> result) {
83 DCHECK(result->HasBitmap());
84 *bitmap_result = result->TakeBitmap();
85 quit_closure.Run();
88 protected:
89 LayerTreeSettings settings_;
90 FakeOutputSurfaceClient output_surface_client_;
91 scoped_ptr<FakeOutputSurface> output_surface_;
92 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
93 scoped_ptr<ResourceProvider> resource_provider_;
94 scoped_ptr<SoftwareRenderer> renderer_;
97 TEST_F(SoftwareRendererTest, SolidColorQuad) {
98 gfx::Size outer_size(100, 100);
99 gfx::Size inner_size(98, 98);
100 gfx::Rect outer_rect(outer_size);
101 gfx::Rect inner_rect(gfx::Point(1, 1), inner_size);
102 gfx::Rect visible_rect(gfx::Point(1, 2), gfx::Size(98, 97));
104 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
106 RenderPassId root_render_pass_id = RenderPassId(1, 1);
107 scoped_ptr<TestRenderPass> root_render_pass = TestRenderPass::Create();
108 root_render_pass->SetNew(
109 root_render_pass_id, outer_rect, outer_rect, gfx::Transform());
110 SharedQuadState* shared_quad_state =
111 root_render_pass->CreateAndAppendSharedQuadState();
112 shared_quad_state->SetAll(gfx::Transform(),
113 outer_size,
114 outer_rect,
115 outer_rect,
116 false,
117 1.0,
118 SkXfermode::kSrcOver_Mode,
120 SolidColorDrawQuad* inner_quad =
121 root_render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
122 inner_quad->SetNew(
123 shared_quad_state, inner_rect, inner_rect, SK_ColorCYAN, false);
124 inner_quad->visible_rect = visible_rect;
125 SolidColorDrawQuad* outer_quad =
126 root_render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
127 outer_quad->SetNew(
128 shared_quad_state, outer_rect, outer_rect, SK_ColorYELLOW, false);
130 RenderPassList list;
131 list.push_back(root_render_pass.PassAs<RenderPass>());
133 float device_scale_factor = 1.f;
134 gfx::Rect device_viewport_rect(outer_size);
135 scoped_ptr<SkBitmap> output =
136 DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
137 EXPECT_EQ(outer_rect.width(), output->info().fWidth);
138 EXPECT_EQ(outer_rect.width(), output->info().fHeight);
140 EXPECT_EQ(SK_ColorYELLOW, output->getColor(0, 0));
141 EXPECT_EQ(SK_ColorYELLOW,
142 output->getColor(outer_size.width() - 1, outer_size.height() - 1));
143 EXPECT_EQ(SK_ColorYELLOW, output->getColor(1, 1));
144 EXPECT_EQ(SK_ColorCYAN, output->getColor(1, 2));
145 EXPECT_EQ(SK_ColorCYAN,
146 output->getColor(inner_size.width() - 1, inner_size.height() - 1));
149 TEST_F(SoftwareRendererTest, TileQuad) {
150 gfx::Size outer_size(100, 100);
151 gfx::Size inner_size(98, 98);
152 gfx::Rect outer_rect(outer_size);
153 gfx::Rect inner_rect(gfx::Point(1, 1), inner_size);
154 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
156 ResourceProvider::ResourceId resource_yellow =
157 resource_provider()->CreateResource(
158 outer_size,
159 GL_CLAMP_TO_EDGE,
160 ResourceProvider::TextureHintImmutable,
161 RGBA_8888);
162 ResourceProvider::ResourceId resource_cyan =
163 resource_provider()->CreateResource(
164 inner_size,
165 GL_CLAMP_TO_EDGE,
166 ResourceProvider::TextureHintImmutable,
167 RGBA_8888);
169 SkBitmap yellow_tile;
170 yellow_tile.allocN32Pixels(outer_size.width(), outer_size.height());
171 yellow_tile.eraseColor(SK_ColorYELLOW);
173 SkBitmap cyan_tile;
174 cyan_tile.allocN32Pixels(inner_size.width(), inner_size.height());
175 cyan_tile.eraseColor(SK_ColorCYAN);
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());
189 gfx::Rect root_rect = outer_rect;
191 RenderPassId root_render_pass_id = RenderPassId(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,
205 TileDrawQuad* inner_quad =
206 root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
207 inner_quad->SetNew(shared_quad_state,
208 inner_rect,
209 inner_rect,
210 inner_rect,
211 resource_cyan,
212 gfx::RectF(inner_size),
213 inner_size,
214 false);
215 TileDrawQuad* outer_quad =
216 root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
217 outer_quad->SetNew(shared_quad_state,
218 outer_rect,
219 outer_rect,
220 outer_rect,
221 resource_yellow,
222 gfx::RectF(outer_size),
223 outer_size,
224 false);
226 RenderPassList list;
227 list.push_back(root_render_pass.PassAs<RenderPass>());
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);
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));
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));
251 ResourceProvider::ResourceId resource_cyan =
252 resource_provider()->CreateResource(
253 tile_size,
254 GL_CLAMP_TO_EDGE,
255 ResourceProvider::TextureHintImmutable,
256 RGBA_8888);
258 SkBitmap cyan_tile; // The lowest five rows are yellow.
259 cyan_tile.allocN32Pixels(tile_size.width(), tile_size.height());
260 cyan_tile.eraseColor(SK_ColorCYAN);
261 cyan_tile.eraseArea(
262 SkIRect::MakeLTRB(
263 0, visible_rect.bottom() - 1, tile_rect.width(), tile_rect.bottom()),
264 SK_ColorYELLOW);
266 resource_provider()->SetPixels(resource_cyan,
267 static_cast<uint8_t*>(cyan_tile.getPixels()),
268 gfx::Rect(tile_size),
269 gfx::Rect(tile_size),
270 gfx::Vector2d());
272 gfx::Rect root_rect(tile_size);
274 RenderPassId root_render_pass_id = RenderPassId(1, 1);
275 scoped_ptr<TestRenderPass> root_render_pass = TestRenderPass::Create();
276 root_render_pass->SetNew(
277 root_render_pass_id, root_rect, root_rect, gfx::Transform());
278 SharedQuadState* shared_quad_state =
279 root_render_pass->CreateAndAppendSharedQuadState();
280 shared_quad_state->SetAll(gfx::Transform(),
281 tile_size,
282 tile_rect,
283 tile_rect,
284 false,
285 1.0,
286 SkXfermode::kSrcOver_Mode,
288 TileDrawQuad* quad =
289 root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
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;
300 RenderPassList list;
301 list.push_back(root_render_pass.PassAs<RenderPass>());
303 float device_scale_factor = 1.f;
304 gfx::Rect device_viewport_rect(tile_size);
305 scoped_ptr<SkBitmap> output =
306 DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
307 EXPECT_EQ(tile_rect.width(), output->info().fWidth);
308 EXPECT_EQ(tile_rect.width(), output->info().fHeight);
310 // Check portion of tile not in visible rect isn't drawn.
311 const unsigned int kTransparent = SK_ColorTRANSPARENT;
312 EXPECT_EQ(kTransparent, output->getColor(0, 0));
313 EXPECT_EQ(kTransparent,
314 output->getColor(tile_rect.width() - 1, tile_rect.height() - 1));
315 EXPECT_EQ(kTransparent,
316 output->getColor(visible_rect.x() - 1, visible_rect.y() - 1));
317 EXPECT_EQ(kTransparent,
318 output->getColor(visible_rect.right(), visible_rect.bottom()));
319 // Ensure visible part is drawn correctly.
320 EXPECT_EQ(SK_ColorCYAN, output->getColor(visible_rect.x(), visible_rect.y()));
321 EXPECT_EQ(
322 SK_ColorCYAN,
323 output->getColor(visible_rect.right() - 2, visible_rect.bottom() - 2));
324 // Ensure last visible line is correct.
325 EXPECT_EQ(
326 SK_ColorYELLOW,
327 output->getColor(visible_rect.right() - 1, visible_rect.bottom() - 1));
330 TEST_F(SoftwareRendererTest, ShouldClearRootRenderPass) {
331 float device_scale_factor = 1.f;
332 gfx::Rect device_viewport_rect(0, 0, 100, 100);
334 settings_.should_clear_root_render_pass = false;
335 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
337 RenderPassList list;
339 // Draw a fullscreen green quad in a first frame.
340 RenderPassId root_clear_pass_id(1, 0);
341 TestRenderPass* root_clear_pass = AddRenderPass(
342 &list, root_clear_pass_id, device_viewport_rect, gfx::Transform());
343 AddQuad(root_clear_pass, device_viewport_rect, SK_ColorGREEN);
345 renderer()->DecideRenderPassAllocationsForFrame(list);
347 scoped_ptr<SkBitmap> output =
348 DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
349 EXPECT_EQ(device_viewport_rect.width(), output->info().fWidth);
350 EXPECT_EQ(device_viewport_rect.width(), output->info().fHeight);
352 EXPECT_EQ(SK_ColorGREEN, output->getColor(0, 0));
353 EXPECT_EQ(SK_ColorGREEN,
354 output->getColor(device_viewport_rect.width() - 1,
355 device_viewport_rect.height() - 1));
357 list.clear();
359 // Draw a smaller magenta rect without filling the viewport in a separate
360 // frame.
361 gfx::Rect smaller_rect(20, 20, 60, 60);
363 RenderPassId root_smaller_pass_id(2, 0);
364 TestRenderPass* root_smaller_pass = AddRenderPass(
365 &list, root_smaller_pass_id, device_viewport_rect, gfx::Transform());
366 AddQuad(root_smaller_pass, smaller_rect, SK_ColorMAGENTA);
368 renderer()->DecideRenderPassAllocationsForFrame(list);
370 output = DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
371 EXPECT_EQ(device_viewport_rect.width(), output->info().fWidth);
372 EXPECT_EQ(device_viewport_rect.width(), output->info().fHeight);
374 // If we didn't clear, the borders should still be green.
375 EXPECT_EQ(SK_ColorGREEN, output->getColor(0, 0));
376 EXPECT_EQ(SK_ColorGREEN,
377 output->getColor(device_viewport_rect.width() - 1,
378 device_viewport_rect.height() - 1));
380 EXPECT_EQ(SK_ColorMAGENTA,
381 output->getColor(smaller_rect.x(), smaller_rect.y()));
382 EXPECT_EQ(
383 SK_ColorMAGENTA,
384 output->getColor(smaller_rect.right() - 1, smaller_rect.bottom() - 1));
387 TEST_F(SoftwareRendererTest, RenderPassVisibleRect) {
388 float device_scale_factor = 1.f;
389 gfx::Rect device_viewport_rect(0, 0, 100, 100);
390 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
392 RenderPassList list;
394 // Pass drawn as inner quad is magenta.
395 gfx::Rect smaller_rect(20, 20, 60, 60);
396 RenderPassId smaller_pass_id(2, 1);
397 TestRenderPass* smaller_pass =
398 AddRenderPass(&list, smaller_pass_id, smaller_rect, gfx::Transform());
399 AddQuad(smaller_pass, smaller_rect, SK_ColorMAGENTA);
401 // Root pass is green.
402 RenderPassId root_clear_pass_id(1, 0);
403 TestRenderPass* root_clear_pass = AddRenderPass(
404 &list, root_clear_pass_id, device_viewport_rect, gfx::Transform());
405 AddRenderPassQuad(root_clear_pass, smaller_pass);
406 AddQuad(root_clear_pass, device_viewport_rect, SK_ColorGREEN);
408 // Interior pass quad has smaller visible rect.
409 gfx::Rect interior_visible_rect(30, 30, 40, 40);
410 root_clear_pass->quad_list[0]->visible_rect = interior_visible_rect;
412 renderer()->DecideRenderPassAllocationsForFrame(list);
414 scoped_ptr<SkBitmap> output =
415 DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
416 EXPECT_EQ(device_viewport_rect.width(), output->info().fWidth);
417 EXPECT_EQ(device_viewport_rect.width(), output->info().fHeight);
419 EXPECT_EQ(SK_ColorGREEN, output->getColor(0, 0));
420 EXPECT_EQ(SK_ColorGREEN,
421 output->getColor(device_viewport_rect.width() - 1,
422 device_viewport_rect.height() - 1));
424 // Part outside visible rect should remain green.
425 EXPECT_EQ(SK_ColorGREEN,
426 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