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.
4
5#include "base/message_loop/message_loop.h"
6#include "cc/layers/append_quads_data.h"
7#include "cc/output/gl_renderer.h"
8#include "cc/quads/draw_quad.h"
9#include "cc/quads/picture_draw_quad.h"
10#include "cc/quads/texture_draw_quad.h"
11#include "cc/resources/video_resource_updater.h"
12#include "cc/test/fake_picture_pile_impl.h"
13#include "cc/test/pixel_test.h"
14#include "gpu/GLES2/gl2extchromium.h"
15#include "gpu/command_buffer/client/gles2_interface.h"
16#include "media/base/video_frame.h"
17#include "third_party/skia/include/core/SkBitmapDevice.h"
18#include "third_party/skia/include/core/SkImageFilter.h"
19#include "third_party/skia/include/core/SkMatrix.h"
20#include "third_party/skia/include/effects/SkColorFilterImageFilter.h"
21#include "third_party/skia/include/effects/SkColorMatrixFilter.h"
22#include "ui/gfx/rect_conversions.h"
23
24using gpu::gles2::GLES2Interface;
25
26namespace cc {
27namespace {
28
29#if !defined(OS_ANDROID)
30scoped_ptr<RenderPass> CreateTestRootRenderPass(RenderPass::Id id,
31                                                const gfx::Rect& rect) {
32  scoped_ptr<RenderPass> pass = RenderPass::Create();
33  const gfx::Rect output_rect = rect;
34  const gfx::Rect damage_rect = rect;
35  const gfx::Transform transform_to_root_target;
36  pass->SetNew(id, output_rect, damage_rect, transform_to_root_target);
37  return pass.Pass();
38}
39
40scoped_ptr<RenderPass> CreateTestRenderPass(
41    RenderPass::Id id,
42    const gfx::Rect& rect,
43    const gfx::Transform& transform_to_root_target) {
44  scoped_ptr<RenderPass> pass = RenderPass::Create();
45  const gfx::Rect output_rect = rect;
46  const gfx::Rect damage_rect = rect;
47  pass->SetNew(id, output_rect, damage_rect, transform_to_root_target);
48  return pass.Pass();
49}
50
51SharedQuadState* CreateTestSharedQuadState(
52    RenderPass* render_pass,
53    gfx::Transform content_to_target_transform,
54    const gfx::Rect& rect) {
55  const gfx::Size content_bounds = rect.size();
56  const gfx::Rect visible_content_rect = rect;
57  const gfx::Rect clip_rect = rect;
58  const bool is_clipped = false;
59  const float opacity = 1.0f;
60  const SkXfermode::Mode blend_mode = SkXfermode::kSrcOver_Mode;
61  int sorting_context_id = 0;
62  SharedQuadState* shared_state = render_pass->CreateAndAppendSharedQuadState();
63  shared_state->SetAll(content_to_target_transform,
64                       content_bounds,
65                       visible_content_rect,
66                       clip_rect,
67                       is_clipped,
68                       opacity,
69                       blend_mode,
70                       sorting_context_id);
71  return shared_state;
72}
73
74SharedQuadState* CreateTestSharedQuadStateClipped(
75    RenderPass* render_pass,
76    gfx::Transform content_to_target_transform,
77    const gfx::Rect& rect,
78    const gfx::Rect& clip_rect) {
79  const gfx::Size content_bounds = rect.size();
80  const gfx::Rect visible_content_rect = clip_rect;
81  const bool is_clipped = true;
82  const float opacity = 1.0f;
83  const SkXfermode::Mode blend_mode = SkXfermode::kSrcOver_Mode;
84  int sorting_context_id = 0;
85  SharedQuadState* shared_state = render_pass->CreateAndAppendSharedQuadState();
86  shared_state->SetAll(content_to_target_transform,
87                       content_bounds,
88                       visible_content_rect,
89                       clip_rect,
90                       is_clipped,
91                       opacity,
92                       blend_mode,
93                       sorting_context_id);
94  return shared_state;
95}
96
97scoped_ptr<DrawQuad> CreateTestRenderPassDrawQuad(
98    SharedQuadState* shared_state,
99    const gfx::Rect& rect,
100    RenderPass::Id pass_id) {
101  scoped_ptr<RenderPassDrawQuad> quad = RenderPassDrawQuad::Create();
102  quad->SetNew(shared_state,
103               rect,
104               rect,
105               pass_id,
106               false,                 // is_replica
107               0,                     // mask_resource_id
108               rect,                  // contents_changed_since_last_frame
109               gfx::RectF(1.f, 1.f),  // mask_uv_rect
110               FilterOperations(),    // foreground filters
111               FilterOperations());   // background filters
112
113  return quad.PassAs<DrawQuad>();
114}
115
116scoped_ptr<TextureDrawQuad> CreateTestTextureDrawQuad(
117    const gfx::Rect& rect,
118    SkColor texel_color,
119    SkColor background_color,
120    bool premultiplied_alpha,
121    SharedQuadState* shared_state,
122    ResourceProvider* resource_provider) {
123  SkPMColor pixel_color = premultiplied_alpha ?
124      SkPreMultiplyColor(texel_color) :
125      SkPackARGB32NoCheck(SkColorGetA(texel_color),
126                          SkColorGetR(texel_color),
127                          SkColorGetG(texel_color),
128                          SkColorGetB(texel_color));
129  std::vector<uint32_t> pixels(rect.size().GetArea(), pixel_color);
130
131  ResourceProvider::ResourceId resource =
132      resource_provider->CreateResource(rect.size(),
133                                        GL_CLAMP_TO_EDGE,
134                                        ResourceProvider::TextureUsageAny,
135                                        RGBA_8888);
136  resource_provider->SetPixels(
137      resource,
138      reinterpret_cast<uint8_t*>(&pixels.front()),
139      rect,
140      rect,
141      gfx::Vector2d());
142
143  float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
144
145  scoped_ptr<TextureDrawQuad> quad = TextureDrawQuad::Create();
146  quad->SetNew(shared_state,
147               rect,
148               gfx::Rect(),
149               rect,
150               resource,
151               premultiplied_alpha,
152               gfx::PointF(0.0f, 0.0f),  // uv_top_left
153               gfx::PointF(1.0f, 1.0f),  // uv_bottom_right
154               background_color,
155               vertex_opacity,
156               false);  // flipped
157  return quad.Pass();
158}
159
160typedef ::testing::Types<GLRenderer,
161                         SoftwareRenderer,
162                         GLRendererWithExpandedViewport,
163                         SoftwareRendererWithExpandedViewport> RendererTypes;
164TYPED_TEST_CASE(RendererPixelTest, RendererTypes);
165
166// All pixels can be off by one, but any more than that is an error.
167class FuzzyPixelOffByOneComparator : public FuzzyPixelComparator {
168 public:
169  explicit FuzzyPixelOffByOneComparator(bool discard_alpha)
170    : FuzzyPixelComparator(discard_alpha, 100.f, 0.f, 1.f, 1, 0) {}
171};
172
173template <typename RendererType>
174class FuzzyForSoftwareOnlyPixelComparator : public PixelComparator {
175 public:
176  explicit FuzzyForSoftwareOnlyPixelComparator(bool discard_alpha)
177      : fuzzy_(discard_alpha), exact_(discard_alpha) {}
178
179  virtual bool Compare(const SkBitmap& actual_bmp,
180                       const SkBitmap& expected_bmp) const;
181
182 private:
183  FuzzyPixelOffByOneComparator fuzzy_;
184  ExactPixelComparator exact_;
185};
186
187template<>
188bool FuzzyForSoftwareOnlyPixelComparator<SoftwareRenderer>::Compare(
189    const SkBitmap& actual_bmp,
190    const SkBitmap& expected_bmp) const {
191  return fuzzy_.Compare(actual_bmp, expected_bmp);
192}
193
194template <>
195bool FuzzyForSoftwareOnlyPixelComparator<
196    SoftwareRendererWithExpandedViewport>::Compare(
197    const SkBitmap& actual_bmp,
198    const SkBitmap& expected_bmp) const {
199  return fuzzy_.Compare(actual_bmp, expected_bmp);
200}
201
202template<typename RendererType>
203bool FuzzyForSoftwareOnlyPixelComparator<RendererType>::Compare(
204    const SkBitmap& actual_bmp,
205    const SkBitmap& expected_bmp) const {
206  return exact_.Compare(actual_bmp, expected_bmp);
207}
208
209TYPED_TEST(RendererPixelTest, SimpleGreenRect) {
210  gfx::Rect rect(this->device_viewport_size_);
211
212  RenderPass::Id id(1, 1);
213  scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
214
215  SharedQuadState* shared_state =
216      CreateTestSharedQuadState(pass.get(), gfx::Transform(), rect);
217
218  scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create();
219  color_quad->SetNew(shared_state, rect, rect, SK_ColorGREEN, false);
220
221  pass->quad_list.push_back(color_quad.PassAs<DrawQuad>());
222
223  RenderPassList pass_list;
224  pass_list.push_back(pass.Pass());
225
226  EXPECT_TRUE(this->RunPixelTest(
227      &pass_list,
228      base::FilePath(FILE_PATH_LITERAL("green.png")),
229      ExactPixelComparator(true)));
230}
231
232TYPED_TEST(RendererPixelTest, SimpleGreenRect_NonRootRenderPass) {
233  gfx::Rect rect(this->device_viewport_size_);
234  gfx::Rect small_rect(100, 100);
235
236  RenderPass::Id child_id(2, 1);
237  scoped_ptr<RenderPass> child_pass =
238      CreateTestRenderPass(child_id, small_rect, gfx::Transform());
239
240  SharedQuadState* child_shared_state =
241      CreateTestSharedQuadState(child_pass.get(), gfx::Transform(), small_rect);
242
243  scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create();
244  color_quad->SetNew(child_shared_state, rect, rect, SK_ColorGREEN, false);
245  child_pass->quad_list.push_back(color_quad.PassAs<DrawQuad>());
246
247  RenderPass::Id root_id(1, 1);
248  scoped_ptr<RenderPass> root_pass =
249      CreateTestRenderPass(root_id, rect, gfx::Transform());
250
251  SharedQuadState* root_shared_state =
252      CreateTestSharedQuadState(root_pass.get(), gfx::Transform(), rect);
253
254  scoped_ptr<DrawQuad> render_pass_quad =
255      CreateTestRenderPassDrawQuad(root_shared_state, small_rect, child_id);
256  root_pass->quad_list.push_back(render_pass_quad.PassAs<DrawQuad>());
257
258  RenderPass* child_pass_ptr = child_pass.get();
259
260  RenderPassList pass_list;
261  pass_list.push_back(child_pass.Pass());
262  pass_list.push_back(root_pass.Pass());
263
264  EXPECT_TRUE(this->RunPixelTestWithReadbackTarget(
265      &pass_list,
266      child_pass_ptr,
267      base::FilePath(FILE_PATH_LITERAL("green_small.png")),
268      ExactPixelComparator(true)));
269}
270
271TYPED_TEST(RendererPixelTest, PremultipliedTextureWithoutBackground) {
272  gfx::Rect rect(this->device_viewport_size_);
273
274  RenderPass::Id id(1, 1);
275  scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
276
277  SharedQuadState* shared_state =
278      CreateTestSharedQuadState(pass.get(), gfx::Transform(), rect);
279
280  scoped_ptr<TextureDrawQuad> texture_quad =
281      CreateTestTextureDrawQuad(gfx::Rect(this->device_viewport_size_),
282                                SkColorSetARGB(128, 0, 255, 0),  // Texel color.
283                                SK_ColorTRANSPARENT,  // Background color.
284                                true,                 // Premultiplied alpha.
285                                shared_state,
286                                this->resource_provider_.get());
287  pass->quad_list.push_back(texture_quad.PassAs<DrawQuad>());
288
289  scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create();
290  color_quad->SetNew(shared_state, rect, rect, SK_ColorWHITE, false);
291  pass->quad_list.push_back(color_quad.PassAs<DrawQuad>());
292
293  RenderPassList pass_list;
294  pass_list.push_back(pass.Pass());
295
296  EXPECT_TRUE(this->RunPixelTest(
297      &pass_list,
298      base::FilePath(FILE_PATH_LITERAL("green_alpha.png")),
299      FuzzyPixelOffByOneComparator(true)));
300}
301
302TYPED_TEST(RendererPixelTest, PremultipliedTextureWithBackground) {
303  gfx::Rect rect(this->device_viewport_size_);
304
305  RenderPass::Id id(1, 1);
306  scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
307
308  SharedQuadState* texture_quad_state =
309      CreateTestSharedQuadState(pass.get(), gfx::Transform(), rect);
310  texture_quad_state->opacity = 0.8f;
311
312  scoped_ptr<TextureDrawQuad> texture_quad = CreateTestTextureDrawQuad(
313      gfx::Rect(this->device_viewport_size_),
314      SkColorSetARGB(204, 120, 255, 120),  // Texel color.
315      SK_ColorGREEN,                       // Background color.
316      true,                                // Premultiplied alpha.
317      texture_quad_state,
318      this->resource_provider_.get());
319  pass->quad_list.push_back(texture_quad.PassAs<DrawQuad>());
320
321  SharedQuadState* color_quad_state =
322      CreateTestSharedQuadState(pass.get(), gfx::Transform(), rect);
323  scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create();
324  color_quad->SetNew(color_quad_state, rect, rect, SK_ColorWHITE, false);
325  pass->quad_list.push_back(color_quad.PassAs<DrawQuad>());
326
327  RenderPassList pass_list;
328  pass_list.push_back(pass.Pass());
329
330  EXPECT_TRUE(this->RunPixelTest(
331      &pass_list,
332      base::FilePath(FILE_PATH_LITERAL("green_alpha.png")),
333      FuzzyPixelOffByOneComparator(true)));
334}
335
336// TODO(skaslev): The software renderer does not support non-premultplied alpha.
337TEST_F(GLRendererPixelTest, NonPremultipliedTextureWithoutBackground) {
338  gfx::Rect rect(this->device_viewport_size_);
339
340  RenderPass::Id id(1, 1);
341  scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
342
343  SharedQuadState* shared_state =
344      CreateTestSharedQuadState(pass.get(), gfx::Transform(), rect);
345
346  scoped_ptr<TextureDrawQuad> texture_quad =
347      CreateTestTextureDrawQuad(gfx::Rect(this->device_viewport_size_),
348                                SkColorSetARGB(128, 0, 255, 0),  // Texel color.
349                                SK_ColorTRANSPARENT,  // Background color.
350                                false,                // Premultiplied alpha.
351                                shared_state,
352                                this->resource_provider_.get());
353  pass->quad_list.push_back(texture_quad.PassAs<DrawQuad>());
354
355  scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create();
356  color_quad->SetNew(shared_state, rect, rect, SK_ColorWHITE, false);
357  pass->quad_list.push_back(color_quad.PassAs<DrawQuad>());
358
359  RenderPassList pass_list;
360  pass_list.push_back(pass.Pass());
361
362  EXPECT_TRUE(this->RunPixelTest(
363      &pass_list,
364      base::FilePath(FILE_PATH_LITERAL("green_alpha.png")),
365      FuzzyPixelOffByOneComparator(true)));
366}
367
368// TODO(skaslev): The software renderer does not support non-premultplied alpha.
369TEST_F(GLRendererPixelTest, NonPremultipliedTextureWithBackground) {
370  gfx::Rect rect(this->device_viewport_size_);
371
372  RenderPass::Id id(1, 1);
373  scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
374
375  SharedQuadState* texture_quad_state =
376      CreateTestSharedQuadState(pass.get(), gfx::Transform(), rect);
377  texture_quad_state->opacity = 0.8f;
378
379  scoped_ptr<TextureDrawQuad> texture_quad = CreateTestTextureDrawQuad(
380      gfx::Rect(this->device_viewport_size_),
381      SkColorSetARGB(204, 120, 255, 120),  // Texel color.
382      SK_ColorGREEN,                       // Background color.
383      false,                               // Premultiplied alpha.
384      texture_quad_state,
385      this->resource_provider_.get());
386  pass->quad_list.push_back(texture_quad.PassAs<DrawQuad>());
387
388  SharedQuadState* color_quad_state =
389      CreateTestSharedQuadState(pass.get(), gfx::Transform(), rect);
390  scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create();
391  color_quad->SetNew(color_quad_state, rect, rect, SK_ColorWHITE, false);
392  pass->quad_list.push_back(color_quad.PassAs<DrawQuad>());
393
394  RenderPassList pass_list;
395  pass_list.push_back(pass.Pass());
396
397  EXPECT_TRUE(this->RunPixelTest(
398      &pass_list,
399      base::FilePath(FILE_PATH_LITERAL("green_alpha.png")),
400      FuzzyPixelOffByOneComparator(true)));
401}
402
403class VideoGLRendererPixelTest : public GLRendererPixelTest {
404 protected:
405  scoped_ptr<YUVVideoDrawQuad> CreateTestYUVVideoDrawQuad_Striped(
406      SharedQuadState* shared_state,
407      media::VideoFrame::Format format,
408      bool is_transparent,
409      const gfx::RectF& tex_coord_rect) {
410    const gfx::Rect rect(this->device_viewport_size_);
411
412    scoped_refptr<media::VideoFrame> video_frame =
413        media::VideoFrame::CreateFrame(
414            format, rect.size(), rect, rect.size(), base::TimeDelta());
415
416    // YUV values representing a striped pattern, for validating texture
417    // coordinates for sampling.
418    uint8_t y_value = 0;
419    uint8_t u_value = 0;
420    uint8_t v_value = 0;
421    for (int i = 0; i < video_frame->rows(media::VideoFrame::kYPlane); ++i) {
422      uint8_t* y_row = video_frame->data(media::VideoFrame::kYPlane) +
423                       video_frame->stride(media::VideoFrame::kYPlane) * i;
424      for (int j = 0; j < video_frame->row_bytes(media::VideoFrame::kYPlane);
425           ++j) {
426        y_row[j] = (y_value += 1);
427      }
428    }
429    for (int i = 0; i < video_frame->rows(media::VideoFrame::kUPlane); ++i) {
430      uint8_t* u_row = video_frame->data(media::VideoFrame::kUPlane) +
431                       video_frame->stride(media::VideoFrame::kUPlane) * i;
432      uint8_t* v_row = video_frame->data(media::VideoFrame::kVPlane) +
433                       video_frame->stride(media::VideoFrame::kVPlane) * i;
434      for (int j = 0; j < video_frame->row_bytes(media::VideoFrame::kUPlane);
435           ++j) {
436        u_row[j] = (u_value += 3);
437        v_row[j] = (v_value += 5);
438      }
439    }
440    return CreateTestYUVVideoDrawQuad_FromVideoFrame(
441        shared_state, video_frame, is_transparent, tex_coord_rect);
442  }
443
444  scoped_ptr<YUVVideoDrawQuad> CreateTestYUVVideoDrawQuad_Solid(
445      SharedQuadState* shared_state,
446      media::VideoFrame::Format format,
447      bool is_transparent,
448      const gfx::RectF& tex_coord_rect,
449      uint8 y,
450      uint8 u,
451      uint8 v) {
452    const gfx::Rect rect(this->device_viewport_size_);
453
454    scoped_refptr<media::VideoFrame> video_frame =
455        media::VideoFrame::CreateFrame(
456            format, rect.size(), rect, rect.size(), base::TimeDelta());
457
458    // YUV values of a solid, constant, color. Useful for testing that color
459    // space/color range are being handled properly.
460    memset(video_frame->data(media::VideoFrame::kYPlane),
461           y,
462           video_frame->stride(media::VideoFrame::kYPlane) *
463               video_frame->rows(media::VideoFrame::kYPlane));
464    memset(video_frame->data(media::VideoFrame::kUPlane),
465           u,
466           video_frame->stride(media::VideoFrame::kUPlane) *
467               video_frame->rows(media::VideoFrame::kUPlane));
468    memset(video_frame->data(media::VideoFrame::kVPlane),
469           v,
470           video_frame->stride(media::VideoFrame::kVPlane) *
471               video_frame->rows(media::VideoFrame::kVPlane));
472
473    return CreateTestYUVVideoDrawQuad_FromVideoFrame(
474        shared_state, video_frame, is_transparent, tex_coord_rect);
475  }
476
477  scoped_ptr<YUVVideoDrawQuad> CreateTestYUVVideoDrawQuad_FromVideoFrame(
478      SharedQuadState* shared_state,
479      scoped_refptr<media::VideoFrame> video_frame,
480      bool is_transparent,
481      const gfx::RectF& tex_coord_rect) {
482    const bool with_alpha = (video_frame->format() == media::VideoFrame::YV12A);
483    const YUVVideoDrawQuad::ColorSpace color_space =
484        (video_frame->format() == media::VideoFrame::YV12J
485             ? YUVVideoDrawQuad::REC_601_JPEG
486             : YUVVideoDrawQuad::REC_601);
487    const gfx::Rect rect(this->device_viewport_size_);
488    const gfx::Rect opaque_rect(0, 0, 0, 0);
489
490    if (with_alpha)
491      memset(video_frame->data(media::VideoFrame::kAPlane),
492             is_transparent ? 0 : 128,
493             video_frame->stride(media::VideoFrame::kAPlane) *
494                 video_frame->rows(media::VideoFrame::kAPlane));
495
496    VideoFrameExternalResources resources =
497        video_resource_updater_->CreateExternalResourcesFromVideoFrame(
498            video_frame);
499
500    EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE, resources.type);
501    EXPECT_EQ(media::VideoFrame::NumPlanes(video_frame->format()),
502              resources.mailboxes.size());
503    EXPECT_EQ(media::VideoFrame::NumPlanes(video_frame->format()),
504              resources.release_callbacks.size());
505
506    ResourceProvider::ResourceId y_resource =
507        resource_provider_->CreateResourceFromTextureMailbox(
508            resources.mailboxes[media::VideoFrame::kYPlane],
509            SingleReleaseCallback::Create(
510                resources.release_callbacks[media::VideoFrame::kYPlane]));
511    ResourceProvider::ResourceId u_resource =
512        resource_provider_->CreateResourceFromTextureMailbox(
513            resources.mailboxes[media::VideoFrame::kUPlane],
514            SingleReleaseCallback::Create(
515                resources.release_callbacks[media::VideoFrame::kUPlane]));
516    ResourceProvider::ResourceId v_resource =
517        resource_provider_->CreateResourceFromTextureMailbox(
518            resources.mailboxes[media::VideoFrame::kVPlane],
519            SingleReleaseCallback::Create(
520                resources.release_callbacks[media::VideoFrame::kVPlane]));
521    ResourceProvider::ResourceId a_resource = 0;
522    if (with_alpha) {
523      a_resource = resource_provider_->CreateResourceFromTextureMailbox(
524          resources.mailboxes[media::VideoFrame::kAPlane],
525          SingleReleaseCallback::Create(
526              resources.release_callbacks[media::VideoFrame::kAPlane]));
527    }
528
529    scoped_ptr<YUVVideoDrawQuad> yuv_quad = YUVVideoDrawQuad::Create();
530    yuv_quad->SetNew(shared_state,
531                     rect,
532                     opaque_rect,
533                     rect,
534                     tex_coord_rect,
535                     y_resource,
536                     u_resource,
537                     v_resource,
538                     a_resource,
539                     color_space);
540    return yuv_quad.Pass();
541  }
542
543  virtual void SetUp() OVERRIDE {
544    GLRendererPixelTest::SetUp();
545    video_resource_updater_.reset(new VideoResourceUpdater(
546        output_surface_->context_provider().get(), resource_provider_.get()));
547  }
548
549 private:
550  scoped_ptr<VideoResourceUpdater> video_resource_updater_;
551};
552
553TEST_F(VideoGLRendererPixelTest, SimpleYUVRect) {
554  gfx::Rect rect(this->device_viewport_size_);
555
556  RenderPass::Id id(1, 1);
557  scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
558
559  SharedQuadState* shared_state =
560      CreateTestSharedQuadState(pass.get(), gfx::Transform(), rect);
561
562  scoped_ptr<YUVVideoDrawQuad> yuv_quad =
563      CreateTestYUVVideoDrawQuad_Striped(shared_state,
564                                         media::VideoFrame::YV12,
565                                         false,
566                                         gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f));
567
568  pass->quad_list.push_back(yuv_quad.PassAs<DrawQuad>());
569
570  RenderPassList pass_list;
571  pass_list.push_back(pass.Pass());
572
573  EXPECT_TRUE(
574      this->RunPixelTest(&pass_list,
575                         base::FilePath(FILE_PATH_LITERAL("yuv_stripes.png")),
576                         FuzzyPixelOffByOneComparator(true)));
577}
578
579TEST_F(VideoGLRendererPixelTest, OffsetYUVRect) {
580  gfx::Rect rect(this->device_viewport_size_);
581
582  RenderPass::Id id(1, 1);
583  scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
584
585  SharedQuadState* shared_state =
586      CreateTestSharedQuadState(pass.get(), gfx::Transform(), rect);
587
588  // Intentionally sets frame format to I420 for testing coverage.
589  scoped_ptr<YUVVideoDrawQuad> yuv_quad = CreateTestYUVVideoDrawQuad_Striped(
590      shared_state,
591      media::VideoFrame::I420,
592      false,
593      gfx::RectF(0.125f, 0.25f, 0.75f, 0.5f));
594
595  pass->quad_list.push_back(yuv_quad.PassAs<DrawQuad>());
596
597  RenderPassList pass_list;
598  pass_list.push_back(pass.Pass());
599
600  EXPECT_TRUE(this->RunPixelTest(
601      &pass_list,
602      base::FilePath(FILE_PATH_LITERAL("yuv_stripes_offset.png")),
603      FuzzyPixelOffByOneComparator(true)));
604}
605
606TEST_F(VideoGLRendererPixelTest, SimpleYUVRectBlack) {
607  gfx::Rect rect(this->device_viewport_size_);
608
609  RenderPass::Id id(1, 1);
610  scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
611
612  SharedQuadState* shared_state =
613      CreateTestSharedQuadState(pass.get(), gfx::Transform(), rect);
614
615  // In MPEG color range YUV values of (15,128,128) should produce black.
616  scoped_ptr<YUVVideoDrawQuad> yuv_quad =
617      CreateTestYUVVideoDrawQuad_Solid(shared_state,
618                                       media::VideoFrame::YV12,
619                                       false,
620                                       gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f),
621                                       15,
622                                       128,
623                                       128);
624
625  pass->quad_list.push_back(yuv_quad.PassAs<DrawQuad>());
626
627  RenderPassList pass_list;
628  pass_list.push_back(pass.Pass());
629
630  // If we didn't get black out of the YUV values above, then we probably have a
631  // color range issue.
632  EXPECT_TRUE(this->RunPixelTest(&pass_list,
633                                 base::FilePath(FILE_PATH_LITERAL("black.png")),
634                                 FuzzyPixelOffByOneComparator(true)));
635}
636
637TEST_F(VideoGLRendererPixelTest, SimpleYUVJRect) {
638  gfx::Rect rect(this->device_viewport_size_);
639
640  RenderPass::Id id(1, 1);
641  scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
642
643  SharedQuadState* shared_state =
644      CreateTestSharedQuadState(pass.get(), gfx::Transform(), rect);
645
646  // YUV of (149,43,21) should be green (0,255,0) in RGB.
647  scoped_ptr<YUVVideoDrawQuad> yuv_quad =
648      CreateTestYUVVideoDrawQuad_Solid(shared_state,
649                                       media::VideoFrame::YV12J,
650                                       false,
651                                       gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f),
652                                       149,
653                                       43,
654                                       21);
655
656  pass->quad_list.push_back(yuv_quad.PassAs<DrawQuad>());
657
658  RenderPassList pass_list;
659  pass_list.push_back(pass.Pass());
660
661  EXPECT_TRUE(this->RunPixelTest(&pass_list,
662                                 base::FilePath(FILE_PATH_LITERAL("green.png")),
663                                 FuzzyPixelOffByOneComparator(true)));
664}
665
666TEST_F(VideoGLRendererPixelTest, SimpleYUVJRectGrey) {
667  gfx::Rect rect(this->device_viewport_size_);
668
669  RenderPass::Id id(1, 1);
670  scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
671
672  SharedQuadState* shared_state =
673      CreateTestSharedQuadState(pass.get(), gfx::Transform(), rect);
674
675  // Dark grey in JPEG color range (in MPEG, this is black).
676  scoped_ptr<YUVVideoDrawQuad> yuv_quad =
677      CreateTestYUVVideoDrawQuad_Solid(shared_state,
678                                       media::VideoFrame::YV12J,
679                                       false,
680                                       gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f),
681                                       15,
682                                       128,
683                                       128);
684
685  pass->quad_list.push_back(yuv_quad.PassAs<DrawQuad>());
686
687  RenderPassList pass_list;
688  pass_list.push_back(pass.Pass());
689
690  EXPECT_TRUE(
691      this->RunPixelTest(&pass_list,
692                         base::FilePath(FILE_PATH_LITERAL("dark_grey.png")),
693                         FuzzyPixelOffByOneComparator(true)));
694}
695
696TEST_F(VideoGLRendererPixelTest, SimpleYUVARect) {
697  gfx::Rect rect(this->device_viewport_size_);
698
699  RenderPass::Id id(1, 1);
700  scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
701
702  SharedQuadState* shared_state =
703      CreateTestSharedQuadState(pass.get(), gfx::Transform(), rect);
704
705  scoped_ptr<YUVVideoDrawQuad> yuv_quad =
706      CreateTestYUVVideoDrawQuad_Striped(shared_state,
707                                         media::VideoFrame::YV12A,
708                                         false,
709                                         gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f));
710
711  pass->quad_list.push_back(yuv_quad.PassAs<DrawQuad>());
712
713  scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create();
714  color_quad->SetNew(shared_state, rect, rect, SK_ColorWHITE, false);
715
716  pass->quad_list.push_back(color_quad.PassAs<DrawQuad>());
717
718  RenderPassList pass_list;
719  pass_list.push_back(pass.Pass());
720
721  EXPECT_TRUE(this->RunPixelTest(
722      &pass_list,
723      base::FilePath(FILE_PATH_LITERAL("yuv_stripes_alpha.png")),
724      FuzzyPixelOffByOneComparator(true)));
725}
726
727TEST_F(VideoGLRendererPixelTest, FullyTransparentYUVARect) {
728  gfx::Rect rect(this->device_viewport_size_);
729
730  RenderPass::Id id(1, 1);
731  scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
732
733  SharedQuadState* shared_state =
734      CreateTestSharedQuadState(pass.get(), gfx::Transform(), rect);
735
736  scoped_ptr<YUVVideoDrawQuad> yuv_quad =
737      CreateTestYUVVideoDrawQuad_Striped(shared_state,
738                                         media::VideoFrame::YV12A,
739                                         true,
740                                         gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f));
741
742  pass->quad_list.push_back(yuv_quad.PassAs<DrawQuad>());
743
744  scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create();
745  color_quad->SetNew(shared_state, rect, rect, SK_ColorBLACK, false);
746
747  pass->quad_list.push_back(color_quad.PassAs<DrawQuad>());
748
749  RenderPassList pass_list;
750  pass_list.push_back(pass.Pass());
751
752  EXPECT_TRUE(this->RunPixelTest(
753      &pass_list,
754      base::FilePath(FILE_PATH_LITERAL("black.png")),
755      ExactPixelComparator(true)));
756}
757
758TYPED_TEST(RendererPixelTest, FastPassColorFilterAlpha) {
759  gfx::Rect viewport_rect(this->device_viewport_size_);
760
761  RenderPass::Id root_pass_id(1, 1);
762  scoped_ptr<RenderPass> root_pass =
763      CreateTestRootRenderPass(root_pass_id, viewport_rect);
764
765  RenderPass::Id child_pass_id(2, 2);
766  gfx::Rect pass_rect(this->device_viewport_size_);
767  gfx::Transform transform_to_root;
768  scoped_ptr<RenderPass> child_pass =
769      CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
770
771  gfx::Transform content_to_target_transform;
772  SharedQuadState* shared_state = CreateTestSharedQuadState(
773      child_pass.get(), content_to_target_transform, viewport_rect);
774  shared_state->opacity = 0.5f;
775
776  gfx::Rect blue_rect(0,
777                      0,
778                      this->device_viewport_size_.width(),
779                      this->device_viewport_size_.height() / 2);
780  scoped_ptr<SolidColorDrawQuad> blue = SolidColorDrawQuad::Create();
781  blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
782  gfx::Rect yellow_rect(0,
783                        this->device_viewport_size_.height() / 2,
784                        this->device_viewport_size_.width(),
785                        this->device_viewport_size_.height() / 2);
786  scoped_ptr<SolidColorDrawQuad> yellow = SolidColorDrawQuad::Create();
787  yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false);
788
789  SharedQuadState* blank_state = CreateTestSharedQuadState(
790      child_pass.get(), content_to_target_transform, viewport_rect);
791
792  scoped_ptr<SolidColorDrawQuad> white = SolidColorDrawQuad::Create();
793  white->SetNew(
794      blank_state, viewport_rect, viewport_rect, SK_ColorWHITE, false);
795
796  child_pass->quad_list.push_back(blue.PassAs<DrawQuad>());
797  child_pass->quad_list.push_back(yellow.PassAs<DrawQuad>());
798  child_pass->quad_list.push_back(white.PassAs<DrawQuad>());
799
800  SharedQuadState* pass_shared_state =
801      CreateTestSharedQuadState(root_pass.get(), gfx::Transform(), pass_rect);
802
803  SkScalar matrix[20];
804  float amount = 0.5f;
805  matrix[0] = 0.213f + 0.787f * amount;
806  matrix[1] = 0.715f - 0.715f * amount;
807  matrix[2] = 1.f - (matrix[0] + matrix[1]);
808  matrix[3] = matrix[4] = 0;
809  matrix[5] = 0.213f - 0.213f * amount;
810  matrix[6] = 0.715f + 0.285f * amount;
811  matrix[7] = 1.f - (matrix[5] + matrix[6]);
812  matrix[8] = matrix[9] = 0;
813  matrix[10] = 0.213f - 0.213f * amount;
814  matrix[11] = 0.715f - 0.715f * amount;
815  matrix[12] = 1.f - (matrix[10] + matrix[11]);
816  matrix[13] = matrix[14] = 0;
817  matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0;
818  matrix[18] = 1;
819  skia::RefPtr<SkColorFilter> colorFilter(
820      skia::AdoptRef(SkColorMatrixFilter::Create(matrix)));
821  skia::RefPtr<SkImageFilter> filter =
822      skia::AdoptRef(SkColorFilterImageFilter::Create(colorFilter.get(), NULL));
823  FilterOperations filters;
824  filters.Append(FilterOperation::CreateReferenceFilter(filter));
825
826  scoped_ptr<RenderPassDrawQuad> render_pass_quad =
827      RenderPassDrawQuad::Create();
828  render_pass_quad->SetNew(pass_shared_state,
829                           pass_rect,
830                           pass_rect,
831                           child_pass_id,
832                           false,
833                           0,
834                           pass_rect,
835                           gfx::RectF(),
836                           filters,
837                           FilterOperations());
838
839  root_pass->quad_list.push_back(render_pass_quad.PassAs<DrawQuad>());
840
841  RenderPassList pass_list;
842  pass_list.push_back(child_pass.Pass());
843  pass_list.push_back(root_pass.Pass());
844
845  // This test has alpha=254 for the software renderer vs. alpha=255 for the gl
846  // renderer so use a fuzzy comparator.
847  EXPECT_TRUE(this->RunPixelTest(
848      &pass_list,
849      base::FilePath(FILE_PATH_LITERAL("blue_yellow_alpha.png")),
850      FuzzyForSoftwareOnlyPixelComparator<TypeParam>(false)));
851}
852
853TYPED_TEST(RendererPixelTest, FastPassSaturateFilter) {
854  gfx::Rect viewport_rect(this->device_viewport_size_);
855
856  RenderPass::Id root_pass_id(1, 1);
857  scoped_ptr<RenderPass> root_pass =
858      CreateTestRootRenderPass(root_pass_id, viewport_rect);
859
860  RenderPass::Id child_pass_id(2, 2);
861  gfx::Rect pass_rect(this->device_viewport_size_);
862  gfx::Transform transform_to_root;
863  scoped_ptr<RenderPass> child_pass =
864      CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
865
866  gfx::Transform content_to_target_transform;
867  SharedQuadState* shared_state = CreateTestSharedQuadState(
868      child_pass.get(), content_to_target_transform, viewport_rect);
869  shared_state->opacity = 0.5f;
870
871  gfx::Rect blue_rect(0,
872                      0,
873                      this->device_viewport_size_.width(),
874                      this->device_viewport_size_.height() / 2);
875  scoped_ptr<SolidColorDrawQuad> blue = SolidColorDrawQuad::Create();
876  blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
877  gfx::Rect yellow_rect(0,
878                        this->device_viewport_size_.height() / 2,
879                        this->device_viewport_size_.width(),
880                        this->device_viewport_size_.height() / 2);
881  scoped_ptr<SolidColorDrawQuad> yellow = SolidColorDrawQuad::Create();
882  yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false);
883
884  SharedQuadState* blank_state = CreateTestSharedQuadState(
885      child_pass.get(), content_to_target_transform, viewport_rect);
886
887  scoped_ptr<SolidColorDrawQuad> white = SolidColorDrawQuad::Create();
888  white->SetNew(
889      blank_state, viewport_rect, viewport_rect, SK_ColorWHITE, false);
890
891  child_pass->quad_list.push_back(blue.PassAs<DrawQuad>());
892  child_pass->quad_list.push_back(yellow.PassAs<DrawQuad>());
893  child_pass->quad_list.push_back(white.PassAs<DrawQuad>());
894
895  SharedQuadState* pass_shared_state =
896      CreateTestSharedQuadState(root_pass.get(), gfx::Transform(), pass_rect);
897
898  FilterOperations filters;
899  filters.Append(FilterOperation::CreateSaturateFilter(0.5f));
900
901  scoped_ptr<RenderPassDrawQuad> render_pass_quad =
902      RenderPassDrawQuad::Create();
903  render_pass_quad->SetNew(pass_shared_state,
904                           pass_rect,
905                           pass_rect,
906                           child_pass_id,
907                           false,
908                           0,
909                           pass_rect,
910                           gfx::RectF(),
911                           filters,
912                           FilterOperations());
913
914  root_pass->quad_list.push_back(render_pass_quad.PassAs<DrawQuad>());
915
916  RenderPassList pass_list;
917  pass_list.push_back(child_pass.Pass());
918  pass_list.push_back(root_pass.Pass());
919
920  EXPECT_TRUE(this->RunPixelTest(
921      &pass_list,
922      base::FilePath(FILE_PATH_LITERAL("blue_yellow_alpha.png")),
923      ExactPixelComparator(true)));
924}
925
926TYPED_TEST(RendererPixelTest, FastPassFilterChain) {
927  gfx::Rect viewport_rect(this->device_viewport_size_);
928
929  RenderPass::Id root_pass_id(1, 1);
930  scoped_ptr<RenderPass> root_pass =
931      CreateTestRootRenderPass(root_pass_id, viewport_rect);
932
933  RenderPass::Id child_pass_id(2, 2);
934  gfx::Rect pass_rect(this->device_viewport_size_);
935  gfx::Transform transform_to_root;
936  scoped_ptr<RenderPass> child_pass =
937      CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
938
939  gfx::Transform content_to_target_transform;
940  SharedQuadState* shared_state = CreateTestSharedQuadState(
941      child_pass.get(), content_to_target_transform, viewport_rect);
942  shared_state->opacity = 0.5f;
943
944  gfx::Rect blue_rect(0,
945                      0,
946                      this->device_viewport_size_.width(),
947                      this->device_viewport_size_.height() / 2);
948  scoped_ptr<SolidColorDrawQuad> blue = SolidColorDrawQuad::Create();
949  blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
950  gfx::Rect yellow_rect(0,
951                        this->device_viewport_size_.height() / 2,
952                        this->device_viewport_size_.width(),
953                        this->device_viewport_size_.height() / 2);
954  scoped_ptr<SolidColorDrawQuad> yellow = SolidColorDrawQuad::Create();
955  yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false);
956
957  SharedQuadState* blank_state = CreateTestSharedQuadState(
958      child_pass.get(), content_to_target_transform, viewport_rect);
959
960  scoped_ptr<SolidColorDrawQuad> white = SolidColorDrawQuad::Create();
961  white->SetNew(
962      blank_state, viewport_rect, viewport_rect, SK_ColorWHITE, false);
963
964  child_pass->quad_list.push_back(blue.PassAs<DrawQuad>());
965  child_pass->quad_list.push_back(yellow.PassAs<DrawQuad>());
966  child_pass->quad_list.push_back(white.PassAs<DrawQuad>());
967
968  SharedQuadState* pass_shared_state =
969      CreateTestSharedQuadState(root_pass.get(), gfx::Transform(), pass_rect);
970
971  FilterOperations filters;
972  filters.Append(FilterOperation::CreateGrayscaleFilter(1.f));
973  filters.Append(FilterOperation::CreateBrightnessFilter(0.5f));
974
975  scoped_ptr<RenderPassDrawQuad> render_pass_quad =
976      RenderPassDrawQuad::Create();
977  render_pass_quad->SetNew(pass_shared_state,
978                           pass_rect,
979                           pass_rect,
980                           child_pass_id,
981                           false,
982                           0,
983                           pass_rect,
984                           gfx::RectF(),
985                           filters,
986                           FilterOperations());
987
988  root_pass->quad_list.push_back(render_pass_quad.PassAs<DrawQuad>());
989
990  RenderPassList pass_list;
991  pass_list.push_back(child_pass.Pass());
992  pass_list.push_back(root_pass.Pass());
993
994  EXPECT_TRUE(this->RunPixelTest(
995      &pass_list,
996      base::FilePath(FILE_PATH_LITERAL("blue_yellow_filter_chain.png")),
997      ExactPixelComparator(true)));
998}
999
1000TYPED_TEST(RendererPixelTest, FastPassColorFilterAlphaTranslation) {
1001  gfx::Rect viewport_rect(this->device_viewport_size_);
1002
1003  RenderPass::Id root_pass_id(1, 1);
1004  scoped_ptr<RenderPass> root_pass =
1005      CreateTestRootRenderPass(root_pass_id, viewport_rect);
1006
1007  RenderPass::Id child_pass_id(2, 2);
1008  gfx::Rect pass_rect(this->device_viewport_size_);
1009  gfx::Transform transform_to_root;
1010  scoped_ptr<RenderPass> child_pass =
1011      CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
1012
1013  gfx::Transform content_to_target_transform;
1014  SharedQuadState* shared_state = CreateTestSharedQuadState(
1015      child_pass.get(), content_to_target_transform, viewport_rect);
1016  shared_state->opacity = 0.5f;
1017
1018  gfx::Rect blue_rect(0,
1019                      0,
1020                      this->device_viewport_size_.width(),
1021                      this->device_viewport_size_.height() / 2);
1022  scoped_ptr<SolidColorDrawQuad> blue = SolidColorDrawQuad::Create();
1023  blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
1024  gfx::Rect yellow_rect(0,
1025                        this->device_viewport_size_.height() / 2,
1026                        this->device_viewport_size_.width(),
1027                        this->device_viewport_size_.height() / 2);
1028  scoped_ptr<SolidColorDrawQuad> yellow = SolidColorDrawQuad::Create();
1029  yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false);
1030
1031  SharedQuadState* blank_state = CreateTestSharedQuadState(
1032      child_pass.get(), content_to_target_transform, viewport_rect);
1033
1034  scoped_ptr<SolidColorDrawQuad> white = SolidColorDrawQuad::Create();
1035  white->SetNew(
1036      blank_state, viewport_rect, viewport_rect, SK_ColorWHITE, false);
1037
1038  child_pass->quad_list.push_back(blue.PassAs<DrawQuad>());
1039  child_pass->quad_list.push_back(yellow.PassAs<DrawQuad>());
1040  child_pass->quad_list.push_back(white.PassAs<DrawQuad>());
1041
1042  SharedQuadState* pass_shared_state =
1043      CreateTestSharedQuadState(root_pass.get(), gfx::Transform(), pass_rect);
1044
1045  SkScalar matrix[20];
1046  float amount = 0.5f;
1047  matrix[0] = 0.213f + 0.787f * amount;
1048  matrix[1] = 0.715f - 0.715f * amount;
1049  matrix[2] = 1.f - (matrix[0] + matrix[1]);
1050  matrix[3] = 0;
1051  matrix[4] = 20.f;
1052  matrix[5] = 0.213f - 0.213f * amount;
1053  matrix[6] = 0.715f + 0.285f * amount;
1054  matrix[7] = 1.f - (matrix[5] + matrix[6]);
1055  matrix[8] = 0;
1056  matrix[9] = 200.f;
1057  matrix[10] = 0.213f - 0.213f * amount;
1058  matrix[11] = 0.715f - 0.715f * amount;
1059  matrix[12] = 1.f - (matrix[10] + matrix[11]);
1060  matrix[13] = 0;
1061  matrix[14] = 1.5f;
1062  matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0;
1063  matrix[18] = 1;
1064  skia::RefPtr<SkColorFilter> colorFilter(
1065      skia::AdoptRef(SkColorMatrixFilter::Create(matrix)));
1066  skia::RefPtr<SkImageFilter> filter =
1067      skia::AdoptRef(SkColorFilterImageFilter::Create(colorFilter.get(), NULL));
1068  FilterOperations filters;
1069  filters.Append(FilterOperation::CreateReferenceFilter(filter));
1070
1071  scoped_ptr<RenderPassDrawQuad> render_pass_quad =
1072      RenderPassDrawQuad::Create();
1073  render_pass_quad->SetNew(pass_shared_state,
1074                           pass_rect,
1075                           pass_rect,
1076                           child_pass_id,
1077                           false,
1078                           0,
1079                           pass_rect,
1080                           gfx::RectF(),
1081                           filters,
1082                           FilterOperations());
1083
1084  root_pass->quad_list.push_back(render_pass_quad.PassAs<DrawQuad>());
1085  RenderPassList pass_list;
1086
1087  pass_list.push_back(child_pass.Pass());
1088  pass_list.push_back(root_pass.Pass());
1089
1090  // This test has alpha=254 for the software renderer vs. alpha=255 for the gl
1091  // renderer so use a fuzzy comparator.
1092  EXPECT_TRUE(this->RunPixelTest(
1093      &pass_list,
1094      base::FilePath(FILE_PATH_LITERAL("blue_yellow_alpha_translate.png")),
1095      FuzzyForSoftwareOnlyPixelComparator<TypeParam>(false)));
1096}
1097
1098TYPED_TEST(RendererPixelTest, EnlargedRenderPassTexture) {
1099  gfx::Rect viewport_rect(this->device_viewport_size_);
1100
1101  RenderPass::Id root_pass_id(1, 1);
1102  scoped_ptr<RenderPass> root_pass =
1103      CreateTestRootRenderPass(root_pass_id, viewport_rect);
1104
1105  RenderPass::Id child_pass_id(2, 2);
1106  gfx::Rect pass_rect(this->device_viewport_size_);
1107  gfx::Transform transform_to_root;
1108  scoped_ptr<RenderPass> child_pass =
1109      CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
1110
1111  gfx::Transform content_to_target_transform;
1112  SharedQuadState* shared_state = CreateTestSharedQuadState(
1113      child_pass.get(), content_to_target_transform, viewport_rect);
1114
1115  gfx::Rect blue_rect(0,
1116                      0,
1117                      this->device_viewport_size_.width(),
1118                      this->device_viewport_size_.height() / 2);
1119  scoped_ptr<SolidColorDrawQuad> blue = SolidColorDrawQuad::Create();
1120  blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
1121  gfx::Rect yellow_rect(0,
1122                        this->device_viewport_size_.height() / 2,
1123                        this->device_viewport_size_.width(),
1124                        this->device_viewport_size_.height() / 2);
1125  scoped_ptr<SolidColorDrawQuad> yellow = SolidColorDrawQuad::Create();
1126  yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false);
1127
1128  child_pass->quad_list.push_back(blue.PassAs<DrawQuad>());
1129  child_pass->quad_list.push_back(yellow.PassAs<DrawQuad>());
1130
1131  SharedQuadState* pass_shared_state =
1132      CreateTestSharedQuadState(root_pass.get(), gfx::Transform(), pass_rect);
1133  root_pass->quad_list.push_back(CreateTestRenderPassDrawQuad(
1134      pass_shared_state, pass_rect, child_pass_id));
1135
1136  RenderPassList pass_list;
1137  pass_list.push_back(child_pass.Pass());
1138  pass_list.push_back(root_pass.Pass());
1139
1140  this->renderer_->SetEnlargePassTextureAmountForTesting(gfx::Vector2d(50, 75));
1141
1142  EXPECT_TRUE(this->RunPixelTest(
1143      &pass_list,
1144      base::FilePath(FILE_PATH_LITERAL("blue_yellow.png")),
1145      ExactPixelComparator(true)));
1146}
1147
1148TYPED_TEST(RendererPixelTest, EnlargedRenderPassTextureWithAntiAliasing) {
1149  gfx::Rect viewport_rect(this->device_viewport_size_);
1150
1151  RenderPass::Id root_pass_id(1, 1);
1152  scoped_ptr<RenderPass> root_pass =
1153      CreateTestRootRenderPass(root_pass_id, viewport_rect);
1154
1155  RenderPass::Id child_pass_id(2, 2);
1156  gfx::Rect pass_rect(this->device_viewport_size_);
1157  gfx::Transform transform_to_root;
1158  scoped_ptr<RenderPass> child_pass =
1159      CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
1160
1161  gfx::Transform content_to_target_transform;
1162  SharedQuadState* shared_state = CreateTestSharedQuadState(
1163      child_pass.get(), content_to_target_transform, viewport_rect);
1164
1165  gfx::Rect blue_rect(0,
1166                      0,
1167                      this->device_viewport_size_.width(),
1168                      this->device_viewport_size_.height() / 2);
1169  scoped_ptr<SolidColorDrawQuad> blue = SolidColorDrawQuad::Create();
1170  blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
1171  gfx::Rect yellow_rect(0,
1172                        this->device_viewport_size_.height() / 2,
1173                        this->device_viewport_size_.width(),
1174                        this->device_viewport_size_.height() / 2);
1175  scoped_ptr<SolidColorDrawQuad> yellow = SolidColorDrawQuad::Create();
1176  yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false);
1177
1178  child_pass->quad_list.push_back(blue.PassAs<DrawQuad>());
1179  child_pass->quad_list.push_back(yellow.PassAs<DrawQuad>());
1180
1181  gfx::Transform aa_transform;
1182  aa_transform.Translate(0.5, 0.0);
1183
1184  SharedQuadState* pass_shared_state =
1185      CreateTestSharedQuadState(root_pass.get(), aa_transform, pass_rect);
1186  root_pass->quad_list.push_back(CreateTestRenderPassDrawQuad(
1187      pass_shared_state, pass_rect, child_pass_id));
1188
1189  SharedQuadState* root_shared_state = CreateTestSharedQuadState(
1190      root_pass.get(), gfx::Transform(), viewport_rect);
1191  scoped_ptr<SolidColorDrawQuad> background = SolidColorDrawQuad::Create();
1192  background->SetNew(root_shared_state,
1193                     gfx::Rect(this->device_viewport_size_),
1194                     gfx::Rect(this->device_viewport_size_),
1195                     SK_ColorWHITE,
1196                     false);
1197  root_pass->quad_list.push_back(background.PassAs<DrawQuad>());
1198
1199  RenderPassList pass_list;
1200  pass_list.push_back(child_pass.Pass());
1201  pass_list.push_back(root_pass.Pass());
1202
1203  this->renderer_->SetEnlargePassTextureAmountForTesting(gfx::Vector2d(50, 75));
1204
1205  EXPECT_TRUE(this->RunPixelTest(
1206      &pass_list,
1207      base::FilePath(FILE_PATH_LITERAL("blue_yellow_anti_aliasing.png")),
1208      FuzzyPixelOffByOneComparator(true)));
1209}
1210
1211// This tests the case where we have a RenderPass with a mask, but the quad
1212// for the masked surface does not include the full surface texture.
1213TYPED_TEST(RendererPixelTest, RenderPassAndMaskWithPartialQuad) {
1214  gfx::Rect viewport_rect(this->device_viewport_size_);
1215
1216  RenderPass::Id root_pass_id(1, 1);
1217  scoped_ptr<RenderPass> root_pass =
1218      CreateTestRootRenderPass(root_pass_id, viewport_rect);
1219  SharedQuadState* root_pass_shared_state = CreateTestSharedQuadState(
1220      root_pass.get(), gfx::Transform(), viewport_rect);
1221
1222  RenderPass::Id child_pass_id(2, 2);
1223  gfx::Transform transform_to_root;
1224  scoped_ptr<RenderPass> child_pass =
1225      CreateTestRenderPass(child_pass_id, viewport_rect, transform_to_root);
1226  SharedQuadState* child_pass_shared_state = CreateTestSharedQuadState(
1227      child_pass.get(), gfx::Transform(), viewport_rect);
1228
1229  // The child render pass is just a green box.
1230  static const SkColor kCSSGreen = 0xff008000;
1231  scoped_ptr<SolidColorDrawQuad> green = SolidColorDrawQuad::Create();
1232  green->SetNew(
1233      child_pass_shared_state, viewport_rect, viewport_rect, kCSSGreen, false);
1234  child_pass->quad_list.push_back(green.PassAs<DrawQuad>());
1235
1236  // Make a mask.
1237  gfx::Rect mask_rect = viewport_rect;
1238  SkBitmap bitmap;
1239  bitmap.allocPixels(
1240      SkImageInfo::MakeN32Premul(mask_rect.width(), mask_rect.height()));
1241  SkCanvas canvas(bitmap);
1242  SkPaint paint;
1243  paint.setStyle(SkPaint::kStroke_Style);
1244  paint.setStrokeWidth(SkIntToScalar(4));
1245  paint.setColor(SK_ColorWHITE);
1246  canvas.clear(SK_ColorTRANSPARENT);
1247  gfx::Rect rect = mask_rect;
1248  while (!rect.IsEmpty()) {
1249    rect.Inset(6, 6, 4, 4);
1250    canvas.drawRect(
1251        SkRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height()),
1252        paint);
1253    rect.Inset(6, 6, 4, 4);
1254  }
1255
1256  ResourceProvider::ResourceId mask_resource_id =
1257      this->resource_provider_->CreateResource(
1258          mask_rect.size(),
1259          GL_CLAMP_TO_EDGE,
1260          ResourceProvider::TextureUsageAny,
1261          RGBA_8888);
1262  {
1263    SkAutoLockPixels lock(bitmap);
1264    this->resource_provider_->SetPixels(
1265        mask_resource_id,
1266        reinterpret_cast<uint8_t*>(bitmap.getPixels()),
1267        mask_rect,
1268        mask_rect,
1269        gfx::Vector2d());
1270  }
1271
1272  // This RenderPassDrawQuad does not include the full |viewport_rect| which is
1273  // the size of the child render pass.
1274  gfx::Rect sub_rect = gfx::Rect(50, 50, 100, 100);
1275  EXPECT_NE(sub_rect.x(), child_pass->output_rect.x());
1276  EXPECT_NE(sub_rect.y(), child_pass->output_rect.y());
1277  EXPECT_NE(sub_rect.right(), child_pass->output_rect.right());
1278  EXPECT_NE(sub_rect.bottom(), child_pass->output_rect.bottom());
1279  EXPECT_TRUE(child_pass->output_rect.Contains(sub_rect));
1280
1281  // Set up a mask on the RenderPassDrawQuad.
1282  scoped_ptr<RenderPassDrawQuad> mask_quad = RenderPassDrawQuad::Create();
1283  mask_quad->SetNew(root_pass_shared_state,
1284                    sub_rect,
1285                    sub_rect,
1286                    child_pass_id,
1287                    false,  // is_replica
1288                    mask_resource_id,
1289                    sub_rect,              // contents_changed_since_last_frame
1290                    gfx::RectF(1.f, 1.f),  // mask_uv_rect
1291                    FilterOperations(),    // foreground filters
1292                    FilterOperations());   // background filters
1293  root_pass->quad_list.push_back(mask_quad.PassAs<DrawQuad>());
1294
1295  // White background behind the masked render pass.
1296  scoped_ptr<SolidColorDrawQuad> white = SolidColorDrawQuad::Create();
1297  white->SetNew(root_pass_shared_state,
1298                viewport_rect,
1299                viewport_rect,
1300                SK_ColorWHITE,
1301                false);
1302  root_pass->quad_list.push_back(white.PassAs<DrawQuad>());
1303
1304  RenderPassList pass_list;
1305  pass_list.push_back(child_pass.Pass());
1306  pass_list.push_back(root_pass.Pass());
1307
1308  EXPECT_TRUE(this->RunPixelTest(
1309      &pass_list,
1310      base::FilePath(FILE_PATH_LITERAL("image_mask_of_layer.png")),
1311      ExactPixelComparator(true)));
1312}
1313
1314template <typename RendererType>
1315class RendererPixelTestWithBackgroundFilter
1316    : public RendererPixelTest<RendererType> {
1317 protected:
1318  void SetUpRenderPassList() {
1319    gfx::Rect device_viewport_rect(this->device_viewport_size_);
1320
1321    RenderPass::Id root_id(1, 1);
1322    scoped_ptr<RenderPass> root_pass =
1323        CreateTestRootRenderPass(root_id, device_viewport_rect);
1324    root_pass->has_transparent_background = false;
1325
1326    gfx::Transform identity_content_to_target_transform;
1327
1328    RenderPass::Id filter_pass_id(2, 1);
1329    gfx::Transform transform_to_root;
1330    scoped_ptr<RenderPass> filter_pass =
1331        CreateTestRenderPass(filter_pass_id,
1332                             filter_pass_content_rect_,
1333                             transform_to_root);
1334
1335    // A non-visible quad in the filtering render pass.
1336    {
1337      SharedQuadState* shared_state =
1338          CreateTestSharedQuadState(filter_pass.get(),
1339                                    identity_content_to_target_transform,
1340                                    filter_pass_content_rect_);
1341      scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create();
1342      color_quad->SetNew(shared_state,
1343                         filter_pass_content_rect_,
1344                         filter_pass_content_rect_,
1345                         SK_ColorTRANSPARENT,
1346                         false);
1347      filter_pass->quad_list.push_back(color_quad.PassAs<DrawQuad>());
1348    }
1349
1350    {
1351      SharedQuadState* shared_state =
1352          CreateTestSharedQuadState(filter_pass.get(),
1353                                    filter_pass_to_target_transform_,
1354                                    filter_pass_content_rect_);
1355      scoped_ptr<RenderPassDrawQuad> filter_pass_quad =
1356          RenderPassDrawQuad::Create();
1357      filter_pass_quad->SetNew(
1358          shared_state,
1359          filter_pass_content_rect_,
1360          filter_pass_content_rect_,
1361          filter_pass_id,
1362          false,                      // is_replica
1363          0,                          // mask_resource_id
1364          filter_pass_content_rect_,  // contents_changed_since_last_frame
1365          gfx::RectF(),               // mask_uv_rect
1366          FilterOperations(),         // filters
1367          this->background_filters_);
1368      root_pass->quad_list.push_back(filter_pass_quad.PassAs<DrawQuad>());
1369    }
1370
1371    const int kColumnWidth = device_viewport_rect.width() / 3;
1372
1373    gfx::Rect left_rect = gfx::Rect(0, 0, kColumnWidth, 20);
1374    for (int i = 0; left_rect.y() < device_viewport_rect.height(); ++i) {
1375      SharedQuadState* shared_state = CreateTestSharedQuadState(
1376          root_pass.get(), identity_content_to_target_transform, left_rect);
1377      scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create();
1378      color_quad->SetNew(
1379          shared_state, left_rect, left_rect, SK_ColorGREEN, false);
1380      root_pass->quad_list.push_back(color_quad.PassAs<DrawQuad>());
1381      left_rect += gfx::Vector2d(0, left_rect.height() + 1);
1382    }
1383
1384    gfx::Rect middle_rect = gfx::Rect(kColumnWidth+1, 0, kColumnWidth, 20);
1385    for (int i = 0; middle_rect.y() < device_viewport_rect.height(); ++i) {
1386      SharedQuadState* shared_state = CreateTestSharedQuadState(
1387          root_pass.get(), identity_content_to_target_transform, middle_rect);
1388      scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create();
1389      color_quad->SetNew(
1390          shared_state, middle_rect, middle_rect, SK_ColorRED, false);
1391      root_pass->quad_list.push_back(color_quad.PassAs<DrawQuad>());
1392      middle_rect += gfx::Vector2d(0, middle_rect.height() + 1);
1393    }
1394
1395    gfx::Rect right_rect = gfx::Rect((kColumnWidth+1)*2, 0, kColumnWidth, 20);
1396    for (int i = 0; right_rect.y() < device_viewport_rect.height(); ++i) {
1397      SharedQuadState* shared_state = CreateTestSharedQuadState(
1398          root_pass.get(), identity_content_to_target_transform, right_rect);
1399      scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create();
1400      color_quad->SetNew(
1401          shared_state, right_rect, right_rect, SK_ColorBLUE, false);
1402      root_pass->quad_list.push_back(color_quad.PassAs<DrawQuad>());
1403      right_rect += gfx::Vector2d(0, right_rect.height() + 1);
1404    }
1405
1406    SharedQuadState* shared_state =
1407        CreateTestSharedQuadState(root_pass.get(),
1408                                  identity_content_to_target_transform,
1409                                  device_viewport_rect);
1410    scoped_ptr<SolidColorDrawQuad> background_quad =
1411        SolidColorDrawQuad::Create();
1412    background_quad->SetNew(shared_state,
1413                            device_viewport_rect,
1414                            device_viewport_rect,
1415                            SK_ColorWHITE,
1416                            false);
1417    root_pass->quad_list.push_back(background_quad.PassAs<DrawQuad>());
1418
1419    pass_list_.push_back(filter_pass.Pass());
1420    pass_list_.push_back(root_pass.Pass());
1421  }
1422
1423  RenderPassList pass_list_;
1424  FilterOperations background_filters_;
1425  gfx::Transform filter_pass_to_target_transform_;
1426  gfx::Rect filter_pass_content_rect_;
1427};
1428
1429typedef ::testing::Types<GLRenderer, SoftwareRenderer>
1430    BackgroundFilterRendererTypes;
1431TYPED_TEST_CASE(RendererPixelTestWithBackgroundFilter,
1432                BackgroundFilterRendererTypes);
1433
1434typedef RendererPixelTestWithBackgroundFilter<GLRenderer>
1435GLRendererPixelTestWithBackgroundFilter;
1436
1437// TODO(skaslev): The software renderer does not support filters yet.
1438TEST_F(GLRendererPixelTestWithBackgroundFilter, InvertFilter) {
1439  this->background_filters_.Append(
1440      FilterOperation::CreateInvertFilter(1.f));
1441
1442  this->filter_pass_content_rect_ = gfx::Rect(this->device_viewport_size_);
1443  this->filter_pass_content_rect_.Inset(12, 14, 16, 18);
1444
1445  this->SetUpRenderPassList();
1446  EXPECT_TRUE(this->RunPixelTest(
1447      &this->pass_list_,
1448      base::FilePath(FILE_PATH_LITERAL("background_filter.png")),
1449      ExactPixelComparator(true)));
1450}
1451
1452class ExternalStencilPixelTest : public GLRendererPixelTest {
1453 protected:
1454  void ClearBackgroundToGreen() {
1455    GLES2Interface* gl = output_surface_->context_provider()->ContextGL();
1456    output_surface_->EnsureBackbuffer();
1457    output_surface_->Reshape(device_viewport_size_, 1);
1458    gl->ClearColor(0.f, 1.f, 0.f, 1.f);
1459    gl->Clear(GL_COLOR_BUFFER_BIT);
1460  }
1461
1462  void PopulateStencilBuffer() {
1463    // Set two quadrants of the stencil buffer to 1.
1464    GLES2Interface* gl = output_surface_->context_provider()->ContextGL();
1465    output_surface_->EnsureBackbuffer();
1466    output_surface_->Reshape(device_viewport_size_, 1);
1467    gl->ClearStencil(0);
1468    gl->Clear(GL_STENCIL_BUFFER_BIT);
1469    gl->Enable(GL_SCISSOR_TEST);
1470    gl->ClearStencil(1);
1471    gl->Scissor(0,
1472                0,
1473                device_viewport_size_.width() / 2,
1474                device_viewport_size_.height() / 2);
1475    gl->Clear(GL_STENCIL_BUFFER_BIT);
1476    gl->Scissor(device_viewport_size_.width() / 2,
1477                device_viewport_size_.height() / 2,
1478                device_viewport_size_.width(),
1479                device_viewport_size_.height());
1480    gl->Clear(GL_STENCIL_BUFFER_BIT);
1481  }
1482};
1483
1484TEST_F(ExternalStencilPixelTest, StencilTestEnabled) {
1485  ClearBackgroundToGreen();
1486  PopulateStencilBuffer();
1487  this->EnableExternalStencilTest();
1488
1489  // Draw a blue quad that covers the entire device viewport. It should be
1490  // clipped to the bottom left and top right corners by the external stencil.
1491  gfx::Rect rect(this->device_viewport_size_);
1492  RenderPass::Id id(1, 1);
1493  scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
1494  SharedQuadState* blue_shared_state =
1495      CreateTestSharedQuadState(pass.get(), gfx::Transform(), rect);
1496  scoped_ptr<SolidColorDrawQuad> blue = SolidColorDrawQuad::Create();
1497  blue->SetNew(blue_shared_state, rect, rect, SK_ColorBLUE, false);
1498  pass->quad_list.push_back(blue.PassAs<DrawQuad>());
1499  pass->has_transparent_background = false;
1500  RenderPassList pass_list;
1501  pass_list.push_back(pass.Pass());
1502
1503  EXPECT_TRUE(this->RunPixelTest(
1504      &pass_list,
1505      base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")),
1506      ExactPixelComparator(true)));
1507}
1508
1509TEST_F(ExternalStencilPixelTest, StencilTestDisabled) {
1510  PopulateStencilBuffer();
1511
1512  // Draw a green quad that covers the entire device viewport. The stencil
1513  // buffer should be ignored.
1514  gfx::Rect rect(this->device_viewport_size_);
1515  RenderPass::Id id(1, 1);
1516  scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
1517  SharedQuadState* green_shared_state =
1518      CreateTestSharedQuadState(pass.get(), gfx::Transform(), rect);
1519  scoped_ptr<SolidColorDrawQuad> green = SolidColorDrawQuad::Create();
1520  green->SetNew(green_shared_state, rect, rect, SK_ColorGREEN, false);
1521  pass->quad_list.push_back(green.PassAs<DrawQuad>());
1522  RenderPassList pass_list;
1523  pass_list.push_back(pass.Pass());
1524
1525  EXPECT_TRUE(this->RunPixelTest(
1526      &pass_list,
1527      base::FilePath(FILE_PATH_LITERAL("green.png")),
1528      ExactPixelComparator(true)));
1529}
1530
1531TEST_F(ExternalStencilPixelTest, RenderSurfacesIgnoreStencil) {
1532  // The stencil test should apply only to the final render pass.
1533  ClearBackgroundToGreen();
1534  PopulateStencilBuffer();
1535  this->EnableExternalStencilTest();
1536
1537  gfx::Rect viewport_rect(this->device_viewport_size_);
1538
1539  RenderPass::Id root_pass_id(1, 1);
1540  scoped_ptr<RenderPass> root_pass =
1541      CreateTestRootRenderPass(root_pass_id, viewport_rect);
1542  root_pass->has_transparent_background = false;
1543
1544  RenderPass::Id child_pass_id(2, 2);
1545  gfx::Rect pass_rect(this->device_viewport_size_);
1546  gfx::Transform transform_to_root;
1547  scoped_ptr<RenderPass> child_pass =
1548      CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
1549
1550  gfx::Transform content_to_target_transform;
1551  SharedQuadState* shared_state = CreateTestSharedQuadState(
1552      child_pass.get(), content_to_target_transform, viewport_rect);
1553
1554  gfx::Rect blue_rect(0,
1555                      0,
1556                      this->device_viewport_size_.width(),
1557                      this->device_viewport_size_.height());
1558  scoped_ptr<SolidColorDrawQuad> blue = SolidColorDrawQuad::Create();
1559  blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
1560  child_pass->quad_list.push_back(blue.PassAs<DrawQuad>());
1561
1562  SharedQuadState* pass_shared_state =
1563      CreateTestSharedQuadState(root_pass.get(), gfx::Transform(), pass_rect);
1564  root_pass->quad_list.push_back(CreateTestRenderPassDrawQuad(
1565      pass_shared_state, pass_rect, child_pass_id));
1566  RenderPassList pass_list;
1567  pass_list.push_back(child_pass.Pass());
1568  pass_list.push_back(root_pass.Pass());
1569
1570  EXPECT_TRUE(this->RunPixelTest(
1571      &pass_list,
1572      base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")),
1573      ExactPixelComparator(true)));
1574}
1575
1576TEST_F(ExternalStencilPixelTest, DeviceClip) {
1577  ClearBackgroundToGreen();
1578  gfx::Rect clip_rect(gfx::Point(150, 150), gfx::Size(50, 50));
1579  this->ForceDeviceClip(clip_rect);
1580
1581  // Draw a blue quad that covers the entire device viewport. It should be
1582  // clipped to the bottom right corner by the device clip.
1583  gfx::Rect rect(this->device_viewport_size_);
1584  RenderPass::Id id(1, 1);
1585  scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
1586  SharedQuadState* blue_shared_state =
1587      CreateTestSharedQuadState(pass.get(), gfx::Transform(), rect);
1588  scoped_ptr<SolidColorDrawQuad> blue = SolidColorDrawQuad::Create();
1589  blue->SetNew(blue_shared_state, rect, rect, SK_ColorBLUE, false);
1590  pass->quad_list.push_back(blue.PassAs<DrawQuad>());
1591  RenderPassList pass_list;
1592  pass_list.push_back(pass.Pass());
1593
1594  EXPECT_TRUE(this->RunPixelTest(
1595      &pass_list,
1596      base::FilePath(FILE_PATH_LITERAL("green_with_blue_corner.png")),
1597      ExactPixelComparator(true)));
1598}
1599
1600// Software renderer does not support anti-aliased edges.
1601TEST_F(GLRendererPixelTest, AntiAliasing) {
1602  gfx::Rect rect(this->device_viewport_size_);
1603
1604  RenderPass::Id id(1, 1);
1605  scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
1606
1607  gfx::Transform red_content_to_target_transform;
1608  red_content_to_target_transform.Rotate(10);
1609  SharedQuadState* red_shared_state = CreateTestSharedQuadState(
1610      pass.get(), red_content_to_target_transform, rect);
1611
1612  scoped_ptr<SolidColorDrawQuad> red = SolidColorDrawQuad::Create();
1613  red->SetNew(red_shared_state, rect, rect, SK_ColorRED, false);
1614
1615  pass->quad_list.push_back(red.PassAs<DrawQuad>());
1616
1617  gfx::Transform yellow_content_to_target_transform;
1618  yellow_content_to_target_transform.Rotate(5);
1619  SharedQuadState* yellow_shared_state = CreateTestSharedQuadState(
1620      pass.get(), yellow_content_to_target_transform, rect);
1621
1622  scoped_ptr<SolidColorDrawQuad> yellow = SolidColorDrawQuad::Create();
1623  yellow->SetNew(yellow_shared_state, rect, rect, SK_ColorYELLOW, false);
1624
1625  pass->quad_list.push_back(yellow.PassAs<DrawQuad>());
1626
1627  gfx::Transform blue_content_to_target_transform;
1628  SharedQuadState* blue_shared_state = CreateTestSharedQuadState(
1629      pass.get(), blue_content_to_target_transform, rect);
1630
1631  scoped_ptr<SolidColorDrawQuad> blue = SolidColorDrawQuad::Create();
1632  blue->SetNew(blue_shared_state, rect, rect, SK_ColorBLUE, false);
1633
1634  pass->quad_list.push_back(blue.PassAs<DrawQuad>());
1635
1636  RenderPassList pass_list;
1637  pass_list.push_back(pass.Pass());
1638
1639  EXPECT_TRUE(this->RunPixelTest(
1640      &pass_list,
1641      base::FilePath(FILE_PATH_LITERAL("anti_aliasing.png")),
1642      FuzzyPixelOffByOneComparator(true)));
1643}
1644
1645// This test tests that anti-aliasing works for axis aligned quads.
1646// Anti-aliasing is only supported in the gl renderer.
1647TEST_F(GLRendererPixelTest, AxisAligned) {
1648  gfx::Rect rect(this->device_viewport_size_);
1649
1650  RenderPass::Id id(1, 1);
1651  gfx::Transform transform_to_root;
1652  scoped_ptr<RenderPass> pass =
1653      CreateTestRenderPass(id, rect, transform_to_root);
1654
1655  gfx::Transform red_content_to_target_transform;
1656  red_content_to_target_transform.Translate(50, 50);
1657  red_content_to_target_transform.Scale(
1658      0.5f + 1.0f / (rect.width() * 2.0f),
1659      0.5f + 1.0f / (rect.height() * 2.0f));
1660  SharedQuadState* red_shared_state = CreateTestSharedQuadState(
1661      pass.get(), red_content_to_target_transform, rect);
1662
1663  scoped_ptr<SolidColorDrawQuad> red = SolidColorDrawQuad::Create();
1664  red->SetNew(red_shared_state, rect, rect, SK_ColorRED, false);
1665
1666  pass->quad_list.push_back(red.PassAs<DrawQuad>());
1667
1668  gfx::Transform yellow_content_to_target_transform;
1669  yellow_content_to_target_transform.Translate(25.5f, 25.5f);
1670  yellow_content_to_target_transform.Scale(0.5f, 0.5f);
1671  SharedQuadState* yellow_shared_state = CreateTestSharedQuadState(
1672      pass.get(), yellow_content_to_target_transform, rect);
1673
1674  scoped_ptr<SolidColorDrawQuad> yellow = SolidColorDrawQuad::Create();
1675  yellow->SetNew(yellow_shared_state, rect, rect, SK_ColorYELLOW, false);
1676
1677  pass->quad_list.push_back(yellow.PassAs<DrawQuad>());
1678
1679  gfx::Transform blue_content_to_target_transform;
1680  SharedQuadState* blue_shared_state = CreateTestSharedQuadState(
1681      pass.get(), blue_content_to_target_transform, rect);
1682
1683  scoped_ptr<SolidColorDrawQuad> blue = SolidColorDrawQuad::Create();
1684  blue->SetNew(blue_shared_state, rect, rect, SK_ColorBLUE, false);
1685
1686  pass->quad_list.push_back(blue.PassAs<DrawQuad>());
1687
1688  RenderPassList pass_list;
1689  pass_list.push_back(pass.Pass());
1690
1691  EXPECT_TRUE(this->RunPixelTest(
1692      &pass_list,
1693      base::FilePath(FILE_PATH_LITERAL("axis_aligned.png")),
1694      ExactPixelComparator(true)));
1695}
1696
1697// This test tests that forcing anti-aliasing off works as expected.
1698// Anti-aliasing is only supported in the gl renderer.
1699TEST_F(GLRendererPixelTest, ForceAntiAliasingOff) {
1700  gfx::Rect rect(this->device_viewport_size_);
1701
1702  RenderPass::Id id(1, 1);
1703  gfx::Transform transform_to_root;
1704  scoped_ptr<RenderPass> pass =
1705      CreateTestRenderPass(id, rect, transform_to_root);
1706
1707  gfx::Transform hole_content_to_target_transform;
1708  hole_content_to_target_transform.Translate(50, 50);
1709  hole_content_to_target_transform.Scale(
1710      0.5f + 1.0f / (rect.width() * 2.0f),
1711      0.5f + 1.0f / (rect.height() * 2.0f));
1712  SharedQuadState* hole_shared_state = CreateTestSharedQuadState(
1713      pass.get(), hole_content_to_target_transform, rect);
1714
1715  scoped_ptr<SolidColorDrawQuad> hole = SolidColorDrawQuad::Create();
1716  hole->SetAll(
1717      hole_shared_state, rect, rect, rect, false, SK_ColorTRANSPARENT, true);
1718  pass->quad_list.push_back(hole.PassAs<DrawQuad>());
1719
1720  gfx::Transform green_content_to_target_transform;
1721  SharedQuadState* green_shared_state = CreateTestSharedQuadState(
1722      pass.get(), green_content_to_target_transform, rect);
1723
1724  scoped_ptr<SolidColorDrawQuad> green = SolidColorDrawQuad::Create();
1725  green->SetNew(green_shared_state, rect, rect, SK_ColorGREEN, false);
1726
1727  pass->quad_list.push_back(green.PassAs<DrawQuad>());
1728
1729  RenderPassList pass_list;
1730  pass_list.push_back(pass.Pass());
1731
1732  EXPECT_TRUE(this->RunPixelTest(
1733      &pass_list,
1734      base::FilePath(FILE_PATH_LITERAL("force_anti_aliasing_off.png")),
1735      ExactPixelComparator(false)));
1736}
1737
1738TEST_F(GLRendererPixelTest, AntiAliasingPerspective) {
1739  gfx::Rect rect(this->device_viewport_size_);
1740
1741  scoped_ptr<RenderPass> pass =
1742      CreateTestRootRenderPass(RenderPass::Id(1, 1), rect);
1743
1744  gfx::Rect red_rect(0, 0, 180, 500);
1745  gfx::Transform red_content_to_target_transform(
1746      1.0f,  2.4520f,  10.6206f, 19.0f,
1747      0.0f,  0.3528f,  5.9737f,  9.5f,
1748      0.0f, -0.2250f, -0.9744f,  0.0f,
1749      0.0f,  0.0225f,  0.0974f,  1.0f);
1750  SharedQuadState* red_shared_state = CreateTestSharedQuadState(
1751      pass.get(), red_content_to_target_transform, red_rect);
1752  scoped_ptr<SolidColorDrawQuad> red = SolidColorDrawQuad::Create();
1753  red->SetNew(red_shared_state, red_rect, red_rect, SK_ColorRED, false);
1754  pass->quad_list.push_back(red.PassAs<DrawQuad>());
1755
1756  gfx::Rect green_rect(19, 7, 180, 10);
1757  SharedQuadState* green_shared_state =
1758      CreateTestSharedQuadState(pass.get(), gfx::Transform(), green_rect);
1759  scoped_ptr<SolidColorDrawQuad> green = SolidColorDrawQuad::Create();
1760  green->SetNew(
1761      green_shared_state, green_rect, green_rect, SK_ColorGREEN, false);
1762  pass->quad_list.push_back(green.PassAs<DrawQuad>());
1763
1764  SharedQuadState* blue_shared_state =
1765      CreateTestSharedQuadState(pass.get(), gfx::Transform(), rect);
1766  scoped_ptr<SolidColorDrawQuad> blue = SolidColorDrawQuad::Create();
1767  blue->SetNew(blue_shared_state, rect, rect, SK_ColorBLUE, false);
1768  pass->quad_list.push_back(blue.PassAs<DrawQuad>());
1769
1770  RenderPassList pass_list;
1771  pass_list.push_back(pass.Pass());
1772
1773  EXPECT_TRUE(this->RunPixelTest(
1774      &pass_list,
1775      base::FilePath(FILE_PATH_LITERAL("anti_aliasing_perspective.png")),
1776      FuzzyPixelOffByOneComparator(true)));
1777}
1778
1779TYPED_TEST(RendererPixelTest, PictureDrawQuadIdentityScale) {
1780  gfx::Size pile_tile_size(1000, 1000);
1781  gfx::Rect viewport(this->device_viewport_size_);
1782  // TODO(enne): the renderer should figure this out on its own.
1783  ResourceFormat texture_format = RGBA_8888;
1784
1785  RenderPass::Id id(1, 1);
1786  gfx::Transform transform_to_root;
1787  scoped_ptr<RenderPass> pass =
1788      CreateTestRenderPass(id, viewport, transform_to_root);
1789
1790  // One clipped blue quad in the lower right corner.  Outside the clip
1791  // is red, which should not appear.
1792  gfx::Rect blue_rect(gfx::Size(100, 100));
1793  gfx::Rect blue_clip_rect(gfx::Point(50, 50), gfx::Size(50, 50));
1794  scoped_refptr<FakePicturePileImpl> blue_pile =
1795      FakePicturePileImpl::CreateFilledPile(pile_tile_size, blue_rect.size());
1796  SkPaint red_paint;
1797  red_paint.setColor(SK_ColorRED);
1798  blue_pile->add_draw_rect_with_paint(blue_rect, red_paint);
1799  SkPaint blue_paint;
1800  blue_paint.setColor(SK_ColorBLUE);
1801  blue_pile->add_draw_rect_with_paint(blue_clip_rect, blue_paint);
1802  blue_pile->RerecordPile();
1803
1804  gfx::Transform blue_content_to_target_transform;
1805  gfx::Vector2d offset(viewport.bottom_right() - blue_rect.bottom_right());
1806  blue_content_to_target_transform.Translate(offset.x(), offset.y());
1807  gfx::RectF blue_scissor_rect = blue_clip_rect;
1808  blue_content_to_target_transform.TransformRect(&blue_scissor_rect);
1809  SharedQuadState* blue_shared_state =
1810      CreateTestSharedQuadStateClipped(pass.get(),
1811                                       blue_content_to_target_transform,
1812                                       blue_rect,
1813                                       gfx::ToEnclosingRect(blue_scissor_rect));
1814
1815  scoped_ptr<PictureDrawQuad> blue_quad = PictureDrawQuad::Create();
1816
1817  blue_quad->SetNew(blue_shared_state,
1818                    viewport,  // Intentionally bigger than clip.
1819                    gfx::Rect(),
1820                    viewport,
1821                    gfx::RectF(viewport),
1822                    viewport.size(),
1823                    texture_format,
1824                    viewport,
1825                    1.f,
1826                    PicturePileImpl::CreateFromOther(blue_pile));
1827  pass->quad_list.push_back(blue_quad.PassAs<DrawQuad>());
1828
1829  // One viewport-filling green quad.
1830  scoped_refptr<FakePicturePileImpl> green_pile =
1831      FakePicturePileImpl::CreateFilledPile(pile_tile_size, viewport.size());
1832  SkPaint green_paint;
1833  green_paint.setColor(SK_ColorGREEN);
1834  green_pile->add_draw_rect_with_paint(viewport, green_paint);
1835  green_pile->RerecordPile();
1836
1837  gfx::Transform green_content_to_target_transform;
1838  SharedQuadState* green_shared_state = CreateTestSharedQuadState(
1839      pass.get(), green_content_to_target_transform, viewport);
1840
1841  scoped_ptr<PictureDrawQuad> green_quad = PictureDrawQuad::Create();
1842  green_quad->SetNew(green_shared_state,
1843                     viewport,
1844                     gfx::Rect(),
1845                     viewport,
1846                     gfx::RectF(0.f, 0.f, 1.f, 1.f),
1847                     viewport.size(),
1848                     texture_format,
1849                     viewport,
1850                     1.f,
1851                     PicturePileImpl::CreateFromOther(green_pile));
1852  pass->quad_list.push_back(green_quad.PassAs<DrawQuad>());
1853
1854  RenderPassList pass_list;
1855  pass_list.push_back(pass.Pass());
1856
1857  EXPECT_TRUE(this->RunPixelTest(
1858      &pass_list,
1859      base::FilePath(FILE_PATH_LITERAL("green_with_blue_corner.png")),
1860      ExactPixelComparator(true)));
1861}
1862
1863// Not WithSkiaGPUBackend since that path currently requires tiles for opacity.
1864TYPED_TEST(RendererPixelTest, PictureDrawQuadOpacity) {
1865  gfx::Size pile_tile_size(1000, 1000);
1866  gfx::Rect viewport(this->device_viewport_size_);
1867  ResourceFormat texture_format = RGBA_8888;
1868
1869  RenderPass::Id id(1, 1);
1870  gfx::Transform transform_to_root;
1871  scoped_ptr<RenderPass> pass =
1872      CreateTestRenderPass(id, viewport, transform_to_root);
1873
1874  // One viewport-filling 0.5-opacity green quad.
1875  scoped_refptr<FakePicturePileImpl> green_pile =
1876      FakePicturePileImpl::CreateFilledPile(pile_tile_size, viewport.size());
1877  SkPaint green_paint;
1878  green_paint.setColor(SK_ColorGREEN);
1879  green_pile->add_draw_rect_with_paint(viewport, green_paint);
1880  green_pile->RerecordPile();
1881
1882  gfx::Transform green_content_to_target_transform;
1883  SharedQuadState* green_shared_state = CreateTestSharedQuadState(
1884      pass.get(), green_content_to_target_transform, viewport);
1885  green_shared_state->opacity = 0.5f;
1886
1887  scoped_ptr<PictureDrawQuad> green_quad = PictureDrawQuad::Create();
1888  green_quad->SetNew(green_shared_state,
1889                     viewport,
1890                     gfx::Rect(),
1891                     viewport,
1892                     gfx::RectF(0, 0, 1, 1),
1893                     viewport.size(),
1894                     texture_format,
1895                     viewport,
1896                     1.f,
1897                     PicturePileImpl::CreateFromOther(green_pile));
1898  pass->quad_list.push_back(green_quad.PassAs<DrawQuad>());
1899
1900  // One viewport-filling white quad.
1901  scoped_refptr<FakePicturePileImpl> white_pile =
1902      FakePicturePileImpl::CreateFilledPile(pile_tile_size, viewport.size());
1903  SkPaint white_paint;
1904  white_paint.setColor(SK_ColorWHITE);
1905  white_pile->add_draw_rect_with_paint(viewport, white_paint);
1906  white_pile->RerecordPile();
1907
1908  gfx::Transform white_content_to_target_transform;
1909  SharedQuadState* white_shared_state = CreateTestSharedQuadState(
1910      pass.get(), white_content_to_target_transform, viewport);
1911
1912  scoped_ptr<PictureDrawQuad> white_quad = PictureDrawQuad::Create();
1913  white_quad->SetNew(white_shared_state,
1914                     viewport,
1915                     gfx::Rect(),
1916                     viewport,
1917                     gfx::RectF(0, 0, 1, 1),
1918                     viewport.size(),
1919                     texture_format,
1920                     viewport,
1921                     1.f,
1922                     PicturePileImpl::CreateFromOther(white_pile));
1923  pass->quad_list.push_back(white_quad.PassAs<DrawQuad>());
1924
1925  RenderPassList pass_list;
1926  pass_list.push_back(pass.Pass());
1927
1928  EXPECT_TRUE(this->RunPixelTest(
1929      &pass_list,
1930      base::FilePath(FILE_PATH_LITERAL("green_alpha.png")),
1931      FuzzyPixelOffByOneComparator(true)));
1932}
1933
1934template<typename TypeParam> bool IsSoftwareRenderer() {
1935  return false;
1936}
1937
1938template<>
1939bool IsSoftwareRenderer<SoftwareRenderer>() {
1940  return true;
1941}
1942
1943template<>
1944bool IsSoftwareRenderer<SoftwareRendererWithExpandedViewport>() {
1945  return true;
1946}
1947
1948// If we disable image filtering, then a 2x2 bitmap should appear as four
1949// huge sharp squares.
1950TYPED_TEST(RendererPixelTest, PictureDrawQuadDisableImageFiltering) {
1951  // We only care about this in software mode since bilinear filtering is
1952  // cheap in hardware.
1953  if (!IsSoftwareRenderer<TypeParam>())
1954    return;
1955
1956  gfx::Size pile_tile_size(1000, 1000);
1957  gfx::Rect viewport(this->device_viewport_size_);
1958  ResourceFormat texture_format = RGBA_8888;
1959
1960  RenderPass::Id id(1, 1);
1961  gfx::Transform transform_to_root;
1962  scoped_ptr<RenderPass> pass =
1963      CreateTestRenderPass(id, viewport, transform_to_root);
1964
1965  SkBitmap bitmap;
1966  bitmap.allocN32Pixels(2, 2);
1967  {
1968    SkAutoLockPixels lock(bitmap);
1969    SkCanvas canvas(bitmap);
1970    canvas.drawPoint(0, 0, SK_ColorGREEN);
1971    canvas.drawPoint(0, 1, SK_ColorBLUE);
1972    canvas.drawPoint(1, 0, SK_ColorBLUE);
1973    canvas.drawPoint(1, 1, SK_ColorGREEN);
1974  }
1975
1976  scoped_refptr<FakePicturePileImpl> pile =
1977      FakePicturePileImpl::CreateFilledPile(pile_tile_size, viewport.size());
1978  SkPaint paint;
1979  paint.setFilterLevel(SkPaint::kLow_FilterLevel);
1980  pile->add_draw_bitmap_with_paint(bitmap, gfx::Point(), paint);
1981  pile->RerecordPile();
1982
1983  gfx::Transform content_to_target_transform;
1984  SharedQuadState* shared_state = CreateTestSharedQuadState(
1985      pass.get(), content_to_target_transform, viewport);
1986
1987  scoped_ptr<PictureDrawQuad> quad = PictureDrawQuad::Create();
1988  quad->SetNew(shared_state,
1989               viewport,
1990               gfx::Rect(),
1991               viewport,
1992               gfx::RectF(0, 0, 2, 2),
1993               viewport.size(),
1994               texture_format,
1995               viewport,
1996               1.f,
1997               PicturePileImpl::CreateFromOther(pile));
1998  pass->quad_list.push_back(quad.PassAs<DrawQuad>());
1999
2000  RenderPassList pass_list;
2001  pass_list.push_back(pass.Pass());
2002
2003  this->disable_picture_quad_image_filtering_ = true;
2004
2005  EXPECT_TRUE(this->RunPixelTest(
2006      &pass_list,
2007      base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")),
2008      ExactPixelComparator(true)));
2009}
2010
2011TYPED_TEST(RendererPixelTest, PictureDrawQuadNonIdentityScale) {
2012  gfx::Size pile_tile_size(1000, 1000);
2013  gfx::Rect viewport(this->device_viewport_size_);
2014  // TODO(enne): the renderer should figure this out on its own.
2015  ResourceFormat texture_format = RGBA_8888;
2016
2017  RenderPass::Id id(1, 1);
2018  gfx::Transform transform_to_root;
2019  scoped_ptr<RenderPass> pass =
2020      CreateTestRenderPass(id, viewport, transform_to_root);
2021
2022  // As scaling up the blue checkerboards will cause sampling on the GPU,
2023  // a few extra "cleanup rects" need to be added to clobber the blending
2024  // to make the output image more clean.  This will also test subrects
2025  // of the layer.
2026  gfx::Transform green_content_to_target_transform;
2027  gfx::Rect green_rect1(gfx::Point(80, 0), gfx::Size(20, 100));
2028  gfx::Rect green_rect2(gfx::Point(0, 80), gfx::Size(100, 20));
2029  scoped_refptr<FakePicturePileImpl> green_pile =
2030      FakePicturePileImpl::CreateFilledPile(pile_tile_size, viewport.size());
2031  SkPaint red_paint;
2032  red_paint.setColor(SK_ColorRED);
2033  green_pile->add_draw_rect_with_paint(viewport, red_paint);
2034  SkPaint green_paint;
2035  green_paint.setColor(SK_ColorGREEN);
2036  green_pile->add_draw_rect_with_paint(green_rect1, green_paint);
2037  green_pile->add_draw_rect_with_paint(green_rect2, green_paint);
2038  green_pile->RerecordPile();
2039
2040  SharedQuadState* top_right_green_shared_quad_state =
2041      CreateTestSharedQuadState(
2042          pass.get(), green_content_to_target_transform, viewport);
2043
2044  scoped_ptr<PictureDrawQuad> green_quad1 = PictureDrawQuad::Create();
2045  green_quad1->SetNew(top_right_green_shared_quad_state,
2046                      green_rect1,
2047                      gfx::Rect(),
2048                      green_rect1,
2049                      gfx::RectF(green_rect1.size()),
2050                      green_rect1.size(),
2051                      texture_format,
2052                      green_rect1,
2053                      1.f,
2054                      PicturePileImpl::CreateFromOther(green_pile));
2055  pass->quad_list.push_back(green_quad1.PassAs<DrawQuad>());
2056
2057  scoped_ptr<PictureDrawQuad> green_quad2 = PictureDrawQuad::Create();
2058  green_quad2->SetNew(top_right_green_shared_quad_state,
2059                      green_rect2,
2060                      gfx::Rect(),
2061                      green_rect2,
2062                      gfx::RectF(green_rect2.size()),
2063                      green_rect2.size(),
2064                      texture_format,
2065                      green_rect2,
2066                      1.f,
2067                      PicturePileImpl::CreateFromOther(green_pile));
2068  pass->quad_list.push_back(green_quad2.PassAs<DrawQuad>());
2069
2070  // Add a green clipped checkerboard in the bottom right to help test
2071  // interleaving picture quad content and solid color content.
2072  gfx::Rect bottom_right_rect(
2073      gfx::Point(viewport.width() / 2, viewport.height() / 2),
2074      gfx::Size(viewport.width() / 2, viewport.height() / 2));
2075  SharedQuadState* bottom_right_green_shared_state =
2076      CreateTestSharedQuadStateClipped(pass.get(),
2077                                       green_content_to_target_transform,
2078                                       viewport,
2079                                       bottom_right_rect);
2080  scoped_ptr<SolidColorDrawQuad> bottom_right_color_quad =
2081      SolidColorDrawQuad::Create();
2082  bottom_right_color_quad->SetNew(bottom_right_green_shared_state,
2083                                  viewport,
2084                                  viewport,
2085                                  SK_ColorGREEN,
2086                                  false);
2087  pass->quad_list.push_back(bottom_right_color_quad.PassAs<DrawQuad>());
2088
2089  // Add two blue checkerboards taking up the bottom left and top right,
2090  // but use content scales as content rects to make this happen.
2091  // The content is at a 4x content scale.
2092  gfx::Rect layer_rect(gfx::Size(20, 30));
2093  float contents_scale = 4.f;
2094  // Two rects that touch at their corners, arbitrarily placed in the layer.
2095  gfx::RectF blue_layer_rect1(gfx::PointF(5.5f, 9.0f), gfx::SizeF(2.5f, 2.5f));
2096  gfx::RectF blue_layer_rect2(gfx::PointF(8.0f, 6.5f), gfx::SizeF(2.5f, 2.5f));
2097  gfx::RectF union_layer_rect = blue_layer_rect1;
2098  union_layer_rect.Union(blue_layer_rect2);
2099
2100  // Because scaling up will cause sampling outside the rects, add one extra
2101  // pixel of buffer at the final content scale.
2102  float inset = -1.f / contents_scale;
2103  blue_layer_rect1.Inset(inset, inset, inset, inset);
2104  blue_layer_rect2.Inset(inset, inset, inset, inset);
2105
2106  scoped_refptr<FakePicturePileImpl> pile =
2107      FakePicturePileImpl::CreateFilledPile(pile_tile_size, layer_rect.size());
2108
2109  Region outside(layer_rect);
2110  outside.Subtract(gfx::ToEnclosingRect(union_layer_rect));
2111  for (Region::Iterator iter(outside); iter.has_rect(); iter.next()) {
2112    pile->add_draw_rect_with_paint(iter.rect(), red_paint);
2113  }
2114
2115  SkPaint blue_paint;
2116  blue_paint.setColor(SK_ColorBLUE);
2117  pile->add_draw_rect_with_paint(blue_layer_rect1, blue_paint);
2118  pile->add_draw_rect_with_paint(blue_layer_rect2, blue_paint);
2119  pile->RerecordPile();
2120
2121  gfx::Rect content_rect(
2122      gfx::ScaleToEnclosingRect(layer_rect, contents_scale));
2123  gfx::Rect content_union_rect(
2124      gfx::ToEnclosingRect(gfx::ScaleRect(union_layer_rect, contents_scale)));
2125
2126  // At a scale of 4x the rectangles with a width of 2.5 will take up 10 pixels,
2127  // so scale an additional 10x to make them 100x100.
2128  gfx::Transform content_to_target_transform;
2129  content_to_target_transform.Scale(10.0, 10.0);
2130  gfx::Rect quad_content_rect(gfx::Size(20, 20));
2131  SharedQuadState* blue_shared_state = CreateTestSharedQuadState(
2132      pass.get(), content_to_target_transform, quad_content_rect);
2133
2134  scoped_ptr<PictureDrawQuad> blue_quad = PictureDrawQuad::Create();
2135  blue_quad->SetNew(blue_shared_state,
2136                    quad_content_rect,
2137                    gfx::Rect(),
2138                    quad_content_rect,
2139                    gfx::RectF(quad_content_rect),
2140                    content_union_rect.size(),
2141                    texture_format,
2142                    content_union_rect,
2143                    contents_scale,
2144                    PicturePileImpl::CreateFromOther(pile));
2145  pass->quad_list.push_back(blue_quad.PassAs<DrawQuad>());
2146
2147  // Fill left half of viewport with green.
2148  gfx::Transform half_green_content_to_target_transform;
2149  gfx::Rect half_green_rect(gfx::Size(viewport.width() / 2, viewport.height()));
2150  SharedQuadState* half_green_shared_state = CreateTestSharedQuadState(
2151      pass.get(), half_green_content_to_target_transform, half_green_rect);
2152  scoped_ptr<SolidColorDrawQuad> half_color_quad = SolidColorDrawQuad::Create();
2153  half_color_quad->SetNew(half_green_shared_state,
2154                          half_green_rect,
2155                          half_green_rect,
2156                          SK_ColorGREEN,
2157                          false);
2158  pass->quad_list.push_back(half_color_quad.PassAs<DrawQuad>());
2159
2160  RenderPassList pass_list;
2161  pass_list.push_back(pass.Pass());
2162
2163  EXPECT_TRUE(this->RunPixelTest(
2164      &pass_list,
2165      base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")),
2166      ExactPixelComparator(true)));
2167}
2168
2169TYPED_TEST(RendererPixelTest, WrapModeRepeat) {
2170  gfx::Rect rect(this->device_viewport_size_);
2171
2172  RenderPass::Id id(1, 1);
2173  scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
2174
2175  SharedQuadState* shared_state =
2176      CreateTestSharedQuadState(pass.get(), gfx::Transform(), rect);
2177
2178  gfx::Rect texture_rect(4, 4);
2179  SkPMColor colors[4] = {
2180    SkPreMultiplyColor(SkColorSetARGB(255, 0, 255, 0)),
2181    SkPreMultiplyColor(SkColorSetARGB(255, 0, 128, 0)),
2182    SkPreMultiplyColor(SkColorSetARGB(255, 0,  64, 0)),
2183    SkPreMultiplyColor(SkColorSetARGB(255, 0,   0, 0)),
2184  };
2185  uint32_t pixels[16] = {
2186    colors[0], colors[0], colors[1], colors[1],
2187    colors[0], colors[0], colors[1], colors[1],
2188    colors[2], colors[2], colors[3], colors[3],
2189    colors[2], colors[2], colors[3], colors[3],
2190  };
2191  ResourceProvider::ResourceId resource =
2192      this->resource_provider_->CreateResource(
2193          texture_rect.size(),
2194          GL_REPEAT,
2195          ResourceProvider::TextureUsageAny,
2196          RGBA_8888);
2197  this->resource_provider_->SetPixels(
2198      resource,
2199      reinterpret_cast<uint8_t*>(pixels),
2200      texture_rect,
2201      texture_rect,
2202      gfx::Vector2d());
2203
2204  float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
2205  scoped_ptr<TextureDrawQuad> texture_quad = TextureDrawQuad::Create();
2206  texture_quad->SetNew(
2207      shared_state,
2208      gfx::Rect(this->device_viewport_size_),
2209      gfx::Rect(),
2210      gfx::Rect(this->device_viewport_size_),
2211      resource,
2212      true,                     // premultiplied_alpha
2213      gfx::PointF(0.0f, 0.0f),  // uv_top_left
2214      gfx::PointF(              // uv_bottom_right
2215          this->device_viewport_size_.width() / texture_rect.width(),
2216          this->device_viewport_size_.height() / texture_rect.height()),
2217      SK_ColorWHITE,
2218      vertex_opacity,
2219      false);  // flipped
2220  pass->quad_list.push_back(texture_quad.PassAs<DrawQuad>());
2221
2222  RenderPassList pass_list;
2223  pass_list.push_back(pass.Pass());
2224
2225  EXPECT_TRUE(this->RunPixelTest(
2226      &pass_list,
2227      base::FilePath(FILE_PATH_LITERAL("wrap_mode_repeat.png")),
2228      FuzzyPixelOffByOneComparator(true)));
2229}
2230
2231#endif  // !defined(OS_ANDROID)
2232
2233}  // namespace
2234}  // namespace cc
2235