cc: Added inline to Tile::IsReadyToDraw
[chromium-blink-merge.git] / cc / output / software_renderer_unittest.cc
blobba1a0da1f162a55a2a251a5ad22caf543de4645c
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 SoftwareRendererTest() : should_clear_root_render_pass_(true) {}
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 resource_provider_ = ResourceProvider::Create(output_surface_.get(), 0);
39 renderer_ = SoftwareRenderer::Create(
40 this, output_surface_.get(), resource_provider());
43 ResourceProvider* resource_provider() const {
44 return resource_provider_.get();
47 SoftwareRenderer* renderer() const { return renderer_.get(); }
49 void set_viewport(gfx::Rect viewport) {
50 viewport_ = viewport;
53 void set_should_clear_root_render_pass(bool clear_root_render_pass) {
54 should_clear_root_render_pass_ = clear_root_render_pass;
57 // RendererClient implementation.
58 virtual gfx::Rect DeviceViewport() const OVERRIDE {
59 return viewport_;
61 virtual float DeviceScaleFactor() const OVERRIDE {
62 return 1.f;
64 virtual const LayerTreeSettings& Settings() const OVERRIDE {
65 return settings_;
67 virtual void SetFullRootLayerDamage() OVERRIDE {}
68 virtual bool HasImplThread() const OVERRIDE { return false; }
69 virtual bool ShouldClearRootRenderPass() const OVERRIDE {
70 return should_clear_root_render_pass_;
72 virtual CompositorFrameMetadata MakeCompositorFrameMetadata() const OVERRIDE {
73 return CompositorFrameMetadata();
75 virtual bool AllowPartialSwap() const OVERRIDE {
76 return true;
78 virtual bool ExternalStencilTestEnabled() const OVERRIDE { return false; }
80 protected:
81 FakeOutputSurfaceClient output_surface_client_;
82 scoped_ptr<FakeOutputSurface> output_surface_;
83 scoped_ptr<ResourceProvider> resource_provider_;
84 scoped_ptr<SoftwareRenderer> renderer_;
85 gfx::Rect viewport_;
86 LayerTreeSettings settings_;
87 bool should_clear_root_render_pass_;
90 TEST_F(SoftwareRendererTest, SolidColorQuad) {
91 gfx::Size outer_size(100, 100);
92 gfx::Size inner_size(98, 98);
93 gfx::Rect outer_rect(outer_size);
94 gfx::Rect inner_rect(gfx::Point(1, 1), inner_size);
95 gfx::Rect visible_rect(gfx::Point(1, 2), gfx::Size(98, 97));
96 set_viewport(gfx::Rect(outer_size));
98 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
100 scoped_ptr<SharedQuadState> shared_quad_state = SharedQuadState::Create();
101 shared_quad_state->SetAll(
102 gfx::Transform(), outer_size, outer_rect, outer_rect, false, 1.0);
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 scoped_ptr<SolidColorDrawQuad> outer_quad = SolidColorDrawQuad::Create();
108 outer_quad->SetNew(
109 shared_quad_state.get(), outer_rect, SK_ColorYELLOW, false);
110 scoped_ptr<SolidColorDrawQuad> inner_quad = SolidColorDrawQuad::Create();
111 inner_quad->SetNew(shared_quad_state.get(), inner_rect, SK_ColorCYAN, false);
112 inner_quad->visible_rect = visible_rect;
113 root_render_pass->AppendQuad(inner_quad.PassAs<DrawQuad>());
114 root_render_pass->AppendQuad(outer_quad.PassAs<DrawQuad>());
116 RenderPassList list;
117 list.push_back(root_render_pass.PassAs<RenderPass>());
118 renderer()->DrawFrame(&list, NULL);
120 SkBitmap output;
121 output.setConfig(SkBitmap::kARGB_8888_Config,
122 DeviceViewport().width(),
123 DeviceViewport().height());
124 output.allocPixels();
125 renderer()->GetFramebufferPixels(output.getPixels(), outer_rect);
127 EXPECT_EQ(SK_ColorYELLOW, output.getColor(0, 0));
128 EXPECT_EQ(SK_ColorYELLOW,
129 output.getColor(outer_size.width() - 1, outer_size.height() - 1));
130 EXPECT_EQ(SK_ColorYELLOW, output.getColor(1, 1));
131 EXPECT_EQ(SK_ColorCYAN, output.getColor(1, 2));
132 EXPECT_EQ(SK_ColorCYAN,
133 output.getColor(inner_size.width() - 1, inner_size.height() - 1));
136 TEST_F(SoftwareRendererTest, TileQuad) {
137 gfx::Size outer_size(100, 100);
138 gfx::Size inner_size(98, 98);
139 gfx::Rect outer_rect(outer_size);
140 gfx::Rect inner_rect(gfx::Point(1, 1), inner_size);
141 set_viewport(gfx::Rect(outer_size));
142 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
144 ResourceProvider::ResourceId resource_yellow =
145 resource_provider()->CreateResource(
146 outer_size, GL_RGBA, ResourceProvider::TextureUsageAny);
147 ResourceProvider::ResourceId resource_cyan =
148 resource_provider()->CreateResource(
149 inner_size, GL_RGBA, ResourceProvider::TextureUsageAny);
151 SkBitmap yellow_tile;
152 yellow_tile.setConfig(
153 SkBitmap::kARGB_8888_Config, outer_size.width(), outer_size.height());
154 yellow_tile.allocPixels();
155 yellow_tile.eraseColor(SK_ColorYELLOW);
157 SkBitmap cyan_tile;
158 cyan_tile.setConfig(
159 SkBitmap::kARGB_8888_Config, inner_size.width(), inner_size.height());
160 cyan_tile.allocPixels();
161 cyan_tile.eraseColor(SK_ColorCYAN);
163 resource_provider()->SetPixels(
164 resource_yellow,
165 static_cast<uint8_t*>(yellow_tile.getPixels()),
166 gfx::Rect(outer_size),
167 gfx::Rect(outer_size),
168 gfx::Vector2d());
169 resource_provider()->SetPixels(resource_cyan,
170 static_cast<uint8_t*>(cyan_tile.getPixels()),
171 gfx::Rect(inner_size),
172 gfx::Rect(inner_size),
173 gfx::Vector2d());
175 gfx::Rect root_rect = DeviceViewport();
177 scoped_ptr<SharedQuadState> shared_quad_state = SharedQuadState::Create();
178 shared_quad_state->SetAll(
179 gfx::Transform(), outer_size, outer_rect, outer_rect, false, 1.0);
180 RenderPass::Id root_render_pass_id = RenderPass::Id(1, 1);
181 scoped_ptr<TestRenderPass> root_render_pass = TestRenderPass::Create();
182 root_render_pass->SetNew(
183 root_render_pass_id, root_rect, root_rect, gfx::Transform());
184 scoped_ptr<TileDrawQuad> outer_quad = TileDrawQuad::Create();
185 outer_quad->SetNew(shared_quad_state.get(),
186 outer_rect,
187 outer_rect,
188 resource_yellow,
189 gfx::RectF(outer_size),
190 outer_size,
191 false);
192 scoped_ptr<TileDrawQuad> inner_quad = TileDrawQuad::Create();
193 inner_quad->SetNew(shared_quad_state.get(),
194 inner_rect,
195 inner_rect,
196 resource_cyan,
197 gfx::RectF(inner_size),
198 inner_size,
199 false);
200 root_render_pass->AppendQuad(inner_quad.PassAs<DrawQuad>());
201 root_render_pass->AppendQuad(outer_quad.PassAs<DrawQuad>());
203 RenderPassList list;
204 list.push_back(root_render_pass.PassAs<RenderPass>());
205 renderer()->DrawFrame(&list, NULL);
207 SkBitmap output;
208 output.setConfig(SkBitmap::kARGB_8888_Config,
209 DeviceViewport().width(),
210 DeviceViewport().height());
211 output.allocPixels();
212 renderer()->GetFramebufferPixels(output.getPixels(), outer_rect);
214 EXPECT_EQ(SK_ColorYELLOW, output.getColor(0, 0));
215 EXPECT_EQ(SK_ColorYELLOW,
216 output.getColor(outer_size.width() - 1, outer_size.height() - 1));
217 EXPECT_EQ(SK_ColorCYAN, output.getColor(1, 1));
218 EXPECT_EQ(SK_ColorCYAN,
219 output.getColor(inner_size.width() - 1, inner_size.height() - 1));
222 TEST_F(SoftwareRendererTest, TileQuadVisibleRect) {
223 gfx::Size tile_size(100, 100);
224 gfx::Rect tile_rect(tile_size);
225 gfx::Rect visible_rect = tile_rect;
226 visible_rect.Inset(1, 2, 3, 4);
227 set_viewport(gfx::Rect(tile_size));
228 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
230 ResourceProvider::ResourceId resource_cyan =
231 resource_provider()->CreateResource(
232 tile_size, GL_RGBA, ResourceProvider::TextureUsageAny);
234 SkBitmap cyan_tile; // The lowest five rows are yellow.
235 cyan_tile.setConfig(
236 SkBitmap::kARGB_8888_Config, tile_size.width(), tile_size.height());
237 cyan_tile.allocPixels();
238 cyan_tile.eraseColor(SK_ColorCYAN);
239 cyan_tile.eraseArea(
240 SkIRect::MakeLTRB(
241 0, visible_rect.bottom() - 1, tile_rect.width(), tile_rect.bottom()),
242 SK_ColorYELLOW);
244 resource_provider()->SetPixels(resource_cyan,
245 static_cast<uint8_t*>(cyan_tile.getPixels()),
246 gfx::Rect(tile_size),
247 gfx::Rect(tile_size),
248 gfx::Vector2d());
250 gfx::Rect root_rect = DeviceViewport();
252 scoped_ptr<SharedQuadState> shared_quad_state = SharedQuadState::Create();
253 shared_quad_state->SetAll(
254 gfx::Transform(), tile_size, tile_rect, tile_rect, false, 1.0);
255 RenderPass::Id root_render_pass_id = RenderPass::Id(1, 1);
256 scoped_ptr<TestRenderPass> root_render_pass = TestRenderPass::Create();
257 root_render_pass->SetNew(
258 root_render_pass_id, root_rect, root_rect, gfx::Transform());
259 scoped_ptr<TileDrawQuad> quad = TileDrawQuad::Create();
260 quad->SetNew(shared_quad_state.get(),
261 tile_rect,
262 tile_rect,
263 resource_cyan,
264 gfx::RectF(tile_size),
265 tile_size,
266 false);
267 quad->visible_rect = visible_rect;
268 root_render_pass->AppendQuad(quad.PassAs<DrawQuad>());
270 RenderPassList list;
271 list.push_back(root_render_pass.PassAs<RenderPass>());
272 renderer()->DrawFrame(&list, NULL);
274 SkBitmap output;
275 output.setConfig(SkBitmap::kARGB_8888_Config,
276 DeviceViewport().width(),
277 DeviceViewport().height());
278 output.allocPixels();
279 renderer()->GetFramebufferPixels(output.getPixels(), tile_rect);
281 // Check portion of tile not in visible rect isn't drawn.
282 const unsigned int kTransparent = SK_ColorTRANSPARENT;
283 EXPECT_EQ(kTransparent, output.getColor(0, 0));
284 EXPECT_EQ(kTransparent,
285 output.getColor(tile_rect.width() - 1, tile_rect.height() - 1));
286 EXPECT_EQ(kTransparent,
287 output.getColor(visible_rect.x() - 1, visible_rect.y() - 1));
288 EXPECT_EQ(kTransparent,
289 output.getColor(visible_rect.right(), visible_rect.bottom()));
290 // Ensure visible part is drawn correctly.
291 EXPECT_EQ(SK_ColorCYAN, output.getColor(visible_rect.x(), visible_rect.y()));
292 EXPECT_EQ(
293 SK_ColorCYAN,
294 output.getColor(visible_rect.right() - 2, visible_rect.bottom() - 2));
295 // Ensure last visible line is correct.
296 EXPECT_EQ(
297 SK_ColorYELLOW,
298 output.getColor(visible_rect.right() - 1, visible_rect.bottom() - 1));
301 TEST_F(SoftwareRendererTest, ShouldClearRootRenderPass) {
302 gfx::Rect viewport_rect(0, 0, 100, 100);
303 set_viewport(viewport_rect);
304 set_should_clear_root_render_pass(false);
305 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
307 RenderPassList list;
309 SkBitmap output;
310 output.setConfig(SkBitmap::kARGB_8888_Config,
311 viewport_rect.width(),
312 viewport_rect.height());
313 output.allocPixels();
315 // Draw a fullscreen green quad in a first frame.
316 RenderPass::Id root_clear_pass_id(1, 0);
317 TestRenderPass* root_clear_pass = AddRenderPass(
318 &list, root_clear_pass_id, viewport_rect, gfx::Transform());
319 AddQuad(root_clear_pass, viewport_rect, SK_ColorGREEN);
321 renderer()->DecideRenderPassAllocationsForFrame(list);
322 renderer()->DrawFrame(&list, NULL);
323 renderer()->GetFramebufferPixels(output.getPixels(), viewport_rect);
325 EXPECT_EQ(SK_ColorGREEN, output.getColor(0, 0));
326 EXPECT_EQ(SK_ColorGREEN,
327 output.getColor(viewport_rect.width() - 1, viewport_rect.height() - 1));
329 list.clear();
331 // Draw a smaller magenta rect without filling the viewport in a separate
332 // frame.
333 gfx::Rect smaller_rect(20, 20, 60, 60);
335 RenderPass::Id root_smaller_pass_id(2, 0);
336 TestRenderPass* root_smaller_pass = AddRenderPass(
337 &list, root_smaller_pass_id, viewport_rect, gfx::Transform());
338 AddQuad(root_smaller_pass, smaller_rect, SK_ColorMAGENTA);
340 renderer()->DecideRenderPassAllocationsForFrame(list);
341 renderer()->DrawFrame(&list, NULL);
342 renderer()->GetFramebufferPixels(output.getPixels(), viewport_rect);
344 // If we didn't clear, the borders should still be green.
345 EXPECT_EQ(SK_ColorGREEN, output.getColor(0, 0));
346 EXPECT_EQ(SK_ColorGREEN,
347 output.getColor(viewport_rect.width() - 1, viewport_rect.height() - 1));
349 EXPECT_EQ(SK_ColorMAGENTA,
350 output.getColor(smaller_rect.x(), smaller_rect.y()));
351 EXPECT_EQ(SK_ColorMAGENTA,
352 output.getColor(smaller_rect.right() - 1, smaller_rect.bottom() - 1));
355 TEST_F(SoftwareRendererTest, RenderPassVisibleRect) {
356 gfx::Rect viewport_rect(0, 0, 100, 100);
357 set_viewport(viewport_rect);
358 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
360 RenderPassList list;
362 SkBitmap output;
363 output.setConfig(SkBitmap::kARGB_8888_Config,
364 viewport_rect.width(),
365 viewport_rect.height());
366 output.allocPixels();
368 // Pass drawn as inner quad is magenta.
369 gfx::Rect smaller_rect(20, 20, 60, 60);
370 RenderPass::Id smaller_pass_id(2, 1);
371 TestRenderPass* smaller_pass =
372 AddRenderPass(&list, smaller_pass_id, smaller_rect, gfx::Transform());
373 AddQuad(smaller_pass, smaller_rect, SK_ColorMAGENTA);
375 // Root pass is green.
376 RenderPass::Id root_clear_pass_id(1, 0);
377 TestRenderPass* root_clear_pass =
378 AddRenderPass(&list, root_clear_pass_id, viewport_rect, gfx::Transform());
379 AddRenderPassQuad(root_clear_pass, smaller_pass);
380 AddQuad(root_clear_pass, viewport_rect, SK_ColorGREEN);
382 // Interior pass quad has smaller visible rect.
383 gfx::Rect interior_visible_rect(30, 30, 40, 40);
384 root_clear_pass->quad_list[0]->visible_rect = interior_visible_rect;
386 renderer()->DecideRenderPassAllocationsForFrame(list);
387 renderer()->DrawFrame(&list, NULL);
388 renderer()->GetFramebufferPixels(output.getPixels(), viewport_rect);
390 EXPECT_EQ(SK_ColorGREEN, output.getColor(0, 0));
391 EXPECT_EQ(
392 SK_ColorGREEN,
393 output.getColor(viewport_rect.width() - 1, viewport_rect.height() - 1));
395 // Part outside visible rect should remain green.
396 EXPECT_EQ(SK_ColorGREEN, output.getColor(smaller_rect.x(), smaller_rect.y()));
397 EXPECT_EQ(
398 SK_ColorGREEN,
399 output.getColor(smaller_rect.right() - 1, smaller_rect.bottom() - 1));
401 EXPECT_EQ(
402 SK_ColorMAGENTA,
403 output.getColor(interior_visible_rect.x(), interior_visible_rect.y()));
404 EXPECT_EQ(SK_ColorMAGENTA,
405 output.getColor(interior_visible_rect.right() - 1,
406 interior_visible_rect.bottom() - 1));
409 } // namespace
410 } // namespace cc