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