Include all dupe types (event when value is zero) in scan stats.
[chromium-blink-merge.git] / cc / output / renderer_pixeltest.cc
blob136550c528e229f70b867c9ebf0cbe2a8d9b6415
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 "base/message_loop/message_loop.h"
6 #include "cc/output/gl_renderer.h"
7 #include "cc/quads/draw_quad.h"
8 #include "cc/quads/picture_draw_quad.h"
9 #include "cc/quads/texture_draw_quad.h"
10 #include "cc/resources/video_resource_updater.h"
11 #include "cc/test/fake_picture_pile_impl.h"
12 #include "cc/test/pixel_test.h"
13 #include "gpu/command_buffer/client/gles2_interface.h"
14 #include "media/base/video_frame.h"
15 #include "third_party/skia/include/core/SkColorPriv.h"
16 #include "third_party/skia/include/core/SkImageFilter.h"
17 #include "third_party/skia/include/core/SkMatrix.h"
18 #include "third_party/skia/include/effects/SkColorFilterImageFilter.h"
19 #include "third_party/skia/include/effects/SkColorMatrixFilter.h"
20 #include "ui/gfx/geometry/rect_conversions.h"
22 using gpu::gles2::GLES2Interface;
24 namespace cc {
25 namespace {
27 #if !defined(OS_ANDROID)
28 scoped_ptr<RenderPass> CreateTestRootRenderPass(RenderPassId id,
29 const gfx::Rect& rect) {
30 scoped_ptr<RenderPass> pass = RenderPass::Create();
31 const gfx::Rect output_rect = rect;
32 const gfx::Rect damage_rect = rect;
33 const gfx::Transform transform_to_root_target;
34 pass->SetNew(id, output_rect, damage_rect, transform_to_root_target);
35 return pass.Pass();
38 scoped_ptr<RenderPass> CreateTestRenderPass(
39 RenderPassId id,
40 const gfx::Rect& rect,
41 const gfx::Transform& transform_to_root_target) {
42 scoped_ptr<RenderPass> pass = RenderPass::Create();
43 const gfx::Rect output_rect = rect;
44 const gfx::Rect damage_rect = rect;
45 pass->SetNew(id, output_rect, damage_rect, transform_to_root_target);
46 return pass.Pass();
49 SharedQuadState* CreateTestSharedQuadState(
50 gfx::Transform content_to_target_transform,
51 const gfx::Rect& rect,
52 RenderPass* render_pass) {
53 const gfx::Size content_bounds = rect.size();
54 const gfx::Rect visible_content_rect = rect;
55 const gfx::Rect clip_rect = rect;
56 const bool is_clipped = false;
57 const float opacity = 1.0f;
58 const SkXfermode::Mode blend_mode = SkXfermode::kSrcOver_Mode;
59 int sorting_context_id = 0;
60 SharedQuadState* shared_state = render_pass->CreateAndAppendSharedQuadState();
61 shared_state->SetAll(content_to_target_transform,
62 content_bounds,
63 visible_content_rect,
64 clip_rect,
65 is_clipped,
66 opacity,
67 blend_mode,
68 sorting_context_id);
69 return shared_state;
72 SharedQuadState* CreateTestSharedQuadStateClipped(
73 gfx::Transform content_to_target_transform,
74 const gfx::Rect& rect,
75 const gfx::Rect& clip_rect,
76 RenderPass* render_pass) {
77 const gfx::Size content_bounds = rect.size();
78 const gfx::Rect visible_content_rect = clip_rect;
79 const bool is_clipped = true;
80 const float opacity = 1.0f;
81 const SkXfermode::Mode blend_mode = SkXfermode::kSrcOver_Mode;
82 int sorting_context_id = 0;
83 SharedQuadState* shared_state = render_pass->CreateAndAppendSharedQuadState();
84 shared_state->SetAll(content_to_target_transform,
85 content_bounds,
86 visible_content_rect,
87 clip_rect,
88 is_clipped,
89 opacity,
90 blend_mode,
91 sorting_context_id);
92 return shared_state;
95 void CreateTestRenderPassDrawQuad(const SharedQuadState* shared_state,
96 const gfx::Rect& rect,
97 RenderPassId pass_id,
98 RenderPass* render_pass) {
99 RenderPassDrawQuad* quad =
100 render_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
101 quad->SetNew(shared_state,
102 rect,
103 rect,
104 pass_id,
105 0, // mask_resource_id
106 gfx::Vector2dF(), // mask_uv_scale
107 gfx::Size(), // mask_texture_size
108 FilterOperations(), // foreground filters
109 gfx::Vector2dF(), // filters scale
110 FilterOperations()); // background filters
113 void CreateTestTwoColoredTextureDrawQuad(const gfx::Rect& rect,
114 SkColor texel_color,
115 SkColor texel_stripe_color,
116 SkColor background_color,
117 bool premultiplied_alpha,
118 const SharedQuadState* shared_state,
119 ResourceProvider* resource_provider,
120 RenderPass* render_pass) {
121 SkPMColor pixel_color = premultiplied_alpha
122 ? SkPreMultiplyColor(texel_color)
123 : SkPackARGB32NoCheck(SkColorGetA(texel_color),
124 SkColorGetR(texel_color),
125 SkColorGetG(texel_color),
126 SkColorGetB(texel_color));
127 SkPMColor pixel_stripe_color =
128 premultiplied_alpha
129 ? SkPreMultiplyColor(texel_stripe_color)
130 : SkPackARGB32NoCheck(SkColorGetA(texel_stripe_color),
131 SkColorGetR(texel_stripe_color),
132 SkColorGetG(texel_stripe_color),
133 SkColorGetB(texel_stripe_color));
134 std::vector<uint32_t> pixels(rect.size().GetArea(), pixel_color);
135 for (int i = rect.height() / 4; i < (rect.height() * 3 / 4); ++i) {
136 for (int k = rect.width() / 4; k < (rect.width() * 3 / 4); ++k) {
137 pixels[i * rect.width() + k] = pixel_stripe_color;
140 ResourceId resource = resource_provider->CreateResource(
141 rect.size(), GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
142 RGBA_8888);
143 resource_provider->SetPixels(resource,
144 reinterpret_cast<uint8_t*>(&pixels.front()),
145 rect, rect, gfx::Vector2d());
147 float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
148 const gfx::PointF uv_top_left(0.0f, 0.0f);
149 const gfx::PointF uv_bottom_right(1.0f, 1.0f);
150 const bool flipped = false;
151 const bool nearest_neighbor = false;
152 TextureDrawQuad* quad =
153 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
154 quad->SetNew(shared_state, rect, gfx::Rect(), rect, resource,
155 premultiplied_alpha, uv_top_left, uv_bottom_right,
156 background_color, vertex_opacity, flipped, nearest_neighbor);
159 void CreateTestTextureDrawQuad(const gfx::Rect& rect,
160 SkColor texel_color,
161 SkColor background_color,
162 bool premultiplied_alpha,
163 const SharedQuadState* shared_state,
164 ResourceProvider* resource_provider,
165 RenderPass* render_pass) {
166 SkPMColor pixel_color = premultiplied_alpha ?
167 SkPreMultiplyColor(texel_color) :
168 SkPackARGB32NoCheck(SkColorGetA(texel_color),
169 SkColorGetR(texel_color),
170 SkColorGetG(texel_color),
171 SkColorGetB(texel_color));
172 size_t num_pixels = static_cast<size_t>(rect.width()) * rect.height();
173 std::vector<uint32_t> pixels(num_pixels, pixel_color);
175 ResourceId resource = resource_provider->CreateResource(
176 rect.size(), GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
177 RGBA_8888);
178 resource_provider->CopyToResource(
179 resource, reinterpret_cast<uint8_t*>(&pixels.front()), rect.size());
181 float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
183 const gfx::PointF uv_top_left(0.0f, 0.0f);
184 const gfx::PointF uv_bottom_right(1.0f, 1.0f);
185 const bool flipped = false;
186 const bool nearest_neighbor = false;
187 TextureDrawQuad* quad =
188 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
189 quad->SetNew(shared_state, rect, gfx::Rect(), rect, resource,
190 premultiplied_alpha, uv_top_left, uv_bottom_right,
191 background_color, vertex_opacity, flipped, nearest_neighbor);
194 void CreateTestYUVVideoDrawQuad_FromVideoFrame(
195 const SharedQuadState* shared_state,
196 scoped_refptr<media::VideoFrame> video_frame,
197 uint8 alpha_value,
198 const gfx::RectF& tex_coord_rect,
199 RenderPass* render_pass,
200 VideoResourceUpdater* video_resource_updater,
201 const gfx::Rect& rect,
202 const gfx::Rect& visible_rect,
203 ResourceProvider* resource_provider) {
204 const bool with_alpha = (video_frame->format() == media::VideoFrame::YV12A);
205 YUVVideoDrawQuad::ColorSpace color_space = YUVVideoDrawQuad::REC_601;
206 int video_frame_color_space;
207 if (video_frame->metadata()->GetInteger(
208 media::VideoFrameMetadata::COLOR_SPACE, &video_frame_color_space) &&
209 video_frame_color_space == media::VideoFrame::COLOR_SPACE_JPEG) {
210 color_space = YUVVideoDrawQuad::JPEG;
213 const gfx::Rect opaque_rect(0, 0, 0, 0);
215 if (with_alpha) {
216 memset(video_frame->data(media::VideoFrame::kAPlane), alpha_value,
217 video_frame->stride(media::VideoFrame::kAPlane) *
218 video_frame->rows(media::VideoFrame::kAPlane));
221 VideoFrameExternalResources resources =
222 video_resource_updater->CreateExternalResourcesFromVideoFrame(
223 video_frame);
225 EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE, resources.type);
226 EXPECT_EQ(media::VideoFrame::NumPlanes(video_frame->format()),
227 resources.mailboxes.size());
228 EXPECT_EQ(media::VideoFrame::NumPlanes(video_frame->format()),
229 resources.release_callbacks.size());
231 ResourceId y_resource = resource_provider->CreateResourceFromTextureMailbox(
232 resources.mailboxes[media::VideoFrame::kYPlane],
233 SingleReleaseCallbackImpl::Create(
234 resources.release_callbacks[media::VideoFrame::kYPlane]));
235 ResourceId u_resource = resource_provider->CreateResourceFromTextureMailbox(
236 resources.mailboxes[media::VideoFrame::kUPlane],
237 SingleReleaseCallbackImpl::Create(
238 resources.release_callbacks[media::VideoFrame::kUPlane]));
239 ResourceId v_resource = resource_provider->CreateResourceFromTextureMailbox(
240 resources.mailboxes[media::VideoFrame::kVPlane],
241 SingleReleaseCallbackImpl::Create(
242 resources.release_callbacks[media::VideoFrame::kVPlane]));
243 ResourceId a_resource = 0;
244 if (with_alpha) {
245 a_resource = resource_provider->CreateResourceFromTextureMailbox(
246 resources.mailboxes[media::VideoFrame::kAPlane],
247 SingleReleaseCallbackImpl::Create(
248 resources.release_callbacks[media::VideoFrame::kAPlane]));
251 const gfx::Size ya_tex_size = video_frame->coded_size();
252 const gfx::Size uv_tex_size = media::VideoFrame::PlaneSize(
253 video_frame->format(), media::VideoFrame::kUPlane,
254 video_frame->coded_size());
255 DCHECK(uv_tex_size == media::VideoFrame::PlaneSize(
256 video_frame->format(), media::VideoFrame::kVPlane,
257 video_frame->coded_size()));
258 if (with_alpha) {
259 DCHECK(ya_tex_size == media::VideoFrame::PlaneSize(
260 video_frame->format(), media::VideoFrame::kAPlane,
261 video_frame->coded_size()));
264 gfx::RectF ya_tex_coord_rect(tex_coord_rect.x() * ya_tex_size.width(),
265 tex_coord_rect.y() * ya_tex_size.height(),
266 tex_coord_rect.width() * ya_tex_size.width(),
267 tex_coord_rect.height() * ya_tex_size.height());
268 gfx::RectF uv_tex_coord_rect(tex_coord_rect.x() * uv_tex_size.width(),
269 tex_coord_rect.y() * uv_tex_size.height(),
270 tex_coord_rect.width() * uv_tex_size.width(),
271 tex_coord_rect.height() * uv_tex_size.height());
273 YUVVideoDrawQuad* yuv_quad =
274 render_pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>();
275 yuv_quad->SetNew(shared_state, rect, opaque_rect, visible_rect,
276 ya_tex_coord_rect, uv_tex_coord_rect, ya_tex_size,
277 uv_tex_size, y_resource, u_resource, v_resource, a_resource,
278 color_space);
281 void CreateTestYUVVideoDrawQuad_Striped(
282 const SharedQuadState* shared_state,
283 media::VideoFrame::Format format,
284 bool is_transparent,
285 const gfx::RectF& tex_coord_rect,
286 RenderPass* render_pass,
287 VideoResourceUpdater* video_resource_updater,
288 const gfx::Rect& rect,
289 const gfx::Rect& visible_rect,
290 ResourceProvider* resource_provider) {
291 scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame(
292 format, rect.size(), rect, rect.size(), base::TimeDelta());
294 // YUV values representing a striped pattern, for validating texture
295 // coordinates for sampling.
296 uint8_t y_value = 0;
297 uint8_t u_value = 0;
298 uint8_t v_value = 0;
299 for (int i = 0; i < video_frame->rows(media::VideoFrame::kYPlane); ++i) {
300 uint8_t* y_row = video_frame->data(media::VideoFrame::kYPlane) +
301 video_frame->stride(media::VideoFrame::kYPlane) * i;
302 for (int j = 0; j < video_frame->row_bytes(media::VideoFrame::kYPlane);
303 ++j) {
304 y_row[j] = (y_value += 1);
307 for (int i = 0; i < video_frame->rows(media::VideoFrame::kUPlane); ++i) {
308 uint8_t* u_row = video_frame->data(media::VideoFrame::kUPlane) +
309 video_frame->stride(media::VideoFrame::kUPlane) * i;
310 uint8_t* v_row = video_frame->data(media::VideoFrame::kVPlane) +
311 video_frame->stride(media::VideoFrame::kVPlane) * i;
312 for (int j = 0; j < video_frame->row_bytes(media::VideoFrame::kUPlane);
313 ++j) {
314 u_row[j] = (u_value += 3);
315 v_row[j] = (v_value += 5);
318 uint8 alpha_value = is_transparent ? 0 : 128;
319 CreateTestYUVVideoDrawQuad_FromVideoFrame(
320 shared_state, video_frame, alpha_value, tex_coord_rect, render_pass,
321 video_resource_updater, rect, visible_rect, resource_provider);
324 // Creates a video frame of size background_size filled with yuv_background,
325 // and then draws a foreground rectangle in a different color on top of
326 // that. The foreground rectangle must have coordinates that are divisible
327 // by 2 because YUV is a block format.
328 void CreateTestYUVVideoDrawQuad_TwoColor(
329 const SharedQuadState* shared_state,
330 media::VideoFrame::Format format,
331 media::VideoFrame::ColorSpace color_space,
332 bool is_transparent,
333 const gfx::RectF& tex_coord_rect,
334 const gfx::Size& background_size,
335 const gfx::Rect& visible_rect,
336 uint8 y_background,
337 uint8 u_background,
338 uint8 v_background,
339 const gfx::Rect& foreground_rect,
340 uint8 y_foreground,
341 uint8 u_foreground,
342 uint8 v_foreground,
343 RenderPass* render_pass,
344 VideoResourceUpdater* video_resource_updater,
345 ResourceProvider* resource_provider) {
346 const gfx::Rect rect(background_size);
348 scoped_refptr<media::VideoFrame> video_frame =
349 media::VideoFrame::CreateFrame(format, background_size, foreground_rect,
350 foreground_rect.size(), base::TimeDelta());
351 video_frame->metadata()->SetInteger(media::VideoFrameMetadata::COLOR_SPACE,
352 color_space);
354 int planes[] = {media::VideoFrame::kYPlane,
355 media::VideoFrame::kUPlane,
356 media::VideoFrame::kVPlane};
357 uint8 yuv_background[] = {y_background, u_background, v_background};
358 uint8 yuv_foreground[] = {y_foreground, u_foreground, v_foreground};
359 int sample_size[] = {1, 2, 2};
361 for (int i = 0; i < 3; ++i) {
362 memset(video_frame->data(planes[i]), yuv_background[i],
363 video_frame->stride(planes[i]) * video_frame->rows(planes[i]));
366 for (int i = 0; i < 3; ++i) {
367 // Since yuv encoding uses block encoding, widths have to be divisible
368 // by the sample size in order for this function to behave properly.
369 DCHECK_EQ(foreground_rect.x() % sample_size[i], 0);
370 DCHECK_EQ(foreground_rect.y() % sample_size[i], 0);
371 DCHECK_EQ(foreground_rect.width() % sample_size[i], 0);
372 DCHECK_EQ(foreground_rect.height() % sample_size[i], 0);
374 gfx::Rect sample_rect(foreground_rect.x() / sample_size[i],
375 foreground_rect.y() / sample_size[i],
376 foreground_rect.width() / sample_size[i],
377 foreground_rect.height() / sample_size[i]);
378 for (int y = sample_rect.y(); y < sample_rect.bottom(); ++y) {
379 for (int x = sample_rect.x(); x < sample_rect.right(); ++x) {
380 size_t offset = y * video_frame->stride(planes[i]) + x;
381 video_frame->data(planes[i])[offset] = yuv_foreground[i];
386 uint8 alpha_value = 255;
387 CreateTestYUVVideoDrawQuad_FromVideoFrame(
388 shared_state, video_frame, alpha_value, tex_coord_rect, render_pass,
389 video_resource_updater, rect, visible_rect, resource_provider);
392 void CreateTestYUVVideoDrawQuad_Solid(
393 const SharedQuadState* shared_state,
394 media::VideoFrame::Format format,
395 media::VideoFrame::ColorSpace color_space,
396 bool is_transparent,
397 const gfx::RectF& tex_coord_rect,
398 uint8 y,
399 uint8 u,
400 uint8 v,
401 RenderPass* render_pass,
402 VideoResourceUpdater* video_resource_updater,
403 const gfx::Rect& rect,
404 const gfx::Rect& visible_rect,
405 ResourceProvider* resource_provider) {
406 scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame(
407 format, rect.size(), rect, rect.size(), base::TimeDelta());
408 video_frame->metadata()->SetInteger(media::VideoFrameMetadata::COLOR_SPACE,
409 color_space);
411 // YUV values of a solid, constant, color. Useful for testing that color
412 // space/color range are being handled properly.
413 memset(video_frame->data(media::VideoFrame::kYPlane), y,
414 video_frame->stride(media::VideoFrame::kYPlane) *
415 video_frame->rows(media::VideoFrame::kYPlane));
416 memset(video_frame->data(media::VideoFrame::kUPlane), u,
417 video_frame->stride(media::VideoFrame::kUPlane) *
418 video_frame->rows(media::VideoFrame::kUPlane));
419 memset(video_frame->data(media::VideoFrame::kVPlane), v,
420 video_frame->stride(media::VideoFrame::kVPlane) *
421 video_frame->rows(media::VideoFrame::kVPlane));
423 uint8 alpha_value = is_transparent ? 0 : 128;
424 CreateTestYUVVideoDrawQuad_FromVideoFrame(
425 shared_state, video_frame, alpha_value, tex_coord_rect, render_pass,
426 video_resource_updater, rect, visible_rect, resource_provider);
429 typedef ::testing::Types<GLRenderer,
430 SoftwareRenderer,
431 GLRendererWithExpandedViewport,
432 SoftwareRendererWithExpandedViewport> RendererTypes;
433 TYPED_TEST_CASE(RendererPixelTest, RendererTypes);
435 template <typename RendererType>
436 class SoftwareRendererPixelTest : public RendererPixelTest<RendererType> {};
438 typedef ::testing::Types<SoftwareRenderer, SoftwareRendererWithExpandedViewport>
439 SoftwareRendererTypes;
440 TYPED_TEST_CASE(SoftwareRendererPixelTest, SoftwareRendererTypes);
442 template <typename RendererType>
443 class FuzzyForSoftwareOnlyPixelComparator : public PixelComparator {
444 public:
445 explicit FuzzyForSoftwareOnlyPixelComparator(bool discard_alpha)
446 : fuzzy_(discard_alpha), exact_(discard_alpha) {}
448 bool Compare(const SkBitmap& actual_bmp,
449 const SkBitmap& expected_bmp) const override;
451 private:
452 FuzzyPixelOffByOneComparator fuzzy_;
453 ExactPixelComparator exact_;
456 template<>
457 bool FuzzyForSoftwareOnlyPixelComparator<SoftwareRenderer>::Compare(
458 const SkBitmap& actual_bmp,
459 const SkBitmap& expected_bmp) const {
460 return fuzzy_.Compare(actual_bmp, expected_bmp);
463 template <>
464 bool FuzzyForSoftwareOnlyPixelComparator<
465 SoftwareRendererWithExpandedViewport>::Compare(
466 const SkBitmap& actual_bmp,
467 const SkBitmap& expected_bmp) const {
468 return fuzzy_.Compare(actual_bmp, expected_bmp);
471 template<typename RendererType>
472 bool FuzzyForSoftwareOnlyPixelComparator<RendererType>::Compare(
473 const SkBitmap& actual_bmp,
474 const SkBitmap& expected_bmp) const {
475 return exact_.Compare(actual_bmp, expected_bmp);
478 TYPED_TEST(RendererPixelTest, SimpleGreenRect) {
479 gfx::Rect rect(this->device_viewport_size_);
481 RenderPassId id(1, 1);
482 scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
484 SharedQuadState* shared_state =
485 CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
487 SolidColorDrawQuad* color_quad =
488 pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
489 color_quad->SetNew(shared_state, rect, rect, SK_ColorGREEN, false);
491 RenderPassList pass_list;
492 pass_list.push_back(pass.Pass());
494 EXPECT_TRUE(this->RunPixelTest(
495 &pass_list,
496 base::FilePath(FILE_PATH_LITERAL("green.png")),
497 ExactPixelComparator(true)));
500 TYPED_TEST(RendererPixelTest, SimpleGreenRect_NonRootRenderPass) {
501 gfx::Rect rect(this->device_viewport_size_);
502 gfx::Rect small_rect(100, 100);
504 RenderPassId child_id(2, 1);
505 scoped_ptr<RenderPass> child_pass =
506 CreateTestRenderPass(child_id, small_rect, gfx::Transform());
508 SharedQuadState* child_shared_state =
509 CreateTestSharedQuadState(gfx::Transform(), small_rect, child_pass.get());
511 SolidColorDrawQuad* color_quad =
512 child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
513 color_quad->SetNew(child_shared_state, rect, rect, SK_ColorGREEN, false);
515 RenderPassId root_id(1, 1);
516 scoped_ptr<RenderPass> root_pass =
517 CreateTestRenderPass(root_id, rect, gfx::Transform());
519 SharedQuadState* root_shared_state =
520 CreateTestSharedQuadState(gfx::Transform(), rect, root_pass.get());
522 CreateTestRenderPassDrawQuad(
523 root_shared_state, small_rect, child_id, root_pass.get());
525 RenderPass* child_pass_ptr = child_pass.get();
527 RenderPassList pass_list;
528 pass_list.push_back(child_pass.Pass());
529 pass_list.push_back(root_pass.Pass());
531 EXPECT_TRUE(this->RunPixelTestWithReadbackTarget(
532 &pass_list,
533 child_pass_ptr,
534 base::FilePath(FILE_PATH_LITERAL("green_small.png")),
535 ExactPixelComparator(true)));
538 TYPED_TEST(RendererPixelTest, PremultipliedTextureWithoutBackground) {
539 gfx::Rect rect(this->device_viewport_size_);
541 RenderPassId id(1, 1);
542 scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
544 SharedQuadState* shared_state =
545 CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
547 CreateTestTextureDrawQuad(gfx::Rect(this->device_viewport_size_),
548 SkColorSetARGB(128, 0, 255, 0), // Texel color.
549 SK_ColorTRANSPARENT, // Background color.
550 true, // Premultiplied alpha.
551 shared_state,
552 this->resource_provider_.get(),
553 pass.get());
555 SolidColorDrawQuad* color_quad =
556 pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
557 color_quad->SetNew(shared_state, rect, rect, SK_ColorWHITE, false);
559 RenderPassList pass_list;
560 pass_list.push_back(pass.Pass());
562 EXPECT_TRUE(this->RunPixelTest(
563 &pass_list,
564 base::FilePath(FILE_PATH_LITERAL("green_alpha.png")),
565 FuzzyPixelOffByOneComparator(true)));
568 TYPED_TEST(RendererPixelTest, PremultipliedTextureWithBackground) {
569 gfx::Rect rect(this->device_viewport_size_);
571 RenderPassId id(1, 1);
572 scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
574 SharedQuadState* texture_quad_state =
575 CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
576 texture_quad_state->opacity = 0.8f;
578 CreateTestTextureDrawQuad(gfx::Rect(this->device_viewport_size_),
579 SkColorSetARGB(204, 120, 255, 120), // Texel color.
580 SK_ColorGREEN, // Background color.
581 true, // Premultiplied alpha.
582 texture_quad_state,
583 this->resource_provider_.get(),
584 pass.get());
586 SharedQuadState* color_quad_state =
587 CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
588 SolidColorDrawQuad* color_quad =
589 pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
590 color_quad->SetNew(color_quad_state, rect, rect, SK_ColorWHITE, false);
592 RenderPassList pass_list;
593 pass_list.push_back(pass.Pass());
595 EXPECT_TRUE(this->RunPixelTest(
596 &pass_list,
597 base::FilePath(FILE_PATH_LITERAL("green_alpha.png")),
598 FuzzyPixelOffByOneComparator(true)));
601 template <typename QuadType>
602 static const base::FilePath::CharType* IntersectingQuadImage() {
603 return FILE_PATH_LITERAL("intersecting_blue_green_squares.png");
605 template <>
606 const base::FilePath::CharType* IntersectingQuadImage<SolidColorDrawQuad>() {
607 return FILE_PATH_LITERAL("intersecting_blue_green.png");
609 template <>
610 const base::FilePath::CharType* IntersectingQuadImage<YUVVideoDrawQuad>() {
611 return FILE_PATH_LITERAL("intersecting_blue_green_squares_video.png");
614 template <typename TypeParam>
615 class IntersectingQuadPixelTest : public RendererPixelTest<TypeParam> {
616 protected:
617 void SetupQuadStateAndRenderPass() {
618 // This sets up a pair of draw quads. They are both rotated
619 // relative to the root plane, they are also rotated relative to each other.
620 // The intersect in the middle at a non-perpendicular angle so that any
621 // errors are hopefully magnified.
622 // The quads should intersect correctly, as in the front quad should only
623 // be partially in front of the back quad, and partially behind.
625 viewport_rect_ = gfx::Rect(this->device_viewport_size_);
626 quad_rect_ = gfx::Rect(0, 0, this->device_viewport_size_.width(),
627 this->device_viewport_size_.height() / 2.0);
629 RenderPassId id(1, 1);
630 render_pass_ = CreateTestRootRenderPass(id, viewport_rect_);
632 // Create the front quad rotated on the Z and Y axis.
633 gfx::Transform trans;
634 trans.Translate3d(0, 0, 0.707 * this->device_viewport_size_.width() / 2.0);
635 trans.RotateAboutZAxis(45.0);
636 trans.RotateAboutYAxis(45.0);
637 front_quad_state_ =
638 CreateTestSharedQuadState(trans, viewport_rect_, render_pass_.get());
639 front_quad_state_->clip_rect = quad_rect_;
640 // Make sure they end up in a 3d sorting context.
641 front_quad_state_->sorting_context_id = 1;
643 // Create the back quad, and rotate on just the y axis. This will intersect
644 // the first quad partially.
645 trans = gfx::Transform();
646 trans.Translate3d(0, 0, -0.707 * this->device_viewport_size_.width() / 2.0);
647 trans.RotateAboutYAxis(-45.0);
648 back_quad_state_ =
649 CreateTestSharedQuadState(trans, viewport_rect_, render_pass_.get());
650 back_quad_state_->sorting_context_id = 1;
651 back_quad_state_->clip_rect = quad_rect_;
653 template <typename T>
654 void AppendBackgroundAndRunTest(const PixelComparator& comparator) {
655 SharedQuadState* background_quad_state = CreateTestSharedQuadState(
656 gfx::Transform(), viewport_rect_, render_pass_.get());
657 SolidColorDrawQuad* background_quad =
658 render_pass_->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
659 background_quad->SetNew(background_quad_state, viewport_rect_,
660 viewport_rect_, SK_ColorWHITE, false);
661 pass_list_.push_back(render_pass_.Pass());
662 const base::FilePath::CharType* fileName = IntersectingQuadImage<T>();
663 EXPECT_TRUE(
664 this->RunPixelTest(&pass_list_, base::FilePath(fileName), comparator));
666 template <typename T>
667 T* CreateAndAppendDrawQuad() {
668 return render_pass_->CreateAndAppendDrawQuad<T>();
671 scoped_ptr<RenderPass> render_pass_;
672 gfx::Rect viewport_rect_;
673 SharedQuadState* front_quad_state_;
674 SharedQuadState* back_quad_state_;
675 gfx::Rect quad_rect_;
676 RenderPassList pass_list_;
679 template <typename TypeParam>
680 class IntersectingQuadGLPixelTest
681 : public IntersectingQuadPixelTest<TypeParam> {
682 public:
683 void SetUp() override {
684 IntersectingQuadPixelTest<TypeParam>::SetUp();
685 video_resource_updater_.reset(
686 new VideoResourceUpdater(this->output_surface_->context_provider(),
687 this->resource_provider_.get()));
688 video_resource_updater2_.reset(
689 new VideoResourceUpdater(this->output_surface_->context_provider(),
690 this->resource_provider_.get()));
693 protected:
694 scoped_ptr<VideoResourceUpdater> video_resource_updater_;
695 scoped_ptr<VideoResourceUpdater> video_resource_updater2_;
698 template <typename TypeParam>
699 class IntersectingQuadSoftwareTest
700 : public IntersectingQuadPixelTest<TypeParam> {};
702 typedef ::testing::Types<SoftwareRenderer, SoftwareRendererWithExpandedViewport>
703 SoftwareRendererTypes;
704 typedef ::testing::Types<GLRenderer, GLRendererWithExpandedViewport>
705 GLRendererTypes;
707 TYPED_TEST_CASE(IntersectingQuadPixelTest, RendererTypes);
708 TYPED_TEST_CASE(IntersectingQuadGLPixelTest, GLRendererTypes);
709 TYPED_TEST_CASE(IntersectingQuadSoftwareTest, SoftwareRendererTypes);
711 TYPED_TEST(IntersectingQuadPixelTest, SolidColorQuads) {
712 this->SetupQuadStateAndRenderPass();
714 SolidColorDrawQuad* quad =
715 this->template CreateAndAppendDrawQuad<SolidColorDrawQuad>();
716 SolidColorDrawQuad* quad2 =
717 this->template CreateAndAppendDrawQuad<SolidColorDrawQuad>();
719 quad->SetNew(this->front_quad_state_, this->quad_rect_, this->quad_rect_,
720 SK_ColorBLUE, false);
721 quad2->SetNew(this->back_quad_state_, this->quad_rect_, this->quad_rect_,
722 SK_ColorGREEN, false);
723 SCOPED_TRACE("IntersectingSolidColorQuads");
724 this->template AppendBackgroundAndRunTest<SolidColorDrawQuad>(
725 FuzzyPixelComparator(false, 2.f, 0.f, 256.f, 256, 0.f));
728 template <typename TypeParam>
729 SkColor GetColor(const SkColor& color) {
730 return color;
733 template <>
734 SkColor GetColor<GLRenderer>(const SkColor& color) {
735 return SkColorSetARGB(SkColorGetA(color), SkColorGetB(color),
736 SkColorGetG(color), SkColorGetR(color));
738 template <>
739 SkColor GetColor<GLRendererWithExpandedViewport>(const SkColor& color) {
740 return GetColor<GLRenderer>(color);
743 TYPED_TEST(IntersectingQuadPixelTest, TexturedQuads) {
744 this->SetupQuadStateAndRenderPass();
745 CreateTestTwoColoredTextureDrawQuad(
746 this->quad_rect_, GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 0)),
747 GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 255)), SK_ColorTRANSPARENT,
748 true, this->front_quad_state_, this->resource_provider_.get(),
749 this->render_pass_.get());
750 CreateTestTwoColoredTextureDrawQuad(
751 this->quad_rect_, GetColor<TypeParam>(SkColorSetARGB(255, 0, 255, 0)),
752 GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 0)), SK_ColorTRANSPARENT,
753 true, this->back_quad_state_, this->resource_provider_.get(),
754 this->render_pass_.get());
756 SCOPED_TRACE("IntersectingTexturedQuads");
757 this->template AppendBackgroundAndRunTest<TextureDrawQuad>(
758 FuzzyPixelComparator(false, 2.f, 0.f, 256.f, 256, 0.f));
761 TYPED_TEST(IntersectingQuadSoftwareTest, PictureQuads) {
762 this->SetupQuadStateAndRenderPass();
763 gfx::RectF outer_rect(this->quad_rect_);
764 gfx::RectF inner_rect(this->quad_rect_.x() + (this->quad_rect_.width() / 4),
765 this->quad_rect_.y() + (this->quad_rect_.height() / 4),
766 this->quad_rect_.width() / 2,
767 this->quad_rect_.height() / 2);
769 SkPaint black_paint;
770 black_paint.setColor(SK_ColorBLACK);
771 SkPaint blue_paint;
772 blue_paint.setColor(SK_ColorBLUE);
773 SkPaint green_paint;
774 green_paint.setColor(SK_ColorGREEN);
776 scoped_ptr<FakePicturePile> blue_recording =
777 FakePicturePile::CreateFilledPile(gfx::Size(1000, 1000),
778 this->quad_rect_.size());
779 blue_recording->add_draw_rect_with_paint(outer_rect, black_paint);
780 blue_recording->add_draw_rect_with_paint(inner_rect, blue_paint);
781 blue_recording->Rerecord();
782 scoped_refptr<FakePicturePileImpl> blue_pile =
783 FakePicturePileImpl::CreateFromPile(blue_recording.get(), nullptr);
785 PictureDrawQuad* blue_quad =
786 this->render_pass_->template CreateAndAppendDrawQuad<PictureDrawQuad>();
788 blue_quad->SetNew(this->front_quad_state_, this->quad_rect_, gfx::Rect(),
789 this->quad_rect_, this->quad_rect_, this->quad_rect_.size(),
790 false, RGBA_8888, this->quad_rect_, 1.f, blue_pile);
792 scoped_ptr<FakePicturePile> green_recording =
793 FakePicturePile::CreateFilledPile(this->quad_rect_.size(),
794 this->quad_rect_.size());
795 green_recording->add_draw_rect_with_paint(outer_rect, green_paint);
796 green_recording->add_draw_rect_with_paint(inner_rect, black_paint);
797 green_recording->Rerecord();
798 scoped_refptr<FakePicturePileImpl> green_pile =
799 FakePicturePileImpl::CreateFromPile(green_recording.get(), nullptr);
801 PictureDrawQuad* green_quad =
802 this->render_pass_->template CreateAndAppendDrawQuad<PictureDrawQuad>();
803 green_quad->SetNew(this->back_quad_state_, this->quad_rect_, gfx::Rect(),
804 this->quad_rect_, this->quad_rect_,
805 this->quad_rect_.size(), false, RGBA_8888,
806 this->quad_rect_, 1.f, green_pile);
807 SCOPED_TRACE("IntersectingPictureQuadsPass");
808 this->template AppendBackgroundAndRunTest<PictureDrawQuad>(
809 FuzzyPixelComparator(false, 2.f, 0.f, 256.f, 256, 0.f));
812 TYPED_TEST(IntersectingQuadPixelTest, RenderPassQuads) {
813 this->SetupQuadStateAndRenderPass();
814 RenderPassId child_pass_id1(2, 2);
815 RenderPassId child_pass_id2(2, 3);
816 scoped_ptr<RenderPass> child_pass1 =
817 CreateTestRenderPass(child_pass_id1, this->quad_rect_, gfx::Transform());
818 SharedQuadState* child1_quad_state = CreateTestSharedQuadState(
819 gfx::Transform(), this->quad_rect_, child_pass1.get());
820 scoped_ptr<RenderPass> child_pass2 =
821 CreateTestRenderPass(child_pass_id2, this->quad_rect_, gfx::Transform());
822 SharedQuadState* child2_quad_state = CreateTestSharedQuadState(
823 gfx::Transform(), this->quad_rect_, child_pass2.get());
825 CreateTestTwoColoredTextureDrawQuad(
826 this->quad_rect_, GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 0)),
827 GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 255)), SK_ColorTRANSPARENT,
828 true, child1_quad_state, this->resource_provider_.get(),
829 child_pass1.get());
830 CreateTestTwoColoredTextureDrawQuad(
831 this->quad_rect_, GetColor<TypeParam>(SkColorSetARGB(255, 0, 255, 0)),
832 GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 0)), SK_ColorTRANSPARENT,
833 true, child2_quad_state, this->resource_provider_.get(),
834 child_pass2.get());
836 CreateTestRenderPassDrawQuad(this->front_quad_state_, this->quad_rect_,
837 child_pass_id1, this->render_pass_.get());
838 CreateTestRenderPassDrawQuad(this->back_quad_state_, this->quad_rect_,
839 child_pass_id2, this->render_pass_.get());
841 this->pass_list_.push_back(child_pass1.Pass());
842 this->pass_list_.push_back(child_pass2.Pass());
843 SCOPED_TRACE("IntersectingRenderQuadsPass");
844 this->template AppendBackgroundAndRunTest<RenderPassDrawQuad>(
845 FuzzyPixelComparator(false, 2.f, 0.f, 256.f, 256, 0.f));
848 TYPED_TEST(IntersectingQuadGLPixelTest, YUVVideoQuads) {
849 this->SetupQuadStateAndRenderPass();
850 gfx::Rect inner_rect(
851 ((this->quad_rect_.x() + (this->quad_rect_.width() / 4)) & ~0xF),
852 ((this->quad_rect_.y() + (this->quad_rect_.height() / 4)) & ~0xF),
853 (this->quad_rect_.width() / 2) & ~0xF,
854 (this->quad_rect_.height() / 2) & ~0xF);
856 CreateTestYUVVideoDrawQuad_TwoColor(
857 this->front_quad_state_, media::VideoFrame::YV12,
858 media::VideoFrame::COLOR_SPACE_JPEG, false,
859 gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), this->quad_rect_.size(),
860 this->quad_rect_, 0, 128, 128, inner_rect, 29, 255, 107,
861 this->render_pass_.get(), this->video_resource_updater_.get(),
862 this->resource_provider_.get());
864 CreateTestYUVVideoDrawQuad_TwoColor(
865 this->back_quad_state_, media::VideoFrame::YV12,
866 media::VideoFrame::COLOR_SPACE_JPEG, false,
867 gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), this->quad_rect_.size(),
868 this->quad_rect_, 149, 43, 21, inner_rect, 0, 128, 128,
869 this->render_pass_.get(), this->video_resource_updater2_.get(),
870 this->resource_provider_.get());
872 SCOPED_TRACE("IntersectingVideoQuads");
873 this->template AppendBackgroundAndRunTest<YUVVideoDrawQuad>(
874 FuzzyPixelOffByOneComparator(false));
877 // TODO(skaslev): The software renderer does not support non-premultplied alpha.
878 TEST_F(GLRendererPixelTest, NonPremultipliedTextureWithoutBackground) {
879 gfx::Rect rect(this->device_viewport_size_);
881 RenderPassId id(1, 1);
882 scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
884 SharedQuadState* shared_state =
885 CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
887 CreateTestTextureDrawQuad(gfx::Rect(this->device_viewport_size_),
888 SkColorSetARGB(128, 0, 255, 0), // Texel color.
889 SK_ColorTRANSPARENT, // Background color.
890 false, // Premultiplied alpha.
891 shared_state,
892 this->resource_provider_.get(),
893 pass.get());
895 SolidColorDrawQuad* color_quad =
896 pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
897 color_quad->SetNew(shared_state, rect, rect, SK_ColorWHITE, false);
899 RenderPassList pass_list;
900 pass_list.push_back(pass.Pass());
902 EXPECT_TRUE(this->RunPixelTest(
903 &pass_list,
904 base::FilePath(FILE_PATH_LITERAL("green_alpha.png")),
905 FuzzyPixelOffByOneComparator(true)));
908 // TODO(skaslev): The software renderer does not support non-premultplied alpha.
909 TEST_F(GLRendererPixelTest, NonPremultipliedTextureWithBackground) {
910 gfx::Rect rect(this->device_viewport_size_);
912 RenderPassId id(1, 1);
913 scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
915 SharedQuadState* texture_quad_state =
916 CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
917 texture_quad_state->opacity = 0.8f;
919 CreateTestTextureDrawQuad(gfx::Rect(this->device_viewport_size_),
920 SkColorSetARGB(204, 120, 255, 120), // Texel color.
921 SK_ColorGREEN, // Background color.
922 false, // Premultiplied alpha.
923 texture_quad_state,
924 this->resource_provider_.get(),
925 pass.get());
927 SharedQuadState* color_quad_state =
928 CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
929 SolidColorDrawQuad* color_quad =
930 pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
931 color_quad->SetNew(color_quad_state, rect, rect, SK_ColorWHITE, false);
933 RenderPassList pass_list;
934 pass_list.push_back(pass.Pass());
936 EXPECT_TRUE(this->RunPixelTest(
937 &pass_list,
938 base::FilePath(FILE_PATH_LITERAL("green_alpha.png")),
939 FuzzyPixelOffByOneComparator(true)));
942 class VideoGLRendererPixelTest : public GLRendererPixelTest {
943 protected:
944 void CreateEdgeBleedPass(media::VideoFrame::Format format,
945 media::VideoFrame::ColorSpace color_space,
946 RenderPassList* pass_list) {
947 gfx::Rect rect(200, 200);
949 RenderPassId id(1, 1);
950 scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
952 // Scale the video up so that bilinear filtering kicks in to sample more
953 // than just nearest neighbor would.
954 gfx::Transform scale_by_2;
955 scale_by_2.Scale(2.f, 2.f);
956 gfx::Rect half_rect(100, 100);
957 SharedQuadState* shared_state =
958 CreateTestSharedQuadState(scale_by_2, half_rect, pass.get());
960 gfx::Size background_size(200, 200);
961 gfx::Rect green_rect(16, 20, 100, 100);
962 gfx::RectF tex_coord_rect(
963 static_cast<float>(green_rect.x()) / background_size.width(),
964 static_cast<float>(green_rect.y()) / background_size.height(),
965 static_cast<float>(green_rect.width()) / background_size.width(),
966 static_cast<float>(green_rect.height()) / background_size.height());
968 // YUV of (149,43,21) should be green (0,255,0) in RGB.
969 // Create a video frame that has a non-green background rect, with a
970 // green sub-rectangle that should be the only thing displayed in
971 // the final image. Bleeding will appear on all four sides of the video
972 // if the tex coords are not clamped.
973 CreateTestYUVVideoDrawQuad_TwoColor(
974 shared_state, format, color_space, false, tex_coord_rect,
975 background_size, gfx::Rect(background_size), 128, 128, 128, green_rect,
976 149, 43, 21, pass.get(), video_resource_updater_.get(),
977 resource_provider_.get());
978 pass_list->push_back(pass.Pass());
981 void SetUp() override {
982 GLRendererPixelTest::SetUp();
983 video_resource_updater_.reset(new VideoResourceUpdater(
984 output_surface_->context_provider(), resource_provider_.get()));
987 scoped_ptr<VideoResourceUpdater> video_resource_updater_;
990 TEST_F(VideoGLRendererPixelTest, SimpleYUVRect) {
991 gfx::Rect rect(this->device_viewport_size_);
993 RenderPassId id(1, 1);
994 scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
996 SharedQuadState* shared_state =
997 CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
999 CreateTestYUVVideoDrawQuad_Striped(shared_state, media::VideoFrame::YV12,
1000 false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f),
1001 pass.get(), video_resource_updater_.get(),
1002 rect, rect, resource_provider_.get());
1004 RenderPassList pass_list;
1005 pass_list.push_back(pass.Pass());
1007 EXPECT_TRUE(
1008 this->RunPixelTest(&pass_list,
1009 base::FilePath(FILE_PATH_LITERAL("yuv_stripes.png")),
1010 FuzzyPixelOffByOneComparator(true)));
1013 TEST_F(VideoGLRendererPixelTest, ClippedYUVRect) {
1014 gfx::Rect viewport(this->device_viewport_size_);
1015 gfx::Rect draw_rect(this->device_viewport_size_.width() * 1.5,
1016 this->device_viewport_size_.height() * 1.5);
1018 RenderPassId id(1, 1);
1019 scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, viewport);
1021 SharedQuadState* shared_state =
1022 CreateTestSharedQuadState(gfx::Transform(), viewport, pass.get());
1024 CreateTestYUVVideoDrawQuad_Striped(shared_state, media::VideoFrame::YV12,
1025 false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f),
1026 pass.get(), video_resource_updater_.get(),
1027 draw_rect, viewport,
1028 resource_provider_.get());
1029 RenderPassList pass_list;
1030 pass_list.push_back(pass.Pass());
1032 EXPECT_TRUE(this->RunPixelTest(
1033 &pass_list, base::FilePath(FILE_PATH_LITERAL("yuv_stripes_clipped.png")),
1034 FuzzyPixelOffByOneComparator(true)));
1037 TEST_F(VideoGLRendererPixelTest, OffsetYUVRect) {
1038 gfx::Rect rect(this->device_viewport_size_);
1040 RenderPassId id(1, 1);
1041 scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
1043 SharedQuadState* shared_state =
1044 CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
1046 // Intentionally sets frame format to I420 for testing coverage.
1047 CreateTestYUVVideoDrawQuad_Striped(
1048 shared_state, media::VideoFrame::I420, false,
1049 gfx::RectF(0.125f, 0.25f, 0.75f, 0.5f), pass.get(),
1050 video_resource_updater_.get(), rect, rect, resource_provider_.get());
1052 RenderPassList pass_list;
1053 pass_list.push_back(pass.Pass());
1055 EXPECT_TRUE(this->RunPixelTest(
1056 &pass_list,
1057 base::FilePath(FILE_PATH_LITERAL("yuv_stripes_offset.png")),
1058 FuzzyPixelOffByOneComparator(true)));
1061 TEST_F(VideoGLRendererPixelTest, SimpleYUVRectBlack) {
1062 gfx::Rect rect(this->device_viewport_size_);
1064 RenderPassId id(1, 1);
1065 scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
1067 SharedQuadState* shared_state =
1068 CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
1070 // In MPEG color range YUV values of (15,128,128) should produce black.
1071 CreateTestYUVVideoDrawQuad_Solid(
1072 shared_state, media::VideoFrame::YV12,
1073 media::VideoFrame::COLOR_SPACE_UNSPECIFIED, false,
1074 gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 15, 128, 128, pass.get(),
1075 video_resource_updater_.get(), rect, rect, resource_provider_.get());
1077 RenderPassList pass_list;
1078 pass_list.push_back(pass.Pass());
1080 // If we didn't get black out of the YUV values above, then we probably have a
1081 // color range issue.
1082 EXPECT_TRUE(this->RunPixelTest(&pass_list,
1083 base::FilePath(FILE_PATH_LITERAL("black.png")),
1084 FuzzyPixelOffByOneComparator(true)));
1087 TEST_F(VideoGLRendererPixelTest, SimpleYUVJRect) {
1088 gfx::Rect rect(this->device_viewport_size_);
1090 RenderPassId id(1, 1);
1091 scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
1093 SharedQuadState* shared_state =
1094 CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
1096 // YUV of (149,43,21) should be green (0,255,0) in RGB.
1097 CreateTestYUVVideoDrawQuad_Solid(
1098 shared_state, media::VideoFrame::YV12,
1099 media::VideoFrame::COLOR_SPACE_JPEG, false,
1100 gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 149, 43, 21, pass.get(),
1101 video_resource_updater_.get(), rect, rect, resource_provider_.get());
1103 RenderPassList pass_list;
1104 pass_list.push_back(pass.Pass());
1106 EXPECT_TRUE(this->RunPixelTest(&pass_list,
1107 base::FilePath(FILE_PATH_LITERAL("green.png")),
1108 FuzzyPixelOffByOneComparator(true)));
1111 // Test that a YUV video doesn't bleed outside of its tex coords when the
1112 // tex coord rect is only a partial subrectangle of the coded contents.
1113 TEST_F(VideoGLRendererPixelTest, YUVEdgeBleed) {
1114 RenderPassList pass_list;
1115 CreateEdgeBleedPass(media::VideoFrame::YV12,
1116 media::VideoFrame::COLOR_SPACE_JPEG, &pass_list);
1117 EXPECT_TRUE(this->RunPixelTest(&pass_list,
1118 base::FilePath(FILE_PATH_LITERAL("green.png")),
1119 FuzzyPixelOffByOneComparator(true)));
1122 TEST_F(VideoGLRendererPixelTest, YUVAEdgeBleed) {
1123 RenderPassList pass_list;
1124 CreateEdgeBleedPass(media::VideoFrame::YV12A,
1125 media::VideoFrame::COLOR_SPACE_UNSPECIFIED, &pass_list);
1126 EXPECT_TRUE(this->RunPixelTest(&pass_list,
1127 base::FilePath(FILE_PATH_LITERAL("green.png")),
1128 FuzzyPixelOffByOneComparator(true)));
1131 TEST_F(VideoGLRendererPixelTest, SimpleYUVJRectGrey) {
1132 gfx::Rect rect(this->device_viewport_size_);
1134 RenderPassId id(1, 1);
1135 scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
1137 SharedQuadState* shared_state =
1138 CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
1140 // Dark grey in JPEG color range (in MPEG, this is black).
1141 CreateTestYUVVideoDrawQuad_Solid(
1142 shared_state, media::VideoFrame::YV12,
1143 media::VideoFrame::COLOR_SPACE_JPEG, false,
1144 gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 15, 128, 128, pass.get(),
1145 video_resource_updater_.get(), rect, rect, resource_provider_.get());
1147 RenderPassList pass_list;
1148 pass_list.push_back(pass.Pass());
1150 EXPECT_TRUE(
1151 this->RunPixelTest(&pass_list,
1152 base::FilePath(FILE_PATH_LITERAL("dark_grey.png")),
1153 FuzzyPixelOffByOneComparator(true)));
1156 TEST_F(VideoGLRendererPixelTest, SimpleYUVARect) {
1157 gfx::Rect rect(this->device_viewport_size_);
1159 RenderPassId id(1, 1);
1160 scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
1162 SharedQuadState* shared_state =
1163 CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
1165 CreateTestYUVVideoDrawQuad_Striped(shared_state, media::VideoFrame::YV12A,
1166 false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f),
1167 pass.get(), video_resource_updater_.get(),
1168 rect, rect, resource_provider_.get());
1170 SolidColorDrawQuad* color_quad =
1171 pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1172 color_quad->SetNew(shared_state, rect, rect, SK_ColorWHITE, false);
1174 RenderPassList pass_list;
1175 pass_list.push_back(pass.Pass());
1177 EXPECT_TRUE(this->RunPixelTest(
1178 &pass_list,
1179 base::FilePath(FILE_PATH_LITERAL("yuv_stripes_alpha.png")),
1180 FuzzyPixelOffByOneComparator(true)));
1183 TEST_F(VideoGLRendererPixelTest, FullyTransparentYUVARect) {
1184 gfx::Rect rect(this->device_viewport_size_);
1186 RenderPassId id(1, 1);
1187 scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
1189 SharedQuadState* shared_state =
1190 CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
1192 CreateTestYUVVideoDrawQuad_Striped(shared_state, media::VideoFrame::YV12A,
1193 true, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f),
1194 pass.get(), video_resource_updater_.get(),
1195 rect, rect, resource_provider_.get());
1197 SolidColorDrawQuad* color_quad =
1198 pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1199 color_quad->SetNew(shared_state, rect, rect, SK_ColorBLACK, false);
1201 RenderPassList pass_list;
1202 pass_list.push_back(pass.Pass());
1204 EXPECT_TRUE(this->RunPixelTest(
1205 &pass_list,
1206 base::FilePath(FILE_PATH_LITERAL("black.png")),
1207 ExactPixelComparator(true)));
1210 TYPED_TEST(RendererPixelTest, FastPassColorFilterAlpha) {
1211 gfx::Rect viewport_rect(this->device_viewport_size_);
1213 RenderPassId root_pass_id(1, 1);
1214 scoped_ptr<RenderPass> root_pass =
1215 CreateTestRootRenderPass(root_pass_id, viewport_rect);
1217 RenderPassId child_pass_id(2, 2);
1218 gfx::Rect pass_rect(this->device_viewport_size_);
1219 gfx::Transform transform_to_root;
1220 scoped_ptr<RenderPass> child_pass =
1221 CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
1223 gfx::Transform content_to_target_transform;
1224 SharedQuadState* shared_state = CreateTestSharedQuadState(
1225 content_to_target_transform, viewport_rect, child_pass.get());
1226 shared_state->opacity = 0.5f;
1228 gfx::Rect blue_rect(0,
1230 this->device_viewport_size_.width(),
1231 this->device_viewport_size_.height() / 2);
1232 SolidColorDrawQuad* blue =
1233 child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1234 blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
1235 gfx::Rect yellow_rect(0,
1236 this->device_viewport_size_.height() / 2,
1237 this->device_viewport_size_.width(),
1238 this->device_viewport_size_.height() / 2);
1239 SolidColorDrawQuad* yellow =
1240 child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1241 yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false);
1243 SharedQuadState* blank_state = CreateTestSharedQuadState(
1244 content_to_target_transform, viewport_rect, child_pass.get());
1246 SolidColorDrawQuad* white =
1247 child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1248 white->SetNew(
1249 blank_state, viewport_rect, viewport_rect, SK_ColorWHITE, false);
1251 SharedQuadState* pass_shared_state =
1252 CreateTestSharedQuadState(gfx::Transform(), pass_rect, root_pass.get());
1254 SkScalar matrix[20];
1255 float amount = 0.5f;
1256 matrix[0] = 0.213f + 0.787f * amount;
1257 matrix[1] = 0.715f - 0.715f * amount;
1258 matrix[2] = 1.f - (matrix[0] + matrix[1]);
1259 matrix[3] = matrix[4] = 0;
1260 matrix[5] = 0.213f - 0.213f * amount;
1261 matrix[6] = 0.715f + 0.285f * amount;
1262 matrix[7] = 1.f - (matrix[5] + matrix[6]);
1263 matrix[8] = matrix[9] = 0;
1264 matrix[10] = 0.213f - 0.213f * amount;
1265 matrix[11] = 0.715f - 0.715f * amount;
1266 matrix[12] = 1.f - (matrix[10] + matrix[11]);
1267 matrix[13] = matrix[14] = 0;
1268 matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0;
1269 matrix[18] = 1;
1270 skia::RefPtr<SkColorFilter> colorFilter(
1271 skia::AdoptRef(SkColorMatrixFilter::Create(matrix)));
1272 skia::RefPtr<SkImageFilter> filter =
1273 skia::AdoptRef(SkColorFilterImageFilter::Create(colorFilter.get(), NULL));
1274 FilterOperations filters;
1275 filters.Append(FilterOperation::CreateReferenceFilter(filter));
1277 RenderPassDrawQuad* render_pass_quad =
1278 root_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
1279 render_pass_quad->SetNew(pass_shared_state,
1280 pass_rect,
1281 pass_rect,
1282 child_pass_id,
1284 gfx::Vector2dF(),
1285 gfx::Size(),
1286 filters,
1287 gfx::Vector2dF(),
1288 FilterOperations());
1290 RenderPassList pass_list;
1291 pass_list.push_back(child_pass.Pass());
1292 pass_list.push_back(root_pass.Pass());
1294 // This test has alpha=254 for the software renderer vs. alpha=255 for the gl
1295 // renderer so use a fuzzy comparator.
1296 EXPECT_TRUE(this->RunPixelTest(
1297 &pass_list,
1298 base::FilePath(FILE_PATH_LITERAL("blue_yellow_alpha.png")),
1299 FuzzyForSoftwareOnlyPixelComparator<TypeParam>(false)));
1302 TYPED_TEST(RendererPixelTest, FastPassSaturateFilter) {
1303 gfx::Rect viewport_rect(this->device_viewport_size_);
1305 RenderPassId root_pass_id(1, 1);
1306 scoped_ptr<RenderPass> root_pass =
1307 CreateTestRootRenderPass(root_pass_id, viewport_rect);
1309 RenderPassId child_pass_id(2, 2);
1310 gfx::Rect pass_rect(this->device_viewport_size_);
1311 gfx::Transform transform_to_root;
1312 scoped_ptr<RenderPass> child_pass =
1313 CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
1315 gfx::Transform content_to_target_transform;
1316 SharedQuadState* shared_state = CreateTestSharedQuadState(
1317 content_to_target_transform, viewport_rect, child_pass.get());
1318 shared_state->opacity = 0.5f;
1320 gfx::Rect blue_rect(0,
1322 this->device_viewport_size_.width(),
1323 this->device_viewport_size_.height() / 2);
1324 SolidColorDrawQuad* blue =
1325 child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1326 blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
1327 gfx::Rect yellow_rect(0,
1328 this->device_viewport_size_.height() / 2,
1329 this->device_viewport_size_.width(),
1330 this->device_viewport_size_.height() / 2);
1331 SolidColorDrawQuad* yellow =
1332 child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1333 yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false);
1335 SharedQuadState* blank_state = CreateTestSharedQuadState(
1336 content_to_target_transform, viewport_rect, child_pass.get());
1338 SolidColorDrawQuad* white =
1339 child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1340 white->SetNew(
1341 blank_state, viewport_rect, viewport_rect, SK_ColorWHITE, false);
1343 SharedQuadState* pass_shared_state =
1344 CreateTestSharedQuadState(gfx::Transform(), pass_rect, root_pass.get());
1346 FilterOperations filters;
1347 filters.Append(FilterOperation::CreateSaturateFilter(0.5f));
1349 RenderPassDrawQuad* render_pass_quad =
1350 root_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
1351 render_pass_quad->SetNew(pass_shared_state,
1352 pass_rect,
1353 pass_rect,
1354 child_pass_id,
1356 gfx::Vector2dF(),
1357 gfx::Size(),
1358 filters,
1359 gfx::Vector2dF(),
1360 FilterOperations());
1362 RenderPassList pass_list;
1363 pass_list.push_back(child_pass.Pass());
1364 pass_list.push_back(root_pass.Pass());
1366 // This test blends slightly differently with the software renderer vs. the gl
1367 // renderer so use a fuzzy comparator.
1368 EXPECT_TRUE(this->RunPixelTest(
1369 &pass_list, base::FilePath(FILE_PATH_LITERAL("blue_yellow_alpha.png")),
1370 FuzzyForSoftwareOnlyPixelComparator<TypeParam>(false)));
1373 TYPED_TEST(RendererPixelTest, FastPassFilterChain) {
1374 gfx::Rect viewport_rect(this->device_viewport_size_);
1376 RenderPassId root_pass_id(1, 1);
1377 scoped_ptr<RenderPass> root_pass =
1378 CreateTestRootRenderPass(root_pass_id, viewport_rect);
1380 RenderPassId child_pass_id(2, 2);
1381 gfx::Rect pass_rect(this->device_viewport_size_);
1382 gfx::Transform transform_to_root;
1383 scoped_ptr<RenderPass> child_pass =
1384 CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
1386 gfx::Transform content_to_target_transform;
1387 SharedQuadState* shared_state = CreateTestSharedQuadState(
1388 content_to_target_transform, viewport_rect, child_pass.get());
1389 shared_state->opacity = 0.5f;
1391 gfx::Rect blue_rect(0,
1393 this->device_viewport_size_.width(),
1394 this->device_viewport_size_.height() / 2);
1395 SolidColorDrawQuad* blue =
1396 child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1397 blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
1398 gfx::Rect yellow_rect(0,
1399 this->device_viewport_size_.height() / 2,
1400 this->device_viewport_size_.width(),
1401 this->device_viewport_size_.height() / 2);
1402 SolidColorDrawQuad* yellow =
1403 child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1404 yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false);
1406 SharedQuadState* blank_state = CreateTestSharedQuadState(
1407 content_to_target_transform, viewport_rect, child_pass.get());
1409 SolidColorDrawQuad* white =
1410 child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1411 white->SetNew(
1412 blank_state, viewport_rect, viewport_rect, SK_ColorWHITE, false);
1414 SharedQuadState* pass_shared_state =
1415 CreateTestSharedQuadState(gfx::Transform(), pass_rect, root_pass.get());
1417 FilterOperations filters;
1418 filters.Append(FilterOperation::CreateGrayscaleFilter(1.f));
1419 filters.Append(FilterOperation::CreateBrightnessFilter(0.5f));
1421 RenderPassDrawQuad* render_pass_quad =
1422 root_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
1423 render_pass_quad->SetNew(pass_shared_state,
1424 pass_rect,
1425 pass_rect,
1426 child_pass_id,
1428 gfx::Vector2dF(),
1429 gfx::Size(),
1430 filters,
1431 gfx::Vector2dF(),
1432 FilterOperations());
1434 RenderPassList pass_list;
1435 pass_list.push_back(child_pass.Pass());
1436 pass_list.push_back(root_pass.Pass());
1438 // This test blends slightly differently with the software renderer vs. the gl
1439 // renderer so use a fuzzy comparator.
1440 EXPECT_TRUE(this->RunPixelTest(
1441 &pass_list,
1442 base::FilePath(FILE_PATH_LITERAL("blue_yellow_filter_chain.png")),
1443 FuzzyForSoftwareOnlyPixelComparator<TypeParam>(false)));
1446 TYPED_TEST(RendererPixelTest, FastPassColorFilterAlphaTranslation) {
1447 gfx::Rect viewport_rect(this->device_viewport_size_);
1449 RenderPassId root_pass_id(1, 1);
1450 scoped_ptr<RenderPass> root_pass =
1451 CreateTestRootRenderPass(root_pass_id, viewport_rect);
1453 RenderPassId child_pass_id(2, 2);
1454 gfx::Rect pass_rect(this->device_viewport_size_);
1455 gfx::Transform transform_to_root;
1456 scoped_ptr<RenderPass> child_pass =
1457 CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
1459 gfx::Transform content_to_target_transform;
1460 SharedQuadState* shared_state = CreateTestSharedQuadState(
1461 content_to_target_transform, viewport_rect, child_pass.get());
1462 shared_state->opacity = 0.5f;
1464 gfx::Rect blue_rect(0,
1466 this->device_viewport_size_.width(),
1467 this->device_viewport_size_.height() / 2);
1468 SolidColorDrawQuad* blue =
1469 child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1470 blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
1471 gfx::Rect yellow_rect(0,
1472 this->device_viewport_size_.height() / 2,
1473 this->device_viewport_size_.width(),
1474 this->device_viewport_size_.height() / 2);
1475 SolidColorDrawQuad* yellow =
1476 child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1477 yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false);
1479 SharedQuadState* blank_state = CreateTestSharedQuadState(
1480 content_to_target_transform, viewport_rect, child_pass.get());
1482 SolidColorDrawQuad* white =
1483 child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1484 white->SetNew(
1485 blank_state, viewport_rect, viewport_rect, SK_ColorWHITE, false);
1487 SharedQuadState* pass_shared_state =
1488 CreateTestSharedQuadState(gfx::Transform(), pass_rect, root_pass.get());
1490 SkScalar matrix[20];
1491 float amount = 0.5f;
1492 matrix[0] = 0.213f + 0.787f * amount;
1493 matrix[1] = 0.715f - 0.715f * amount;
1494 matrix[2] = 1.f - (matrix[0] + matrix[1]);
1495 matrix[3] = 0;
1496 matrix[4] = 20.f;
1497 matrix[5] = 0.213f - 0.213f * amount;
1498 matrix[6] = 0.715f + 0.285f * amount;
1499 matrix[7] = 1.f - (matrix[5] + matrix[6]);
1500 matrix[8] = 0;
1501 matrix[9] = 200.f;
1502 matrix[10] = 0.213f - 0.213f * amount;
1503 matrix[11] = 0.715f - 0.715f * amount;
1504 matrix[12] = 1.f - (matrix[10] + matrix[11]);
1505 matrix[13] = 0;
1506 matrix[14] = 1.5f;
1507 matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0;
1508 matrix[18] = 1;
1509 skia::RefPtr<SkColorFilter> colorFilter(
1510 skia::AdoptRef(SkColorMatrixFilter::Create(matrix)));
1511 skia::RefPtr<SkImageFilter> filter =
1512 skia::AdoptRef(SkColorFilterImageFilter::Create(colorFilter.get(), NULL));
1513 FilterOperations filters;
1514 filters.Append(FilterOperation::CreateReferenceFilter(filter));
1516 RenderPassDrawQuad* render_pass_quad =
1517 root_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
1518 render_pass_quad->SetNew(pass_shared_state,
1519 pass_rect,
1520 pass_rect,
1521 child_pass_id,
1523 gfx::Vector2dF(),
1524 gfx::Size(),
1525 filters,
1526 gfx::Vector2dF(),
1527 FilterOperations());
1529 RenderPassList pass_list;
1531 pass_list.push_back(child_pass.Pass());
1532 pass_list.push_back(root_pass.Pass());
1534 // This test has alpha=254 for the software renderer vs. alpha=255 for the gl
1535 // renderer so use a fuzzy comparator.
1536 EXPECT_TRUE(this->RunPixelTest(
1537 &pass_list,
1538 base::FilePath(FILE_PATH_LITERAL("blue_yellow_alpha_translate.png")),
1539 FuzzyForSoftwareOnlyPixelComparator<TypeParam>(false)));
1542 TYPED_TEST(RendererPixelTest, EnlargedRenderPassTexture) {
1543 gfx::Rect viewport_rect(this->device_viewport_size_);
1545 RenderPassId root_pass_id(1, 1);
1546 scoped_ptr<RenderPass> root_pass =
1547 CreateTestRootRenderPass(root_pass_id, viewport_rect);
1549 RenderPassId child_pass_id(2, 2);
1550 gfx::Rect pass_rect(this->device_viewport_size_);
1551 gfx::Transform transform_to_root;
1552 scoped_ptr<RenderPass> child_pass =
1553 CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
1555 gfx::Transform content_to_target_transform;
1556 SharedQuadState* shared_state = CreateTestSharedQuadState(
1557 content_to_target_transform, viewport_rect, child_pass.get());
1559 gfx::Rect blue_rect(0,
1561 this->device_viewport_size_.width(),
1562 this->device_viewport_size_.height() / 2);
1563 SolidColorDrawQuad* blue =
1564 child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1565 blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
1566 gfx::Rect yellow_rect(0,
1567 this->device_viewport_size_.height() / 2,
1568 this->device_viewport_size_.width(),
1569 this->device_viewport_size_.height() / 2);
1570 SolidColorDrawQuad* yellow =
1571 child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1572 yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false);
1574 SharedQuadState* pass_shared_state =
1575 CreateTestSharedQuadState(gfx::Transform(), pass_rect, root_pass.get());
1576 CreateTestRenderPassDrawQuad(
1577 pass_shared_state, pass_rect, child_pass_id, root_pass.get());
1579 RenderPassList pass_list;
1580 pass_list.push_back(child_pass.Pass());
1581 pass_list.push_back(root_pass.Pass());
1583 this->renderer_->SetEnlargePassTextureAmountForTesting(gfx::Vector2d(50, 75));
1585 EXPECT_TRUE(this->RunPixelTest(
1586 &pass_list,
1587 base::FilePath(FILE_PATH_LITERAL("blue_yellow.png")),
1588 ExactPixelComparator(true)));
1591 TYPED_TEST(RendererPixelTest, EnlargedRenderPassTextureWithAntiAliasing) {
1592 gfx::Rect viewport_rect(this->device_viewport_size_);
1594 RenderPassId root_pass_id(1, 1);
1595 scoped_ptr<RenderPass> root_pass =
1596 CreateTestRootRenderPass(root_pass_id, viewport_rect);
1598 RenderPassId child_pass_id(2, 2);
1599 gfx::Rect pass_rect(this->device_viewport_size_);
1600 gfx::Transform transform_to_root;
1601 scoped_ptr<RenderPass> child_pass =
1602 CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
1604 gfx::Transform content_to_target_transform;
1605 SharedQuadState* shared_state = CreateTestSharedQuadState(
1606 content_to_target_transform, viewport_rect, child_pass.get());
1608 gfx::Rect blue_rect(0,
1610 this->device_viewport_size_.width(),
1611 this->device_viewport_size_.height() / 2);
1612 SolidColorDrawQuad* blue =
1613 child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1614 blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
1615 gfx::Rect yellow_rect(0,
1616 this->device_viewport_size_.height() / 2,
1617 this->device_viewport_size_.width(),
1618 this->device_viewport_size_.height() / 2);
1619 SolidColorDrawQuad* yellow =
1620 child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1621 yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false);
1623 gfx::Transform aa_transform;
1624 aa_transform.Translate(0.5, 0.0);
1626 SharedQuadState* pass_shared_state =
1627 CreateTestSharedQuadState(aa_transform, pass_rect, root_pass.get());
1628 CreateTestRenderPassDrawQuad(
1629 pass_shared_state, pass_rect, child_pass_id, root_pass.get());
1631 SharedQuadState* root_shared_state = CreateTestSharedQuadState(
1632 gfx::Transform(), viewport_rect, root_pass.get());
1633 SolidColorDrawQuad* background =
1634 root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1635 background->SetNew(root_shared_state,
1636 gfx::Rect(this->device_viewport_size_),
1637 gfx::Rect(this->device_viewport_size_),
1638 SK_ColorWHITE,
1639 false);
1641 RenderPassList pass_list;
1642 pass_list.push_back(child_pass.Pass());
1643 pass_list.push_back(root_pass.Pass());
1645 this->renderer_->SetEnlargePassTextureAmountForTesting(gfx::Vector2d(50, 75));
1647 EXPECT_TRUE(this->RunPixelTest(
1648 &pass_list,
1649 base::FilePath(FILE_PATH_LITERAL("blue_yellow_anti_aliasing.png")),
1650 FuzzyPixelOffByOneComparator(true)));
1653 // This tests the case where we have a RenderPass with a mask, but the quad
1654 // for the masked surface does not include the full surface texture.
1655 TYPED_TEST(RendererPixelTest, RenderPassAndMaskWithPartialQuad) {
1656 gfx::Rect viewport_rect(this->device_viewport_size_);
1658 RenderPassId root_pass_id(1, 1);
1659 scoped_ptr<RenderPass> root_pass =
1660 CreateTestRootRenderPass(root_pass_id, viewport_rect);
1661 SharedQuadState* root_pass_shared_state = CreateTestSharedQuadState(
1662 gfx::Transform(), viewport_rect, root_pass.get());
1664 RenderPassId child_pass_id(2, 2);
1665 gfx::Transform transform_to_root;
1666 scoped_ptr<RenderPass> child_pass =
1667 CreateTestRenderPass(child_pass_id, viewport_rect, transform_to_root);
1668 SharedQuadState* child_pass_shared_state = CreateTestSharedQuadState(
1669 gfx::Transform(), viewport_rect, child_pass.get());
1671 // The child render pass is just a green box.
1672 static const SkColor kCSSGreen = 0xff008000;
1673 SolidColorDrawQuad* green =
1674 child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1675 green->SetNew(
1676 child_pass_shared_state, viewport_rect, viewport_rect, kCSSGreen, false);
1678 // Make a mask.
1679 gfx::Rect mask_rect = viewport_rect;
1680 SkBitmap bitmap;
1681 bitmap.allocPixels(
1682 SkImageInfo::MakeN32Premul(mask_rect.width(), mask_rect.height()));
1683 SkCanvas canvas(bitmap);
1684 SkPaint paint;
1685 paint.setStyle(SkPaint::kStroke_Style);
1686 paint.setStrokeWidth(SkIntToScalar(4));
1687 paint.setColor(SK_ColorWHITE);
1688 canvas.clear(SK_ColorTRANSPARENT);
1689 gfx::Rect rect = mask_rect;
1690 while (!rect.IsEmpty()) {
1691 rect.Inset(6, 6, 4, 4);
1692 canvas.drawRect(
1693 SkRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height()),
1694 paint);
1695 rect.Inset(6, 6, 4, 4);
1698 ResourceId mask_resource_id = this->resource_provider_->CreateResource(
1699 mask_rect.size(), GL_CLAMP_TO_EDGE,
1700 ResourceProvider::TEXTURE_HINT_IMMUTABLE, RGBA_8888);
1702 SkAutoLockPixels lock(bitmap);
1703 this->resource_provider_->CopyToResource(
1704 mask_resource_id, reinterpret_cast<uint8_t*>(bitmap.getPixels()),
1705 mask_rect.size());
1708 // This RenderPassDrawQuad does not include the full |viewport_rect| which is
1709 // the size of the child render pass.
1710 gfx::Rect sub_rect = gfx::Rect(50, 50, 200, 100);
1711 EXPECT_NE(sub_rect.x(), child_pass->output_rect.x());
1712 EXPECT_NE(sub_rect.y(), child_pass->output_rect.y());
1713 EXPECT_NE(sub_rect.right(), child_pass->output_rect.right());
1714 EXPECT_NE(sub_rect.bottom(), child_pass->output_rect.bottom());
1716 // Set up a mask on the RenderPassDrawQuad.
1717 RenderPassDrawQuad* mask_quad =
1718 root_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
1719 mask_quad->SetNew(root_pass_shared_state,
1720 sub_rect,
1721 sub_rect,
1722 child_pass_id,
1723 mask_resource_id,
1724 gfx::Vector2dF(2.f, 1.f), // mask_uv_scale
1725 gfx::Size(mask_rect.size()), // mask_texture_size
1726 FilterOperations(), // foreground filters
1727 gfx::Vector2dF(), // filters scale
1728 FilterOperations()); // background filters
1730 // White background behind the masked render pass.
1731 SolidColorDrawQuad* white =
1732 root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1733 white->SetNew(root_pass_shared_state,
1734 viewport_rect,
1735 viewport_rect,
1736 SK_ColorWHITE,
1737 false);
1739 RenderPassList pass_list;
1740 pass_list.push_back(child_pass.Pass());
1741 pass_list.push_back(root_pass.Pass());
1743 EXPECT_TRUE(this->RunPixelTest(
1744 &pass_list,
1745 base::FilePath(FILE_PATH_LITERAL("mask_bottom_right.png")),
1746 ExactPixelComparator(true)));
1749 template <typename RendererType>
1750 class RendererPixelTestWithBackgroundFilter
1751 : public RendererPixelTest<RendererType> {
1752 protected:
1753 void SetUpRenderPassList() {
1754 gfx::Rect device_viewport_rect(this->device_viewport_size_);
1756 RenderPassId root_id(1, 1);
1757 scoped_ptr<RenderPass> root_pass =
1758 CreateTestRootRenderPass(root_id, device_viewport_rect);
1759 root_pass->has_transparent_background = false;
1761 gfx::Transform identity_content_to_target_transform;
1763 RenderPassId filter_pass_id(2, 1);
1764 gfx::Transform transform_to_root;
1765 scoped_ptr<RenderPass> filter_pass =
1766 CreateTestRenderPass(filter_pass_id,
1767 filter_pass_content_rect_,
1768 transform_to_root);
1770 // A non-visible quad in the filtering render pass.
1772 SharedQuadState* shared_state =
1773 CreateTestSharedQuadState(identity_content_to_target_transform,
1774 filter_pass_content_rect_,
1775 filter_pass.get());
1776 SolidColorDrawQuad* color_quad =
1777 filter_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1778 color_quad->SetNew(shared_state,
1779 filter_pass_content_rect_,
1780 filter_pass_content_rect_,
1781 SK_ColorTRANSPARENT,
1782 false);
1786 SharedQuadState* shared_state =
1787 CreateTestSharedQuadState(filter_pass_to_target_transform_,
1788 filter_pass_content_rect_,
1789 filter_pass.get());
1790 RenderPassDrawQuad* filter_pass_quad =
1791 root_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
1792 filter_pass_quad->SetNew(shared_state,
1793 filter_pass_content_rect_,
1794 filter_pass_content_rect_,
1795 filter_pass_id,
1796 0, // mask_resource_id
1797 gfx::Vector2dF(), // mask_uv_scale
1798 gfx::Size(), // mask_texture_size
1799 FilterOperations(), // filters
1800 gfx::Vector2dF(), // filters_scale
1801 this->background_filters_);
1804 const int kColumnWidth = device_viewport_rect.width() / 3;
1806 gfx::Rect left_rect = gfx::Rect(0, 0, kColumnWidth, 20);
1807 for (int i = 0; left_rect.y() < device_viewport_rect.height(); ++i) {
1808 SharedQuadState* shared_state = CreateTestSharedQuadState(
1809 identity_content_to_target_transform, left_rect, root_pass.get());
1810 SolidColorDrawQuad* color_quad =
1811 root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1812 color_quad->SetNew(
1813 shared_state, left_rect, left_rect, SK_ColorGREEN, false);
1814 left_rect += gfx::Vector2d(0, left_rect.height() + 1);
1817 gfx::Rect middle_rect = gfx::Rect(kColumnWidth+1, 0, kColumnWidth, 20);
1818 for (int i = 0; middle_rect.y() < device_viewport_rect.height(); ++i) {
1819 SharedQuadState* shared_state = CreateTestSharedQuadState(
1820 identity_content_to_target_transform, middle_rect, root_pass.get());
1821 SolidColorDrawQuad* color_quad =
1822 root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1823 color_quad->SetNew(
1824 shared_state, middle_rect, middle_rect, SK_ColorRED, false);
1825 middle_rect += gfx::Vector2d(0, middle_rect.height() + 1);
1828 gfx::Rect right_rect = gfx::Rect((kColumnWidth+1)*2, 0, kColumnWidth, 20);
1829 for (int i = 0; right_rect.y() < device_viewport_rect.height(); ++i) {
1830 SharedQuadState* shared_state = CreateTestSharedQuadState(
1831 identity_content_to_target_transform, right_rect, root_pass.get());
1832 SolidColorDrawQuad* color_quad =
1833 root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1834 color_quad->SetNew(
1835 shared_state, right_rect, right_rect, SK_ColorBLUE, false);
1836 right_rect += gfx::Vector2d(0, right_rect.height() + 1);
1839 SharedQuadState* shared_state =
1840 CreateTestSharedQuadState(identity_content_to_target_transform,
1841 device_viewport_rect,
1842 root_pass.get());
1843 SolidColorDrawQuad* background_quad =
1844 root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1845 background_quad->SetNew(shared_state,
1846 device_viewport_rect,
1847 device_viewport_rect,
1848 SK_ColorWHITE,
1849 false);
1851 pass_list_.push_back(filter_pass.Pass());
1852 pass_list_.push_back(root_pass.Pass());
1855 RenderPassList pass_list_;
1856 FilterOperations background_filters_;
1857 gfx::Transform filter_pass_to_target_transform_;
1858 gfx::Rect filter_pass_content_rect_;
1861 typedef ::testing::Types<GLRenderer, SoftwareRenderer>
1862 BackgroundFilterRendererTypes;
1863 TYPED_TEST_CASE(RendererPixelTestWithBackgroundFilter,
1864 BackgroundFilterRendererTypes);
1866 typedef RendererPixelTestWithBackgroundFilter<GLRenderer>
1867 GLRendererPixelTestWithBackgroundFilter;
1869 // TODO(skaslev): The software renderer does not support filters yet.
1870 TEST_F(GLRendererPixelTestWithBackgroundFilter, InvertFilter) {
1871 this->background_filters_.Append(
1872 FilterOperation::CreateInvertFilter(1.f));
1874 this->filter_pass_content_rect_ = gfx::Rect(this->device_viewport_size_);
1875 this->filter_pass_content_rect_.Inset(12, 14, 16, 18);
1877 this->SetUpRenderPassList();
1878 EXPECT_TRUE(this->RunPixelTest(
1879 &this->pass_list_,
1880 base::FilePath(FILE_PATH_LITERAL("background_filter.png")),
1881 ExactPixelComparator(true)));
1884 class ExternalStencilPixelTest : public GLRendererPixelTest {
1885 protected:
1886 void ClearBackgroundToGreen() {
1887 GLES2Interface* gl = output_surface_->context_provider()->ContextGL();
1888 output_surface_->EnsureBackbuffer();
1889 output_surface_->Reshape(device_viewport_size_, 1);
1890 gl->ClearColor(0.f, 1.f, 0.f, 1.f);
1891 gl->Clear(GL_COLOR_BUFFER_BIT);
1894 void PopulateStencilBuffer() {
1895 // Set two quadrants of the stencil buffer to 1.
1896 GLES2Interface* gl = output_surface_->context_provider()->ContextGL();
1897 output_surface_->EnsureBackbuffer();
1898 output_surface_->Reshape(device_viewport_size_, 1);
1899 gl->ClearStencil(0);
1900 gl->Clear(GL_STENCIL_BUFFER_BIT);
1901 gl->Enable(GL_SCISSOR_TEST);
1902 gl->ClearStencil(1);
1903 gl->Scissor(0,
1905 device_viewport_size_.width() / 2,
1906 device_viewport_size_.height() / 2);
1907 gl->Clear(GL_STENCIL_BUFFER_BIT);
1908 gl->Scissor(device_viewport_size_.width() / 2,
1909 device_viewport_size_.height() / 2,
1910 device_viewport_size_.width(),
1911 device_viewport_size_.height());
1912 gl->Clear(GL_STENCIL_BUFFER_BIT);
1916 TEST_F(ExternalStencilPixelTest, StencilTestEnabled) {
1917 ClearBackgroundToGreen();
1918 PopulateStencilBuffer();
1919 this->EnableExternalStencilTest();
1921 // Draw a blue quad that covers the entire device viewport. It should be
1922 // clipped to the bottom left and top right corners by the external stencil.
1923 gfx::Rect rect(this->device_viewport_size_);
1924 RenderPassId id(1, 1);
1925 scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
1926 SharedQuadState* blue_shared_state =
1927 CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
1928 SolidColorDrawQuad* blue =
1929 pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1930 blue->SetNew(blue_shared_state, rect, rect, SK_ColorBLUE, false);
1931 pass->has_transparent_background = false;
1932 RenderPassList pass_list;
1933 pass_list.push_back(pass.Pass());
1935 EXPECT_TRUE(this->RunPixelTest(
1936 &pass_list,
1937 base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")),
1938 ExactPixelComparator(true)));
1941 TEST_F(ExternalStencilPixelTest, StencilTestDisabled) {
1942 PopulateStencilBuffer();
1944 // Draw a green quad that covers the entire device viewport. The stencil
1945 // buffer should be ignored.
1946 gfx::Rect rect(this->device_viewport_size_);
1947 RenderPassId id(1, 1);
1948 scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
1949 SharedQuadState* green_shared_state =
1950 CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
1951 SolidColorDrawQuad* green =
1952 pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1953 green->SetNew(green_shared_state, rect, rect, SK_ColorGREEN, false);
1954 RenderPassList pass_list;
1955 pass_list.push_back(pass.Pass());
1957 EXPECT_TRUE(this->RunPixelTest(
1958 &pass_list,
1959 base::FilePath(FILE_PATH_LITERAL("green.png")),
1960 ExactPixelComparator(true)));
1963 TEST_F(ExternalStencilPixelTest, RenderSurfacesIgnoreStencil) {
1964 // The stencil test should apply only to the final render pass.
1965 ClearBackgroundToGreen();
1966 PopulateStencilBuffer();
1967 this->EnableExternalStencilTest();
1969 gfx::Rect viewport_rect(this->device_viewport_size_);
1971 RenderPassId root_pass_id(1, 1);
1972 scoped_ptr<RenderPass> root_pass =
1973 CreateTestRootRenderPass(root_pass_id, viewport_rect);
1974 root_pass->has_transparent_background = false;
1976 RenderPassId child_pass_id(2, 2);
1977 gfx::Rect pass_rect(this->device_viewport_size_);
1978 gfx::Transform transform_to_root;
1979 scoped_ptr<RenderPass> child_pass =
1980 CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
1982 gfx::Transform content_to_target_transform;
1983 SharedQuadState* shared_state = CreateTestSharedQuadState(
1984 content_to_target_transform, viewport_rect, child_pass.get());
1986 gfx::Rect blue_rect(0,
1988 this->device_viewport_size_.width(),
1989 this->device_viewport_size_.height());
1990 SolidColorDrawQuad* blue =
1991 child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1992 blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
1994 SharedQuadState* pass_shared_state =
1995 CreateTestSharedQuadState(gfx::Transform(), pass_rect, root_pass.get());
1996 CreateTestRenderPassDrawQuad(
1997 pass_shared_state, pass_rect, child_pass_id, root_pass.get());
1998 RenderPassList pass_list;
1999 pass_list.push_back(child_pass.Pass());
2000 pass_list.push_back(root_pass.Pass());
2002 EXPECT_TRUE(this->RunPixelTest(
2003 &pass_list,
2004 base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")),
2005 ExactPixelComparator(true)));
2008 TEST_F(ExternalStencilPixelTest, DeviceClip) {
2009 ClearBackgroundToGreen();
2010 gfx::Rect clip_rect(gfx::Point(150, 150), gfx::Size(50, 50));
2011 this->ForceDeviceClip(clip_rect);
2013 // Draw a blue quad that covers the entire device viewport. It should be
2014 // clipped to the bottom right corner by the device clip.
2015 gfx::Rect rect(this->device_viewport_size_);
2016 RenderPassId id(1, 1);
2017 scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
2018 SharedQuadState* blue_shared_state =
2019 CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
2020 SolidColorDrawQuad* blue =
2021 pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2022 blue->SetNew(blue_shared_state, rect, rect, SK_ColorBLUE, false);
2023 RenderPassList pass_list;
2024 pass_list.push_back(pass.Pass());
2026 EXPECT_TRUE(this->RunPixelTest(
2027 &pass_list,
2028 base::FilePath(FILE_PATH_LITERAL("green_with_blue_corner.png")),
2029 ExactPixelComparator(true)));
2032 // Software renderer does not support anti-aliased edges.
2033 TEST_F(GLRendererPixelTest, AntiAliasing) {
2034 gfx::Rect rect(this->device_viewport_size_);
2036 RenderPassId id(1, 1);
2037 scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
2039 gfx::Transform red_content_to_target_transform;
2040 red_content_to_target_transform.Rotate(10);
2041 SharedQuadState* red_shared_state = CreateTestSharedQuadState(
2042 red_content_to_target_transform, rect, pass.get());
2044 SolidColorDrawQuad* red = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2045 red->SetNew(red_shared_state, rect, rect, SK_ColorRED, false);
2047 gfx::Transform yellow_content_to_target_transform;
2048 yellow_content_to_target_transform.Rotate(5);
2049 SharedQuadState* yellow_shared_state = CreateTestSharedQuadState(
2050 yellow_content_to_target_transform, rect, pass.get());
2052 SolidColorDrawQuad* yellow =
2053 pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2054 yellow->SetNew(yellow_shared_state, rect, rect, SK_ColorYELLOW, false);
2056 gfx::Transform blue_content_to_target_transform;
2057 SharedQuadState* blue_shared_state = CreateTestSharedQuadState(
2058 blue_content_to_target_transform, rect, pass.get());
2060 SolidColorDrawQuad* blue =
2061 pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2062 blue->SetNew(blue_shared_state, rect, rect, SK_ColorBLUE, false);
2064 RenderPassList pass_list;
2065 pass_list.push_back(pass.Pass());
2067 EXPECT_TRUE(this->RunPixelTest(
2068 &pass_list,
2069 base::FilePath(FILE_PATH_LITERAL("anti_aliasing.png")),
2070 FuzzyPixelOffByOneComparator(true)));
2073 // This test tests that anti-aliasing works for axis aligned quads.
2074 // Anti-aliasing is only supported in the gl renderer.
2075 TEST_F(GLRendererPixelTest, AxisAligned) {
2076 gfx::Rect rect(this->device_viewport_size_);
2078 RenderPassId id(1, 1);
2079 gfx::Transform transform_to_root;
2080 scoped_ptr<RenderPass> pass =
2081 CreateTestRenderPass(id, rect, transform_to_root);
2083 gfx::Transform red_content_to_target_transform;
2084 red_content_to_target_transform.Translate(50, 50);
2085 red_content_to_target_transform.Scale(
2086 0.5f + 1.0f / (rect.width() * 2.0f),
2087 0.5f + 1.0f / (rect.height() * 2.0f));
2088 SharedQuadState* red_shared_state = CreateTestSharedQuadState(
2089 red_content_to_target_transform, rect, pass.get());
2091 SolidColorDrawQuad* red = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2092 red->SetNew(red_shared_state, rect, rect, SK_ColorRED, false);
2094 gfx::Transform yellow_content_to_target_transform;
2095 yellow_content_to_target_transform.Translate(25.5f, 25.5f);
2096 yellow_content_to_target_transform.Scale(0.5f, 0.5f);
2097 SharedQuadState* yellow_shared_state = CreateTestSharedQuadState(
2098 yellow_content_to_target_transform, rect, pass.get());
2100 SolidColorDrawQuad* yellow =
2101 pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2102 yellow->SetNew(yellow_shared_state, rect, rect, SK_ColorYELLOW, false);
2104 gfx::Transform blue_content_to_target_transform;
2105 SharedQuadState* blue_shared_state = CreateTestSharedQuadState(
2106 blue_content_to_target_transform, rect, pass.get());
2108 SolidColorDrawQuad* blue =
2109 pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2110 blue->SetNew(blue_shared_state, rect, rect, SK_ColorBLUE, false);
2112 RenderPassList pass_list;
2113 pass_list.push_back(pass.Pass());
2115 EXPECT_TRUE(this->RunPixelTest(
2116 &pass_list,
2117 base::FilePath(FILE_PATH_LITERAL("axis_aligned.png")),
2118 ExactPixelComparator(true)));
2121 // This test tests that forcing anti-aliasing off works as expected.
2122 // Anti-aliasing is only supported in the gl renderer.
2123 TEST_F(GLRendererPixelTest, ForceAntiAliasingOff) {
2124 gfx::Rect rect(this->device_viewport_size_);
2126 RenderPassId id(1, 1);
2127 gfx::Transform transform_to_root;
2128 scoped_ptr<RenderPass> pass =
2129 CreateTestRenderPass(id, rect, transform_to_root);
2131 gfx::Transform hole_content_to_target_transform;
2132 hole_content_to_target_transform.Translate(50, 50);
2133 hole_content_to_target_transform.Scale(
2134 0.5f + 1.0f / (rect.width() * 2.0f),
2135 0.5f + 1.0f / (rect.height() * 2.0f));
2136 SharedQuadState* hole_shared_state = CreateTestSharedQuadState(
2137 hole_content_to_target_transform, rect, pass.get());
2139 SolidColorDrawQuad* hole =
2140 pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2141 hole->SetAll(
2142 hole_shared_state, rect, rect, rect, false, SK_ColorTRANSPARENT, true);
2144 gfx::Transform green_content_to_target_transform;
2145 SharedQuadState* green_shared_state = CreateTestSharedQuadState(
2146 green_content_to_target_transform, rect, pass.get());
2148 SolidColorDrawQuad* green =
2149 pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2150 green->SetNew(green_shared_state, rect, rect, SK_ColorGREEN, false);
2152 RenderPassList pass_list;
2153 pass_list.push_back(pass.Pass());
2155 EXPECT_TRUE(this->RunPixelTest(
2156 &pass_list,
2157 base::FilePath(FILE_PATH_LITERAL("force_anti_aliasing_off.png")),
2158 ExactPixelComparator(false)));
2161 TEST_F(GLRendererPixelTest, AntiAliasingPerspective) {
2162 gfx::Rect rect(this->device_viewport_size_);
2164 scoped_ptr<RenderPass> pass =
2165 CreateTestRootRenderPass(RenderPassId(1, 1), rect);
2167 gfx::Rect red_rect(0, 0, 180, 500);
2168 gfx::Transform red_content_to_target_transform(
2169 1.0f, 2.4520f, 10.6206f, 19.0f,
2170 0.0f, 0.3528f, 5.9737f, 9.5f,
2171 0.0f, -0.2250f, -0.9744f, 0.0f,
2172 0.0f, 0.0225f, 0.0974f, 1.0f);
2173 SharedQuadState* red_shared_state = CreateTestSharedQuadState(
2174 red_content_to_target_transform, red_rect, pass.get());
2175 SolidColorDrawQuad* red = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2176 red->SetNew(red_shared_state, red_rect, red_rect, SK_ColorRED, false);
2178 gfx::Rect green_rect(19, 7, 180, 10);
2179 SharedQuadState* green_shared_state =
2180 CreateTestSharedQuadState(gfx::Transform(), green_rect, pass.get());
2181 SolidColorDrawQuad* green =
2182 pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2183 green->SetNew(
2184 green_shared_state, green_rect, green_rect, SK_ColorGREEN, false);
2186 SharedQuadState* blue_shared_state =
2187 CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
2188 SolidColorDrawQuad* blue =
2189 pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2190 blue->SetNew(blue_shared_state, rect, rect, SK_ColorBLUE, false);
2192 RenderPassList pass_list;
2193 pass_list.push_back(pass.Pass());
2195 EXPECT_TRUE(this->RunPixelTest(
2196 &pass_list,
2197 base::FilePath(FILE_PATH_LITERAL("anti_aliasing_perspective.png")),
2198 FuzzyPixelOffByOneComparator(true)));
2201 TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadIdentityScale) {
2202 gfx::Size pile_tile_size(1000, 1000);
2203 gfx::Rect viewport(this->device_viewport_size_);
2204 // TODO(enne): the renderer should figure this out on its own.
2205 ResourceFormat texture_format = RGBA_8888;
2206 bool nearest_neighbor = false;
2208 RenderPassId id(1, 1);
2209 gfx::Transform transform_to_root;
2210 scoped_ptr<RenderPass> pass =
2211 CreateTestRenderPass(id, viewport, transform_to_root);
2213 // One clipped blue quad in the lower right corner. Outside the clip
2214 // is red, which should not appear.
2215 gfx::Rect blue_rect(gfx::Size(100, 100));
2216 gfx::Rect blue_clip_rect(gfx::Point(50, 50), gfx::Size(50, 50));
2218 scoped_ptr<FakePicturePile> blue_recording =
2219 FakePicturePile::CreateFilledPile(pile_tile_size, blue_rect.size());
2220 SkPaint red_paint;
2221 red_paint.setColor(SK_ColorRED);
2222 blue_recording->add_draw_rect_with_paint(blue_rect, red_paint);
2223 SkPaint blue_paint;
2224 blue_paint.setColor(SK_ColorBLUE);
2225 blue_recording->add_draw_rect_with_paint(blue_clip_rect, blue_paint);
2226 blue_recording->Rerecord();
2228 scoped_refptr<FakePicturePileImpl> blue_pile =
2229 FakePicturePileImpl::CreateFromPile(blue_recording.get(), nullptr);
2231 gfx::Transform blue_content_to_target_transform;
2232 gfx::Vector2d offset(viewport.bottom_right() - blue_rect.bottom_right());
2233 blue_content_to_target_transform.Translate(offset.x(), offset.y());
2234 gfx::RectF blue_scissor_rect = blue_clip_rect;
2235 blue_content_to_target_transform.TransformRect(&blue_scissor_rect);
2236 SharedQuadState* blue_shared_state =
2237 CreateTestSharedQuadStateClipped(blue_content_to_target_transform,
2238 blue_rect,
2239 gfx::ToEnclosingRect(blue_scissor_rect),
2240 pass.get());
2242 PictureDrawQuad* blue_quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
2244 blue_quad->SetNew(blue_shared_state,
2245 viewport, // Intentionally bigger than clip.
2246 gfx::Rect(), viewport, gfx::RectF(viewport),
2247 viewport.size(), nearest_neighbor, texture_format, viewport,
2248 1.f, blue_pile.get());
2250 // One viewport-filling green quad.
2251 scoped_ptr<FakePicturePile> green_recording =
2252 FakePicturePile::CreateFilledPile(pile_tile_size, viewport.size());
2253 SkPaint green_paint;
2254 green_paint.setColor(SK_ColorGREEN);
2255 green_recording->add_draw_rect_with_paint(viewport, green_paint);
2256 green_recording->Rerecord();
2257 scoped_refptr<FakePicturePileImpl> green_pile =
2258 FakePicturePileImpl::CreateFromPile(green_recording.get(), nullptr);
2260 gfx::Transform green_content_to_target_transform;
2261 SharedQuadState* green_shared_state = CreateTestSharedQuadState(
2262 green_content_to_target_transform, viewport, pass.get());
2264 PictureDrawQuad* green_quad =
2265 pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
2266 green_quad->SetNew(green_shared_state, viewport, gfx::Rect(), viewport,
2267 gfx::RectF(0.f, 0.f, 1.f, 1.f), viewport.size(),
2268 nearest_neighbor, texture_format, viewport, 1.f,
2269 green_pile.get());
2271 RenderPassList pass_list;
2272 pass_list.push_back(pass.Pass());
2274 EXPECT_TRUE(this->RunPixelTest(
2275 &pass_list,
2276 base::FilePath(FILE_PATH_LITERAL("green_with_blue_corner.png")),
2277 ExactPixelComparator(true)));
2280 // Not WithSkiaGPUBackend since that path currently requires tiles for opacity.
2281 TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadOpacity) {
2282 gfx::Size pile_tile_size(1000, 1000);
2283 gfx::Rect viewport(this->device_viewport_size_);
2284 ResourceFormat texture_format = RGBA_8888;
2285 bool nearest_neighbor = false;
2287 RenderPassId id(1, 1);
2288 gfx::Transform transform_to_root;
2289 scoped_ptr<RenderPass> pass =
2290 CreateTestRenderPass(id, viewport, transform_to_root);
2292 // One viewport-filling 0.5-opacity green quad.
2293 scoped_ptr<FakePicturePile> green_recording =
2294 FakePicturePile::CreateFilledPile(pile_tile_size, viewport.size());
2295 SkPaint green_paint;
2296 green_paint.setColor(SK_ColorGREEN);
2297 green_recording->add_draw_rect_with_paint(viewport, green_paint);
2298 green_recording->Rerecord();
2299 scoped_refptr<FakePicturePileImpl> green_pile =
2300 FakePicturePileImpl::CreateFromPile(green_recording.get(), nullptr);
2302 gfx::Transform green_content_to_target_transform;
2303 SharedQuadState* green_shared_state = CreateTestSharedQuadState(
2304 green_content_to_target_transform, viewport, pass.get());
2305 green_shared_state->opacity = 0.5f;
2307 PictureDrawQuad* green_quad =
2308 pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
2309 green_quad->SetNew(green_shared_state, viewport, gfx::Rect(), viewport,
2310 gfx::RectF(0, 0, 1, 1), viewport.size(), nearest_neighbor,
2311 texture_format, viewport, 1.f, green_pile.get());
2313 // One viewport-filling white quad.
2314 scoped_ptr<FakePicturePile> white_recording =
2315 FakePicturePile::CreateFilledPile(pile_tile_size, viewport.size());
2316 SkPaint white_paint;
2317 white_paint.setColor(SK_ColorWHITE);
2318 white_recording->add_draw_rect_with_paint(viewport, white_paint);
2319 white_recording->Rerecord();
2320 scoped_refptr<FakePicturePileImpl> white_pile =
2321 FakePicturePileImpl::CreateFromPile(white_recording.get(), nullptr);
2323 gfx::Transform white_content_to_target_transform;
2324 SharedQuadState* white_shared_state = CreateTestSharedQuadState(
2325 white_content_to_target_transform, viewport, pass.get());
2327 PictureDrawQuad* white_quad =
2328 pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
2329 white_quad->SetNew(white_shared_state, viewport, gfx::Rect(), viewport,
2330 gfx::RectF(0, 0, 1, 1), viewport.size(), nearest_neighbor,
2331 texture_format, viewport, 1.f, white_pile.get());
2333 RenderPassList pass_list;
2334 pass_list.push_back(pass.Pass());
2336 EXPECT_TRUE(this->RunPixelTest(
2337 &pass_list,
2338 base::FilePath(FILE_PATH_LITERAL("green_alpha.png")),
2339 FuzzyPixelOffByOneComparator(true)));
2342 template<typename TypeParam> bool IsSoftwareRenderer() {
2343 return false;
2346 template<>
2347 bool IsSoftwareRenderer<SoftwareRenderer>() {
2348 return true;
2351 template<>
2352 bool IsSoftwareRenderer<SoftwareRendererWithExpandedViewport>() {
2353 return true;
2356 // If we disable image filtering, then a 2x2 bitmap should appear as four
2357 // huge sharp squares.
2358 TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadDisableImageFiltering) {
2359 // We only care about this in software mode since bilinear filtering is
2360 // cheap in hardware.
2361 if (!IsSoftwareRenderer<TypeParam>())
2362 return;
2364 gfx::Size pile_tile_size(1000, 1000);
2365 gfx::Rect viewport(this->device_viewport_size_);
2366 ResourceFormat texture_format = RGBA_8888;
2367 bool nearest_neighbor = false;
2369 RenderPassId id(1, 1);
2370 gfx::Transform transform_to_root;
2371 scoped_ptr<RenderPass> pass =
2372 CreateTestRenderPass(id, viewport, transform_to_root);
2374 SkBitmap bitmap;
2375 bitmap.allocN32Pixels(2, 2);
2377 SkAutoLockPixels lock(bitmap);
2378 SkCanvas canvas(bitmap);
2379 canvas.drawPoint(0, 0, SK_ColorGREEN);
2380 canvas.drawPoint(0, 1, SK_ColorBLUE);
2381 canvas.drawPoint(1, 0, SK_ColorBLUE);
2382 canvas.drawPoint(1, 1, SK_ColorGREEN);
2385 scoped_ptr<FakePicturePile> recording =
2386 FakePicturePile::CreateFilledPile(pile_tile_size, viewport.size());
2387 SkPaint paint;
2388 paint.setFilterQuality(kLow_SkFilterQuality);
2389 recording->add_draw_bitmap_with_paint(bitmap, gfx::Point(), paint);
2390 recording->Rerecord();
2391 scoped_refptr<FakePicturePileImpl> pile =
2392 FakePicturePileImpl::CreateFromPile(recording.get(), nullptr);
2394 gfx::Transform content_to_target_transform;
2395 SharedQuadState* shared_state = CreateTestSharedQuadState(
2396 content_to_target_transform, viewport, pass.get());
2398 PictureDrawQuad* quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
2399 quad->SetNew(shared_state, viewport, gfx::Rect(), viewport,
2400 gfx::RectF(0, 0, 2, 2), viewport.size(), nearest_neighbor,
2401 texture_format, viewport, 1.f, pile.get());
2403 RenderPassList pass_list;
2404 pass_list.push_back(pass.Pass());
2406 this->disable_picture_quad_image_filtering_ = true;
2408 EXPECT_TRUE(this->RunPixelTest(
2409 &pass_list,
2410 base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")),
2411 ExactPixelComparator(true)));
2414 // This disables filtering by setting |nearest_neighbor| on the PictureDrawQuad.
2415 TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadNearestNeighbor) {
2416 gfx::Size pile_tile_size(1000, 1000);
2417 gfx::Rect viewport(this->device_viewport_size_);
2418 ResourceFormat texture_format = RGBA_8888;
2419 bool nearest_neighbor = true;
2421 RenderPassId id(1, 1);
2422 gfx::Transform transform_to_root;
2423 scoped_ptr<RenderPass> pass =
2424 CreateTestRenderPass(id, viewport, transform_to_root);
2426 SkBitmap bitmap;
2427 bitmap.allocN32Pixels(2, 2);
2429 SkAutoLockPixels lock(bitmap);
2430 SkCanvas canvas(bitmap);
2431 canvas.drawPoint(0, 0, SK_ColorGREEN);
2432 canvas.drawPoint(0, 1, SK_ColorBLUE);
2433 canvas.drawPoint(1, 0, SK_ColorBLUE);
2434 canvas.drawPoint(1, 1, SK_ColorGREEN);
2437 scoped_ptr<FakePicturePile> recording =
2438 FakePicturePile::CreateFilledPile(pile_tile_size, viewport.size());
2439 SkPaint paint;
2440 paint.setFilterQuality(kLow_SkFilterQuality);
2441 recording->add_draw_bitmap_with_paint(bitmap, gfx::Point(), paint);
2442 recording->Rerecord();
2443 scoped_refptr<FakePicturePileImpl> pile =
2444 FakePicturePileImpl::CreateFromPile(recording.get(), nullptr);
2446 gfx::Transform content_to_target_transform;
2447 SharedQuadState* shared_state = CreateTestSharedQuadState(
2448 content_to_target_transform, viewport, pass.get());
2450 PictureDrawQuad* quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
2451 quad->SetNew(shared_state, viewport, gfx::Rect(), viewport,
2452 gfx::RectF(0, 0, 2, 2), viewport.size(), nearest_neighbor,
2453 texture_format, viewport, 1.f, pile.get());
2455 RenderPassList pass_list;
2456 pass_list.push_back(pass.Pass());
2458 EXPECT_TRUE(this->RunPixelTest(
2459 &pass_list,
2460 base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")),
2461 ExactPixelComparator(true)));
2464 // This disables filtering by setting |nearest_neighbor| on the TileDrawQuad.
2465 TYPED_TEST(RendererPixelTest, TileDrawQuadNearestNeighbor) {
2466 gfx::Rect viewport(this->device_viewport_size_);
2467 bool swizzle_contents = true;
2468 bool nearest_neighbor = true;
2470 SkBitmap bitmap;
2471 bitmap.allocN32Pixels(2, 2);
2473 SkAutoLockPixels lock(bitmap);
2474 SkCanvas canvas(bitmap);
2475 canvas.drawPoint(0, 0, SK_ColorGREEN);
2476 canvas.drawPoint(0, 1, SK_ColorBLUE);
2477 canvas.drawPoint(1, 0, SK_ColorBLUE);
2478 canvas.drawPoint(1, 1, SK_ColorGREEN);
2481 gfx::Size tile_size(2, 2);
2482 ResourceId resource = this->resource_provider_->CreateResource(
2483 tile_size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
2484 RGBA_8888);
2487 SkAutoLockPixels lock(bitmap);
2488 this->resource_provider_->CopyToResource(
2489 resource, static_cast<uint8_t*>(bitmap.getPixels()), tile_size);
2492 RenderPassId id(1, 1);
2493 gfx::Transform transform_to_root;
2494 scoped_ptr<RenderPass> pass =
2495 CreateTestRenderPass(id, viewport, transform_to_root);
2497 gfx::Transform content_to_target_transform;
2498 SharedQuadState* shared_state = CreateTestSharedQuadState(
2499 content_to_target_transform, viewport, pass.get());
2501 TileDrawQuad* quad = pass->CreateAndAppendDrawQuad<TileDrawQuad>();
2502 quad->SetNew(shared_state, viewport, gfx::Rect(), viewport, resource,
2503 gfx::Rect(tile_size), tile_size, swizzle_contents,
2504 nearest_neighbor);
2506 RenderPassList pass_list;
2507 pass_list.push_back(pass.Pass());
2509 EXPECT_TRUE(this->RunPixelTest(
2510 &pass_list,
2511 base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")),
2512 ExactPixelComparator(true)));
2515 // This disables filtering by setting |nearest_neighbor| to true on the
2516 // TextureDrawQuad.
2517 TYPED_TEST(SoftwareRendererPixelTest, TextureDrawQuadNearestNeighbor) {
2518 gfx::Rect viewport(this->device_viewport_size_);
2519 bool nearest_neighbor = true;
2521 SkBitmap bitmap;
2522 bitmap.allocN32Pixels(2, 2);
2524 SkAutoLockPixels lock(bitmap);
2525 SkCanvas canvas(bitmap);
2526 canvas.drawPoint(0, 0, SK_ColorGREEN);
2527 canvas.drawPoint(0, 1, SK_ColorBLUE);
2528 canvas.drawPoint(1, 0, SK_ColorBLUE);
2529 canvas.drawPoint(1, 1, SK_ColorGREEN);
2532 gfx::Size tile_size(2, 2);
2533 ResourceId resource = this->resource_provider_->CreateResource(
2534 tile_size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
2535 RGBA_8888);
2538 SkAutoLockPixels lock(bitmap);
2539 this->resource_provider_->CopyToResource(
2540 resource, static_cast<uint8_t*>(bitmap.getPixels()), tile_size);
2543 RenderPassId id(1, 1);
2544 gfx::Transform transform_to_root;
2545 scoped_ptr<RenderPass> pass =
2546 CreateTestRenderPass(id, viewport, transform_to_root);
2548 gfx::Transform content_to_target_transform;
2549 SharedQuadState* shared_state = CreateTestSharedQuadState(
2550 content_to_target_transform, viewport, pass.get());
2552 float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
2553 TextureDrawQuad* quad = pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
2554 quad->SetNew(shared_state, viewport, gfx::Rect(), viewport, resource, false,
2555 gfx::PointF(0, 0), gfx::PointF(1, 1), SK_ColorBLACK,
2556 vertex_opacity, false, nearest_neighbor);
2558 RenderPassList pass_list;
2559 pass_list.push_back(pass.Pass());
2561 EXPECT_TRUE(this->RunPixelTest(
2562 &pass_list,
2563 base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")),
2564 FuzzyPixelComparator(false, 2.f, 0.f, 256.f, 256, 0.f)));
2567 // This ensures filtering is enabled by setting |nearest_neighbor| to false on
2568 // the TextureDrawQuad.
2569 TYPED_TEST(SoftwareRendererPixelTest, TextureDrawQuadLinear) {
2570 gfx::Rect viewport(this->device_viewport_size_);
2571 bool nearest_neighbor = false;
2573 SkBitmap bitmap;
2574 bitmap.allocN32Pixels(2, 2);
2576 SkAutoLockPixels lock(bitmap);
2577 SkCanvas canvas(bitmap);
2578 canvas.drawPoint(0, 0, SK_ColorGREEN);
2579 canvas.drawPoint(0, 1, SK_ColorBLUE);
2580 canvas.drawPoint(1, 0, SK_ColorBLUE);
2581 canvas.drawPoint(1, 1, SK_ColorGREEN);
2584 gfx::Size tile_size(2, 2);
2585 ResourceId resource = this->resource_provider_->CreateResource(
2586 tile_size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
2587 RGBA_8888);
2590 SkAutoLockPixels lock(bitmap);
2591 this->resource_provider_->CopyToResource(
2592 resource, static_cast<uint8_t*>(bitmap.getPixels()), tile_size);
2595 RenderPassId id(1, 1);
2596 gfx::Transform transform_to_root;
2597 scoped_ptr<RenderPass> pass =
2598 CreateTestRenderPass(id, viewport, transform_to_root);
2600 gfx::Transform content_to_target_transform;
2601 SharedQuadState* shared_state = CreateTestSharedQuadState(
2602 content_to_target_transform, viewport, pass.get());
2604 float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
2605 TextureDrawQuad* quad = pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
2606 quad->SetNew(shared_state, viewport, gfx::Rect(), viewport, resource, false,
2607 gfx::PointF(0, 0), gfx::PointF(1, 1), SK_ColorBLACK,
2608 vertex_opacity, false, nearest_neighbor);
2610 RenderPassList pass_list;
2611 pass_list.push_back(pass.Pass());
2613 // Allow for a small amount of error as the blending alogrithm used by Skia is
2614 // affected by the offset in the expanded rect.
2615 EXPECT_TRUE(this->RunPixelTest(
2616 &pass_list,
2617 base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers_linear.png")),
2618 FuzzyPixelComparator(false, 100.f, 0.f, 16.f, 16.f, 0.f)));
2621 TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadNonIdentityScale) {
2622 gfx::Size pile_tile_size(1000, 1000);
2623 gfx::Rect viewport(this->device_viewport_size_);
2624 // TODO(enne): the renderer should figure this out on its own.
2625 ResourceFormat texture_format = RGBA_8888;
2626 bool nearest_neighbor = false;
2628 RenderPassId id(1, 1);
2629 gfx::Transform transform_to_root;
2630 scoped_ptr<RenderPass> pass =
2631 CreateTestRenderPass(id, viewport, transform_to_root);
2633 // As scaling up the blue checkerboards will cause sampling on the GPU,
2634 // a few extra "cleanup rects" need to be added to clobber the blending
2635 // to make the output image more clean. This will also test subrects
2636 // of the layer.
2637 gfx::Transform green_content_to_target_transform;
2638 gfx::Rect green_rect1(gfx::Point(80, 0), gfx::Size(20, 100));
2639 gfx::Rect green_rect2(gfx::Point(0, 80), gfx::Size(100, 20));
2641 scoped_ptr<FakePicturePile> green_recording =
2642 FakePicturePile::CreateFilledPile(pile_tile_size, viewport.size());
2644 SkPaint red_paint;
2645 red_paint.setColor(SK_ColorRED);
2646 green_recording->add_draw_rect_with_paint(viewport, red_paint);
2647 SkPaint green_paint;
2648 green_paint.setColor(SK_ColorGREEN);
2649 green_recording->add_draw_rect_with_paint(green_rect1, green_paint);
2650 green_recording->add_draw_rect_with_paint(green_rect2, green_paint);
2651 green_recording->Rerecord();
2652 scoped_refptr<FakePicturePileImpl> green_pile =
2653 FakePicturePileImpl::CreateFromPile(green_recording.get(), nullptr);
2655 SharedQuadState* top_right_green_shared_quad_state =
2656 CreateTestSharedQuadState(
2657 green_content_to_target_transform, viewport, pass.get());
2659 PictureDrawQuad* green_quad1 =
2660 pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
2661 green_quad1->SetNew(top_right_green_shared_quad_state, green_rect1,
2662 gfx::Rect(), green_rect1, gfx::RectF(green_rect1.size()),
2663 green_rect1.size(), nearest_neighbor, texture_format,
2664 green_rect1, 1.f, green_pile.get());
2666 PictureDrawQuad* green_quad2 =
2667 pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
2668 green_quad2->SetNew(top_right_green_shared_quad_state, green_rect2,
2669 gfx::Rect(), green_rect2, gfx::RectF(green_rect2.size()),
2670 green_rect2.size(), nearest_neighbor, texture_format,
2671 green_rect2, 1.f, green_pile.get());
2673 // Add a green clipped checkerboard in the bottom right to help test
2674 // interleaving picture quad content and solid color content.
2675 gfx::Rect bottom_right_rect(
2676 gfx::Point(viewport.width() / 2, viewport.height() / 2),
2677 gfx::Size(viewport.width() / 2, viewport.height() / 2));
2678 SharedQuadState* bottom_right_green_shared_state =
2679 CreateTestSharedQuadStateClipped(green_content_to_target_transform,
2680 viewport,
2681 bottom_right_rect,
2682 pass.get());
2683 SolidColorDrawQuad* bottom_right_color_quad =
2684 pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2685 bottom_right_color_quad->SetNew(bottom_right_green_shared_state,
2686 viewport,
2687 viewport,
2688 SK_ColorGREEN,
2689 false);
2691 // Add two blue checkerboards taking up the bottom left and top right,
2692 // but use content scales as content rects to make this happen.
2693 // The content is at a 4x content scale.
2694 gfx::Rect layer_rect(gfx::Size(20, 30));
2695 float contents_scale = 4.f;
2696 // Two rects that touch at their corners, arbitrarily placed in the layer.
2697 gfx::RectF blue_layer_rect1(gfx::PointF(5.5f, 9.0f), gfx::SizeF(2.5f, 2.5f));
2698 gfx::RectF blue_layer_rect2(gfx::PointF(8.0f, 6.5f), gfx::SizeF(2.5f, 2.5f));
2699 gfx::RectF union_layer_rect = blue_layer_rect1;
2700 union_layer_rect.Union(blue_layer_rect2);
2702 // Because scaling up will cause sampling outside the rects, add one extra
2703 // pixel of buffer at the final content scale.
2704 float inset = -1.f / contents_scale;
2705 blue_layer_rect1.Inset(inset, inset, inset, inset);
2706 blue_layer_rect2.Inset(inset, inset, inset, inset);
2708 scoped_ptr<FakePicturePile> recording =
2709 FakePicturePile::CreateFilledPile(pile_tile_size, layer_rect.size());
2711 Region outside(layer_rect);
2712 outside.Subtract(gfx::ToEnclosingRect(union_layer_rect));
2713 for (Region::Iterator iter(outside); iter.has_rect(); iter.next()) {
2714 recording->add_draw_rect_with_paint(iter.rect(), red_paint);
2717 SkPaint blue_paint;
2718 blue_paint.setColor(SK_ColorBLUE);
2719 recording->add_draw_rect_with_paint(blue_layer_rect1, blue_paint);
2720 recording->add_draw_rect_with_paint(blue_layer_rect2, blue_paint);
2721 recording->Rerecord();
2722 scoped_refptr<FakePicturePileImpl> pile =
2723 FakePicturePileImpl::CreateFromPile(recording.get(), nullptr);
2725 gfx::Rect content_rect(
2726 gfx::ScaleToEnclosingRect(layer_rect, contents_scale));
2727 gfx::Rect content_union_rect(
2728 gfx::ToEnclosingRect(gfx::ScaleRect(union_layer_rect, contents_scale)));
2730 // At a scale of 4x the rectangles with a width of 2.5 will take up 10 pixels,
2731 // so scale an additional 10x to make them 100x100.
2732 gfx::Transform content_to_target_transform;
2733 content_to_target_transform.Scale(10.0, 10.0);
2734 gfx::Rect quad_content_rect(gfx::Size(20, 20));
2735 SharedQuadState* blue_shared_state = CreateTestSharedQuadState(
2736 content_to_target_transform, quad_content_rect, pass.get());
2738 PictureDrawQuad* blue_quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
2739 blue_quad->SetNew(blue_shared_state, quad_content_rect, gfx::Rect(),
2740 quad_content_rect, gfx::RectF(quad_content_rect),
2741 content_union_rect.size(), nearest_neighbor, texture_format,
2742 content_union_rect, contents_scale, pile.get());
2744 // Fill left half of viewport with green.
2745 gfx::Transform half_green_content_to_target_transform;
2746 gfx::Rect half_green_rect(gfx::Size(viewport.width() / 2, viewport.height()));
2747 SharedQuadState* half_green_shared_state = CreateTestSharedQuadState(
2748 half_green_content_to_target_transform, half_green_rect, pass.get());
2749 SolidColorDrawQuad* half_color_quad =
2750 pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2751 half_color_quad->SetNew(half_green_shared_state,
2752 half_green_rect,
2753 half_green_rect,
2754 SK_ColorGREEN,
2755 false);
2757 RenderPassList pass_list;
2758 pass_list.push_back(pass.Pass());
2760 EXPECT_TRUE(this->RunPixelTest(
2761 &pass_list,
2762 base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")),
2763 ExactPixelComparator(true)));
2766 typedef RendererPixelTest<GLRendererWithFlippedSurface>
2767 GLRendererPixelTestWithFlippedOutputSurface;
2769 TEST_F(GLRendererPixelTestWithFlippedOutputSurface, ExplicitFlipTest) {
2770 // This draws a blue rect above a yellow rect with an inverted output surface.
2771 gfx::Rect viewport_rect(this->device_viewport_size_);
2773 RenderPassId root_pass_id(1, 1);
2774 scoped_ptr<RenderPass> root_pass =
2775 CreateTestRootRenderPass(root_pass_id, viewport_rect);
2777 RenderPassId child_pass_id(2, 2);
2778 gfx::Rect pass_rect(this->device_viewport_size_);
2779 gfx::Transform transform_to_root;
2780 scoped_ptr<RenderPass> child_pass =
2781 CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
2783 gfx::Transform content_to_target_transform;
2784 SharedQuadState* shared_state = CreateTestSharedQuadState(
2785 content_to_target_transform, viewport_rect, child_pass.get());
2787 gfx::Rect blue_rect(0,
2789 this->device_viewport_size_.width(),
2790 this->device_viewport_size_.height() / 2);
2791 SolidColorDrawQuad* blue =
2792 child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2793 blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
2794 gfx::Rect yellow_rect(0,
2795 this->device_viewport_size_.height() / 2,
2796 this->device_viewport_size_.width(),
2797 this->device_viewport_size_.height() / 2);
2798 SolidColorDrawQuad* yellow =
2799 child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2800 yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false);
2802 SharedQuadState* pass_shared_state =
2803 CreateTestSharedQuadState(gfx::Transform(), pass_rect, root_pass.get());
2804 CreateTestRenderPassDrawQuad(
2805 pass_shared_state, pass_rect, child_pass_id, root_pass.get());
2807 RenderPassList pass_list;
2808 pass_list.push_back(child_pass.Pass());
2809 pass_list.push_back(root_pass.Pass());
2811 EXPECT_TRUE(this->RunPixelTest(
2812 &pass_list,
2813 base::FilePath(FILE_PATH_LITERAL("blue_yellow_flipped.png")),
2814 ExactPixelComparator(true)));
2817 TEST_F(GLRendererPixelTestWithFlippedOutputSurface, CheckChildPassUnflipped) {
2818 // This draws a blue rect above a yellow rect with an inverted output surface.
2819 gfx::Rect viewport_rect(this->device_viewport_size_);
2821 RenderPassId root_pass_id(1, 1);
2822 scoped_ptr<RenderPass> root_pass =
2823 CreateTestRootRenderPass(root_pass_id, viewport_rect);
2825 RenderPassId child_pass_id(2, 2);
2826 gfx::Rect pass_rect(this->device_viewport_size_);
2827 gfx::Transform transform_to_root;
2828 scoped_ptr<RenderPass> child_pass =
2829 CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
2831 gfx::Transform content_to_target_transform;
2832 SharedQuadState* shared_state = CreateTestSharedQuadState(
2833 content_to_target_transform, viewport_rect, child_pass.get());
2835 gfx::Rect blue_rect(0,
2837 this->device_viewport_size_.width(),
2838 this->device_viewport_size_.height() / 2);
2839 SolidColorDrawQuad* blue =
2840 child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2841 blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
2842 gfx::Rect yellow_rect(0,
2843 this->device_viewport_size_.height() / 2,
2844 this->device_viewport_size_.width(),
2845 this->device_viewport_size_.height() / 2);
2846 SolidColorDrawQuad* yellow =
2847 child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2848 yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false);
2850 SharedQuadState* pass_shared_state =
2851 CreateTestSharedQuadState(gfx::Transform(), pass_rect, root_pass.get());
2852 CreateTestRenderPassDrawQuad(
2853 pass_shared_state, pass_rect, child_pass_id, root_pass.get());
2855 RenderPassList pass_list;
2856 pass_list.push_back(child_pass.Pass());
2857 pass_list.push_back(root_pass.Pass());
2859 // Check that the child pass remains unflipped.
2860 EXPECT_TRUE(this->RunPixelTestWithReadbackTarget(
2861 &pass_list,
2862 pass_list.front(),
2863 base::FilePath(FILE_PATH_LITERAL("blue_yellow.png")),
2864 ExactPixelComparator(true)));
2867 TEST_F(GLRendererPixelTest, CheckReadbackSubset) {
2868 gfx::Rect viewport_rect(this->device_viewport_size_);
2870 RenderPassId root_pass_id(1, 1);
2871 scoped_ptr<RenderPass> root_pass =
2872 CreateTestRootRenderPass(root_pass_id, viewport_rect);
2874 RenderPassId child_pass_id(2, 2);
2875 gfx::Rect pass_rect(this->device_viewport_size_);
2876 gfx::Transform transform_to_root;
2877 scoped_ptr<RenderPass> child_pass =
2878 CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
2880 gfx::Transform content_to_target_transform;
2881 SharedQuadState* shared_state = CreateTestSharedQuadState(
2882 content_to_target_transform, viewport_rect, child_pass.get());
2884 // Draw a green quad full-size with a blue quad in the lower-right corner.
2885 gfx::Rect blue_rect(this->device_viewport_size_.width() * 3 / 4,
2886 this->device_viewport_size_.height() * 3 / 4,
2887 this->device_viewport_size_.width() * 3 / 4,
2888 this->device_viewport_size_.height() * 3 / 4);
2889 SolidColorDrawQuad* blue =
2890 child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2891 blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
2892 gfx::Rect green_rect(0,
2894 this->device_viewport_size_.width(),
2895 this->device_viewport_size_.height());
2896 SolidColorDrawQuad* green =
2897 child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2898 green->SetNew(shared_state, green_rect, green_rect, SK_ColorGREEN, false);
2900 SharedQuadState* pass_shared_state =
2901 CreateTestSharedQuadState(gfx::Transform(), pass_rect, root_pass.get());
2902 CreateTestRenderPassDrawQuad(
2903 pass_shared_state, pass_rect, child_pass_id, root_pass.get());
2905 RenderPassList pass_list;
2906 pass_list.push_back(child_pass.Pass());
2907 pass_list.push_back(root_pass.Pass());
2909 // Check that the child pass remains unflipped.
2910 gfx::Rect capture_rect(this->device_viewport_size_.width() / 2,
2911 this->device_viewport_size_.height() / 2,
2912 this->device_viewport_size_.width() / 2,
2913 this->device_viewport_size_.height() / 2);
2914 EXPECT_TRUE(this->RunPixelTestWithReadbackTargetAndArea(
2915 &pass_list,
2916 pass_list.front(),
2917 base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")),
2918 ExactPixelComparator(true),
2919 &capture_rect));
2922 TYPED_TEST(RendererPixelTest, WrapModeRepeat) {
2923 gfx::Rect rect(this->device_viewport_size_);
2925 RenderPassId id(1, 1);
2926 scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
2928 SharedQuadState* shared_state =
2929 CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
2931 gfx::Size texture_size(4, 4);
2932 SkPMColor colors[4] = {
2933 SkPreMultiplyColor(SkColorSetARGB(255, 0, 255, 0)),
2934 SkPreMultiplyColor(SkColorSetARGB(255, 0, 128, 0)),
2935 SkPreMultiplyColor(SkColorSetARGB(255, 0, 64, 0)),
2936 SkPreMultiplyColor(SkColorSetARGB(255, 0, 0, 0)),
2938 uint32_t pixels[16] = {
2939 colors[0], colors[0], colors[1], colors[1],
2940 colors[0], colors[0], colors[1], colors[1],
2941 colors[2], colors[2], colors[3], colors[3],
2942 colors[2], colors[2], colors[3], colors[3],
2944 ResourceId resource = this->resource_provider_->CreateResource(
2945 texture_size, GL_REPEAT, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
2946 RGBA_8888);
2947 this->resource_provider_->CopyToResource(
2948 resource, reinterpret_cast<uint8_t*>(pixels), texture_size);
2950 float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
2951 TextureDrawQuad* texture_quad =
2952 pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
2953 texture_quad->SetNew(
2954 shared_state, gfx::Rect(this->device_viewport_size_), gfx::Rect(),
2955 gfx::Rect(this->device_viewport_size_), resource,
2956 true, // premultiplied_alpha
2957 gfx::PointF(0.0f, 0.0f), // uv_top_left
2958 gfx::PointF( // uv_bottom_right
2959 this->device_viewport_size_.width() / texture_size.width(),
2960 this->device_viewport_size_.height() / texture_size.height()),
2961 SK_ColorWHITE, vertex_opacity,
2962 false, // flipped
2963 false); // nearest_neighbor
2965 RenderPassList pass_list;
2966 pass_list.push_back(pass.Pass());
2968 EXPECT_TRUE(this->RunPixelTest(
2969 &pass_list,
2970 base::FilePath(FILE_PATH_LITERAL("wrap_mode_repeat.png")),
2971 FuzzyPixelOffByOneComparator(true)));
2974 TYPED_TEST(RendererPixelTest, Checkerboards) {
2975 gfx::Rect rect(this->device_viewport_size_);
2977 RenderPassId id(1, 1);
2978 scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
2980 SharedQuadState* shared_state =
2981 CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
2983 // The color's alpha value is not used.
2984 SkColor color1 = SK_ColorGREEN;
2985 color1 = SkColorSetA(color1, 0);
2986 SkColor color2 = SK_ColorBLUE;
2987 color2 = SkColorSetA(color2, 0);
2989 gfx::Rect content_rect(rect);
2991 gfx::Rect top_left(content_rect);
2992 gfx::Rect top_right(content_rect);
2993 gfx::Rect bottom_left(content_rect);
2994 gfx::Rect bottom_right(content_rect);
2995 // The format is Inset(left, top, right, bottom).
2996 top_left.Inset(0, 0, content_rect.width() / 2, content_rect.height() / 2);
2997 top_right.Inset(content_rect.width() / 2, 0, 0, content_rect.height() / 2);
2998 bottom_left.Inset(0, content_rect.height() / 2, content_rect.width() / 2, 0);
2999 bottom_right.Inset(content_rect.width() / 2, content_rect.height() / 2, 0, 0);
3001 // Appends checkerboard quads with a scale of 1.
3002 CheckerboardDrawQuad* quad =
3003 pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
3004 quad->SetNew(shared_state, top_left, top_left, color1, 1.f);
3005 quad = pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
3006 quad->SetNew(shared_state, top_right, top_right, color2, 1.f);
3007 quad = pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
3008 quad->SetNew(shared_state, bottom_left, bottom_left, color2, 1.f);
3009 quad = pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
3010 quad->SetNew(shared_state, bottom_right, bottom_right, color1, 1.f);
3012 RenderPassList pass_list;
3013 pass_list.push_back(pass.Pass());
3015 base::FilePath::StringType path =
3016 IsSoftwareRenderer<TypeParam>()
3017 ? FILE_PATH_LITERAL("four_blue_green_checkers.png")
3018 : FILE_PATH_LITERAL("checkers.png");
3019 EXPECT_TRUE(this->RunPixelTest(&pass_list, base::FilePath(path),
3020 ExactPixelComparator(true)));
3023 TYPED_TEST(RendererPixelTest, CheckerboardsScaled) {
3024 gfx::Rect rect(this->device_viewport_size_);
3026 RenderPassId id(1, 1);
3027 scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
3029 gfx::Transform scale;
3030 scale.Scale(2.f, 2.f);
3032 SharedQuadState* shared_state =
3033 CreateTestSharedQuadState(scale, rect, pass.get());
3035 // The color's alpha value is not used.
3036 SkColor color1 = SK_ColorGREEN;
3037 color1 = SkColorSetA(color1, 0);
3038 SkColor color2 = SK_ColorBLUE;
3039 color2 = SkColorSetA(color2, 0);
3041 gfx::Rect content_rect(rect);
3042 content_rect.Inset(0, 0, rect.width() / 2, rect.height() / 2);
3044 gfx::Rect top_left(content_rect);
3045 gfx::Rect top_right(content_rect);
3046 gfx::Rect bottom_left(content_rect);
3047 gfx::Rect bottom_right(content_rect);
3048 // The format is Inset(left, top, right, bottom).
3049 top_left.Inset(0, 0, content_rect.width() / 2, content_rect.height() / 2);
3050 top_right.Inset(content_rect.width() / 2, 0, 0, content_rect.height() / 2);
3051 bottom_left.Inset(0, content_rect.height() / 2, content_rect.width() / 2, 0);
3052 bottom_right.Inset(content_rect.width() / 2, content_rect.height() / 2, 0, 0);
3054 // Appends checkerboard quads with a scale of 2, and a shared quad state
3055 // with a scale of 2. The checkers should be scaled by 2 * 2 = 4.
3056 CheckerboardDrawQuad* quad =
3057 pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
3058 quad->SetNew(shared_state, top_left, top_left, color1, 2.f);
3059 quad = pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
3060 quad->SetNew(shared_state, top_right, top_right, color2, 2.f);
3061 quad = pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
3062 quad->SetNew(shared_state, bottom_left, bottom_left, color2, 2.f);
3063 quad = pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
3064 quad->SetNew(shared_state, bottom_right, bottom_right, color1, 2.f);
3066 RenderPassList pass_list;
3067 pass_list.push_back(pass.Pass());
3069 base::FilePath::StringType path =
3070 IsSoftwareRenderer<TypeParam>()
3071 ? FILE_PATH_LITERAL("four_blue_green_checkers.png")
3072 : FILE_PATH_LITERAL("checkers_big.png");
3073 EXPECT_TRUE(this->RunPixelTest(&pass_list, base::FilePath(path),
3074 ExactPixelComparator(true)));
3077 #endif // !defined(OS_ANDROID)
3079 } // namespace
3080 } // namespace cc