Add ICU message format support
[chromium-blink-merge.git] / cc / output / software_renderer_unittest.cc
bloba7ef1a20f7d8f760ad1f29635b7a271cf4d63e76
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_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_ = FakeResourceProvider::Create(
41 output_surface_.get(), shared_bitmap_manager_.get());
42 renderer_ = SoftwareRenderer::Create(
43 this, &settings_, output_surface_.get(), resource_provider());
46 ResourceProvider* resource_provider() const {
47 return resource_provider_.get();
50 SoftwareRenderer* renderer() const { return renderer_.get(); }
52 // RendererClient implementation.
53 void SetFullRootLayerDamage() override {}
55 scoped_ptr<SkBitmap> DrawAndCopyOutput(RenderPassList* list,
56 float device_scale_factor,
57 gfx::Rect device_viewport_rect) {
58 scoped_ptr<SkBitmap> bitmap_result;
59 base::RunLoop loop;
61 list->back()->copy_requests.push_back(
62 CopyOutputRequest::CreateBitmapRequest(
63 base::Bind(&SoftwareRendererTest::SaveBitmapResult,
64 base::Unretained(&bitmap_result),
65 loop.QuitClosure())));
67 renderer()->DrawFrame(list,
68 device_scale_factor,
69 device_viewport_rect,
70 device_viewport_rect,
71 false);
72 loop.Run();
73 return bitmap_result.Pass();
76 static void SaveBitmapResult(scoped_ptr<SkBitmap>* bitmap_result,
77 const base::Closure& quit_closure,
78 scoped_ptr<CopyOutputResult> result) {
79 DCHECK(result->HasBitmap());
80 *bitmap_result = result->TakeBitmap();
81 quit_closure.Run();
84 protected:
85 RendererSettings settings_;
86 FakeOutputSurfaceClient output_surface_client_;
87 scoped_ptr<FakeOutputSurface> output_surface_;
88 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
89 scoped_ptr<ResourceProvider> resource_provider_;
90 scoped_ptr<SoftwareRenderer> renderer_;
93 TEST_F(SoftwareRendererTest, SolidColorQuad) {
94 gfx::Size outer_size(100, 100);
95 gfx::Size inner_size(98, 98);
96 gfx::Rect outer_rect(outer_size);
97 gfx::Rect inner_rect(gfx::Point(1, 1), inner_size);
98 gfx::Rect visible_rect(gfx::Point(1, 2), gfx::Size(98, 97));
100 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
102 RenderPassId root_render_pass_id = RenderPassId(1, 1);
103 scoped_ptr<TestRenderPass> root_render_pass = TestRenderPass::Create();
104 root_render_pass->SetNew(
105 root_render_pass_id, outer_rect, outer_rect, gfx::Transform());
106 SharedQuadState* shared_quad_state =
107 root_render_pass->CreateAndAppendSharedQuadState();
108 shared_quad_state->SetAll(gfx::Transform(),
109 outer_size,
110 outer_rect,
111 outer_rect,
112 false,
113 1.0,
114 SkXfermode::kSrcOver_Mode,
116 SolidColorDrawQuad* inner_quad =
117 root_render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
118 inner_quad->SetNew(
119 shared_quad_state, inner_rect, inner_rect, SK_ColorCYAN, false);
120 inner_quad->visible_rect = visible_rect;
121 SolidColorDrawQuad* outer_quad =
122 root_render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
123 outer_quad->SetNew(
124 shared_quad_state, outer_rect, outer_rect, SK_ColorYELLOW, false);
126 RenderPassList list;
127 list.push_back(root_render_pass.Pass());
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().width());
134 EXPECT_EQ(outer_rect.height(), output->info().height());
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 ResourceId resource_yellow = resource_provider()->CreateResource(
153 outer_size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
154 RGBA_8888);
155 ResourceId resource_cyan = resource_provider()->CreateResource(
156 inner_size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
157 RGBA_8888);
159 SkBitmap yellow_tile;
160 yellow_tile.allocN32Pixels(outer_size.width(), outer_size.height());
161 yellow_tile.eraseColor(SK_ColorYELLOW);
163 SkBitmap cyan_tile;
164 cyan_tile.allocN32Pixels(inner_size.width(), inner_size.height());
165 cyan_tile.eraseColor(SK_ColorCYAN);
167 resource_provider()->CopyToResource(
168 resource_yellow, static_cast<uint8_t*>(yellow_tile.getPixels()),
169 outer_size);
170 resource_provider()->CopyToResource(
171 resource_cyan, static_cast<uint8_t*>(cyan_tile.getPixels()), inner_size);
173 gfx::Rect root_rect = outer_rect;
175 RenderPassId root_render_pass_id = RenderPassId(1, 1);
176 scoped_ptr<TestRenderPass> root_render_pass = TestRenderPass::Create();
177 root_render_pass->SetNew(
178 root_render_pass_id, root_rect, root_rect, gfx::Transform());
179 SharedQuadState* shared_quad_state =
180 root_render_pass->CreateAndAppendSharedQuadState();
181 shared_quad_state->SetAll(gfx::Transform(),
182 outer_size,
183 outer_rect,
184 outer_rect,
185 false,
186 1.0,
187 SkXfermode::kSrcOver_Mode,
189 TileDrawQuad* inner_quad =
190 root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
191 inner_quad->SetNew(shared_quad_state,
192 inner_rect,
193 inner_rect,
194 inner_rect,
195 resource_cyan,
196 gfx::RectF(inner_size),
197 inner_size,
198 false,
199 false);
200 TileDrawQuad* outer_quad =
201 root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
202 outer_quad->SetNew(shared_quad_state,
203 outer_rect,
204 outer_rect,
205 outer_rect,
206 resource_yellow,
207 gfx::RectF(outer_size),
208 outer_size,
209 false,
210 false);
212 RenderPassList list;
213 list.push_back(root_render_pass.Pass());
215 float device_scale_factor = 1.f;
216 gfx::Rect device_viewport_rect(outer_size);
217 scoped_ptr<SkBitmap> output =
218 DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
219 EXPECT_EQ(outer_rect.width(), output->info().width());
220 EXPECT_EQ(outer_rect.height(), output->info().height());
222 EXPECT_EQ(SK_ColorYELLOW, output->getColor(0, 0));
223 EXPECT_EQ(SK_ColorYELLOW,
224 output->getColor(outer_size.width() - 1, outer_size.height() - 1));
225 EXPECT_EQ(SK_ColorCYAN, output->getColor(1, 1));
226 EXPECT_EQ(SK_ColorCYAN,
227 output->getColor(inner_size.width() - 1, inner_size.height() - 1));
230 TEST_F(SoftwareRendererTest, TileQuadVisibleRect) {
231 gfx::Size tile_size(100, 100);
232 gfx::Rect tile_rect(tile_size);
233 gfx::Rect visible_rect = tile_rect;
234 visible_rect.Inset(1, 2, 3, 4);
235 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
237 ResourceId resource_cyan = resource_provider()->CreateResource(
238 tile_size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
239 RGBA_8888);
241 SkBitmap cyan_tile; // The lowest five rows are yellow.
242 cyan_tile.allocN32Pixels(tile_size.width(), tile_size.height());
243 cyan_tile.eraseColor(SK_ColorCYAN);
244 cyan_tile.eraseArea(
245 SkIRect::MakeLTRB(
246 0, visible_rect.bottom() - 1, tile_rect.width(), tile_rect.bottom()),
247 SK_ColorYELLOW);
249 resource_provider()->CopyToResource(
250 resource_cyan, static_cast<uint8_t*>(cyan_tile.getPixels()), tile_size);
252 gfx::Rect root_rect(tile_size);
254 RenderPassId root_render_pass_id = RenderPassId(1, 1);
255 scoped_ptr<TestRenderPass> root_render_pass = TestRenderPass::Create();
256 root_render_pass->SetNew(
257 root_render_pass_id, root_rect, root_rect, gfx::Transform());
258 SharedQuadState* shared_quad_state =
259 root_render_pass->CreateAndAppendSharedQuadState();
260 shared_quad_state->SetAll(gfx::Transform(),
261 tile_size,
262 tile_rect,
263 tile_rect,
264 false,
265 1.0,
266 SkXfermode::kSrcOver_Mode,
268 TileDrawQuad* quad =
269 root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
270 quad->SetNew(shared_quad_state,
271 tile_rect,
272 tile_rect,
273 tile_rect,
274 resource_cyan,
275 gfx::RectF(tile_size),
276 tile_size,
277 false,
278 false);
279 quad->visible_rect = visible_rect;
281 RenderPassList list;
282 list.push_back(root_render_pass.Pass());
284 float device_scale_factor = 1.f;
285 gfx::Rect device_viewport_rect(tile_size);
286 scoped_ptr<SkBitmap> output =
287 DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
288 EXPECT_EQ(tile_rect.width(), output->info().width());
289 EXPECT_EQ(tile_rect.height(), output->info().height());
291 // Check portion of tile not in visible rect isn't drawn.
292 const unsigned int kTransparent = SK_ColorTRANSPARENT;
293 EXPECT_EQ(kTransparent, output->getColor(0, 0));
294 EXPECT_EQ(kTransparent,
295 output->getColor(tile_rect.width() - 1, tile_rect.height() - 1));
296 EXPECT_EQ(kTransparent,
297 output->getColor(visible_rect.x() - 1, visible_rect.y() - 1));
298 EXPECT_EQ(kTransparent,
299 output->getColor(visible_rect.right(), visible_rect.bottom()));
300 // Ensure visible part is drawn correctly.
301 EXPECT_EQ(SK_ColorCYAN, output->getColor(visible_rect.x(), visible_rect.y()));
302 EXPECT_EQ(
303 SK_ColorCYAN,
304 output->getColor(visible_rect.right() - 2, visible_rect.bottom() - 2));
305 // Ensure last visible line is correct.
306 EXPECT_EQ(
307 SK_ColorYELLOW,
308 output->getColor(visible_rect.right() - 1, visible_rect.bottom() - 1));
311 TEST_F(SoftwareRendererTest, ShouldClearRootRenderPass) {
312 float device_scale_factor = 1.f;
313 gfx::Rect device_viewport_rect(0, 0, 100, 100);
315 settings_.should_clear_root_render_pass = false;
316 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
318 RenderPassList list;
320 // Draw a fullscreen green quad in a first frame.
321 RenderPassId root_clear_pass_id(1, 0);
322 TestRenderPass* root_clear_pass = AddRenderPass(
323 &list, root_clear_pass_id, device_viewport_rect, gfx::Transform());
324 AddQuad(root_clear_pass, device_viewport_rect, SK_ColorGREEN);
326 renderer()->DecideRenderPassAllocationsForFrame(list);
328 scoped_ptr<SkBitmap> output =
329 DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
330 EXPECT_EQ(device_viewport_rect.width(), output->info().width());
331 EXPECT_EQ(device_viewport_rect.height(), output->info().height());
333 EXPECT_EQ(SK_ColorGREEN, output->getColor(0, 0));
334 EXPECT_EQ(SK_ColorGREEN,
335 output->getColor(device_viewport_rect.width() - 1,
336 device_viewport_rect.height() - 1));
338 list.clear();
340 // Draw a smaller magenta rect without filling the viewport in a separate
341 // frame.
342 gfx::Rect smaller_rect(20, 20, 60, 60);
344 RenderPassId root_smaller_pass_id(2, 0);
345 TestRenderPass* root_smaller_pass = AddRenderPass(
346 &list, root_smaller_pass_id, device_viewport_rect, gfx::Transform());
347 AddQuad(root_smaller_pass, smaller_rect, SK_ColorMAGENTA);
349 renderer()->DecideRenderPassAllocationsForFrame(list);
351 output = DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
352 EXPECT_EQ(device_viewport_rect.width(), output->info().width());
353 EXPECT_EQ(device_viewport_rect.height(), output->info().height());
355 // If we didn't clear, the borders should still be green.
356 EXPECT_EQ(SK_ColorGREEN, output->getColor(0, 0));
357 EXPECT_EQ(SK_ColorGREEN,
358 output->getColor(device_viewport_rect.width() - 1,
359 device_viewport_rect.height() - 1));
361 EXPECT_EQ(SK_ColorMAGENTA,
362 output->getColor(smaller_rect.x(), smaller_rect.y()));
363 EXPECT_EQ(
364 SK_ColorMAGENTA,
365 output->getColor(smaller_rect.right() - 1, smaller_rect.bottom() - 1));
368 TEST_F(SoftwareRendererTest, RenderPassVisibleRect) {
369 float device_scale_factor = 1.f;
370 gfx::Rect device_viewport_rect(0, 0, 100, 100);
371 InitializeRenderer(make_scoped_ptr(new SoftwareOutputDevice));
373 RenderPassList list;
375 // Pass drawn as inner quad is magenta.
376 gfx::Rect smaller_rect(20, 20, 60, 60);
377 RenderPassId smaller_pass_id(2, 1);
378 TestRenderPass* smaller_pass =
379 AddRenderPass(&list, smaller_pass_id, smaller_rect, gfx::Transform());
380 AddQuad(smaller_pass, smaller_rect, SK_ColorMAGENTA);
382 // Root pass is green.
383 RenderPassId root_clear_pass_id(1, 0);
384 TestRenderPass* root_clear_pass = AddRenderPass(
385 &list, root_clear_pass_id, device_viewport_rect, gfx::Transform());
386 AddRenderPassQuad(root_clear_pass, smaller_pass);
387 AddQuad(root_clear_pass, device_viewport_rect, SK_ColorGREEN);
389 // Interior pass quad has smaller visible rect.
390 gfx::Rect interior_visible_rect(30, 30, 40, 40);
391 root_clear_pass->quad_list.front()->visible_rect = interior_visible_rect;
393 renderer()->DecideRenderPassAllocationsForFrame(list);
395 scoped_ptr<SkBitmap> output =
396 DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
397 EXPECT_EQ(device_viewport_rect.width(), output->info().width());
398 EXPECT_EQ(device_viewport_rect.height(), output->info().height());
400 EXPECT_EQ(SK_ColorGREEN, output->getColor(0, 0));
401 EXPECT_EQ(SK_ColorGREEN,
402 output->getColor(device_viewport_rect.width() - 1,
403 device_viewport_rect.height() - 1));
405 // Part outside visible rect should remain green.
406 EXPECT_EQ(SK_ColorGREEN,
407 output->getColor(smaller_rect.x(), smaller_rect.y()));
408 EXPECT_EQ(
409 SK_ColorGREEN,
410 output->getColor(smaller_rect.right() - 1, smaller_rect.bottom() - 1));
412 EXPECT_EQ(
413 SK_ColorMAGENTA,
414 output->getColor(interior_visible_rect.x(), interior_visible_rect.y()));
415 EXPECT_EQ(SK_ColorMAGENTA,
416 output->getColor(interior_visible_rect.right() - 1,
417 interior_visible_rect.bottom() - 1));
420 } // namespace
421 } // namespace cc