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 <stddef.h>
6 #include <stdint.h>
7 #include <algorithm>
8 #include <memory>
9 #include <tuple>
10 
11 #include "base/bind.h"
12 #include "base/callback_helpers.h"
13 #include "base/memory/aligned_memory.h"
14 #include "base/memory/read_only_shared_memory_region.h"
15 #include "base/memory/shared_memory_mapping.h"
16 #include "base/numerics/ranges.h"
17 #include "build/build_config.h"
18 #include "cc/base/math_util.h"
19 #include "cc/paint/paint_flags.h"
20 #include "cc/paint/skia_paint_canvas.h"
21 #include "cc/test/fake_raster_source.h"
22 #include "cc/test/fake_recording_source.h"
23 #include "cc/test/pixel_test.h"
24 #include "cc/test/render_pass_test_utils.h"
25 #include "cc/test/resource_provider_test_utils.h"
26 #include "cc/test/test_types.h"
27 #include "components/viz/client/client_resource_provider.h"
28 #include "components/viz/common/quads/picture_draw_quad.h"
29 #include "components/viz/common/quads/texture_draw_quad.h"
30 #include "components/viz/common/resources/bitmap_allocation.h"
31 #include "components/viz/common/resources/resource_format_utils.h"
32 #include "components/viz/service/display/delegated_ink_point_pixel_test_helper.h"
33 #include "components/viz/service/display/gl_renderer.h"
34 #include "components/viz/service/display/software_renderer.h"
35 #include "components/viz/service/display/viz_pixel_test.h"
36 #include "components/viz/test/buildflags.h"
37 #include "components/viz/test/test_in_process_context_provider.h"
38 #include "components/viz/test/test_shared_bitmap_manager.h"
39 #include "components/viz/test/test_types.h"
40 #include "gpu/command_buffer/client/gles2_interface.h"
41 #include "gpu/command_buffer/client/shared_image_interface.h"
42 #include "gpu/command_buffer/common/shared_image_usage.h"
43 #include "media/base/video_frame.h"
44 #include "media/renderers/video_resource_updater.h"
45 #include "media/video/half_float_maker.h"
46 #include "third_party/skia/include/core/SkColorPriv.h"
47 #include "third_party/skia/include/core/SkMatrix.h"
48 #include "third_party/skia/include/core/SkRefCnt.h"
49 #include "third_party/skia/include/core/SkSurface.h"
50 #include "third_party/skia/include/effects/SkColorMatrixFilter.h"
51 #include "ui/gfx/color_transform.h"
52 #include "ui/gfx/geometry/rect_conversions.h"
53 #include "ui/gfx/test/icc_profiles.h"
54 
55 using gpu::gles2::GLES2Interface;
56 
57 namespace viz {
58 namespace {
59 
60 const gfx::DisplayColorSpaces kRec601DisplayColorSpaces(
61     gfx::ColorSpace(gfx::ColorSpace::PrimaryID::SMPTE170M,
62                     gfx::ColorSpace::TransferID::SMPTE170M));
63 
64 #if !defined(OS_ANDROID)
65 template <typename T>
MakePixelSpan(const std::vector<T> & vec)66 base::span<const uint8_t> MakePixelSpan(const std::vector<T>& vec) {
67   return base::make_span(reinterpret_cast<const uint8_t*>(vec.data()),
68                          vec.size() * sizeof(T));
69 }
70 
MakePixelSpan(const SkBitmap & bitmap)71 base::span<const uint8_t> MakePixelSpan(const SkBitmap& bitmap) {
72   return base::make_span(static_cast<const uint8_t*>(bitmap.getPixels()),
73                          bitmap.computeByteSize());
74 }
75 
AllocateAndRegisterSharedBitmapMemory(const SharedBitmapId & id,const gfx::Size & size,SharedBitmapManager * shared_bitmap_manager)76 base::WritableSharedMemoryMapping AllocateAndRegisterSharedBitmapMemory(
77     const SharedBitmapId& id,
78     const gfx::Size& size,
79     SharedBitmapManager* shared_bitmap_manager) {
80   base::MappedReadOnlyRegion shm =
81       bitmap_allocation::AllocateSharedBitmap(size, RGBA_8888);
82   shared_bitmap_manager->ChildAllocatedSharedBitmap(shm.region.Map(), id);
83   return std::move(shm.mapping);
84 }
85 
DeleteSharedImage(scoped_refptr<ContextProvider> context_provider,gpu::Mailbox mailbox,const gpu::SyncToken & sync_token,bool is_lost)86 void DeleteSharedImage(scoped_refptr<ContextProvider> context_provider,
87                        gpu::Mailbox mailbox,
88                        const gpu::SyncToken& sync_token,
89                        bool is_lost) {
90   DCHECK(context_provider);
91   gpu::SharedImageInterface* sii = context_provider->SharedImageInterface();
92   DCHECK(sii);
93   sii->DestroySharedImage(sync_token, mailbox);
94 }
95 
CreateGpuResource(scoped_refptr<ContextProvider> context_provider,ClientResourceProvider * resource_provider,const gfx::Size & size,ResourceFormat format,gfx::ColorSpace color_space,base::span<const uint8_t> pixels)96 ResourceId CreateGpuResource(scoped_refptr<ContextProvider> context_provider,
97                              ClientResourceProvider* resource_provider,
98                              const gfx::Size& size,
99                              ResourceFormat format,
100                              gfx::ColorSpace color_space,
101                              base::span<const uint8_t> pixels) {
102   DCHECK(context_provider);
103   gpu::SharedImageInterface* sii = context_provider->SharedImageInterface();
104   DCHECK(sii);
105   gpu::Mailbox mailbox = sii->CreateSharedImage(
106       format, size, color_space, kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType,
107       gpu::SHARED_IMAGE_USAGE_DISPLAY, pixels);
108   gpu::SyncToken sync_token = sii->GenUnverifiedSyncToken();
109 
110   TransferableResource gl_resource = TransferableResource::MakeGL(
111       mailbox, GL_LINEAR, GL_TEXTURE_2D, sync_token, size,
112       false /* is_overlay_candidate */);
113   gl_resource.format = format;
114   gl_resource.color_space = std::move(color_space);
115   auto release_callback = SingleReleaseCallback::Create(
116       base::BindOnce(&DeleteSharedImage, std::move(context_provider), mailbox));
117   return resource_provider->ImportResource(gl_resource,
118                                            std::move(release_callback));
119 }
120 
CreateTestRootRenderPass(AggregatedRenderPassId id,const gfx::Rect & rect)121 std::unique_ptr<AggregatedRenderPass> CreateTestRootRenderPass(
122     AggregatedRenderPassId id,
123     const gfx::Rect& rect) {
124   auto pass = std::make_unique<AggregatedRenderPass>();
125   const gfx::Rect output_rect = rect;
126   const gfx::Rect damage_rect = rect;
127   const gfx::Transform transform_to_root_target;
128   pass->SetNew(id, output_rect, damage_rect, transform_to_root_target);
129   return pass;
130 }
131 
CreateTestRenderPass(AggregatedRenderPassId id,const gfx::Rect & rect,const gfx::Transform & transform_to_root_target)132 std::unique_ptr<AggregatedRenderPass> CreateTestRenderPass(
133     AggregatedRenderPassId id,
134     const gfx::Rect& rect,
135     const gfx::Transform& transform_to_root_target) {
136   auto pass = std::make_unique<AggregatedRenderPass>();
137   const gfx::Rect output_rect = rect;
138   const gfx::Rect damage_rect = rect;
139   pass->SetNew(id, output_rect, damage_rect, transform_to_root_target);
140   return pass;
141 }
142 
CreateTestSharedQuadState(gfx::Transform quad_to_target_transform,const gfx::Rect & rect,AggregatedRenderPass * render_pass,const gfx::RRectF & rrect)143 SharedQuadState* CreateTestSharedQuadState(
144     gfx::Transform quad_to_target_transform,
145     const gfx::Rect& rect,
146     AggregatedRenderPass* render_pass,
147     const gfx::RRectF& rrect) {
148   const gfx::Rect layer_rect = rect;
149   const gfx::Rect visible_layer_rect = rect;
150   const gfx::Rect clip_rect = rect;
151   const bool is_clipped = false;
152   const bool are_contents_opaque = false;
153   const float opacity = 1.0f;
154   const gfx::MaskFilterInfo mask_filter_info(rrect);
155   const SkBlendMode blend_mode = SkBlendMode::kSrcOver;
156   int sorting_context_id = 0;
157   SharedQuadState* shared_state = render_pass->CreateAndAppendSharedQuadState();
158   shared_state->SetAll(quad_to_target_transform, layer_rect, visible_layer_rect,
159                        mask_filter_info, clip_rect, is_clipped,
160                        are_contents_opaque, opacity, blend_mode,
161                        sorting_context_id);
162   return shared_state;
163 }
164 
CreateTestSharedQuadStateClipped(gfx::Transform quad_to_target_transform,const gfx::Rect & rect,const gfx::Rect & clip_rect,AggregatedRenderPass * render_pass)165 SharedQuadState* CreateTestSharedQuadStateClipped(
166     gfx::Transform quad_to_target_transform,
167     const gfx::Rect& rect,
168     const gfx::Rect& clip_rect,
169     AggregatedRenderPass* render_pass) {
170   const gfx::Rect layer_rect = rect;
171   const gfx::Rect visible_layer_rect = clip_rect;
172   const bool is_clipped = true;
173   const bool are_contents_opaque = false;
174   const float opacity = 1.0f;
175   const SkBlendMode blend_mode = SkBlendMode::kSrcOver;
176   int sorting_context_id = 0;
177   SharedQuadState* shared_state = render_pass->CreateAndAppendSharedQuadState();
178   shared_state->SetAll(quad_to_target_transform, layer_rect, visible_layer_rect,
179                        /*mask_filter_info=*/gfx::MaskFilterInfo(), clip_rect,
180                        is_clipped, are_contents_opaque, opacity, blend_mode,
181                        sorting_context_id);
182   return shared_state;
183 }
184 
CreateTestRenderPassDrawQuad(const SharedQuadState * shared_state,const gfx::Rect & rect,AggregatedRenderPassId pass_id,AggregatedRenderPass * render_pass)185 void CreateTestRenderPassDrawQuad(const SharedQuadState* shared_state,
186                                   const gfx::Rect& rect,
187                                   AggregatedRenderPassId pass_id,
188                                   AggregatedRenderPass* render_pass) {
189   auto* quad =
190       render_pass->CreateAndAppendDrawQuad<AggregatedRenderPassDrawQuad>();
191   quad->SetNew(shared_state, rect, rect, pass_id,
192                0,                 // mask_resource_id
193                gfx::RectF(),      // mask_uv_rect
194                gfx::Size(),       // mask_texture_size
195                gfx::Vector2dF(),  // filters scale
196                gfx::PointF(),     // filter origin
197                gfx::RectF(rect),  // tex_coord_rect
198                false,             // force_anti_aliasing_off
199                1.0f);             // backdrop_filter_quality
200 }
201 
202 // Create a TextureDrawDrawQuad with two given colors.
203 // flipped_texture_quad: The TextureDrawDrawQuad is y flipped.
204 // half_and_half: if true, the upper half part of the texture is filled with
205 //   texel_color_one, other part of the texture is filled with texel_color_two.
206 //   if false, a 1/2 width and height rectangle in the middle of the quad will
207 //   be filled with texel_color_two, other part of the texture is filled with
208 //   texel_color_one,
CreateTestTwoColoredTextureDrawQuad(bool gpu_resource,const gfx::Rect & rect,SkColor texel_color_one,SkColor texel_color_two,SkColor background_color,bool premultiplied_alpha,bool flipped_texture_quad,bool half_and_half,const SharedQuadState * shared_state,DisplayResourceProvider * resource_provider,ClientResourceProvider * child_resource_provider,SharedBitmapManager * shared_bitmap_manager,scoped_refptr<ContextProvider> child_context_provider,AggregatedRenderPass * render_pass)209 void CreateTestTwoColoredTextureDrawQuad(
210     bool gpu_resource,
211     const gfx::Rect& rect,
212     SkColor texel_color_one,
213     SkColor texel_color_two,
214     SkColor background_color,
215     bool premultiplied_alpha,
216     bool flipped_texture_quad,
217     bool half_and_half,
218     const SharedQuadState* shared_state,
219     DisplayResourceProvider* resource_provider,
220     ClientResourceProvider* child_resource_provider,
221     SharedBitmapManager* shared_bitmap_manager,
222     scoped_refptr<ContextProvider> child_context_provider,
223     AggregatedRenderPass* render_pass) {
224   SkPMColor pixel_color_one =
225       premultiplied_alpha
226           ? SkPreMultiplyColor(texel_color_one)
227           : SkPackARGB32NoCheck(
228                 SkColorGetA(texel_color_one), SkColorGetR(texel_color_one),
229                 SkColorGetG(texel_color_one), SkColorGetB(texel_color_one));
230   SkPMColor pixel_color_two =
231       premultiplied_alpha
232           ? SkPreMultiplyColor(texel_color_two)
233           : SkPackARGB32NoCheck(
234                 SkColorGetA(texel_color_two), SkColorGetR(texel_color_two),
235                 SkColorGetG(texel_color_two), SkColorGetB(texel_color_two));
236   // The default color is texel_color_one
237   std::vector<uint32_t> pixels(rect.size().GetArea(), pixel_color_one);
238   if (half_and_half) {
239     // Fill the bottom half part of the texture with texel_color_two.
240     for (int i = rect.height() / 2; i < rect.height(); ++i) {
241       for (int k = 0; k < rect.width(); ++k) {
242         pixels[i * rect.width() + k] = pixel_color_two;
243       }
244     }
245   } else {
246     // Fill a 1/2 width and height rectangle with pixel_color_two.
247     for (int i = rect.height() / 4; i < (rect.height() * 3 / 4); ++i) {
248       for (int k = rect.width() / 4; k < (rect.width() * 3 / 4); ++k) {
249         pixels[i * rect.width() + k] = pixel_color_two;
250       }
251     }
252   }
253 
254   ResourceId resource;
255   if (gpu_resource) {
256     resource = CreateGpuResource(
257         child_context_provider, child_resource_provider, rect.size(), BGRA_8888,
258         gfx::ColorSpace(), MakePixelSpan(pixels));
259   } else {
260     SharedBitmapId shared_bitmap_id = SharedBitmap::GenerateId();
261     base::WritableSharedMemoryMapping mapping =
262         AllocateAndRegisterSharedBitmapMemory(shared_bitmap_id, rect.size(),
263                                               shared_bitmap_manager);
264     resource = child_resource_provider->ImportResource(
265         TransferableResource::MakeSoftware(shared_bitmap_id, rect.size(),
266                                            RGBA_8888),
267         SingleReleaseCallback::Create(base::DoNothing()));
268 
269     auto span = mapping.GetMemoryAsSpan<uint32_t>(pixels.size());
270     std::copy(pixels.begin(), pixels.end(), span.begin());
271   }
272 
273   // Return the mapped resource id.
274   std::unordered_map<ResourceId, ResourceId> resource_map =
275       cc::SendResourceAndGetChildToParentMap({resource}, resource_provider,
276                                              child_resource_provider,
277                                              child_context_provider.get());
278   ResourceId mapped_resource = resource_map[resource];
279 
280   bool needs_blending = true;
281   float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
282   const gfx::PointF uv_top_left(0.0f, 0.0f);
283   const gfx::PointF uv_bottom_right(1.0f, 1.0f);
284   const bool nearest_neighbor = false;
285   auto* quad = render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
286   quad->SetNew(shared_state, rect, rect, needs_blending, mapped_resource,
287                premultiplied_alpha, uv_top_left, uv_bottom_right,
288                background_color, vertex_opacity, flipped_texture_quad,
289                nearest_neighbor, /*secure_output_only=*/false,
290                gfx::ProtectedVideoType::kClear);
291 }
292 
CreateTestTextureDrawQuad(bool gpu_resource,const gfx::Rect & rect,SkColor texel_color,float vertex_opacity[4],SkColor background_color,bool premultiplied_alpha,const SharedQuadState * shared_state,DisplayResourceProvider * resource_provider,ClientResourceProvider * child_resource_provider,SharedBitmapManager * shared_bitmap_manager,scoped_refptr<ContextProvider> child_context_provider,AggregatedRenderPass * render_pass)293 void CreateTestTextureDrawQuad(
294     bool gpu_resource,
295     const gfx::Rect& rect,
296     SkColor texel_color,
297     float vertex_opacity[4],
298     SkColor background_color,
299     bool premultiplied_alpha,
300     const SharedQuadState* shared_state,
301     DisplayResourceProvider* resource_provider,
302     ClientResourceProvider* child_resource_provider,
303     SharedBitmapManager* shared_bitmap_manager,
304     scoped_refptr<ContextProvider> child_context_provider,
305     AggregatedRenderPass* render_pass) {
306   SkPMColor pixel_color = premultiplied_alpha
307                               ? SkPreMultiplyColor(texel_color)
308                               : SkPackARGB32NoCheck(SkColorGetA(texel_color),
309                                                     SkColorGetR(texel_color),
310                                                     SkColorGetG(texel_color),
311                                                     SkColorGetB(texel_color));
312   size_t num_pixels = static_cast<size_t>(rect.width()) * rect.height();
313   std::vector<uint32_t> pixels(num_pixels, pixel_color);
314 
315   ResourceId resource;
316   if (gpu_resource) {
317     resource = CreateGpuResource(
318         child_context_provider, child_resource_provider, rect.size(), RGBA_8888,
319         gfx::ColorSpace(), MakePixelSpan(pixels));
320   } else {
321     SharedBitmapId shared_bitmap_id = SharedBitmap::GenerateId();
322     base::WritableSharedMemoryMapping mapping =
323         AllocateAndRegisterSharedBitmapMemory(shared_bitmap_id, rect.size(),
324                                               shared_bitmap_manager);
325     resource = child_resource_provider->ImportResource(
326         TransferableResource::MakeSoftware(shared_bitmap_id, rect.size(),
327                                            RGBA_8888),
328         SingleReleaseCallback::Create(base::DoNothing()));
329 
330     auto span = mapping.GetMemoryAsSpan<uint32_t>(pixels.size());
331     std::copy(pixels.begin(), pixels.end(), span.begin());
332   }
333 
334   // Return the mapped resource id.
335   std::unordered_map<ResourceId, ResourceId> resource_map =
336       cc::SendResourceAndGetChildToParentMap({resource}, resource_provider,
337                                              child_resource_provider,
338                                              child_context_provider.get());
339   ResourceId mapped_resource = resource_map[resource];
340 
341   bool needs_blending = true;
342   const gfx::PointF uv_top_left(0.0f, 0.0f);
343   const gfx::PointF uv_bottom_right(1.0f, 1.0f);
344   const bool flipped = false;
345   const bool nearest_neighbor = false;
346   auto* quad = render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
347   quad->SetNew(shared_state, rect, rect, needs_blending, mapped_resource,
348                premultiplied_alpha, uv_top_left, uv_bottom_right,
349                background_color, vertex_opacity, flipped, nearest_neighbor,
350                /*secure_output_only=*/false, gfx::ProtectedVideoType::kClear);
351 }
352 
CreateTestTextureDrawQuad(bool gpu_resource,const gfx::Rect & rect,SkColor texel_color,SkColor background_color,bool premultiplied_alpha,const SharedQuadState * shared_state,DisplayResourceProvider * resource_provider,ClientResourceProvider * child_resource_provider,SharedBitmapManager * shared_bitmap_manager,scoped_refptr<ContextProvider> child_context_provider,AggregatedRenderPass * render_pass)353 void CreateTestTextureDrawQuad(
354     bool gpu_resource,
355     const gfx::Rect& rect,
356     SkColor texel_color,
357     SkColor background_color,
358     bool premultiplied_alpha,
359     const SharedQuadState* shared_state,
360     DisplayResourceProvider* resource_provider,
361     ClientResourceProvider* child_resource_provider,
362     SharedBitmapManager* shared_bitmap_manager,
363     scoped_refptr<ContextProvider> child_context_provider,
364     AggregatedRenderPass* render_pass) {
365   float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
366   CreateTestTextureDrawQuad(gpu_resource, rect, texel_color, vertex_opacity,
367                             background_color, premultiplied_alpha, shared_state,
368                             resource_provider, child_resource_provider,
369                             shared_bitmap_manager,
370                             std::move(child_context_provider), render_pass);
371 }
372 
CreateTestYUVVideoDrawQuad_FromVideoFrame(const SharedQuadState * shared_state,scoped_refptr<media::VideoFrame> video_frame,uint8_t alpha_value,const gfx::RectF & tex_coord_rect,AggregatedRenderPass * render_pass,media::VideoResourceUpdater * video_resource_updater,const gfx::Rect & rect,const gfx::Rect & visible_rect,DisplayResourceProvider * resource_provider,ClientResourceProvider * child_resource_provider,ContextProvider * child_context_provider)373 void CreateTestYUVVideoDrawQuad_FromVideoFrame(
374     const SharedQuadState* shared_state,
375     scoped_refptr<media::VideoFrame> video_frame,
376     uint8_t alpha_value,
377     const gfx::RectF& tex_coord_rect,
378     AggregatedRenderPass* render_pass,
379     media::VideoResourceUpdater* video_resource_updater,
380     const gfx::Rect& rect,
381     const gfx::Rect& visible_rect,
382     DisplayResourceProvider* resource_provider,
383     ClientResourceProvider* child_resource_provider,
384     ContextProvider* child_context_provider) {
385   const bool with_alpha = (video_frame->format() == media::PIXEL_FORMAT_I420A);
386 
387   gfx::ColorSpace video_color_space = video_frame->ColorSpace();
388   DCHECK(video_color_space.IsValid());
389 
390   bool needs_blending = true;
391 
392   if (with_alpha) {
393     memset(video_frame->data(media::VideoFrame::kAPlane), alpha_value,
394            video_frame->stride(media::VideoFrame::kAPlane) *
395                video_frame->rows(media::VideoFrame::kAPlane));
396   }
397 
398   media::VideoFrameExternalResources resources =
399       video_resource_updater->CreateExternalResourcesFromVideoFrame(
400           video_frame);
401 
402   EXPECT_EQ(media::VideoFrameResourceType::YUV, resources.type);
403   EXPECT_EQ(media::VideoFrame::NumPlanes(video_frame->format()),
404             resources.resources.size());
405   EXPECT_EQ(media::VideoFrame::NumPlanes(video_frame->format()),
406             resources.release_callbacks.size());
407 
408   ResourceId resource_y = child_resource_provider->ImportResource(
409       resources.resources[media::VideoFrame::kYPlane],
410       SingleReleaseCallback::Create(
411           std::move(resources.release_callbacks[media::VideoFrame::kYPlane])));
412   ResourceId resource_u = child_resource_provider->ImportResource(
413       resources.resources[media::VideoFrame::kUPlane],
414       SingleReleaseCallback::Create(
415           std::move(resources.release_callbacks[media::VideoFrame::kUPlane])));
416   ResourceId resource_v = child_resource_provider->ImportResource(
417       resources.resources[media::VideoFrame::kVPlane],
418       SingleReleaseCallback::Create(
419           std::move(resources.release_callbacks[media::VideoFrame::kVPlane])));
420   ResourceId resource_a = 0;
421   if (with_alpha) {
422     resource_a = child_resource_provider->ImportResource(
423         resources.resources[media::VideoFrame::kAPlane],
424         SingleReleaseCallback::Create(std::move(
425             resources.release_callbacks[media::VideoFrame::kAPlane])));
426   }
427 
428   std::vector<ResourceId> resource_ids_to_transfer;
429   resource_ids_to_transfer.push_back(resource_y);
430   resource_ids_to_transfer.push_back(resource_u);
431   resource_ids_to_transfer.push_back(resource_v);
432   if (with_alpha)
433     resource_ids_to_transfer.push_back(resource_a);
434   // Transfer resources to the parent, and get the resource map.
435   std::unordered_map<ResourceId, ResourceId> resource_map =
436       cc::SendResourceAndGetChildToParentMap(
437           resource_ids_to_transfer, resource_provider, child_resource_provider,
438           child_context_provider);
439 
440   ResourceId mapped_resource_y = resource_map[resource_y];
441   ResourceId mapped_resource_u = resource_map[resource_u];
442   ResourceId mapped_resource_v = resource_map[resource_v];
443   ResourceId mapped_resource_a = 0;
444   if (with_alpha)
445     mapped_resource_a = resource_map[resource_a];
446   const gfx::Size ya_tex_size = video_frame->coded_size();
447   const gfx::Size uv_tex_size = media::VideoFrame::PlaneSize(
448       video_frame->format(), media::VideoFrame::kUPlane,
449       video_frame->coded_size());
450   DCHECK(uv_tex_size == media::VideoFrame::PlaneSize(
451                             video_frame->format(), media::VideoFrame::kVPlane,
452                             video_frame->coded_size()));
453   if (with_alpha) {
454     DCHECK(ya_tex_size == media::VideoFrame::PlaneSize(
455                               video_frame->format(), media::VideoFrame::kAPlane,
456                               video_frame->coded_size()));
457   }
458 
459   gfx::RectF ya_tex_coord_rect(tex_coord_rect.x() * ya_tex_size.width(),
460                                tex_coord_rect.y() * ya_tex_size.height(),
461                                tex_coord_rect.width() * ya_tex_size.width(),
462                                tex_coord_rect.height() * ya_tex_size.height());
463   gfx::RectF uv_tex_coord_rect(tex_coord_rect.x() * uv_tex_size.width(),
464                                tex_coord_rect.y() * uv_tex_size.height(),
465                                tex_coord_rect.width() * uv_tex_size.width(),
466                                tex_coord_rect.height() * uv_tex_size.height());
467 
468   auto* yuv_quad = render_pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>();
469   uint32_t bits_per_channel = 8;
470   if (video_frame->format() == media::PIXEL_FORMAT_YUV420P10 ||
471       video_frame->format() == media::PIXEL_FORMAT_YUV422P10 ||
472       video_frame->format() == media::PIXEL_FORMAT_YUV444P10) {
473     bits_per_channel = 10;
474   }
475 
476   ResourceFormat yuv_highbit_resource_format =
477       video_resource_updater->YuvResourceFormat(bits_per_channel);
478 
479   float offset = 0.0f;
480   float multiplier = 1.0f;
481 
482   if (yuv_highbit_resource_format == R16_EXT) {
483     multiplier = 65535.0f / ((1 << bits_per_channel) - 1);
484   } else if (yuv_highbit_resource_format == LUMINANCE_F16) {
485     std::unique_ptr<media::HalfFloatMaker> half_float_maker =
486         media::HalfFloatMaker::NewHalfFloatMaker(bits_per_channel);
487     offset = half_float_maker->Offset();
488     multiplier = half_float_maker->Multiplier();
489   } else {
490     bits_per_channel = 8;
491   }
492 
493   yuv_quad->SetNew(shared_state, rect, visible_rect, needs_blending,
494                    ya_tex_coord_rect, uv_tex_coord_rect, ya_tex_size,
495                    uv_tex_size, mapped_resource_y, mapped_resource_u,
496                    mapped_resource_v, mapped_resource_a, video_color_space,
497                    offset, multiplier, bits_per_channel);
498 }
499 
CreateTestY16TextureDrawQuad_FromVideoFrame(const SharedQuadState * shared_state,scoped_refptr<media::VideoFrame> video_frame,const gfx::RectF & tex_coord_rect,AggregatedRenderPass * render_pass,media::VideoResourceUpdater * video_resource_updater,const gfx::Rect & rect,const gfx::Rect & visible_rect,DisplayResourceProvider * resource_provider,ClientResourceProvider * child_resource_provider,ContextProvider * child_context_provider)500 void CreateTestY16TextureDrawQuad_FromVideoFrame(
501     const SharedQuadState* shared_state,
502     scoped_refptr<media::VideoFrame> video_frame,
503     const gfx::RectF& tex_coord_rect,
504     AggregatedRenderPass* render_pass,
505     media::VideoResourceUpdater* video_resource_updater,
506     const gfx::Rect& rect,
507     const gfx::Rect& visible_rect,
508     DisplayResourceProvider* resource_provider,
509     ClientResourceProvider* child_resource_provider,
510     ContextProvider* child_context_provider) {
511   media::VideoFrameExternalResources resources =
512       video_resource_updater->CreateExternalResourcesFromVideoFrame(
513           video_frame);
514 
515   EXPECT_EQ(media::VideoFrameResourceType::RGBA, resources.type);
516   EXPECT_EQ(1u, resources.resources.size());
517   EXPECT_EQ(1u, resources.release_callbacks.size());
518 
519   ResourceId resource_y = child_resource_provider->ImportResource(
520       resources.resources[0],
521       SingleReleaseCallback::Create(std::move(resources.release_callbacks[0])));
522 
523   // Transfer resources to the parent, and get the resource map.
524   std::unordered_map<ResourceId, ResourceId> resource_map =
525       cc::SendResourceAndGetChildToParentMap({resource_y}, resource_provider,
526                                              child_resource_provider,
527                                              child_context_provider);
528   ResourceId mapped_resource_y = resource_map[resource_y];
529 
530   auto* quad = render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
531   bool needs_blending = true;
532   float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
533   quad->SetNew(shared_state, rect, rect, needs_blending, mapped_resource_y,
534                false, tex_coord_rect.origin(), tex_coord_rect.bottom_right(),
535                SK_ColorBLACK, vertex_opacity, false, false,
536                /*secure_output_only=*/false, gfx::ProtectedVideoType::kClear);
537 }
538 
539 // Upshift video frame to 10 bit.
CreateHighbitVideoFrame(media::VideoFrame * video_frame)540 scoped_refptr<media::VideoFrame> CreateHighbitVideoFrame(
541     media::VideoFrame* video_frame) {
542   media::VideoPixelFormat format;
543   switch (video_frame->format()) {
544     case media::PIXEL_FORMAT_I420:
545       format = media::PIXEL_FORMAT_YUV420P10;
546       break;
547     case media::PIXEL_FORMAT_I422:
548       format = media::PIXEL_FORMAT_YUV422P10;
549       break;
550     case media::PIXEL_FORMAT_I444:
551       format = media::PIXEL_FORMAT_YUV444P10;
552       break;
553 
554     default:
555       NOTREACHED();
556       return nullptr;
557   }
558   scoped_refptr<media::VideoFrame> ret = media::VideoFrame::CreateFrame(
559       format, video_frame->coded_size(), video_frame->visible_rect(),
560       video_frame->natural_size(), video_frame->timestamp());
561 
562   // Copy all metadata.
563   ret->metadata()->MergeMetadataFrom(video_frame->metadata());
564 
565   for (int plane = media::VideoFrame::kYPlane;
566        plane <= media::VideoFrame::kVPlane; ++plane) {
567     int width = video_frame->row_bytes(plane);
568     const uint8_t* src = video_frame->data(plane);
569     uint16_t* dst = reinterpret_cast<uint16_t*>(ret->data(plane));
570     for (int row = 0; row < video_frame->rows(plane); row++) {
571       for (int x = 0; x < width; x++) {
572         // Replicate the top bits into the lower bits, this way
573         // 0xFF becomes 0x3FF.
574         dst[x] = (src[x] << 2) | (src[x] >> 6);
575       }
576       src += video_frame->stride(plane);
577       dst += ret->stride(plane) / 2;
578     }
579   }
580   return ret;
581 }
582 
CreateTestYUVVideoDrawQuad_Striped(const SharedQuadState * shared_state,media::VideoPixelFormat format,gfx::ColorSpace color_space,bool is_transparent,bool highbit,const gfx::RectF & tex_coord_rect,AggregatedRenderPass * render_pass,media::VideoResourceUpdater * video_resource_updater,const gfx::Rect & rect,const gfx::Rect & visible_rect,DisplayResourceProvider * resource_provider,ClientResourceProvider * child_resource_provider,ContextProvider * child_context_provider)583 void CreateTestYUVVideoDrawQuad_Striped(
584     const SharedQuadState* shared_state,
585     media::VideoPixelFormat format,
586     gfx::ColorSpace color_space,
587     bool is_transparent,
588     bool highbit,
589     const gfx::RectF& tex_coord_rect,
590     AggregatedRenderPass* render_pass,
591     media::VideoResourceUpdater* video_resource_updater,
592     const gfx::Rect& rect,
593     const gfx::Rect& visible_rect,
594     DisplayResourceProvider* resource_provider,
595     ClientResourceProvider* child_resource_provider,
596     ContextProvider* child_context_provider) {
597   scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame(
598       format, rect.size(), rect, rect.size(), base::TimeDelta());
599 
600   // YUV values representing a striped pattern, for validating texture
601   // coordinates for sampling.
602   uint8_t y_value = 0;
603   uint8_t u_value = 0;
604   uint8_t v_value = 0;
605   for (int i = 0; i < video_frame->rows(media::VideoFrame::kYPlane); ++i) {
606     uint8_t* y_row = video_frame->data(media::VideoFrame::kYPlane) +
607                      video_frame->stride(media::VideoFrame::kYPlane) * i;
608     for (int j = 0; j < video_frame->row_bytes(media::VideoFrame::kYPlane);
609          ++j) {
610       y_row[j] = (y_value += 1);
611     }
612   }
613   for (int i = 0; i < video_frame->rows(media::VideoFrame::kUPlane); ++i) {
614     uint8_t* u_row = video_frame->data(media::VideoFrame::kUPlane) +
615                      video_frame->stride(media::VideoFrame::kUPlane) * i;
616     uint8_t* v_row = video_frame->data(media::VideoFrame::kVPlane) +
617                      video_frame->stride(media::VideoFrame::kVPlane) * i;
618     for (int j = 0; j < video_frame->row_bytes(media::VideoFrame::kUPlane);
619          ++j) {
620       u_row[j] = (u_value += 3);
621       v_row[j] = (v_value += 5);
622     }
623   }
624   uint8_t alpha_value = is_transparent ? 0 : 128;
625 
626   if (highbit)
627     video_frame = CreateHighbitVideoFrame(video_frame.get());
628   video_frame->set_color_space(color_space);
629 
630   CreateTestYUVVideoDrawQuad_FromVideoFrame(
631       shared_state, video_frame, alpha_value, tex_coord_rect, render_pass,
632       video_resource_updater, rect, visible_rect, resource_provider,
633       child_resource_provider, child_context_provider);
634 }
635 
636 // Creates a video frame of size background_size filled with yuv_background,
637 // and then draws a foreground rectangle in a different color on top of
638 // that. The foreground rectangle must have coordinates that are divisible
639 // by 2 because YUV is a block format.
CreateTestYUVVideoDrawQuad_TwoColor(const SharedQuadState * shared_state,media::VideoPixelFormat format,gfx::ColorSpace color_space,bool is_transparent,const gfx::RectF & tex_coord_rect,const gfx::Size & background_size,const gfx::Rect & visible_rect,uint8_t y_background,uint8_t u_background,uint8_t v_background,const gfx::Rect & foreground_rect,uint8_t y_foreground,uint8_t u_foreground,uint8_t v_foreground,AggregatedRenderPass * render_pass,media::VideoResourceUpdater * video_resource_updater,DisplayResourceProvider * resource_provider,ClientResourceProvider * child_resource_provider,ContextProvider * child_context_provider)640 void CreateTestYUVVideoDrawQuad_TwoColor(
641     const SharedQuadState* shared_state,
642     media::VideoPixelFormat format,
643     gfx::ColorSpace color_space,
644     bool is_transparent,
645     const gfx::RectF& tex_coord_rect,
646     const gfx::Size& background_size,
647     const gfx::Rect& visible_rect,
648     uint8_t y_background,
649     uint8_t u_background,
650     uint8_t v_background,
651     const gfx::Rect& foreground_rect,
652     uint8_t y_foreground,
653     uint8_t u_foreground,
654     uint8_t v_foreground,
655     AggregatedRenderPass* render_pass,
656     media::VideoResourceUpdater* video_resource_updater,
657     DisplayResourceProvider* resource_provider,
658     ClientResourceProvider* child_resource_provider,
659     ContextProvider* child_context_provider) {
660   const gfx::Rect rect(background_size);
661 
662   scoped_refptr<media::VideoFrame> video_frame =
663       media::VideoFrame::CreateFrame(format, background_size, foreground_rect,
664                                      foreground_rect.size(), base::TimeDelta());
665   video_frame->set_color_space(color_space);
666 
667   int planes[] = {media::VideoFrame::kYPlane, media::VideoFrame::kUPlane,
668                   media::VideoFrame::kVPlane};
669   uint8_t yuv_background[] = {y_background, u_background, v_background};
670   uint8_t yuv_foreground[] = {y_foreground, u_foreground, v_foreground};
671   int sample_size[] = {1, 2, 2};
672 
673   for (int i = 0; i < 3; ++i) {
674     memset(video_frame->data(planes[i]), yuv_background[i],
675            video_frame->stride(planes[i]) * video_frame->rows(planes[i]));
676   }
677 
678   for (int i = 0; i < 3; ++i) {
679     // Since yuv encoding uses block encoding, widths have to be divisible
680     // by the sample size in order for this function to behave properly.
681     DCHECK_EQ(foreground_rect.x() % sample_size[i], 0);
682     DCHECK_EQ(foreground_rect.y() % sample_size[i], 0);
683     DCHECK_EQ(foreground_rect.width() % sample_size[i], 0);
684     DCHECK_EQ(foreground_rect.height() % sample_size[i], 0);
685 
686     gfx::Rect sample_rect(foreground_rect.x() / sample_size[i],
687                           foreground_rect.y() / sample_size[i],
688                           foreground_rect.width() / sample_size[i],
689                           foreground_rect.height() / sample_size[i]);
690     for (int y = sample_rect.y(); y < sample_rect.bottom(); ++y) {
691       for (int x = sample_rect.x(); x < sample_rect.right(); ++x) {
692         size_t offset = y * video_frame->stride(planes[i]) + x;
693         video_frame->data(planes[i])[offset] = yuv_foreground[i];
694       }
695     }
696   }
697 
698   uint8_t alpha_value = 255;
699   CreateTestYUVVideoDrawQuad_FromVideoFrame(
700       shared_state, video_frame, alpha_value, tex_coord_rect, render_pass,
701       video_resource_updater, rect, visible_rect, resource_provider,
702       child_resource_provider, child_context_provider);
703 }
704 
CreateTestYUVVideoDrawQuad_Solid(const SharedQuadState * shared_state,media::VideoPixelFormat format,const gfx::ColorSpace & color_space,bool is_transparent,const gfx::RectF & tex_coord_rect,uint8_t y,uint8_t u,uint8_t v,AggregatedRenderPass * render_pass,media::VideoResourceUpdater * video_resource_updater,const gfx::Rect & rect,const gfx::Rect & visible_rect,DisplayResourceProvider * resource_provider,ClientResourceProvider * child_resource_provider,ContextProvider * child_context_provider)705 void CreateTestYUVVideoDrawQuad_Solid(
706     const SharedQuadState* shared_state,
707     media::VideoPixelFormat format,
708     const gfx::ColorSpace& color_space,
709     bool is_transparent,
710     const gfx::RectF& tex_coord_rect,
711     uint8_t y,
712     uint8_t u,
713     uint8_t v,
714     AggregatedRenderPass* render_pass,
715     media::VideoResourceUpdater* video_resource_updater,
716     const gfx::Rect& rect,
717     const gfx::Rect& visible_rect,
718     DisplayResourceProvider* resource_provider,
719     ClientResourceProvider* child_resource_provider,
720     ContextProvider* child_context_provider) {
721   scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame(
722       format, rect.size(), rect, rect.size(), base::TimeDelta());
723   video_frame->set_color_space(color_space);
724 
725   // YUV values of a solid, constant, color. Useful for testing that color
726   // space/color range are being handled properly.
727   memset(video_frame->data(media::VideoFrame::kYPlane), y,
728          video_frame->stride(media::VideoFrame::kYPlane) *
729              video_frame->rows(media::VideoFrame::kYPlane));
730   memset(video_frame->data(media::VideoFrame::kUPlane), u,
731          video_frame->stride(media::VideoFrame::kUPlane) *
732              video_frame->rows(media::VideoFrame::kUPlane));
733   memset(video_frame->data(media::VideoFrame::kVPlane), v,
734          video_frame->stride(media::VideoFrame::kVPlane) *
735              video_frame->rows(media::VideoFrame::kVPlane));
736 
737   uint8_t alpha_value = is_transparent ? 0 : 128;
738   CreateTestYUVVideoDrawQuad_FromVideoFrame(
739       shared_state, video_frame, alpha_value, tex_coord_rect, render_pass,
740       video_resource_updater, rect, visible_rect, resource_provider,
741       child_resource_provider, child_context_provider);
742 }
743 
CreateTestYUVVideoDrawQuad_NV12(const SharedQuadState * shared_state,const gfx::ColorSpace & color_space,const gfx::RectF & tex_coord_rect,uint8_t y,uint8_t u,uint8_t v,AggregatedRenderPass * render_pass,media::VideoResourceUpdater * video_resource_updater,const gfx::Rect & rect,const gfx::Rect & visible_rect,DisplayResourceProvider * resource_provider,ClientResourceProvider * child_resource_provider,scoped_refptr<ContextProvider> child_context_provider)744 void CreateTestYUVVideoDrawQuad_NV12(
745     const SharedQuadState* shared_state,
746     const gfx::ColorSpace& color_space,
747     const gfx::RectF& tex_coord_rect,
748     uint8_t y,
749     uint8_t u,
750     uint8_t v,
751     AggregatedRenderPass* render_pass,
752     media::VideoResourceUpdater* video_resource_updater,
753     const gfx::Rect& rect,
754     const gfx::Rect& visible_rect,
755     DisplayResourceProvider* resource_provider,
756     ClientResourceProvider* child_resource_provider,
757     scoped_refptr<ContextProvider> child_context_provider) {
758   bool needs_blending = true;
759   const gfx::Size ya_tex_size = rect.size();
760   const gfx::Size uv_tex_size = media::VideoFrame::PlaneSize(
761       media::PIXEL_FORMAT_NV12, media::VideoFrame::kUVPlane, rect.size());
762 
763   std::vector<uint8_t> y_pixels(ya_tex_size.GetArea(), y);
764   ResourceId resource_y = CreateGpuResource(
765       child_context_provider, child_resource_provider, ya_tex_size,
766       video_resource_updater->YuvResourceFormat(8), color_space, y_pixels);
767 
768   // U goes in the R component and V goes in the G component.
769   uint32_t rgba_pixel = (u << 24) | (v << 16);
770   std::vector<uint32_t> uv_pixels(uv_tex_size.GetArea(), rgba_pixel);
771   ResourceId resource_u = CreateGpuResource(
772       child_context_provider, child_resource_provider, uv_tex_size, RGBA_8888,
773       color_space, MakePixelSpan(uv_pixels));
774   ResourceId resource_v = resource_u;
775   ResourceId resource_a = 0;
776 
777   // Transfer resources to the parent, and get the resource map.
778   std::unordered_map<ResourceId, ResourceId> resource_map =
779       cc::SendResourceAndGetChildToParentMap(
780           {resource_y, resource_u, resource_v}, resource_provider,
781           child_resource_provider, child_context_provider.get());
782 
783   ResourceId mapped_resource_y = resource_map[resource_y];
784   ResourceId mapped_resource_u = resource_map[resource_u];
785   ResourceId mapped_resource_v = resource_map[resource_v];
786 
787   gfx::RectF ya_tex_coord_rect(tex_coord_rect.x() * ya_tex_size.width(),
788                                tex_coord_rect.y() * ya_tex_size.height(),
789                                tex_coord_rect.width() * ya_tex_size.width(),
790                                tex_coord_rect.height() * ya_tex_size.height());
791   gfx::RectF uv_tex_coord_rect(tex_coord_rect.x() * uv_tex_size.width(),
792                                tex_coord_rect.y() * uv_tex_size.height(),
793                                tex_coord_rect.width() * uv_tex_size.width(),
794                                tex_coord_rect.height() * uv_tex_size.height());
795 
796   auto* yuv_quad = render_pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>();
797   yuv_quad->SetNew(shared_state, rect, visible_rect, needs_blending,
798                    ya_tex_coord_rect, uv_tex_coord_rect, ya_tex_size,
799                    uv_tex_size, mapped_resource_y, mapped_resource_u,
800                    mapped_resource_v, resource_a, color_space, 0.0f, 1.0f, 8);
801 }
802 
CreateTestY16TextureDrawQuad_TwoColor(const SharedQuadState * shared_state,const gfx::RectF & tex_coord_rect,uint8_t g_foreground,uint8_t g_background,AggregatedRenderPass * render_pass,media::VideoResourceUpdater * video_resource_updater,const gfx::Rect & rect,const gfx::Rect & visible_rect,const gfx::Rect & foreground_rect,DisplayResourceProvider * resource_provider,ClientResourceProvider * child_resource_provider,ContextProvider * child_context_provider)803 void CreateTestY16TextureDrawQuad_TwoColor(
804     const SharedQuadState* shared_state,
805     const gfx::RectF& tex_coord_rect,
806     uint8_t g_foreground,
807     uint8_t g_background,
808     AggregatedRenderPass* render_pass,
809     media::VideoResourceUpdater* video_resource_updater,
810     const gfx::Rect& rect,
811     const gfx::Rect& visible_rect,
812     const gfx::Rect& foreground_rect,
813     DisplayResourceProvider* resource_provider,
814     ClientResourceProvider* child_resource_provider,
815     ContextProvider* child_context_provider) {
816   std::unique_ptr<unsigned char, base::AlignedFreeDeleter> memory(
817       static_cast<unsigned char*>(
818           base::AlignedAlloc(rect.size().GetArea() * 2,
819                              media::VideoFrame::kFrameAddressAlignment)));
820   scoped_refptr<media::VideoFrame> video_frame =
821       media::VideoFrame::WrapExternalData(
822           media::PIXEL_FORMAT_Y16, rect.size(), visible_rect,
823           visible_rect.size(), memory.get(), rect.size().GetArea() * 2,
824           base::TimeDelta());
825   DCHECK_EQ(video_frame->rows(0) % 2, 0);
826   DCHECK_EQ(video_frame->stride(0) % 2, 0);
827 
828   for (int j = 0; j < video_frame->rows(0); ++j) {
829     uint8_t* row = video_frame->data(0) + j * video_frame->stride(0);
830     if (j < foreground_rect.y() || j >= foreground_rect.bottom()) {
831       for (int i = 0; i < video_frame->stride(0) / 2; ++i) {
832         *row++ = i & 0xFF;  // Fill R with anything. It is not rendered.
833         *row++ = g_background;
834       }
835     } else {
836       for (int i = 0;
837            i < std::min(video_frame->stride(0) / 2, foreground_rect.x()); ++i) {
838         *row++ = i & 0xFF;
839         *row++ = g_background;
840       }
841       for (int i = foreground_rect.x();
842            i < std::min(video_frame->stride(0) / 2, foreground_rect.right());
843            ++i) {
844         *row++ = i & 0xFF;
845         *row++ = g_foreground;
846       }
847       for (int i = foreground_rect.right(); i < video_frame->stride(0) / 2;
848            ++i) {
849         *row++ = i & 0xFF;
850         *row++ = g_background;
851       }
852     }
853   }
854 
855   CreateTestY16TextureDrawQuad_FromVideoFrame(
856       shared_state, video_frame, tex_coord_rect, render_pass,
857       video_resource_updater, rect, visible_rect, resource_provider,
858       child_resource_provider, child_context_provider);
859 }
860 
861 // Create two quads of specified colors on half-pixel boundaries.
CreateTestAxisAlignedQuads(const gfx::Rect & rect,SkColor front_color,SkColor back_color,bool needs_blending,bool force_aa_off,AggregatedRenderPass * pass)862 void CreateTestAxisAlignedQuads(const gfx::Rect& rect,
863                                 SkColor front_color,
864                                 SkColor back_color,
865                                 bool needs_blending,
866                                 bool force_aa_off,
867                                 AggregatedRenderPass* pass) {
868   gfx::Transform front_quad_to_target_transform;
869   front_quad_to_target_transform.Translate(50, 50);
870   front_quad_to_target_transform.Scale(0.5f + 1.0f / (rect.width() * 2.0f),
871                                        0.5f + 1.0f / (rect.height() * 2.0f));
872   SharedQuadState* front_shared_state = CreateTestSharedQuadState(
873       front_quad_to_target_transform, rect, pass, gfx::RRectF());
874 
875   auto* front = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
876   front->SetAll(front_shared_state, rect, rect, needs_blending, front_color,
877                 force_aa_off);
878 
879   gfx::Transform back_quad_to_target_transform;
880   back_quad_to_target_transform.Translate(25.5f, 25.5f);
881   back_quad_to_target_transform.Scale(0.5f, 0.5f);
882   SharedQuadState* back_shared_state = CreateTestSharedQuadState(
883       back_quad_to_target_transform, rect, pass, gfx::RRectF());
884 
885   auto* back = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
886   back->SetAll(back_shared_state, rect, rect, needs_blending, back_color,
887                force_aa_off);
888 }
889 
890 using RendererPixelTest = VizPixelTestWithParam;
891 INSTANTIATE_TEST_SUITE_P(,
892                          RendererPixelTest,
893                          testing::ValuesIn(GetRendererTypes()),
894                          testing::PrintToStringParamName());
895 
896 // Test GLRenderer as well as SkiaRenderer.
897 using GPURendererPixelTest = VizPixelTestWithParam;
898 INSTANTIATE_TEST_SUITE_P(,
899                          GPURendererPixelTest,
900                          // TODO(crbug.com/1021566): Enable these tests for
901                          // SkiaRenderer Dawn once video is supported.
902                          testing::ValuesIn(GetGpuRendererTypesNoDawn()),
903                          testing::PrintToStringParamName());
904 
905 // Provides an exact comparator for GLRenderer and fuzzy comparator for Skia
906 // based (eg. SoftwareRenderer and SkiaRenderer).
907 class FuzzyForSkiaOnlyPixelComparator : public cc::PixelComparator {
908  public:
FuzzyForSkiaOnlyPixelComparator(RendererType type)909   explicit FuzzyForSkiaOnlyPixelComparator(RendererType type) {
910     if (type == RendererType::kGL) {
911       comparator_ = std::make_unique<cc::ExactPixelComparator>(false);
912     } else {
913       comparator_ = std::make_unique<cc::FuzzyPixelOffByOneComparator>(false);
914     }
915   }
916 
Compare(const SkBitmap & actual_bmp,const SkBitmap & expected_bmp) const917   bool Compare(const SkBitmap& actual_bmp,
918                const SkBitmap& expected_bmp) const override {
919     return comparator_->Compare(actual_bmp, expected_bmp);
920   }
921 
922  private:
923   std::unique_ptr<cc::PixelComparator> comparator_;
924 };
925 
TEST_P(RendererPixelTest,SimpleGreenRect)926 TEST_P(RendererPixelTest, SimpleGreenRect) {
927   gfx::Rect rect(this->device_viewport_size_);
928 
929   AggregatedRenderPassId id{1};
930   auto pass = CreateTestRootRenderPass(id, rect);
931 
932   SharedQuadState* shared_state = CreateTestSharedQuadState(
933       gfx::Transform(), rect, pass.get(), gfx::RRectF());
934 
935   auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
936   color_quad->SetNew(shared_state, rect, rect, SK_ColorGREEN, false);
937 
938   AggregatedRenderPassList pass_list;
939   pass_list.push_back(std::move(pass));
940 
941   EXPECT_TRUE(this->RunPixelTest(&pass_list,
942                                  base::FilePath(FILE_PATH_LITERAL("green.png")),
943                                  cc::ExactPixelComparator(true)));
944 }
945 
TEST_P(RendererPixelTest,SimpleGreenRectNonRootRenderPass)946 TEST_P(RendererPixelTest, SimpleGreenRectNonRootRenderPass) {
947   gfx::Rect rect(this->device_viewport_size_);
948   gfx::Rect small_rect(100, 100);
949 
950   AggregatedRenderPassId child_id{2};
951   auto child_pass =
952       CreateTestRenderPass(child_id, small_rect, gfx::Transform());
953 
954   SharedQuadState* child_shared_state = CreateTestSharedQuadState(
955       gfx::Transform(), small_rect, child_pass.get(), gfx::RRectF());
956 
957   auto* color_quad = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
958   color_quad->SetNew(child_shared_state, rect, rect, SK_ColorGREEN, false);
959 
960   AggregatedRenderPassId root_id{1};
961   auto root_pass = CreateTestRenderPass(root_id, rect, gfx::Transform());
962 
963   SharedQuadState* root_shared_state = CreateTestSharedQuadState(
964       gfx::Transform(), rect, root_pass.get(), gfx::RRectF());
965 
966   CreateTestRenderPassDrawQuad(root_shared_state, small_rect, child_id,
967                                root_pass.get());
968 
969   auto* child_pass_ptr = child_pass.get();
970 
971   AggregatedRenderPassList pass_list;
972   pass_list.push_back(std::move(child_pass));
973   pass_list.push_back(std::move(root_pass));
974 
975   EXPECT_TRUE(this->RunPixelTestWithReadbackTarget(
976       &pass_list, child_pass_ptr,
977       base::FilePath(FILE_PATH_LITERAL("green_small.png")),
978       cc::ExactPixelComparator(true)));
979 }
980 
TEST_P(RendererPixelTest,PremultipliedTextureWithoutBackground)981 TEST_P(RendererPixelTest, PremultipliedTextureWithoutBackground) {
982   gfx::Rect rect(this->device_viewport_size_);
983 
984   AggregatedRenderPassId id{1};
985   auto pass = CreateTestRootRenderPass(id, rect);
986 
987   SharedQuadState* shared_state = CreateTestSharedQuadState(
988       gfx::Transform(), rect, pass.get(), gfx::RRectF());
989 
990   CreateTestTextureDrawQuad(
991       !is_software_renderer(), gfx::Rect(this->device_viewport_size_),
992       SkColorSetARGB(128, 0, 255, 0),  // Texel color.
993       SK_ColorTRANSPARENT,             // Background color.
994       true,                            // Premultiplied alpha.
995       shared_state, this->resource_provider_.get(),
996       this->child_resource_provider_.get(), this->shared_bitmap_manager_.get(),
997       this->child_context_provider_, pass.get());
998 
999   auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1000   color_quad->SetNew(shared_state, rect, rect, SK_ColorWHITE, false);
1001 
1002   AggregatedRenderPassList pass_list;
1003   pass_list.push_back(std::move(pass));
1004 
1005   EXPECT_TRUE(this->RunPixelTest(
1006       &pass_list, base::FilePath(FILE_PATH_LITERAL("green_alpha.png")),
1007       cc::FuzzyPixelOffByOneComparator(true)));
1008 }
1009 
TEST_P(RendererPixelTest,PremultipliedTextureWithBackground)1010 TEST_P(RendererPixelTest, PremultipliedTextureWithBackground) {
1011   gfx::Rect rect(this->device_viewport_size_);
1012 
1013   AggregatedRenderPassId id{1};
1014   auto pass = CreateTestRootRenderPass(id, rect);
1015 
1016   SharedQuadState* texture_quad_state = CreateTestSharedQuadState(
1017       gfx::Transform(), rect, pass.get(), gfx::RRectF());
1018   texture_quad_state->opacity = 0.8f;
1019 
1020   CreateTestTextureDrawQuad(
1021       !is_software_renderer(), gfx::Rect(this->device_viewport_size_),
1022       SkColorSetARGB(204, 120, 255, 120),  // Texel color.
1023       SK_ColorGREEN,                       // Background color.
1024       true,                                // Premultiplied alpha.
1025       texture_quad_state, this->resource_provider_.get(),
1026       this->child_resource_provider_.get(), this->shared_bitmap_manager_.get(),
1027       this->child_context_provider_, pass.get());
1028 
1029   SharedQuadState* color_quad_state = CreateTestSharedQuadState(
1030       gfx::Transform(), rect, pass.get(), gfx::RRectF());
1031   auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1032   color_quad->SetNew(color_quad_state, rect, rect, SK_ColorWHITE, false);
1033 
1034   AggregatedRenderPassList pass_list;
1035   pass_list.push_back(std::move(pass));
1036 
1037   EXPECT_TRUE(this->RunPixelTest(
1038       &pass_list, base::FilePath(FILE_PATH_LITERAL("green_alpha.png")),
1039       cc::FuzzyPixelOffByOneComparator(true)));
1040 }
1041 
TEST_P(RendererPixelTest,TextureDrawQuadVisibleRectInsetTopLeft)1042 TEST_P(RendererPixelTest, TextureDrawQuadVisibleRectInsetTopLeft) {
1043   gfx::Rect rect(this->device_viewport_size_);
1044 
1045   AggregatedRenderPassId id{1};
1046   auto pass = CreateTestRootRenderPass(id, rect);
1047 
1048   SharedQuadState* texture_quad_state = CreateTestSharedQuadState(
1049       gfx::Transform(), rect, pass.get(), gfx::RRectF());
1050 
1051   CreateTestTwoColoredTextureDrawQuad(
1052       !is_software_renderer(), gfx::Rect(this->device_viewport_size_),
1053       SkColorSetARGB(0, 120, 255, 255),  // Texel color 1.
1054       SkColorSetARGB(204, 120, 0, 255),  // Texel color 2.
1055       SK_ColorGREEN,                     // Background color.
1056       true,                              // Premultiplied alpha.
1057       false,                             // flipped_texture_quad.
1058       false,                             // Half and half.
1059       texture_quad_state, this->resource_provider_.get(),
1060       this->child_resource_provider_.get(), this->shared_bitmap_manager_.get(),
1061       this->child_context_provider_, pass.get());
1062   pass->quad_list.front()->visible_rect.Inset(30, 50, 0, 0);
1063   SharedQuadState* color_quad_state = CreateTestSharedQuadState(
1064       gfx::Transform(), rect, pass.get(), gfx::RRectF());
1065   auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1066   color_quad->SetNew(color_quad_state, rect, rect, SK_ColorWHITE, false);
1067 
1068   AggregatedRenderPassList pass_list;
1069   pass_list.push_back(std::move(pass));
1070 
1071   EXPECT_TRUE(this->RunPixelTest(
1072       &pass_list, base::FilePath(FILE_PATH_LITERAL("inset_top_left.png")),
1073       cc::FuzzyPixelOffByOneComparator(true)));
1074 }
1075 
1076 // This tests drawing a TextureDrawQuad with a visible_rect strictly included in
1077 // rect, custom UVs, and rect.origin() that is not in the origin.
TEST_P(RendererPixelTest,TextureDrawQuadTranslatedAndVisibleRectInsetTopLeftAndCustomUV)1078 TEST_P(RendererPixelTest,
1079        TextureDrawQuadTranslatedAndVisibleRectInsetTopLeftAndCustomUV) {
1080   gfx::Rect rect(this->device_viewport_size_);
1081 
1082   AggregatedRenderPassId id{1};
1083   auto pass = CreateTestRootRenderPass(id, rect);
1084 
1085   SharedQuadState* texture_quad_state = CreateTestSharedQuadState(
1086       gfx::Transform(), rect, pass.get(), gfx::RRectF());
1087 
1088   CreateTestTwoColoredTextureDrawQuad(
1089       !is_software_renderer(), gfx::Rect(this->device_viewport_size_),
1090       SkColorSetARGB(0, 120, 255, 255),  // Texel color 1.
1091       SkColorSetARGB(204, 120, 0, 255),  // Texel color 2.
1092       SK_ColorGREEN,                     // Background color.
1093       true,                              // Premultiplied alpha.
1094       false,                             // flipped_texture_quad.
1095       false,                             // Half and half.
1096       texture_quad_state, this->resource_provider_.get(),
1097       this->child_resource_provider_.get(), this->shared_bitmap_manager_.get(),
1098       this->child_context_provider_, pass.get());
1099   auto* quad = static_cast<TextureDrawQuad*>(pass->quad_list.front());
1100   quad->rect.Offset(10, 10);
1101   quad->visible_rect.Offset(10, 10);
1102   quad->visible_rect.Inset(30, 50, 12, 12);
1103   quad->uv_top_left.SetPoint(.2, .3);
1104   quad->uv_bottom_right.SetPoint(.4, .7);
1105   quad->nearest_neighbor = true;  // To avoid bilinear filter differences.
1106   SharedQuadState* color_quad_state = CreateTestSharedQuadState(
1107       gfx::Transform(), rect, pass.get(), gfx::RRectF());
1108   auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1109   color_quad->SetNew(color_quad_state, rect, rect, SK_ColorWHITE, false);
1110 
1111   AggregatedRenderPassList pass_list;
1112   pass_list.push_back(std::move(pass));
1113 
1114   EXPECT_TRUE(this->RunPixelTest(
1115       &pass_list,
1116       base::FilePath(FILE_PATH_LITERAL("offset_inset_top_left.png")),
1117       cc::FuzzyPixelOffByOneComparator(true)));
1118 }
1119 
TEST_P(RendererPixelTest,TextureDrawQuadVisibleRectInsetBottomRight)1120 TEST_P(RendererPixelTest, TextureDrawQuadVisibleRectInsetBottomRight) {
1121   gfx::Rect rect(this->device_viewport_size_);
1122 
1123   AggregatedRenderPassId id{1};
1124   auto pass = CreateTestRootRenderPass(id, rect);
1125 
1126   SharedQuadState* texture_quad_state = CreateTestSharedQuadState(
1127       gfx::Transform(), rect, pass.get(), gfx::RRectF());
1128 
1129   CreateTestTwoColoredTextureDrawQuad(
1130       !is_software_renderer(), gfx::Rect(this->device_viewport_size_),
1131       SkColorSetARGB(0, 120, 255, 255),  // Texel color 1.
1132       SkColorSetARGB(204, 120, 0, 255),  // Texel color 2.
1133       SK_ColorGREEN,                     // Background color.
1134       true,                              // Premultiplied alpha.
1135       false,                             // flipped_texture_quad.
1136       false,                             // Half and half.
1137       texture_quad_state, this->resource_provider_.get(),
1138       this->child_resource_provider_.get(), this->shared_bitmap_manager_.get(),
1139       this->child_context_provider_, pass.get());
1140   pass->quad_list.front()->visible_rect.Inset(0, 0, 40, 60);
1141   SharedQuadState* color_quad_state = CreateTestSharedQuadState(
1142       gfx::Transform(), rect, pass.get(), gfx::RRectF());
1143   auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1144   color_quad->SetNew(color_quad_state, rect, rect, SK_ColorWHITE, false);
1145 
1146   AggregatedRenderPassList pass_list;
1147   pass_list.push_back(std::move(pass));
1148 
1149   EXPECT_TRUE(this->RunPixelTest(
1150       &pass_list, base::FilePath(FILE_PATH_LITERAL("inset_bottom_right.png")),
1151       cc::FuzzyPixelOffByOneComparator(true)));
1152 }
1153 
TEST_P(GPURendererPixelTest,SolidColorBlend)1154 TEST_P(GPURendererPixelTest, SolidColorBlend) {
1155   gfx::Rect rect(this->device_viewport_size_);
1156 
1157   AggregatedRenderPassId id{1};
1158   auto pass = CreateTestRootRenderPass(id, rect);
1159   pass->has_transparent_background = false;
1160 
1161   SharedQuadState* shared_state = CreateTestSharedQuadState(
1162       gfx::Transform(), rect, pass.get(), gfx::RRectF());
1163   shared_state->opacity = 1 - 16.0f / 255;
1164   shared_state->blend_mode = SkBlendMode::kDstOut;
1165 
1166   auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1167   color_quad->SetNew(shared_state, rect, rect, SK_ColorRED, false);
1168 
1169   SharedQuadState* shared_state_background = CreateTestSharedQuadState(
1170       gfx::Transform(), rect, pass.get(), gfx::RRectF());
1171 
1172   SkColor background_color = SkColorSetRGB(0xff, 0xff * 14 / 16, 0xff);
1173   auto* color_quad_background =
1174       pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1175   color_quad_background->SetNew(shared_state_background, rect, rect,
1176                                 background_color, false);
1177   // Result should be r=16, g=14, b=16.
1178 
1179   AggregatedRenderPassList pass_list;
1180   pass_list.push_back(std::move(pass));
1181 
1182   EXPECT_TRUE(this->RunPixelTest(
1183       &pass_list, base::FilePath(FILE_PATH_LITERAL("dark_grey.png")),
1184       cc::FuzzyPixelOffByOneComparator(/*discard_alpha=*/true)));
1185 }
1186 
TEST_P(GPURendererPixelTest,SolidColorWithTemperature)1187 TEST_P(GPURendererPixelTest, SolidColorWithTemperature) {
1188   gfx::Rect rect(this->device_viewport_size_);
1189 
1190   AggregatedRenderPassId id{1};
1191   auto pass = CreateTestRootRenderPass(id, rect);
1192 
1193   SharedQuadState* shared_state = CreateTestSharedQuadState(
1194       gfx::Transform(), rect, pass.get(), gfx::RRectF());
1195 
1196   auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1197   color_quad->SetNew(shared_state, rect, rect, SK_ColorYELLOW, false);
1198 
1199   AggregatedRenderPassList pass_list;
1200   pass_list.push_back(std::move(pass));
1201 
1202   SkMatrix44 color_matrix(SkMatrix44::kIdentity_Constructor);
1203   color_matrix.set(0, 0, 0.7f);
1204   color_matrix.set(1, 1, 0.4f);
1205   color_matrix.set(2, 2, 0.5f);
1206   this->output_surface_->set_color_matrix(color_matrix);
1207 
1208   EXPECT_TRUE(this->RunPixelTest(
1209       &pass_list, base::FilePath(FILE_PATH_LITERAL("temperature_brown.png")),
1210       cc::FuzzyPixelOffByOneComparator(true)));
1211 }
1212 
TEST_P(GPURendererPixelTest,SolidColorWithTemperatureNonRootRenderPass)1213 TEST_P(GPURendererPixelTest, SolidColorWithTemperatureNonRootRenderPass) {
1214   // Create a root and a child passes with two different solid color quads.
1215   AggregatedRenderPassList render_passes_in_draw_order;
1216   gfx::Rect viewport_rect(this->device_viewport_size_);
1217   gfx::Rect root_rect(0, 0, viewport_rect.width(), viewport_rect.height() / 2);
1218   gfx::Rect child_rect(0, root_rect.bottom(), viewport_rect.width(),
1219                        root_rect.height());
1220 
1221   // Child pass.
1222   AggregatedRenderPassId child_pass_id{2};
1223   AggregatedRenderPass* child_pass = cc::AddRenderPass(
1224       &render_passes_in_draw_order, child_pass_id, viewport_rect,
1225       gfx::Transform(), cc::FilterOperations());
1226   cc::AddQuad(child_pass, child_rect, SK_ColorGREEN);
1227 
1228   // Root pass.
1229   AggregatedRenderPassId root_pass_id{1};
1230   AggregatedRenderPass* root_pass = cc::AddRenderPass(
1231       &render_passes_in_draw_order, root_pass_id, viewport_rect,
1232       gfx::Transform(), cc::FilterOperations());
1233   cc::AddQuad(root_pass, root_rect, SK_ColorYELLOW);
1234 
1235   SharedQuadState* pass_shared_state = CreateTestSharedQuadState(
1236       gfx::Transform(), viewport_rect, root_pass, gfx::RRectF());
1237   CreateTestRenderPassDrawQuad(pass_shared_state, viewport_rect, child_pass_id,
1238                                root_pass);
1239 
1240   // Set a non-identity output color matrix on the output surface, and expect
1241   // that the colors will be transformed.
1242   SkMatrix44 color_matrix(SkMatrix44::kIdentity_Constructor);
1243   color_matrix.set(0, 0, 0.7f);
1244   color_matrix.set(1, 1, 0.4f);
1245   color_matrix.set(2, 2, 0.5f);
1246   this->output_surface_->set_color_matrix(color_matrix);
1247 
1248   EXPECT_TRUE(this->RunPixelTest(
1249       &render_passes_in_draw_order,
1250       base::FilePath(FILE_PATH_LITERAL("temperature_brown_non_root.png")),
1251       cc::FuzzyPixelOffByOneComparator(true)));
1252 }
1253 
TEST_P(GPURendererPixelTest,PremultipliedTextureWithBackgroundAndVertexOpacity)1254 TEST_P(GPURendererPixelTest,
1255        PremultipliedTextureWithBackgroundAndVertexOpacity) {
1256   gfx::Rect rect(this->device_viewport_size_);
1257 
1258   AggregatedRenderPassId id{1};
1259   auto pass = CreateTestRootRenderPass(id, rect);
1260 
1261   SharedQuadState* texture_quad_state = CreateTestSharedQuadState(
1262       gfx::Transform(), rect, pass.get(), gfx::RRectF());
1263   texture_quad_state->opacity = 0.8f;
1264 
1265   float vertex_opacity[4] = {1.f, 1.f, 0.f, 0.f};
1266   CreateTestTextureDrawQuad(
1267       !is_software_renderer(), gfx::Rect(this->device_viewport_size_),
1268       SkColorSetARGB(204, 120, 255, 120),  // Texel color.
1269       vertex_opacity,
1270       SK_ColorGREEN,  // Background color.
1271       true,           // Premultiplied alpha.
1272       texture_quad_state, this->resource_provider_.get(),
1273       this->child_resource_provider_.get(), this->shared_bitmap_manager_.get(),
1274       this->child_context_provider_, pass.get());
1275 
1276   SharedQuadState* color_quad_state = CreateTestSharedQuadState(
1277       gfx::Transform(), rect, pass.get(), gfx::RRectF());
1278   auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1279   color_quad->SetNew(color_quad_state, rect, rect, SK_ColorWHITE, false);
1280 
1281   AggregatedRenderPassList pass_list;
1282   pass_list.push_back(std::move(pass));
1283 
1284   EXPECT_TRUE(this->RunPixelTest(
1285       &pass_list,
1286       base::FilePath(FILE_PATH_LITERAL("green_alpha_vertex_opacity.png")),
1287       cc::FuzzyPixelOffByOneComparator(true)));
1288 }
1289 
1290 class IntersectingQuadPixelTest : public VizPixelTestWithParam {
1291  protected:
SetupQuadStateAndRenderPass()1292   void SetupQuadStateAndRenderPass() {
1293     // This sets up a pair of draw quads. They are both rotated
1294     // relative to the root plane, they are also rotated relative to each other.
1295     // The intersect in the middle at a non-perpendicular angle so that any
1296     // errors are hopefully magnified.
1297     // The quads should intersect correctly, as in the front quad should only
1298     // be partially in front of the back quad, and partially behind.
1299 
1300     viewport_rect_ = gfx::Rect(this->device_viewport_size_);
1301     quad_rect_ = gfx::Rect(0, 0, this->device_viewport_size_.width(),
1302                            this->device_viewport_size_.height() / 2.0);
1303 
1304     AggregatedRenderPassId id{1};
1305     render_pass_ = CreateTestRootRenderPass(id, viewport_rect_);
1306 
1307     // Create the front quad rotated on the Z and Y axis.
1308     gfx::Transform trans;
1309     trans.Translate3d(0, 0, 0.707 * this->device_viewport_size_.width() / 2.0);
1310     trans.RotateAboutZAxis(45.0);
1311     trans.RotateAboutYAxis(45.0);
1312     front_quad_state_ = CreateTestSharedQuadState(
1313         trans, viewport_rect_, render_pass_.get(), gfx::RRectF());
1314     front_quad_state_->clip_rect = quad_rect_;
1315     // Make sure they end up in a 3d sorting context.
1316     front_quad_state_->sorting_context_id = 1;
1317 
1318     // Create the back quad, and rotate on just the y axis. This will intersect
1319     // the first quad partially.
1320     trans = gfx::Transform();
1321     trans.Translate3d(0, 0, -0.707 * this->device_viewport_size_.width() / 2.0);
1322     trans.RotateAboutYAxis(-45.0);
1323     back_quad_state_ = CreateTestSharedQuadState(
1324         trans, viewport_rect_, render_pass_.get(), gfx::RRectF());
1325     back_quad_state_->sorting_context_id = 1;
1326     back_quad_state_->clip_rect = quad_rect_;
1327   }
AppendBackgroundAndRunTest(const cc::PixelComparator & comparator,const base::FilePath::CharType * ref_file)1328   void AppendBackgroundAndRunTest(const cc::PixelComparator& comparator,
1329                                   const base::FilePath::CharType* ref_file) {
1330     SharedQuadState* background_quad_state = CreateTestSharedQuadState(
1331         gfx::Transform(), viewport_rect_, render_pass_.get(), gfx::RRectF());
1332     auto* background_quad =
1333         render_pass_->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1334     background_quad->SetNew(background_quad_state, viewport_rect_,
1335                             viewport_rect_, SK_ColorWHITE, false);
1336     pass_list_.push_back(std::move(render_pass_));
1337     EXPECT_TRUE(
1338         this->RunPixelTest(&pass_list_, base::FilePath(ref_file), comparator));
1339   }
1340   template <typename T>
CreateAndAppendDrawQuad()1341   T* CreateAndAppendDrawQuad() {
1342     return render_pass_->CreateAndAppendDrawQuad<T>();
1343   }
1344 
1345   std::unique_ptr<AggregatedRenderPass> render_pass_;
1346   gfx::Rect viewport_rect_;
1347   SharedQuadState* front_quad_state_;
1348   SharedQuadState* back_quad_state_;
1349   gfx::Rect quad_rect_;
1350   AggregatedRenderPassList pass_list_;
1351 };
1352 
1353 INSTANTIATE_TEST_SUITE_P(,
1354                          IntersectingQuadPixelTest,
1355                          testing::ValuesIn(GetRendererTypes()),
1356                          testing::PrintToStringParamName());
1357 
1358 class IntersectingVideoQuadPixelTest : public IntersectingQuadPixelTest {
1359  public:
SetUp()1360   void SetUp() override {
1361     IntersectingQuadPixelTest::SetUp();
1362     constexpr bool kUseStreamVideoDrawQuad = false;
1363     constexpr bool kUseGpuMemoryBufferResources = false;
1364     constexpr bool kUseR16Texture = false;
1365     constexpr int kMaxResourceSize = 10000;
1366 
1367     video_resource_updater_ = std::make_unique<media::VideoResourceUpdater>(
1368         this->child_context_provider_.get(),
1369         /*raster_context_provider=*/nullptr, nullptr,
1370         this->child_resource_provider_.get(), kUseStreamVideoDrawQuad,
1371         kUseGpuMemoryBufferResources, kUseR16Texture, kMaxResourceSize);
1372     video_resource_updater2_ = std::make_unique<media::VideoResourceUpdater>(
1373         this->child_context_provider_.get(),
1374         /*raster_context_provider=*/nullptr, nullptr,
1375         this->child_resource_provider_.get(), kUseStreamVideoDrawQuad,
1376         kUseGpuMemoryBufferResources, kUseR16Texture, kMaxResourceSize);
1377   }
1378 
1379  protected:
1380   std::unique_ptr<media::VideoResourceUpdater> video_resource_updater_;
1381   std::unique_ptr<media::VideoResourceUpdater> video_resource_updater2_;
1382 };
1383 
1384 INSTANTIATE_TEST_SUITE_P(,
1385                          IntersectingVideoQuadPixelTest,
1386                          // TODO(crbug.com/1021566): Enable these tests for
1387                          // SkiaRenderer Dawn once video is supported.
1388                          testing::ValuesIn(GetGpuRendererTypesNoDawn()),
1389                          testing::PrintToStringParamName());
1390 
1391 class IntersectingQuadSoftwareTest : public IntersectingQuadPixelTest {};
1392 
1393 INSTANTIATE_TEST_SUITE_P(,
1394                          IntersectingQuadSoftwareTest,
1395                          testing::Values(RendererType::kSoftware),
1396                          testing::PrintToStringParamName());
1397 
TEST_P(IntersectingQuadPixelTest,SolidColorQuads)1398 TEST_P(IntersectingQuadPixelTest, SolidColorQuads) {
1399   // TODO(crbug.com/1021566): Enable this test for SkiaRenderer Dawn.
1400   if (renderer_type() == RendererType::kSkiaDawn)
1401     return;
1402 
1403   this->SetupQuadStateAndRenderPass();
1404 
1405   auto* quad = this->template CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1406   auto* quad2 = this->template CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1407 
1408   quad->SetNew(this->front_quad_state_, this->quad_rect_, this->quad_rect_,
1409                SK_ColorBLUE, false);
1410   quad2->SetNew(this->back_quad_state_, this->quad_rect_, this->quad_rect_,
1411                 SK_ColorGREEN, false);
1412   this->AppendBackgroundAndRunTest(
1413       cc::FuzzyPixelComparator(false, 2.f, 0.f, 256.f, 256, 0.f),
1414       FILE_PATH_LITERAL("intersecting_blue_green.png"));
1415 }
1416 
TEST_P(IntersectingQuadPixelTest,TexturedQuads)1417 TEST_P(IntersectingQuadPixelTest, TexturedQuads) {
1418   this->SetupQuadStateAndRenderPass();
1419   CreateTestTwoColoredTextureDrawQuad(
1420       !is_software_renderer(), this->quad_rect_, SkColorSetARGB(255, 0, 0, 0),
1421       SkColorSetARGB(255, 0, 0, 255), SK_ColorTRANSPARENT,
1422       true /* premultiplied_alpha */, false /* flipped_texture_quad */,
1423       false /* half_and_half */, this->front_quad_state_,
1424       this->resource_provider_.get(), this->child_resource_provider_.get(),
1425       this->shared_bitmap_manager_.get(), this->child_context_provider_,
1426       this->render_pass_.get());
1427   CreateTestTwoColoredTextureDrawQuad(
1428       !is_software_renderer(), this->quad_rect_, SkColorSetARGB(255, 0, 255, 0),
1429       SkColorSetARGB(255, 0, 0, 0), SK_ColorTRANSPARENT,
1430       true /* premultiplied_alpha */, false /* flipped_texture_quad */,
1431       false /* half_and_half */, this->back_quad_state_,
1432       this->resource_provider_.get(), this->child_resource_provider_.get(),
1433       this->shared_bitmap_manager_.get(), this->child_context_provider_,
1434       this->render_pass_.get());
1435 
1436   this->AppendBackgroundAndRunTest(
1437       cc::FuzzyPixelComparator(false, 2.f, 0.f, 256.f, 256, 0.f),
1438       FILE_PATH_LITERAL("intersecting_blue_green_squares.png"));
1439 }
1440 
TEST_P(IntersectingQuadPixelTest,NonFlippedTexturedQuads)1441 TEST_P(IntersectingQuadPixelTest, NonFlippedTexturedQuads) {
1442   this->SetupQuadStateAndRenderPass();
1443   CreateTestTwoColoredTextureDrawQuad(
1444       !is_software_renderer(), this->quad_rect_, SkColorSetARGB(255, 0, 0, 0),
1445       SkColorSetARGB(255, 0, 0, 255), SK_ColorTRANSPARENT,
1446       true /* premultiplied_alpha */, false /* flipped_texture_quad */,
1447       true /* half_and_half */, this->front_quad_state_,
1448       this->resource_provider_.get(), this->child_resource_provider_.get(),
1449       this->shared_bitmap_manager_.get(), this->child_context_provider_,
1450       this->render_pass_.get());
1451   CreateTestTwoColoredTextureDrawQuad(
1452       !is_software_renderer(), this->quad_rect_, SkColorSetARGB(255, 0, 255, 0),
1453       SkColorSetARGB(255, 0, 0, 0), SK_ColorTRANSPARENT,
1454       true /* premultiplied_alpha */, false /* flipped_texture_quad */,
1455       true /* half_and_half */, this->back_quad_state_,
1456       this->resource_provider_.get(), this->child_resource_provider_.get(),
1457       this->shared_bitmap_manager_.get(), this->child_context_provider_,
1458       this->render_pass_.get());
1459 
1460   this->AppendBackgroundAndRunTest(
1461       cc::FuzzyPixelComparator(false, 2.f, 0.f, 256.f, 256, 0.f),
1462       FILE_PATH_LITERAL(
1463           "intersecting_non_flipped_blue_green_half_size_rectangles.png"));
1464 }
1465 
TEST_P(IntersectingQuadPixelTest,FlippedTexturedQuads)1466 TEST_P(IntersectingQuadPixelTest, FlippedTexturedQuads) {
1467   this->SetupQuadStateAndRenderPass();
1468   CreateTestTwoColoredTextureDrawQuad(
1469       !is_software_renderer(), this->quad_rect_, SkColorSetARGB(255, 0, 0, 0),
1470       SkColorSetARGB(255, 0, 0, 255), SK_ColorTRANSPARENT,
1471       true /* premultiplied_alpha */, true /* flipped_texture_quad */,
1472       true /* half_and_half */, this->front_quad_state_,
1473       this->resource_provider_.get(), this->child_resource_provider_.get(),
1474       this->shared_bitmap_manager_.get(), this->child_context_provider_,
1475       this->render_pass_.get());
1476   CreateTestTwoColoredTextureDrawQuad(
1477       !is_software_renderer(), this->quad_rect_, SkColorSetARGB(255, 0, 255, 0),
1478       SkColorSetARGB(255, 0, 0, 0), SK_ColorTRANSPARENT,
1479       true /* premultiplied_alpha */, true /* flipped_texture_quad */,
1480       true /* half_and_half */, this->back_quad_state_,
1481       this->resource_provider_.get(), this->child_resource_provider_.get(),
1482       this->shared_bitmap_manager_.get(), this->child_context_provider_,
1483       this->render_pass_.get());
1484 
1485   this->AppendBackgroundAndRunTest(
1486       cc::FuzzyPixelComparator(false, 2.f, 0.f, 256.f, 256, 0.f),
1487       FILE_PATH_LITERAL(
1488           "intersecting_flipped_blue_green_half_size_rectangles.png"));
1489 }
1490 
TEST_P(IntersectingQuadSoftwareTest,PictureQuads)1491 TEST_P(IntersectingQuadSoftwareTest, PictureQuads) {
1492   bool needs_blending = true;
1493   this->SetupQuadStateAndRenderPass();
1494   gfx::Rect outer_rect(this->quad_rect_);
1495   gfx::Rect inner_rect(this->quad_rect_.x() + (this->quad_rect_.width() / 4),
1496                        this->quad_rect_.y() + (this->quad_rect_.height() / 4),
1497                        this->quad_rect_.width() / 2,
1498                        this->quad_rect_.height() / 2);
1499 
1500   cc::PaintFlags black_flags;
1501   black_flags.setColor(SK_ColorBLACK);
1502   cc::PaintFlags blue_flags;
1503   blue_flags.setColor(SK_ColorBLUE);
1504   cc::PaintFlags green_flags;
1505   green_flags.setColor(SK_ColorGREEN);
1506 
1507   std::unique_ptr<cc::FakeRecordingSource> blue_recording =
1508       cc::FakeRecordingSource::CreateFilledRecordingSource(
1509           this->quad_rect_.size());
1510   blue_recording->add_draw_rect_with_flags(outer_rect, black_flags);
1511   blue_recording->add_draw_rect_with_flags(inner_rect, blue_flags);
1512   blue_recording->Rerecord();
1513   scoped_refptr<cc::RasterSource> blue_raster_source =
1514       blue_recording->CreateRasterSource();
1515 
1516   auto* blue_quad =
1517       this->render_pass_->template CreateAndAppendDrawQuad<PictureDrawQuad>();
1518 
1519   blue_quad->SetNew(this->front_quad_state_, this->quad_rect_, this->quad_rect_,
1520                     needs_blending, gfx::RectF(this->quad_rect_),
1521                     this->quad_rect_.size(), false, RGBA_8888, this->quad_rect_,
1522                     1.f, {}, blue_raster_source->GetDisplayItemList());
1523 
1524   std::unique_ptr<cc::FakeRecordingSource> green_recording =
1525       cc::FakeRecordingSource::CreateFilledRecordingSource(
1526           this->quad_rect_.size());
1527   green_recording->add_draw_rect_with_flags(outer_rect, green_flags);
1528   green_recording->add_draw_rect_with_flags(inner_rect, black_flags);
1529   green_recording->Rerecord();
1530   scoped_refptr<cc::RasterSource> green_raster_source =
1531       green_recording->CreateRasterSource();
1532 
1533   auto* green_quad =
1534       this->render_pass_->template CreateAndAppendDrawQuad<PictureDrawQuad>();
1535   green_quad->SetNew(this->back_quad_state_, this->quad_rect_, this->quad_rect_,
1536                      needs_blending, gfx::RectF(this->quad_rect_),
1537                      this->quad_rect_.size(), false, RGBA_8888,
1538                      this->quad_rect_, 1.f, {},
1539                      green_raster_source->GetDisplayItemList());
1540   this->AppendBackgroundAndRunTest(
1541       cc::FuzzyPixelComparator(false, 2.f, 0.f, 256.f, 256, 0.f),
1542       FILE_PATH_LITERAL("intersecting_blue_green_squares.png"));
1543 }
1544 
TEST_P(IntersectingQuadPixelTest,RenderPassQuads)1545 TEST_P(IntersectingQuadPixelTest, RenderPassQuads) {
1546   this->SetupQuadStateAndRenderPass();
1547   AggregatedRenderPassId child_pass_id1{2};
1548   AggregatedRenderPassId child_pass_id2{3};
1549   auto child_pass1 =
1550       CreateTestRenderPass(child_pass_id1, this->quad_rect_, gfx::Transform());
1551   SharedQuadState* child1_quad_state = CreateTestSharedQuadState(
1552       gfx::Transform(), this->quad_rect_, child_pass1.get(), gfx::RRectF());
1553   auto child_pass2 =
1554       CreateTestRenderPass(child_pass_id2, this->quad_rect_, gfx::Transform());
1555   SharedQuadState* child2_quad_state = CreateTestSharedQuadState(
1556       gfx::Transform(), this->quad_rect_, child_pass2.get(), gfx::RRectF());
1557   CreateTestTwoColoredTextureDrawQuad(
1558       !is_software_renderer(), this->quad_rect_, SkColorSetARGB(255, 0, 0, 0),
1559       SkColorSetARGB(255, 0, 0, 255), SK_ColorTRANSPARENT,
1560       true /* premultiplied_alpha */, false /* flipped_texture_quad */,
1561       false /* half_and_half */, child1_quad_state,
1562       this->resource_provider_.get(), this->child_resource_provider_.get(),
1563       this->shared_bitmap_manager_.get(), this->child_context_provider_,
1564       child_pass1.get());
1565   CreateTestTwoColoredTextureDrawQuad(
1566       !is_software_renderer(), this->quad_rect_, SkColorSetARGB(255, 0, 255, 0),
1567       SkColorSetARGB(255, 0, 0, 0), SK_ColorTRANSPARENT,
1568       true /* premultiplied_alpha */, false /* flipped_texture_quad */,
1569       false /* half_and_half */, child2_quad_state,
1570       this->resource_provider_.get(), this->child_resource_provider_.get(),
1571       this->shared_bitmap_manager_.get(), this->child_context_provider_,
1572       child_pass2.get());
1573 
1574   CreateTestRenderPassDrawQuad(this->front_quad_state_, this->quad_rect_,
1575                                child_pass_id1, this->render_pass_.get());
1576   CreateTestRenderPassDrawQuad(this->back_quad_state_, this->quad_rect_,
1577                                child_pass_id2, this->render_pass_.get());
1578 
1579   this->pass_list_.push_back(std::move(child_pass1));
1580   this->pass_list_.push_back(std::move(child_pass2));
1581   this->AppendBackgroundAndRunTest(
1582       cc::FuzzyPixelComparator(false, 2.f, 0.f, 256.f, 256, 0.f),
1583       FILE_PATH_LITERAL("intersecting_blue_green_squares.png"));
1584 }
1585 
TEST_P(IntersectingVideoQuadPixelTest,YUVVideoQuads)1586 TEST_P(IntersectingVideoQuadPixelTest, YUVVideoQuads) {
1587   this->SetupQuadStateAndRenderPass();
1588   gfx::Rect inner_rect(
1589       ((this->quad_rect_.x() + (this->quad_rect_.width() / 4)) & ~0xF),
1590       ((this->quad_rect_.y() + (this->quad_rect_.height() / 4)) & ~0xF),
1591       (this->quad_rect_.width() / 2) & ~0xF,
1592       (this->quad_rect_.height() / 2) & ~0xF);
1593 
1594   CreateTestYUVVideoDrawQuad_TwoColor(
1595       this->front_quad_state_, media::PIXEL_FORMAT_I420,
1596       gfx::ColorSpace::CreateJpeg(), false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f),
1597       this->quad_rect_.size(), this->quad_rect_, 0, 128, 128, inner_rect, 29,
1598       255, 107, this->render_pass_.get(), this->video_resource_updater_.get(),
1599       this->resource_provider_.get(), this->child_resource_provider_.get(),
1600       this->child_context_provider_.get());
1601 
1602   CreateTestYUVVideoDrawQuad_TwoColor(
1603       this->back_quad_state_, media::PIXEL_FORMAT_I420,
1604       gfx::ColorSpace::CreateJpeg(), false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f),
1605       this->quad_rect_.size(), this->quad_rect_, 149, 43, 21, inner_rect, 0,
1606       128, 128, this->render_pass_.get(), this->video_resource_updater2_.get(),
1607       this->resource_provider_.get(), this->child_resource_provider_.get(),
1608       this->child_context_provider_.get());
1609 
1610   this->AppendBackgroundAndRunTest(
1611       cc::FuzzyPixelComparator(true, 0.50f, 0.f, 1.2f, 2, 0),
1612       FILE_PATH_LITERAL("intersecting_blue_green_squares_video.png"));
1613 }
1614 
TEST_P(IntersectingVideoQuadPixelTest,Y16VideoQuads)1615 TEST_P(IntersectingVideoQuadPixelTest, Y16VideoQuads) {
1616   this->SetupQuadStateAndRenderPass();
1617   gfx::Rect inner_rect(
1618       ((this->quad_rect_.x() + (this->quad_rect_.width() / 4)) & ~0xF),
1619       ((this->quad_rect_.y() + (this->quad_rect_.height() / 4)) & ~0xF),
1620       (this->quad_rect_.width() / 2) & ~0xF,
1621       (this->quad_rect_.height() / 2) & ~0xF);
1622 
1623   CreateTestY16TextureDrawQuad_TwoColor(
1624       this->front_quad_state_, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 18, 0,
1625       this->render_pass_.get(), this->video_resource_updater_.get(),
1626       this->quad_rect_, this->quad_rect_, inner_rect,
1627       this->resource_provider_.get(), this->child_resource_provider_.get(),
1628       this->child_context_provider_.get());
1629 
1630   CreateTestY16TextureDrawQuad_TwoColor(
1631       this->back_quad_state_, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 0, 182,
1632       this->render_pass_.get(), this->video_resource_updater2_.get(),
1633       this->quad_rect_, this->quad_rect_, inner_rect,
1634       this->resource_provider_.get(), this->child_resource_provider_.get(),
1635       this->child_context_provider_.get());
1636 
1637   this->AppendBackgroundAndRunTest(
1638       cc::FuzzyPixelOffByOneComparator(false),
1639       FILE_PATH_LITERAL("intersecting_light_dark_squares_video.png"));
1640 }
1641 
1642 // TODO(skaslev): The software renderer does not support non-premultplied alpha.
TEST_P(GPURendererPixelTest,NonPremultipliedTextureWithoutBackground)1643 TEST_P(GPURendererPixelTest, NonPremultipliedTextureWithoutBackground) {
1644   gfx::Rect rect(this->device_viewport_size_);
1645 
1646   AggregatedRenderPassId id{1};
1647   auto pass = CreateTestRootRenderPass(id, rect);
1648 
1649   SharedQuadState* shared_state = CreateTestSharedQuadState(
1650       gfx::Transform(), rect, pass.get(), gfx::RRectF());
1651 
1652   CreateTestTextureDrawQuad(
1653       !is_software_renderer(), gfx::Rect(this->device_viewport_size_),
1654       SkColorSetARGB(128, 0, 255, 0),  // Texel color.
1655       SK_ColorTRANSPARENT,             // Background color.
1656       false,                           // Premultiplied alpha.
1657       shared_state, this->resource_provider_.get(),
1658       this->child_resource_provider_.get(), this->shared_bitmap_manager_.get(),
1659       this->child_context_provider_, pass.get());
1660 
1661   auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1662   color_quad->SetNew(shared_state, rect, rect, SK_ColorWHITE, false);
1663 
1664   AggregatedRenderPassList pass_list;
1665   pass_list.push_back(std::move(pass));
1666 
1667   EXPECT_TRUE(this->RunPixelTest(
1668       &pass_list, base::FilePath(FILE_PATH_LITERAL("green_alpha.png")),
1669       cc::FuzzyPixelOffByOneComparator(true)));
1670 }
1671 
1672 // TODO(skaslev): The software renderer does not support non-premultplied alpha.
TEST_P(GPURendererPixelTest,NonPremultipliedTextureWithBackground)1673 TEST_P(GPURendererPixelTest, NonPremultipliedTextureWithBackground) {
1674   gfx::Rect rect(this->device_viewport_size_);
1675 
1676   AggregatedRenderPassId id{1};
1677   auto pass = CreateTestRootRenderPass(id, rect);
1678 
1679   SharedQuadState* texture_quad_state = CreateTestSharedQuadState(
1680       gfx::Transform(), rect, pass.get(), gfx::RRectF());
1681   texture_quad_state->opacity = 0.8f;
1682 
1683   CreateTestTextureDrawQuad(
1684       !is_software_renderer(), gfx::Rect(this->device_viewport_size_),
1685       SkColorSetARGB(204, 120, 255, 120),  // Texel color.
1686       SK_ColorGREEN,                       // Background color.
1687       false,                               // Premultiplied alpha.
1688       texture_quad_state, this->resource_provider_.get(),
1689       this->child_resource_provider_.get(), this->shared_bitmap_manager_.get(),
1690       this->child_context_provider_, pass.get());
1691 
1692   SharedQuadState* color_quad_state = CreateTestSharedQuadState(
1693       gfx::Transform(), rect, pass.get(), gfx::RRectF());
1694   auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
1695   color_quad->SetNew(color_quad_state, rect, rect, SK_ColorWHITE, false);
1696 
1697   AggregatedRenderPassList pass_list;
1698   pass_list.push_back(std::move(pass));
1699 
1700   EXPECT_TRUE(this->RunPixelTest(
1701       &pass_list, base::FilePath(FILE_PATH_LITERAL("green_alpha.png")),
1702       cc::FuzzyPixelOffByOneComparator(true)));
1703 }
1704 
1705 class VideoRendererPixelTestBase : public VizPixelTest {
1706  public:
VideoRendererPixelTestBase(RendererType type)1707   explicit VideoRendererPixelTestBase(RendererType type) : VizPixelTest(type) {}
1708 
1709  protected:
1710   // Include the protected member variables from the parent class.
1711   using cc::PixelTest::child_context_provider_;
1712   using cc::PixelTest::child_resource_provider_;
1713   using cc::PixelTest::resource_provider_;
1714 
CreateEdgeBleedPass(media::VideoPixelFormat format,const gfx::ColorSpace & color_space,AggregatedRenderPassList * pass_list)1715   void CreateEdgeBleedPass(media::VideoPixelFormat format,
1716                            const gfx::ColorSpace& color_space,
1717                            AggregatedRenderPassList* pass_list) {
1718     gfx::Rect rect(200, 200);
1719 
1720     AggregatedRenderPassId id{1};
1721     auto pass = CreateTestRootRenderPass(id, rect);
1722 
1723     // Scale the video up so that bilinear filtering kicks in to sample more
1724     // than just nearest neighbor would.
1725     gfx::Transform scale_by_2;
1726     scale_by_2.Scale(2.f, 2.f);
1727     gfx::Rect half_rect(100, 100);
1728     SharedQuadState* shared_state = CreateTestSharedQuadState(
1729         scale_by_2, half_rect, pass.get(), gfx::RRectF());
1730 
1731     gfx::Size background_size(200, 200);
1732     gfx::Rect green_rect(16, 20, 100, 100);
1733     gfx::RectF tex_coord_rect(
1734         static_cast<float>(green_rect.x()) / background_size.width(),
1735         static_cast<float>(green_rect.y()) / background_size.height(),
1736         static_cast<float>(green_rect.width()) / background_size.width(),
1737         static_cast<float>(green_rect.height()) / background_size.height());
1738 
1739     // YUV of (149,43,21) should be green (0,255,0) in RGB.
1740     // Create a video frame that has a non-green background rect, with a
1741     // green sub-rectangle that should be the only thing displayed in
1742     // the final image.  Bleeding will appear on all four sides of the video
1743     // if the tex coords are not clamped.
1744     CreateTestYUVVideoDrawQuad_TwoColor(
1745         shared_state, format, color_space, false, tex_coord_rect,
1746         background_size, gfx::Rect(background_size), 128, 128, 128, green_rect,
1747         149, 43, 21, pass.get(), video_resource_updater_.get(),
1748         resource_provider_.get(), child_resource_provider_.get(),
1749         child_context_provider_.get());
1750     pass_list->push_back(std::move(pass));
1751   }
1752 
SetUp()1753   void SetUp() override {
1754     VizPixelTest::SetUp();
1755     constexpr bool kUseStreamVideoDrawQuad = false;
1756     constexpr bool kUseGpuMemoryBufferResources = false;
1757     constexpr bool kUseR16Texture = false;
1758     constexpr int kMaxResourceSize = 10000;
1759     video_resource_updater_ = std::make_unique<media::VideoResourceUpdater>(
1760         child_context_provider_.get(), nullptr, nullptr,
1761         child_resource_provider_.get(), kUseStreamVideoDrawQuad,
1762         kUseGpuMemoryBufferResources, kUseR16Texture, kMaxResourceSize);
1763   }
1764 
TearDown()1765   void TearDown() override {
1766     video_resource_updater_ = nullptr;
1767     VizPixelTest::TearDown();
1768   }
1769 
1770   std::unique_ptr<media::VideoResourceUpdater> video_resource_updater_;
1771 };
1772 
1773 #if BUILDFLAG(ENABLE_GL_BACKEND_TESTS)
1774 class VideoRendererPixelHiLoTest
1775     : public VideoRendererPixelTestBase,
1776       public testing::WithParamInterface<std::tuple<RendererType, bool>> {
1777  public:
VideoRendererPixelHiLoTest()1778   VideoRendererPixelHiLoTest()
1779       : VideoRendererPixelTestBase(std::get<0>(GetParam())) {}
1780 
IsHighbit() const1781   bool IsHighbit() const { return std::get<1>(GetParam()); }
1782 };
1783 
1784 INSTANTIATE_TEST_SUITE_P(
1785     ,
1786     VideoRendererPixelHiLoTest,
1787     testing::Combine(testing::Values(RendererType::kGL, RendererType::kSkiaGL),
1788                      testing::Bool()),
1789     cc::PrintTupleToStringParamName());
1790 
TEST_P(VideoRendererPixelHiLoTest,SimpleYUVRect)1791 TEST_P(VideoRendererPixelHiLoTest, SimpleYUVRect) {
1792   gfx::Rect rect(this->device_viewport_size_);
1793 
1794   AggregatedRenderPassId id{1};
1795   auto pass = CreateTestRootRenderPass(id, rect);
1796   // Set the output color space to match the input primaries and transfer.
1797   this->display_color_spaces_ = kRec601DisplayColorSpaces;
1798 
1799   SharedQuadState* shared_state = CreateTestSharedQuadState(
1800       gfx::Transform(), rect, pass.get(), gfx::RRectF());
1801 
1802   CreateTestYUVVideoDrawQuad_Striped(
1803       shared_state, media::PIXEL_FORMAT_I420, gfx::ColorSpace::CreateREC601(),
1804       false, IsHighbit(), gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), pass.get(),
1805       this->video_resource_updater_.get(), rect, rect,
1806       this->resource_provider_.get(), this->child_resource_provider_.get(),
1807       this->child_context_provider_.get());
1808 
1809   AggregatedRenderPassList pass_list;
1810   pass_list.push_back(std::move(pass));
1811 
1812   EXPECT_TRUE(this->RunPixelTest(
1813       &pass_list, base::FilePath(FILE_PATH_LITERAL("yuv_stripes.png")),
1814       cc::FuzzyPixelOffByOneComparator(true)));
1815 }
1816 
TEST_P(VideoRendererPixelHiLoTest,ClippedYUVRect)1817 TEST_P(VideoRendererPixelHiLoTest, ClippedYUVRect) {
1818   gfx::Rect viewport(this->device_viewport_size_);
1819   gfx::Rect draw_rect(this->device_viewport_size_.width() * 1.5,
1820                       this->device_viewport_size_.height() * 1.5);
1821 
1822   AggregatedRenderPassId id{1};
1823   auto pass = CreateTestRootRenderPass(id, viewport);
1824   // Set the output color space to match the input primaries and transfer.
1825   this->display_color_spaces_ = kRec601DisplayColorSpaces;
1826 
1827   SharedQuadState* shared_state = CreateTestSharedQuadState(
1828       gfx::Transform(), viewport, pass.get(), gfx::RRectF());
1829 
1830   CreateTestYUVVideoDrawQuad_Striped(
1831       shared_state, media::PIXEL_FORMAT_I420, gfx::ColorSpace::CreateREC601(),
1832       false, IsHighbit(), gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), pass.get(),
1833       this->video_resource_updater_.get(), draw_rect, viewport,
1834       this->resource_provider_.get(), this->child_resource_provider_.get(),
1835       this->child_context_provider_.get());
1836   AggregatedRenderPassList pass_list;
1837   pass_list.push_back(std::move(pass));
1838 
1839   EXPECT_TRUE(this->RunPixelTest(
1840       &pass_list, base::FilePath(FILE_PATH_LITERAL("yuv_stripes_clipped.png")),
1841       cc::FuzzyPixelOffByOneComparator(true)));
1842 }
1843 #endif  // #if BUILDFLAG(ENABLE_GL_BACKEND_TESTS)
1844 
1845 class VideoRendererPixelTest
1846     : public VideoRendererPixelTestBase,
1847       public testing::WithParamInterface<RendererType> {
1848  public:
VideoRendererPixelTest()1849   VideoRendererPixelTest() : VideoRendererPixelTestBase(GetParam()) {}
1850 };
1851 
1852 INSTANTIATE_TEST_SUITE_P(,
1853                          VideoRendererPixelTest,
1854                          // TODO(crbug.com/1021566): Enable these tests for
1855                          // SkiaRenderer Dawn once video is supported.
1856                          testing::ValuesIn(GetGpuRendererTypesNoDawn()),
1857                          testing::PrintToStringParamName());
1858 
TEST_P(VideoRendererPixelTest,OffsetYUVRect)1859 TEST_P(VideoRendererPixelTest, OffsetYUVRect) {
1860   gfx::Rect rect(this->device_viewport_size_);
1861 
1862   AggregatedRenderPassId id{1};
1863   auto pass = CreateTestRootRenderPass(id, rect);
1864   // Set the output color space to match the input primaries and transfer.
1865   this->display_color_spaces_ = kRec601DisplayColorSpaces;
1866 
1867   SharedQuadState* shared_state = CreateTestSharedQuadState(
1868       gfx::Transform(), rect, pass.get(), gfx::RRectF());
1869 
1870   // Intentionally sets frame format to I420 for testing coverage.
1871   CreateTestYUVVideoDrawQuad_Striped(
1872       shared_state, media::PIXEL_FORMAT_I420, gfx::ColorSpace::CreateREC601(),
1873       false, false, gfx::RectF(0.125f, 0.25f, 0.75f, 0.5f), pass.get(),
1874       this->video_resource_updater_.get(), rect, rect,
1875       this->resource_provider_.get(), this->child_resource_provider_.get(),
1876       this->child_context_provider_.get());
1877 
1878   AggregatedRenderPassList pass_list;
1879   pass_list.push_back(std::move(pass));
1880 
1881   EXPECT_TRUE(this->RunPixelTest(
1882       &pass_list, base::FilePath(FILE_PATH_LITERAL("yuv_stripes_offset.png")),
1883       cc::FuzzyPixelComparator(true, 100.0f, 1.0f, 1.0f, 1, 0)));
1884 }
1885 
TEST_P(VideoRendererPixelTest,SimpleYUVRectBlack)1886 TEST_P(VideoRendererPixelTest, SimpleYUVRectBlack) {
1887   gfx::Rect rect(this->device_viewport_size_);
1888 
1889   AggregatedRenderPassId id{1};
1890   auto pass = CreateTestRootRenderPass(id, rect);
1891   // Set the output color space to match the input primaries and transfer.
1892   this->display_color_spaces_ = kRec601DisplayColorSpaces;
1893 
1894   SharedQuadState* shared_state = CreateTestSharedQuadState(
1895       gfx::Transform(), rect, pass.get(), gfx::RRectF());
1896 
1897   // In MPEG color range YUV values of (15,128,128) should produce black.
1898   CreateTestYUVVideoDrawQuad_Solid(
1899       shared_state, media::PIXEL_FORMAT_I420, gfx::ColorSpace::CreateREC601(),
1900       false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 15, 128, 128, pass.get(),
1901       this->video_resource_updater_.get(), rect, rect,
1902       this->resource_provider_.get(), this->child_resource_provider_.get(),
1903       this->child_context_provider_.get());
1904 
1905   AggregatedRenderPassList pass_list;
1906   pass_list.push_back(std::move(pass));
1907 
1908   // If we didn't get black out of the YUV values above, then we probably have a
1909   // color range issue.
1910   EXPECT_TRUE(this->RunPixelTest(&pass_list,
1911                                  base::FilePath(FILE_PATH_LITERAL("black.png")),
1912                                  cc::FuzzyPixelOffByOneComparator(true)));
1913 }
1914 
TEST_P(VideoRendererPixelTest,SimpleYUVJRect)1915 TEST_P(VideoRendererPixelTest, SimpleYUVJRect) {
1916   gfx::Rect rect(this->device_viewport_size_);
1917 
1918   AggregatedRenderPassId id{1};
1919   auto pass = CreateTestRootRenderPass(id, rect);
1920 
1921   SharedQuadState* shared_state = CreateTestSharedQuadState(
1922       gfx::Transform(), rect, pass.get(), gfx::RRectF());
1923 
1924   // YUV of (149,43,21) should be green (0,255,0) in RGB.
1925   CreateTestYUVVideoDrawQuad_Solid(
1926       shared_state, media::PIXEL_FORMAT_I420, gfx::ColorSpace::CreateJpeg(),
1927       false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 149, 43, 21, pass.get(),
1928       this->video_resource_updater_.get(), rect, rect,
1929       this->resource_provider_.get(), this->child_resource_provider_.get(),
1930       this->child_context_provider_.get());
1931 
1932   AggregatedRenderPassList pass_list;
1933   pass_list.push_back(std::move(pass));
1934 
1935   EXPECT_TRUE(this->RunPixelTest(&pass_list,
1936                                  base::FilePath(FILE_PATH_LITERAL("green.png")),
1937                                  cc::FuzzyPixelOffByOneComparator(true)));
1938 }
1939 
TEST_P(VideoRendererPixelTest,SimpleNV12JRect)1940 TEST_P(VideoRendererPixelTest, SimpleNV12JRect) {
1941   gfx::Rect rect(this->device_viewport_size_);
1942 
1943   AggregatedRenderPassId id{1};
1944   auto pass = CreateTestRootRenderPass(id, rect);
1945 
1946   SharedQuadState* shared_state = CreateTestSharedQuadState(
1947       gfx::Transform(), rect, pass.get(), gfx::RRectF());
1948 
1949   // YUV of (149,43,21) should be green (0,255,0) in RGB.
1950   CreateTestYUVVideoDrawQuad_NV12(
1951       shared_state, gfx::ColorSpace::CreateJpeg(),
1952       gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 149, 43, 21, pass.get(),
1953       this->video_resource_updater_.get(), rect, rect,
1954       this->resource_provider_.get(), this->child_resource_provider_.get(),
1955       this->child_context_provider_);
1956 
1957   AggregatedRenderPassList pass_list;
1958   pass_list.push_back(std::move(pass));
1959 
1960   EXPECT_TRUE(this->RunPixelTest(&pass_list,
1961                                  base::FilePath(FILE_PATH_LITERAL("green.png")),
1962                                  cc::FuzzyPixelOffByOneComparator(true)));
1963 }
1964 
1965 // Test that a YUV video doesn't bleed outside of its tex coords when the
1966 // tex coord rect is only a partial subrectangle of the coded contents.
TEST_P(VideoRendererPixelTest,YUVEdgeBleed)1967 TEST_P(VideoRendererPixelTest, YUVEdgeBleed) {
1968   AggregatedRenderPassList pass_list;
1969   this->CreateEdgeBleedPass(media::PIXEL_FORMAT_I420,
1970                             gfx::ColorSpace::CreateJpeg(), &pass_list);
1971   EXPECT_TRUE(this->RunPixelTest(&pass_list,
1972                                  base::FilePath(FILE_PATH_LITERAL("green.png")),
1973                                  cc::FuzzyPixelOffByOneComparator(true)));
1974 }
1975 
TEST_P(VideoRendererPixelTest,YUVAEdgeBleed)1976 TEST_P(VideoRendererPixelTest, YUVAEdgeBleed) {
1977   AggregatedRenderPassList pass_list;
1978   this->CreateEdgeBleedPass(media::PIXEL_FORMAT_I420A,
1979                             gfx::ColorSpace::CreateREC601(), &pass_list);
1980   // Set the output color space to match the input primaries and transfer.
1981   this->display_color_spaces_ = kRec601DisplayColorSpaces;
1982   EXPECT_TRUE(this->RunPixelTest(&pass_list,
1983                                  base::FilePath(FILE_PATH_LITERAL("green.png")),
1984                                  cc::FuzzyPixelOffByOneComparator(true)));
1985 }
1986 
TEST_P(VideoRendererPixelTest,SimpleYUVJRectGrey)1987 TEST_P(VideoRendererPixelTest, SimpleYUVJRectGrey) {
1988   gfx::Rect rect(this->device_viewport_size_);
1989 
1990   AggregatedRenderPassId id{1};
1991   auto pass = CreateTestRootRenderPass(id, rect);
1992 
1993   SharedQuadState* shared_state = CreateTestSharedQuadState(
1994       gfx::Transform(), rect, pass.get(), gfx::RRectF());
1995 
1996   // Dark grey in JPEG color range (in MPEG, this is black).
1997   CreateTestYUVVideoDrawQuad_Solid(
1998       shared_state, media::PIXEL_FORMAT_I420, gfx::ColorSpace::CreateJpeg(),
1999       false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 15, 128, 128, pass.get(),
2000       this->video_resource_updater_.get(), rect, rect,
2001       this->resource_provider_.get(), this->child_resource_provider_.get(),
2002       this->child_context_provider_.get());
2003 
2004   AggregatedRenderPassList pass_list;
2005   pass_list.push_back(std::move(pass));
2006 
2007   EXPECT_TRUE(this->RunPixelTest(
2008       &pass_list, base::FilePath(FILE_PATH_LITERAL("dark_grey.png")),
2009       cc::FuzzyPixelOffByOneComparator(true)));
2010 }
2011 
TEST_P(VideoRendererPixelTest,SimpleYUVARect)2012 TEST_P(VideoRendererPixelTest, SimpleYUVARect) {
2013   gfx::Rect rect(this->device_viewport_size_);
2014 
2015   AggregatedRenderPassId id{1};
2016   auto pass = CreateTestRootRenderPass(id, rect);
2017   // Set the output color space to match the input primaries and transfer.
2018   this->display_color_spaces_ = kRec601DisplayColorSpaces;
2019 
2020   SharedQuadState* shared_state = CreateTestSharedQuadState(
2021       gfx::Transform(), rect, pass.get(), gfx::RRectF());
2022 
2023   CreateTestYUVVideoDrawQuad_Striped(
2024       shared_state, media::PIXEL_FORMAT_I420A, gfx::ColorSpace::CreateREC601(),
2025       false, false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), pass.get(),
2026       this->video_resource_updater_.get(), rect, rect,
2027       this->resource_provider_.get(), this->child_resource_provider_.get(),
2028       this->child_context_provider_.get());
2029 
2030   auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2031   color_quad->SetNew(shared_state, rect, rect, SK_ColorWHITE, false);
2032 
2033   AggregatedRenderPassList pass_list;
2034   pass_list.push_back(std::move(pass));
2035 
2036   EXPECT_TRUE(this->RunPixelTest(
2037       &pass_list, base::FilePath(FILE_PATH_LITERAL("yuv_stripes_alpha.png")),
2038       cc::FuzzyPixelOffByOneComparator(true)));
2039 }
2040 
TEST_P(VideoRendererPixelTest,FullyTransparentYUVARect)2041 TEST_P(VideoRendererPixelTest, FullyTransparentYUVARect) {
2042   gfx::Rect rect(this->device_viewport_size_);
2043 
2044   AggregatedRenderPassId id{1};
2045   auto pass = CreateTestRootRenderPass(id, rect);
2046   // Set the output color space to match the input primaries and transfer.
2047   this->display_color_spaces_ = kRec601DisplayColorSpaces;
2048 
2049   SharedQuadState* shared_state = CreateTestSharedQuadState(
2050       gfx::Transform(), rect, pass.get(), gfx::RRectF());
2051 
2052   CreateTestYUVVideoDrawQuad_Striped(
2053       shared_state, media::PIXEL_FORMAT_I420A, gfx::ColorSpace::CreateREC601(),
2054       true, false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), pass.get(),
2055       this->video_resource_updater_.get(), rect, rect,
2056       this->resource_provider_.get(), this->child_resource_provider_.get(),
2057       this->child_context_provider_.get());
2058 
2059   auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2060   color_quad->SetNew(shared_state, rect, rect, SK_ColorBLACK, false);
2061 
2062   AggregatedRenderPassList pass_list;
2063   pass_list.push_back(std::move(pass));
2064 
2065   EXPECT_TRUE(this->RunPixelTest(&pass_list,
2066                                  base::FilePath(FILE_PATH_LITERAL("black.png")),
2067                                  cc::ExactPixelComparator(true)));
2068 }
2069 
TEST_P(VideoRendererPixelTest,TwoColorY16Rect)2070 TEST_P(VideoRendererPixelTest, TwoColorY16Rect) {
2071   gfx::Rect rect(this->device_viewport_size_);
2072 
2073   AggregatedRenderPassId id{1};
2074   auto pass = CreateTestRootRenderPass(id, rect);
2075 
2076   SharedQuadState* shared_state = CreateTestSharedQuadState(
2077       gfx::Transform(), rect, pass.get(), gfx::RRectF());
2078 
2079   gfx::Rect upper_rect(rect.x(), rect.y(), rect.width(), rect.height() / 2);
2080   CreateTestY16TextureDrawQuad_TwoColor(
2081       shared_state, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 68, 123, pass.get(),
2082       this->video_resource_updater_.get(), rect, rect, upper_rect,
2083       this->resource_provider_.get(), this->child_resource_provider_.get(),
2084       this->child_context_provider_.get());
2085 
2086   AggregatedRenderPassList pass_list;
2087   pass_list.push_back(std::move(pass));
2088 
2089   EXPECT_TRUE(this->RunPixelTest(
2090       &pass_list,
2091       base::FilePath(FILE_PATH_LITERAL("blue_yellow_filter_chain.png")),
2092       cc::FuzzyPixelOffByOneComparator(true)));
2093 }
2094 
2095 // TODO(https://crbug.com/1044841): Flaky, especially on Linux/TSAN and Fuchsia.
TEST_P(RendererPixelTest,DISABLED_FastPassColorFilterAlpha)2096 TEST_P(RendererPixelTest, DISABLED_FastPassColorFilterAlpha) {
2097   gfx::Rect viewport_rect(this->device_viewport_size_);
2098 
2099   AggregatedRenderPassId root_pass_id{1};
2100   auto root_pass = CreateTestRootRenderPass(root_pass_id, viewport_rect);
2101 
2102   AggregatedRenderPassId child_pass_id{2};
2103   gfx::Rect pass_rect(this->device_viewport_size_);
2104   gfx::Transform transform_to_root;
2105   float matrix[20];
2106   float amount = 0.5f;
2107   matrix[0] = 0.213f + 0.787f * amount;
2108   matrix[1] = 0.715f - 0.715f * amount;
2109   matrix[2] = 1.f - (matrix[0] + matrix[1]);
2110   matrix[3] = matrix[4] = 0;
2111   matrix[5] = 0.213f - 0.213f * amount;
2112   matrix[6] = 0.715f + 0.285f * amount;
2113   matrix[7] = 1.f - (matrix[5] + matrix[6]);
2114   matrix[8] = matrix[9] = 0;
2115   matrix[10] = 0.213f - 0.213f * amount;
2116   matrix[11] = 0.715f - 0.715f * amount;
2117   matrix[12] = 1.f - (matrix[10] + matrix[11]);
2118   matrix[13] = matrix[14] = 0;
2119   matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0;
2120   matrix[18] = 1;
2121   cc::FilterOperations filters;
2122   filters.Append(cc::FilterOperation::CreateReferenceFilter(
2123       sk_make_sp<cc::ColorFilterPaintFilter>(SkColorFilters::Matrix(matrix),
2124                                              nullptr)));
2125 
2126   auto child_pass =
2127       CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
2128   child_pass->filters = filters;
2129 
2130   gfx::Transform quad_to_target_transform;
2131   SharedQuadState* shared_state = CreateTestSharedQuadState(
2132       quad_to_target_transform, viewport_rect, child_pass.get(), gfx::RRectF());
2133   shared_state->opacity = 0.5f;
2134 
2135   gfx::Rect blue_rect(0, 0, this->device_viewport_size_.width(),
2136                       this->device_viewport_size_.height() / 2);
2137   auto* blue = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2138   blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
2139   gfx::Rect yellow_rect(0, this->device_viewport_size_.height() / 2,
2140                         this->device_viewport_size_.width(),
2141                         this->device_viewport_size_.height() / 2);
2142   auto* yellow = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2143   yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false);
2144 
2145   SharedQuadState* blank_state = CreateTestSharedQuadState(
2146       quad_to_target_transform, viewport_rect, child_pass.get(), gfx::RRectF());
2147 
2148   auto* white = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2149   white->SetNew(blank_state, viewport_rect, viewport_rect, SK_ColorWHITE,
2150                 false);
2151 
2152   SharedQuadState* pass_shared_state = CreateTestSharedQuadState(
2153       gfx::Transform(), pass_rect, root_pass.get(), gfx::RRectF());
2154 
2155   auto* render_pass_quad =
2156       root_pass->CreateAndAppendDrawQuad<AggregatedRenderPassDrawQuad>();
2157   render_pass_quad->SetNew(pass_shared_state, pass_rect, pass_rect,
2158                            child_pass_id, 0, gfx::RectF(), gfx::Size(),
2159                            gfx::Vector2dF(), gfx::PointF(),
2160                            gfx::RectF(pass_rect), false, 1.0f);
2161 
2162   AggregatedRenderPassList pass_list;
2163   pass_list.push_back(std::move(child_pass));
2164   pass_list.push_back(std::move(root_pass));
2165 
2166   // This test has alpha=254 for the software renderer vs. alpha=255 for the gl
2167   // renderer so use a fuzzy comparator.
2168   EXPECT_TRUE(this->RunPixelTest(
2169       &pass_list, base::FilePath(FILE_PATH_LITERAL("blue_yellow_alpha.png")),
2170       FuzzyForSkiaOnlyPixelComparator(renderer_type())));
2171 }
2172 
2173 // TODO(https://crbug.com/1044841): Flaky, especially on Linux/TSAN and Fuchsia.
TEST_P(RendererPixelTest,DISABLED_FastPassSaturateFilter)2174 TEST_P(RendererPixelTest, DISABLED_FastPassSaturateFilter) {
2175   gfx::Rect viewport_rect(this->device_viewport_size_);
2176 
2177   AggregatedRenderPassId root_pass_id{1};
2178   auto root_pass = CreateTestRootRenderPass(root_pass_id, viewport_rect);
2179 
2180   AggregatedRenderPassId child_pass_id{2};
2181   gfx::Rect pass_rect(this->device_viewport_size_);
2182   gfx::Transform transform_to_root;
2183   cc::FilterOperations filters;
2184   filters.Append(cc::FilterOperation::CreateSaturateFilter(0.5f));
2185 
2186   auto child_pass =
2187       CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
2188   child_pass->filters = filters;
2189 
2190   gfx::Transform quad_to_target_transform;
2191   SharedQuadState* shared_state = CreateTestSharedQuadState(
2192       quad_to_target_transform, viewport_rect, child_pass.get(), gfx::RRectF());
2193   shared_state->opacity = 0.5f;
2194 
2195   gfx::Rect blue_rect(0, 0, this->device_viewport_size_.width(),
2196                       this->device_viewport_size_.height() / 2);
2197   auto* blue = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2198   blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
2199   gfx::Rect yellow_rect(0, this->device_viewport_size_.height() / 2,
2200                         this->device_viewport_size_.width(),
2201                         this->device_viewport_size_.height() / 2);
2202   auto* yellow = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2203   yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false);
2204 
2205   SharedQuadState* blank_state = CreateTestSharedQuadState(
2206       quad_to_target_transform, viewport_rect, child_pass.get(), gfx::RRectF());
2207 
2208   auto* white = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2209   white->SetNew(blank_state, viewport_rect, viewport_rect, SK_ColorWHITE,
2210                 false);
2211 
2212   SharedQuadState* pass_shared_state = CreateTestSharedQuadState(
2213       gfx::Transform(), pass_rect, root_pass.get(), gfx::RRectF());
2214 
2215   auto* render_pass_quad =
2216       root_pass->CreateAndAppendDrawQuad<AggregatedRenderPassDrawQuad>();
2217   render_pass_quad->SetNew(pass_shared_state, pass_rect, pass_rect,
2218                            child_pass_id, 0, gfx::RectF(), gfx::Size(),
2219                            gfx::Vector2dF(), gfx::PointF(),
2220                            gfx::RectF(pass_rect), false, 1.0f);
2221 
2222   AggregatedRenderPassList pass_list;
2223   pass_list.push_back(std::move(child_pass));
2224   pass_list.push_back(std::move(root_pass));
2225 
2226   // This test blends slightly differently with the software renderer vs. the gl
2227   // renderer so use a fuzzy comparator.
2228   EXPECT_TRUE(this->RunPixelTest(
2229       &pass_list, base::FilePath(FILE_PATH_LITERAL("blue_yellow_alpha.png")),
2230       FuzzyForSkiaOnlyPixelComparator(renderer_type())));
2231 }
2232 
TEST_P(RendererPixelTest,FastPassFilterChain)2233 TEST_P(RendererPixelTest, FastPassFilterChain) {
2234   gfx::Rect viewport_rect(this->device_viewport_size_);
2235 
2236   AggregatedRenderPassId root_pass_id{1};
2237   auto root_pass = CreateTestRootRenderPass(root_pass_id, viewport_rect);
2238 
2239   AggregatedRenderPassId child_pass_id{2};
2240   gfx::Rect pass_rect(this->device_viewport_size_);
2241   gfx::Transform transform_to_root;
2242   cc::FilterOperations filters;
2243   filters.Append(cc::FilterOperation::CreateGrayscaleFilter(1.f));
2244   filters.Append(cc::FilterOperation::CreateBrightnessFilter(0.5f));
2245 
2246   auto child_pass =
2247       CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
2248   child_pass->filters = filters;
2249 
2250   gfx::Transform quad_to_target_transform;
2251   SharedQuadState* shared_state = CreateTestSharedQuadState(
2252       quad_to_target_transform, viewport_rect, child_pass.get(), gfx::RRectF());
2253   shared_state->opacity = 0.5f;
2254 
2255   gfx::Rect blue_rect(0, 0, this->device_viewport_size_.width(),
2256                       this->device_viewport_size_.height() / 2);
2257   auto* blue = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2258   blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
2259   gfx::Rect yellow_rect(0, this->device_viewport_size_.height() / 2,
2260                         this->device_viewport_size_.width(),
2261                         this->device_viewport_size_.height() / 2);
2262   auto* yellow = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2263   yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false);
2264 
2265   SharedQuadState* blank_state = CreateTestSharedQuadState(
2266       quad_to_target_transform, viewport_rect, child_pass.get(), gfx::RRectF());
2267 
2268   auto* white = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2269   white->SetNew(blank_state, viewport_rect, viewport_rect, SK_ColorWHITE,
2270                 false);
2271 
2272   SharedQuadState* pass_shared_state = CreateTestSharedQuadState(
2273       gfx::Transform(), pass_rect, root_pass.get(), gfx::RRectF());
2274 
2275   auto* render_pass_quad =
2276       root_pass->CreateAndAppendDrawQuad<AggregatedRenderPassDrawQuad>();
2277   render_pass_quad->SetNew(pass_shared_state, pass_rect, pass_rect,
2278                            child_pass_id, 0, gfx::RectF(), gfx::Size(),
2279                            gfx::Vector2dF(), gfx::PointF(),
2280                            gfx::RectF(pass_rect), false, 1.0f);
2281 
2282   AggregatedRenderPassList pass_list;
2283   pass_list.push_back(std::move(child_pass));
2284   pass_list.push_back(std::move(root_pass));
2285 
2286   // This test blends slightly differently with the software renderer vs. the gl
2287   // renderer so use a fuzzy comparator.
2288   EXPECT_TRUE(this->RunPixelTest(
2289       &pass_list,
2290       base::FilePath(FILE_PATH_LITERAL("blue_yellow_filter_chain.png")),
2291       FuzzyForSkiaOnlyPixelComparator(renderer_type())));
2292 }
2293 
2294 // TODO(https://crbug.com/1044841): Flaky, especially on Linux/TSAN and Fuchsia.
TEST_P(RendererPixelTest,DISABLED_FastPassColorFilterAlphaTranslation)2295 TEST_P(RendererPixelTest, DISABLED_FastPassColorFilterAlphaTranslation) {
2296   gfx::Rect viewport_rect(this->device_viewport_size_);
2297 
2298   AggregatedRenderPassId root_pass_id{1};
2299   auto root_pass = CreateTestRootRenderPass(root_pass_id, viewport_rect);
2300 
2301   AggregatedRenderPassId child_pass_id{2};
2302   gfx::Rect pass_rect(this->device_viewport_size_);
2303   gfx::Transform transform_to_root;
2304   float matrix[20];
2305   float amount = 0.5f;
2306   matrix[0] = 0.213f + 0.787f * amount;
2307   matrix[1] = 0.715f - 0.715f * amount;
2308   matrix[2] = 1.f - (matrix[0] + matrix[1]);
2309   matrix[3] = 0;
2310   matrix[4] = 20.f / 255;
2311   matrix[5] = 0.213f - 0.213f * amount;
2312   matrix[6] = 0.715f + 0.285f * amount;
2313   matrix[7] = 1.f - (matrix[5] + matrix[6]);
2314   matrix[8] = 0;
2315   matrix[9] = 200.f / 255;
2316   matrix[10] = 0.213f - 0.213f * amount;
2317   matrix[11] = 0.715f - 0.715f * amount;
2318   matrix[12] = 1.f - (matrix[10] + matrix[11]);
2319   matrix[13] = 0;
2320   matrix[14] = 1.5f / 255;
2321   matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0;
2322   matrix[18] = 1;
2323   cc::FilterOperations filters;
2324   filters.Append(cc::FilterOperation::CreateReferenceFilter(
2325       sk_make_sp<cc::ColorFilterPaintFilter>(SkColorFilters::Matrix(matrix),
2326                                              nullptr)));
2327 
2328   auto child_pass =
2329       CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
2330   child_pass->filters = filters;
2331 
2332   gfx::Transform quad_to_target_transform;
2333   SharedQuadState* shared_state = CreateTestSharedQuadState(
2334       quad_to_target_transform, viewport_rect, child_pass.get(), gfx::RRectF());
2335   shared_state->opacity = 0.5f;
2336 
2337   gfx::Rect blue_rect(0, 0, this->device_viewport_size_.width(),
2338                       this->device_viewport_size_.height() / 2);
2339   auto* blue = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2340   blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
2341   gfx::Rect yellow_rect(0, this->device_viewport_size_.height() / 2,
2342                         this->device_viewport_size_.width(),
2343                         this->device_viewport_size_.height() / 2);
2344   auto* yellow = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2345   yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false);
2346 
2347   SharedQuadState* blank_state = CreateTestSharedQuadState(
2348       quad_to_target_transform, viewport_rect, child_pass.get(), gfx::RRectF());
2349 
2350   auto* white = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2351   white->SetNew(blank_state, viewport_rect, viewport_rect, SK_ColorWHITE,
2352                 false);
2353 
2354   SharedQuadState* pass_shared_state = CreateTestSharedQuadState(
2355       gfx::Transform(), pass_rect, root_pass.get(), gfx::RRectF());
2356 
2357   auto* render_pass_quad =
2358       root_pass->CreateAndAppendDrawQuad<AggregatedRenderPassDrawQuad>();
2359   render_pass_quad->SetNew(pass_shared_state, pass_rect, pass_rect,
2360                            child_pass_id, 0, gfx::RectF(), gfx::Size(),
2361                            gfx::Vector2dF(), gfx::PointF(),
2362                            gfx::RectF(pass_rect), false, 1.0f);
2363 
2364   AggregatedRenderPassList pass_list;
2365 
2366   pass_list.push_back(std::move(child_pass));
2367   pass_list.push_back(std::move(root_pass));
2368 
2369   // This test has alpha=254 for the software renderer vs. alpha=255 for the gl
2370   // renderer so use a fuzzy comparator.
2371   EXPECT_TRUE(this->RunPixelTest(
2372       &pass_list,
2373       base::FilePath(FILE_PATH_LITERAL("blue_yellow_alpha_translate.png")),
2374       FuzzyForSkiaOnlyPixelComparator(renderer_type())));
2375 }
2376 
TEST_P(RendererPixelTest,EnlargedRenderPassTexture)2377 TEST_P(RendererPixelTest, EnlargedRenderPassTexture) {
2378   gfx::Rect viewport_rect(this->device_viewport_size_);
2379 
2380   AggregatedRenderPassId root_pass_id{1};
2381   auto root_pass = CreateTestRootRenderPass(root_pass_id, viewport_rect);
2382 
2383   AggregatedRenderPassId child_pass_id{2};
2384   gfx::Rect pass_rect(this->device_viewport_size_);
2385   gfx::Transform transform_to_root;
2386   auto child_pass =
2387       CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
2388 
2389   gfx::Transform quad_to_target_transform;
2390   SharedQuadState* shared_state = CreateTestSharedQuadState(
2391       quad_to_target_transform, viewport_rect, child_pass.get(), gfx::RRectF());
2392 
2393   gfx::Rect blue_rect(0, 0, this->device_viewport_size_.width(),
2394                       this->device_viewport_size_.height() / 2);
2395   auto* blue = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2396   blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
2397   gfx::Rect yellow_rect(0, this->device_viewport_size_.height() / 2,
2398                         this->device_viewport_size_.width(),
2399                         this->device_viewport_size_.height() / 2);
2400   auto* yellow = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2401   yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false);
2402 
2403   SharedQuadState* pass_shared_state = CreateTestSharedQuadState(
2404       gfx::Transform(), pass_rect, root_pass.get(), gfx::RRectF());
2405   CreateTestRenderPassDrawQuad(pass_shared_state, pass_rect, child_pass_id,
2406                                root_pass.get());
2407 
2408   AggregatedRenderPassList pass_list;
2409   pass_list.push_back(std::move(child_pass));
2410   pass_list.push_back(std::move(root_pass));
2411 
2412   this->renderer_->SetEnlargePassTextureAmountForTesting(gfx::Size(50, 75));
2413 
2414   EXPECT_TRUE(this->RunPixelTest(
2415       &pass_list, base::FilePath(FILE_PATH_LITERAL("blue_yellow.png")),
2416       cc::FuzzyPixelOffByOneComparator(true)));
2417 }
2418 
TEST_P(RendererPixelTest,EnlargedRenderPassTextureWithAntiAliasing)2419 TEST_P(RendererPixelTest, EnlargedRenderPassTextureWithAntiAliasing) {
2420   gfx::Rect viewport_rect(this->device_viewport_size_);
2421 
2422   AggregatedRenderPassId root_pass_id{1};
2423   auto root_pass = CreateTestRootRenderPass(root_pass_id, viewport_rect);
2424 
2425   AggregatedRenderPassId child_pass_id{2};
2426   gfx::Rect pass_rect(this->device_viewport_size_);
2427   gfx::Transform transform_to_root;
2428   auto child_pass =
2429       CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
2430 
2431   gfx::Transform quad_to_target_transform;
2432   SharedQuadState* shared_state = CreateTestSharedQuadState(
2433       quad_to_target_transform, viewport_rect, child_pass.get(), gfx::RRectF());
2434 
2435   gfx::Rect blue_rect(0, 0, this->device_viewport_size_.width(),
2436                       this->device_viewport_size_.height() / 2);
2437   auto* blue = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2438   blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
2439   gfx::Rect yellow_rect(0, this->device_viewport_size_.height() / 2,
2440                         this->device_viewport_size_.width(),
2441                         this->device_viewport_size_.height() / 2);
2442   auto* yellow = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2443   yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false);
2444 
2445   gfx::Transform aa_transform;
2446   aa_transform.Translate(0.5, 0.0);
2447 
2448   SharedQuadState* pass_shared_state = CreateTestSharedQuadState(
2449       aa_transform, pass_rect, root_pass.get(), gfx::RRectF());
2450   CreateTestRenderPassDrawQuad(pass_shared_state, pass_rect, child_pass_id,
2451                                root_pass.get());
2452 
2453   SharedQuadState* root_shared_state = CreateTestSharedQuadState(
2454       gfx::Transform(), viewport_rect, root_pass.get(), gfx::RRectF());
2455   auto* background = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2456   background->SetNew(root_shared_state, gfx::Rect(this->device_viewport_size_),
2457                      gfx::Rect(this->device_viewport_size_), SK_ColorWHITE,
2458                      false);
2459 
2460   AggregatedRenderPassList pass_list;
2461   pass_list.push_back(std::move(child_pass));
2462   pass_list.push_back(std::move(root_pass));
2463 
2464   this->renderer_->SetEnlargePassTextureAmountForTesting(gfx::Size(50, 75));
2465 
2466   EXPECT_TRUE(this->RunPixelTest(
2467       &pass_list,
2468       base::FilePath(FILE_PATH_LITERAL("blue_yellow_anti_aliasing.png")),
2469       cc::FuzzyPixelComparator(true, 100.f, 0.f, 5.f, 7, 0)));
2470 }
2471 
2472 // This tests the case where we have a RenderPass with a mask, but the quad
2473 // for the masked surface does not include the full surface texture.
TEST_P(RendererPixelTest,RenderPassAndMaskWithPartialQuad)2474 TEST_P(RendererPixelTest, RenderPassAndMaskWithPartialQuad) {
2475   gfx::Rect viewport_rect(this->device_viewport_size_);
2476 
2477   AggregatedRenderPassId root_pass_id{1};
2478   auto root_pass = CreateTestRootRenderPass(root_pass_id, viewport_rect);
2479   SharedQuadState* root_pass_shared_state = CreateTestSharedQuadState(
2480       gfx::Transform(), viewport_rect, root_pass.get(), gfx::RRectF());
2481 
2482   AggregatedRenderPassId child_pass_id{2};
2483   gfx::Transform transform_to_root;
2484   auto child_pass =
2485       CreateTestRenderPass(child_pass_id, viewport_rect, transform_to_root);
2486   SharedQuadState* child_pass_shared_state = CreateTestSharedQuadState(
2487       gfx::Transform(), viewport_rect, child_pass.get(), gfx::RRectF());
2488 
2489   // The child render pass is just a green box.
2490   static const SkColor kCSSGreen = 0xff008000;
2491   auto* green = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2492   green->SetNew(child_pass_shared_state, viewport_rect, viewport_rect,
2493                 kCSSGreen, false);
2494 
2495   // Make a mask.
2496   gfx::Rect mask_rect = viewport_rect;
2497   SkBitmap bitmap;
2498   bitmap.allocPixels(
2499       SkImageInfo::MakeN32Premul(mask_rect.width(), mask_rect.height()));
2500   cc::SkiaPaintCanvas canvas(bitmap);
2501   cc::PaintFlags flags;
2502   flags.setStyle(cc::PaintFlags::kStroke_Style);
2503   flags.setStrokeWidth(SkIntToScalar(4));
2504   flags.setColor(SK_ColorWHITE);
2505   canvas.clear(SK_ColorTRANSPARENT);
2506   gfx::Rect rect = mask_rect;
2507   while (!rect.IsEmpty()) {
2508     rect.Inset(6, 6, 4, 4);
2509     canvas.drawRect(
2510         SkRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height()),
2511         flags);
2512     rect.Inset(6, 6, 4, 4);
2513   }
2514 
2515   ResourceId mask_resource_id;
2516   if (!is_software_renderer()) {
2517     mask_resource_id = CreateGpuResource(
2518         this->child_context_provider_, this->child_resource_provider_.get(),
2519         mask_rect.size(), RGBA_8888, gfx::ColorSpace(), MakePixelSpan(bitmap));
2520   } else {
2521     mask_resource_id =
2522         this->AllocateAndFillSoftwareResource(mask_rect.size(), bitmap);
2523   }
2524 
2525   // Return the mapped resource id.
2526   std::unordered_map<ResourceId, ResourceId> resource_map =
2527       cc::SendResourceAndGetChildToParentMap(
2528           {mask_resource_id}, this->resource_provider_.get(),
2529           this->child_resource_provider_.get(),
2530           this->child_context_provider_.get());
2531   ResourceId mapped_mask_resource_id = resource_map[mask_resource_id];
2532 
2533   // This AggregatedRenderPassDrawQuad does not include the full |viewport_rect|
2534   // which is the size of the child render pass.
2535   gfx::Rect sub_rect = gfx::Rect(50, 50, 200, 100);
2536   EXPECT_NE(sub_rect.x(), child_pass->output_rect.x());
2537   EXPECT_NE(sub_rect.y(), child_pass->output_rect.y());
2538   EXPECT_NE(sub_rect.right(), child_pass->output_rect.right());
2539   EXPECT_NE(sub_rect.bottom(), child_pass->output_rect.bottom());
2540 
2541   // Set up a mask on the AggregatedRenderPassDrawQuad.
2542   auto* mask_quad =
2543       root_pass->CreateAndAppendDrawQuad<AggregatedRenderPassDrawQuad>();
2544   mask_quad->SetNew(
2545       root_pass_shared_state, sub_rect, sub_rect, child_pass_id,
2546       mapped_mask_resource_id,
2547       gfx::ScaleRect(gfx::RectF(sub_rect), 2.f / mask_rect.width(),
2548                      2.f / mask_rect.height()),  // mask_uv_rect
2549       gfx::Size(mask_rect.size()),               // mask_texture_size
2550       gfx::Vector2dF(),                          // filters scale
2551       gfx::PointF(),                             // filter origin
2552       gfx::RectF(sub_rect),                      // tex_coord_rect
2553       false,                                     // force_anti_aliasing_off
2554       1.0f);                                     // backdrop_filter_quality
2555   // White background behind the masked render pass.
2556   auto* white = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2557   white->SetNew(root_pass_shared_state, viewport_rect, viewport_rect,
2558                 SK_ColorWHITE, false);
2559 
2560   AggregatedRenderPassList pass_list;
2561   pass_list.push_back(std::move(child_pass));
2562   pass_list.push_back(std::move(root_pass));
2563 
2564   EXPECT_TRUE(this->RunPixelTest(
2565       &pass_list, base::FilePath(FILE_PATH_LITERAL("mask_bottom_right.png")),
2566       cc::ExactPixelComparator(true)));
2567 }
2568 
2569 // This tests the case where we have a RenderPass with a mask, but the quad
2570 // for the masked surface does not include the full surface texture.
TEST_P(RendererPixelTest,RenderPassAndMaskWithPartialQuad2)2571 TEST_P(RendererPixelTest, RenderPassAndMaskWithPartialQuad2) {
2572   gfx::Rect viewport_rect(this->device_viewport_size_);
2573 
2574   AggregatedRenderPassId root_pass_id{1};
2575   auto root_pass = CreateTestRootRenderPass(root_pass_id, viewport_rect);
2576   SharedQuadState* root_pass_shared_state = CreateTestSharedQuadState(
2577       gfx::Transform(), viewport_rect, root_pass.get(), gfx::RRectF());
2578 
2579   AggregatedRenderPassId child_pass_id{2};
2580   gfx::Transform transform_to_root;
2581   auto child_pass =
2582       CreateTestRenderPass(child_pass_id, viewport_rect, transform_to_root);
2583   SharedQuadState* child_pass_shared_state = CreateTestSharedQuadState(
2584       gfx::Transform(), viewport_rect, child_pass.get(), gfx::RRectF());
2585 
2586   // The child render pass is just a green box.
2587   static const SkColor kCSSGreen = 0xff008000;
2588   auto* green = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2589   green->SetNew(child_pass_shared_state, viewport_rect, viewport_rect,
2590                 kCSSGreen, false);
2591 
2592   // Make a mask.
2593   gfx::Rect mask_rect = viewport_rect;
2594   SkBitmap bitmap;
2595   bitmap.allocPixels(
2596       SkImageInfo::MakeN32Premul(mask_rect.width(), mask_rect.height()));
2597   cc::SkiaPaintCanvas canvas(bitmap);
2598   cc::PaintFlags flags;
2599   flags.setStyle(cc::PaintFlags::kStroke_Style);
2600   flags.setStrokeWidth(SkIntToScalar(4));
2601   flags.setColor(SK_ColorWHITE);
2602   canvas.clear(SK_ColorTRANSPARENT);
2603   gfx::Rect rect = mask_rect;
2604   while (!rect.IsEmpty()) {
2605     rect.Inset(6, 6, 4, 4);
2606     canvas.drawRect(
2607         SkRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height()),
2608         flags);
2609     rect.Inset(6, 6, 4, 4);
2610   }
2611 
2612   ResourceId mask_resource_id;
2613   if (!is_software_renderer()) {
2614     mask_resource_id = CreateGpuResource(
2615         this->child_context_provider_, this->child_resource_provider_.get(),
2616         mask_rect.size(), RGBA_8888, gfx::ColorSpace(), MakePixelSpan(bitmap));
2617   } else {
2618     mask_resource_id =
2619         this->AllocateAndFillSoftwareResource(mask_rect.size(), bitmap);
2620   }
2621 
2622   // Return the mapped resource id.
2623   std::unordered_map<ResourceId, ResourceId> resource_map =
2624       cc::SendResourceAndGetChildToParentMap(
2625           {mask_resource_id}, this->resource_provider_.get(),
2626           this->child_resource_provider_.get(),
2627           this->child_context_provider_.get());
2628   ResourceId mapped_mask_resource_id = resource_map[mask_resource_id];
2629 
2630   // This AggregatedRenderPassDrawQuad does not include the full |viewport_rect|
2631   // which is the size of the child render pass.
2632   gfx::Rect sub_rect = gfx::Rect(50, 20, 200, 60);
2633   EXPECT_NE(sub_rect.x(), child_pass->output_rect.x());
2634   EXPECT_NE(sub_rect.y(), child_pass->output_rect.y());
2635   EXPECT_NE(sub_rect.right(), child_pass->output_rect.right());
2636   EXPECT_NE(sub_rect.bottom(), child_pass->output_rect.bottom());
2637 
2638   // Set up a mask on the AggregatedRenderPassDrawQuad.
2639   auto* mask_quad =
2640       root_pass->CreateAndAppendDrawQuad<AggregatedRenderPassDrawQuad>();
2641   mask_quad->SetNew(
2642       root_pass_shared_state, sub_rect, sub_rect, child_pass_id,
2643       mapped_mask_resource_id,
2644       gfx::ScaleRect(gfx::RectF(sub_rect), 2.f / mask_rect.width(),
2645                      2.f / mask_rect.height()),  // mask_uv_rect
2646       gfx::Size(mask_rect.size()),               // mask_texture_size
2647       gfx::Vector2dF(),                          // filters scale
2648       gfx::PointF(),                             // filter origin
2649       gfx::RectF(sub_rect),                      // tex_coord_rect
2650       false,                                     // force_anti_aliasing_off
2651       1.0f);                                     // backdrop_filter_quality
2652   // White background behind the masked render pass.
2653   auto* white = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2654   white->SetNew(root_pass_shared_state, viewport_rect, viewport_rect,
2655                 SK_ColorWHITE, false);
2656 
2657   AggregatedRenderPassList pass_list;
2658   pass_list.push_back(std::move(child_pass));
2659   pass_list.push_back(std::move(root_pass));
2660 
2661   EXPECT_TRUE(this->RunPixelTest(
2662       &pass_list, base::FilePath(FILE_PATH_LITERAL("mask_middle.png")),
2663       cc::ExactPixelComparator(true)));
2664 }
2665 
TEST_P(RendererPixelTest,RenderPassAndMaskForRoundedCorner)2666 TEST_P(RendererPixelTest, RenderPassAndMaskForRoundedCorner) {
2667   gfx::Rect viewport_rect(this->device_viewport_size_);
2668   constexpr int kInset = 20;
2669   constexpr int kCornerRadius = 20;
2670 
2671   AggregatedRenderPassId root_pass_id{1};
2672   auto root_pass = CreateTestRootRenderPass(root_pass_id, viewport_rect);
2673   SharedQuadState* root_pass_shared_state = CreateTestSharedQuadState(
2674       gfx::Transform(), viewport_rect, root_pass.get(), gfx::RRectF());
2675 
2676   AggregatedRenderPassId child_pass_id{2};
2677   gfx::Transform transform_to_root;
2678   auto child_pass =
2679       CreateTestRenderPass(child_pass_id, viewport_rect, transform_to_root);
2680   SharedQuadState* child_pass_shared_state = CreateTestSharedQuadState(
2681       gfx::Transform(), viewport_rect, child_pass.get(), gfx::RRectF());
2682 
2683   // The child render pass is just a blue box.
2684   auto* blue = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2685   blue->SetNew(child_pass_shared_state, viewport_rect, viewport_rect,
2686                SK_ColorBLUE, false);
2687 
2688   // Make a mask.
2689   gfx::Rect mask_rect = viewport_rect;
2690   SkBitmap bitmap;
2691   bitmap.allocPixels(
2692       SkImageInfo::MakeN32Premul(mask_rect.width(), mask_rect.height()));
2693   cc::SkiaPaintCanvas canvas(bitmap);
2694   cc::PaintFlags flags;
2695   flags.setStyle(cc::PaintFlags::kFill_Style);
2696   flags.setColor(SK_ColorWHITE);
2697   flags.setAntiAlias(true);
2698   canvas.clear(SK_ColorTRANSPARENT);
2699   gfx::Rect rounded_corner_rect = mask_rect;
2700   rounded_corner_rect.Inset(kInset, kInset);
2701   SkRRect rounded_corner = SkRRect::MakeRectXY(
2702       gfx::RectToSkRect(rounded_corner_rect), kCornerRadius, kCornerRadius);
2703   canvas.drawRRect(rounded_corner, flags);
2704 
2705   ResourceId mask_resource_id;
2706   if (!is_software_renderer()) {
2707     mask_resource_id = CreateGpuResource(
2708         this->child_context_provider_, this->child_resource_provider_.get(),
2709         mask_rect.size(), RGBA_8888, gfx::ColorSpace(), MakePixelSpan(bitmap));
2710   } else {
2711     mask_resource_id =
2712         this->AllocateAndFillSoftwareResource(mask_rect.size(), bitmap);
2713   }
2714 
2715   // Return the mapped resource id.
2716   std::unordered_map<ResourceId, ResourceId> resource_map =
2717       cc::SendResourceAndGetChildToParentMap(
2718           {mask_resource_id}, this->resource_provider_.get(),
2719           this->child_resource_provider_.get(),
2720           this->child_context_provider_.get());
2721   ResourceId mapped_mask_resource_id = resource_map[mask_resource_id];
2722 
2723   // Set up a mask on the AggregatedRenderPassDrawQuad.
2724   auto* mask_quad =
2725       root_pass->CreateAndAppendDrawQuad<AggregatedRenderPassDrawQuad>();
2726   mask_quad->SetNew(
2727       root_pass_shared_state, viewport_rect, viewport_rect, child_pass_id,
2728       mapped_mask_resource_id,
2729       gfx::ScaleRect(gfx::RectF(viewport_rect), 1.f / mask_rect.width(),
2730                      1.f / mask_rect.height()),  // mask_uv_rect
2731       gfx::Size(mask_rect.size()),               // mask_texture_size
2732       gfx::Vector2dF(),                          // filters scale
2733       gfx::PointF(),                             // filter origin
2734       gfx::RectF(viewport_rect),                 // tex_coord_rect
2735       false,                                     // force_anti_aliasing_off
2736       1.0f);                                     // backdrop_filter_quality
2737   // White background behind the masked render pass.
2738   auto* white = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2739   white->SetNew(root_pass_shared_state, viewport_rect, viewport_rect,
2740                 SK_ColorWHITE, false);
2741 
2742   AggregatedRenderPassList pass_list;
2743   pass_list.push_back(std::move(child_pass));
2744   pass_list.push_back(std::move(root_pass));
2745 
2746   // The rounded corners generated by masks should be very close to the rounded
2747   // corners generated by the fragment shader approach. The percentage of pixel
2748   // mismatch is around 0.52%.
2749   EXPECT_TRUE(this->RunPixelTest(
2750       &pass_list,
2751       base::FilePath(FILE_PATH_LITERAL("rounded_corner_simple.png")),
2752       cc::FuzzyPixelComparator(true, 0.6f, 0.f, 255.f, 255, 0)));
2753 }
2754 
TEST_P(RendererPixelTest,RenderPassAndMaskForRoundedCornerMultiRadii)2755 TEST_P(RendererPixelTest, RenderPassAndMaskForRoundedCornerMultiRadii) {
2756   gfx::Rect viewport_rect(this->device_viewport_size_);
2757   constexpr int kInset = 20;
2758   const SkVector kCornerRadii[4] = {
2759       SkVector::Make(5.0, 5.0),
2760       SkVector::Make(15.0, 15.0),
2761       SkVector::Make(25.0, 25.0),
2762       SkVector::Make(35.0, 35.0),
2763   };
2764 
2765   AggregatedRenderPassId root_pass_id{1};
2766   auto root_pass = CreateTestRootRenderPass(root_pass_id, viewport_rect);
2767   SharedQuadState* root_pass_shared_state = CreateTestSharedQuadState(
2768       gfx::Transform(), viewport_rect, root_pass.get(), gfx::RRectF());
2769 
2770   AggregatedRenderPassId child_pass_id{2};
2771   gfx::Transform transform_to_root;
2772   auto child_pass =
2773       CreateTestRenderPass(child_pass_id, viewport_rect, transform_to_root);
2774   SharedQuadState* child_pass_shared_state = CreateTestSharedQuadState(
2775       gfx::Transform(), viewport_rect, child_pass.get(), gfx::RRectF());
2776 
2777   // The child render pass is half a blue box and other half yellow box.
2778   gfx::Rect blue_rect(0, 0, this->device_viewport_size_.width(),
2779                       this->device_viewport_size_.height() / 2);
2780   auto* blue = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2781   blue->SetNew(child_pass_shared_state, blue_rect, blue_rect, SK_ColorBLUE,
2782                false);
2783 
2784   gfx::Rect yellow_rect(0, this->device_viewport_size_.height() / 2,
2785                         this->device_viewport_size_.width(),
2786                         this->device_viewport_size_.height() / 2);
2787   auto* yellow = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2788   yellow->SetNew(child_pass_shared_state, yellow_rect, yellow_rect,
2789                  SK_ColorYELLOW, false);
2790 
2791   // Make a mask.
2792   gfx::Rect mask_rect = viewport_rect;
2793   SkBitmap bitmap;
2794   bitmap.allocPixels(
2795       SkImageInfo::MakeN32Premul(mask_rect.width(), mask_rect.height()));
2796   cc::SkiaPaintCanvas canvas(bitmap);
2797   cc::PaintFlags flags;
2798   flags.setStyle(cc::PaintFlags::kFill_Style);
2799   flags.setColor(SK_ColorWHITE);
2800   flags.setAntiAlias(true);
2801   canvas.clear(SK_ColorTRANSPARENT);
2802   gfx::Rect rounded_corner_rect = mask_rect;
2803   rounded_corner_rect.Inset(kInset, kInset);
2804   SkRRect rounded_corner =
2805       SkRRect::MakeRect(gfx::RectToSkRect(rounded_corner_rect));
2806   rounded_corner.setRectRadii(rounded_corner.rect(), kCornerRadii);
2807   canvas.drawRRect(rounded_corner, flags);
2808 
2809   ResourceId mask_resource_id;
2810   if (!is_software_renderer()) {
2811     mask_resource_id = CreateGpuResource(
2812         this->child_context_provider_, this->child_resource_provider_.get(),
2813         mask_rect.size(), RGBA_8888, gfx::ColorSpace(), MakePixelSpan(bitmap));
2814   } else {
2815     mask_resource_id =
2816         this->AllocateAndFillSoftwareResource(mask_rect.size(), bitmap);
2817   }
2818 
2819   // Return the mapped resource id.
2820   std::unordered_map<ResourceId, ResourceId> resource_map =
2821       cc::SendResourceAndGetChildToParentMap(
2822           {mask_resource_id}, this->resource_provider_.get(),
2823           this->child_resource_provider_.get(),
2824           this->child_context_provider_.get());
2825   ResourceId mapped_mask_resource_id = resource_map[mask_resource_id];
2826 
2827   // Set up a mask on the AggregatedRenderPassDrawQuad.
2828   auto* mask_quad =
2829       root_pass->CreateAndAppendDrawQuad<AggregatedRenderPassDrawQuad>();
2830   mask_quad->SetNew(
2831       root_pass_shared_state, viewport_rect, viewport_rect, child_pass_id,
2832       mapped_mask_resource_id,
2833       gfx::ScaleRect(gfx::RectF(viewport_rect), 1.f / mask_rect.width(),
2834                      1.f / mask_rect.height()),  // mask_uv_rect
2835       gfx::Size(mask_rect.size()),               // mask_texture_size
2836       gfx::Vector2dF(),                          // filters scale
2837       gfx::PointF(),                             // filter origin
2838       gfx::RectF(viewport_rect),                 // tex_coord_rect
2839       false,                                     // force_anti_aliasing_off
2840       1.0f);                                     // backdrop_filter_quality
2841   // White background behind the masked render pass.
2842   auto* white = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2843   white->SetNew(root_pass_shared_state, viewport_rect, viewport_rect,
2844                 SK_ColorWHITE, false);
2845 
2846   AggregatedRenderPassList pass_list;
2847   pass_list.push_back(std::move(child_pass));
2848   pass_list.push_back(std::move(root_pass));
2849 
2850   EXPECT_TRUE(this->RunPixelTest(
2851       &pass_list,
2852       base::FilePath(FILE_PATH_LITERAL("rounded_corner_multi_radii.png")),
2853       cc::FuzzyPixelComparator(true, 0.6f, 0.f, 255.f, 255, 0)));
2854 }
2855 
2856 class RendererPixelTestWithBackdropFilter : public VizPixelTestWithParam {
2857  protected:
SetUpRenderPassList()2858   void SetUpRenderPassList() {
2859     gfx::Rect device_viewport_rect(this->device_viewport_size_);
2860 
2861     AggregatedRenderPassId root_id{1};
2862     auto root_pass = CreateTestRootRenderPass(root_id, device_viewport_rect);
2863     root_pass->has_transparent_background = false;
2864 
2865     gfx::Transform identity_quad_to_target_transform;
2866 
2867     AggregatedRenderPassId filter_pass_id{2};
2868     gfx::Transform transform_to_root;
2869     auto filter_pass = CreateTestRenderPass(
2870         filter_pass_id, filter_pass_layer_rect_, transform_to_root);
2871     filter_pass->backdrop_filters = this->backdrop_filters_;
2872     filter_pass->backdrop_filter_bounds = this->backdrop_filter_bounds_;
2873 
2874     // A non-visible quad in the filtering render pass.
2875     {
2876       SharedQuadState* shared_state = CreateTestSharedQuadState(
2877           identity_quad_to_target_transform, filter_pass_layer_rect_,
2878           filter_pass.get(), gfx::RRectF());
2879       auto* color_quad =
2880           filter_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2881       color_quad->SetNew(shared_state, filter_pass_layer_rect_,
2882                          filter_pass_layer_rect_, SK_ColorTRANSPARENT, false);
2883     }
2884 
2885     ResourceId mapped_mask_resource_id = 0;
2886     gfx::RectF mask_uv_rect;
2887     gfx::Size mask_texture_size;
2888     if (include_backdrop_mask_) {
2889       // Make a mask.
2890       gfx::Rect viewport_rect(this->device_viewport_size_);
2891       constexpr int kInset = 20;
2892       const SkVector kCornerRadii[4] = {
2893           SkVector::Make(5.0, 5.0),
2894           SkVector::Make(15.0, 15.0),
2895           SkVector::Make(25.0, 25.0),
2896           SkVector::Make(35.0, 35.0),
2897       };
2898       gfx::Rect mask_rect = viewport_rect;
2899       SkBitmap bitmap;
2900       bitmap.allocPixels(
2901           SkImageInfo::MakeN32Premul(mask_rect.width(), mask_rect.height()));
2902       cc::SkiaPaintCanvas canvas(bitmap);
2903       cc::PaintFlags flags;
2904       flags.setStyle(cc::PaintFlags::kFill_Style);
2905       flags.setColor(SK_ColorWHITE);
2906       flags.setAntiAlias(true);
2907       canvas.clear(SK_ColorTRANSPARENT);
2908       gfx::Rect rounded_corner_rect = mask_rect;
2909       rounded_corner_rect.Inset(kInset, kInset);
2910       SkRRect rounded_corner =
2911           SkRRect::MakeRect(gfx::RectToSkRect(rounded_corner_rect));
2912       rounded_corner.setRectRadii(rounded_corner.rect(), kCornerRadii);
2913       canvas.drawRRect(rounded_corner, flags);
2914 
2915       ResourceId mask_resource_id;
2916       if (!is_software_renderer()) {
2917         mask_resource_id = CreateGpuResource(
2918             this->child_context_provider_, this->child_resource_provider_.get(),
2919             mask_rect.size(), RGBA_8888, gfx::ColorSpace(),
2920             MakePixelSpan(bitmap));
2921       } else {
2922         mask_resource_id =
2923             this->AllocateAndFillSoftwareResource(mask_rect.size(), bitmap);
2924       }
2925 
2926       // Return the mapped resource id.
2927       std::unordered_map<ResourceId, ResourceId> resource_map =
2928           cc::SendResourceAndGetChildToParentMap(
2929               {mask_resource_id}, this->resource_provider_.get(),
2930               this->child_resource_provider_.get(),
2931               this->child_context_provider_.get());
2932       mapped_mask_resource_id = resource_map[mask_resource_id];
2933 
2934       mask_uv_rect =
2935           gfx::ScaleRect(gfx::RectF(viewport_rect), 1.f / mask_rect.width(),
2936                          1.f / mask_rect.height()),  // mask_uv_rect
2937           mask_texture_size = gfx::Size(mask_rect.size());
2938     }
2939 
2940     {
2941       SharedQuadState* shared_state = CreateTestSharedQuadState(
2942           filter_pass_to_target_transform_, filter_pass_layer_rect_,
2943           filter_pass.get(), gfx::RRectF());
2944       auto* filter_pass_quad =
2945           root_pass->CreateAndAppendDrawQuad<AggregatedRenderPassDrawQuad>();
2946       filter_pass_quad->SetNew(shared_state, filter_pass_layer_rect_,
2947                                filter_pass_layer_rect_, filter_pass_id,
2948                                mapped_mask_resource_id, mask_uv_rect,
2949                                mask_texture_size,
2950                                gfx::Vector2dF(1.0f, 1.0f),  // filters_scale
2951                                gfx::PointF(),               // filters_origin
2952                                gfx::RectF(),                // tex_coord_rect
2953                                false,  // force_anti_aliasing_off
2954                                1.0f);  // backdrop_filter_quality
2955     }
2956 
2957     const int kColumnWidth = device_viewport_rect.width() / 3;
2958 
2959     gfx::Rect left_rect = gfx::Rect(0, 0, kColumnWidth, 20);
2960     for (int i = 0; left_rect.y() < device_viewport_rect.height(); ++i) {
2961       SharedQuadState* shared_state =
2962           CreateTestSharedQuadState(identity_quad_to_target_transform,
2963                                     left_rect, root_pass.get(), gfx::RRectF());
2964       auto* color_quad =
2965           root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2966       color_quad->SetNew(shared_state, left_rect, left_rect, SK_ColorGREEN,
2967                          false);
2968       left_rect += gfx::Vector2d(0, left_rect.height() + 1);
2969     }
2970 
2971     gfx::Rect middle_rect = gfx::Rect(kColumnWidth + 1, 0, kColumnWidth, 20);
2972     for (int i = 0; middle_rect.y() < device_viewport_rect.height(); ++i) {
2973       SharedQuadState* shared_state = CreateTestSharedQuadState(
2974           identity_quad_to_target_transform, middle_rect, root_pass.get(),
2975           gfx::RRectF());
2976       auto* color_quad =
2977           root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2978       color_quad->SetNew(shared_state, middle_rect, middle_rect, SK_ColorRED,
2979                          false);
2980       middle_rect += gfx::Vector2d(0, middle_rect.height() + 1);
2981     }
2982 
2983     gfx::Rect right_rect =
2984         gfx::Rect((kColumnWidth + 1) * 2, 0, kColumnWidth, 20);
2985     for (int i = 0; right_rect.y() < device_viewport_rect.height(); ++i) {
2986       SharedQuadState* shared_state =
2987           CreateTestSharedQuadState(identity_quad_to_target_transform,
2988                                     right_rect, root_pass.get(), gfx::RRectF());
2989       auto* color_quad =
2990           root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
2991       color_quad->SetNew(shared_state, right_rect, right_rect, SK_ColorBLUE,
2992                          false);
2993       right_rect += gfx::Vector2d(0, right_rect.height() + 1);
2994     }
2995 
2996     SharedQuadState* shared_state = CreateTestSharedQuadState(
2997         identity_quad_to_target_transform, device_viewport_rect,
2998         root_pass.get(), gfx::RRectF());
2999     auto* background_quad =
3000         root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
3001     background_quad->SetNew(shared_state, device_viewport_rect,
3002                             device_viewport_rect, SK_ColorWHITE, false);
3003 
3004     pass_list_.push_back(std::move(filter_pass));
3005     pass_list_.push_back(std::move(root_pass));
3006   }
3007 
3008   AggregatedRenderPassList pass_list_;
3009   cc::FilterOperations backdrop_filters_;
3010   base::Optional<gfx::RRectF> backdrop_filter_bounds_;
3011   bool include_backdrop_mask_ = false;
3012   gfx::Transform filter_pass_to_target_transform_;
3013   gfx::Rect filter_pass_layer_rect_;
3014 };
3015 
3016 INSTANTIATE_TEST_SUITE_P(,
3017                          RendererPixelTestWithBackdropFilter,
3018                          testing::ValuesIn(GetRendererTypes()),
3019                          testing::PrintToStringParamName());
3020 
TEST_P(RendererPixelTestWithBackdropFilter,InvertFilter)3021 TEST_P(RendererPixelTestWithBackdropFilter, InvertFilter) {
3022   this->backdrop_filters_.Append(cc::FilterOperation::CreateInvertFilter(1.f));
3023   this->filter_pass_layer_rect_ = gfx::Rect(this->device_viewport_size_);
3024   this->filter_pass_layer_rect_.Inset(12, 14, 16, 18);
3025   this->backdrop_filter_bounds_ =
3026       gfx::RRectF(gfx::RectF(this->filter_pass_layer_rect_));
3027   this->SetUpRenderPassList();
3028   EXPECT_TRUE(this->RunPixelTest(
3029       &this->pass_list_,
3030       base::FilePath(FILE_PATH_LITERAL("backdrop_filter.png")),
3031       cc::ExactPixelComparator(true)));
3032 }
3033 
TEST_P(RendererPixelTestWithBackdropFilter,InvertFilterWithMask)3034 TEST_P(RendererPixelTestWithBackdropFilter, InvertFilterWithMask) {
3035   // TODO(989312): The mask on gl_renderer and software_renderer appears to be
3036   // offset from the correct location.
3037   if (is_gl_renderer() || is_software_renderer())
3038     return;
3039   this->backdrop_filters_.Append(cc::FilterOperation::CreateInvertFilter(1.f));
3040   this->filter_pass_layer_rect_ = gfx::Rect(this->device_viewport_size_);
3041   this->filter_pass_layer_rect_.Inset(12, 14, 16, 18);
3042   this->backdrop_filter_bounds_ =
3043       gfx::RRectF(gfx::RectF(this->filter_pass_layer_rect_));
3044   this->include_backdrop_mask_ = true;
3045   this->SetUpRenderPassList();
3046   EXPECT_TRUE(this->RunPixelTest(
3047       &this->pass_list_,
3048       base::FilePath(FILE_PATH_LITERAL("backdrop_filter_masked.png")),
3049       cc::FuzzyPixelOffByOneComparator(false)));
3050 }
3051 
3052 class GLRendererPixelTestWithBackdropFilter : public VizPixelTest {
3053  public:
GLRendererPixelTestWithBackdropFilter()3054   GLRendererPixelTestWithBackdropFilter() : VizPixelTest(RendererType::kGL) {}
3055 
3056  protected:
SetUpRenderPassList()3057   void SetUpRenderPassList() {
3058     pass_list_.clear();
3059     gfx::Rect device_viewport_rect(this->device_viewport_size_);
3060 
3061     AggregatedRenderPassId root_id{1};
3062     auto root_pass = CreateTestRootRenderPass(root_id, device_viewport_rect);
3063     root_pass->has_transparent_background = false;
3064 
3065     gfx::Transform identity_quad_to_target_transform;
3066 
3067     AggregatedRenderPassId filter_pass_id{2};
3068     gfx::Transform transform_to_root;
3069     auto filter_pass = CreateTestRenderPass(
3070         filter_pass_id, filter_pass_layer_rect_, transform_to_root);
3071     filter_pass->backdrop_filters = this->backdrop_filters_;
3072     filter_pass->backdrop_filter_bounds = this->backdrop_filter_bounds_;
3073 
3074     // A non-visible quad in the filtering render pass.
3075     {
3076       SharedQuadState* shared_state = CreateTestSharedQuadState(
3077           identity_quad_to_target_transform, filter_pass_layer_rect_,
3078           filter_pass.get(), gfx::RRectF());
3079       auto* color_quad =
3080           filter_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
3081       color_quad->SetNew(shared_state, filter_pass_layer_rect_,
3082                          filter_pass_layer_rect_, SK_ColorTRANSPARENT, false);
3083     }
3084 
3085     {
3086       SharedQuadState* shared_state = CreateTestSharedQuadState(
3087           filter_pass_to_target_transform_, filter_pass_layer_rect_,
3088           filter_pass.get(), gfx::RRectF());
3089       auto* filter_pass_quad =
3090           root_pass->CreateAndAppendDrawQuad<AggregatedRenderPassDrawQuad>();
3091       filter_pass_quad->SetAll(
3092           shared_state, filter_pass_layer_rect_, filter_pass_layer_rect_,
3093           /*needs_blending=*/true, filter_pass_id, 0, gfx::RectF(), gfx::Size(),
3094           gfx::Vector2dF(1.0f, 1.0f),  // filters_scale
3095           gfx::PointF(),               // filters_origin
3096           gfx::RectF(),                // tex_coord_rect
3097           false,                       // force_anti_aliasing_off
3098           backdrop_filter_quality_,    // backdrop_filter_quality
3099           can_use_backdrop_filter_cache_);
3100     }
3101 
3102     const int kGridWidth = device_viewport_rect.width() / 3;
3103     const int kGridHeight = device_viewport_rect.height() / 3;
3104     gfx::Rect left_rect =
3105         gfx::Rect(kGridWidth / 2, kGridHeight, kGridWidth, kGridHeight);
3106 
3107     SharedQuadState* shared_state =
3108         CreateTestSharedQuadState(identity_quad_to_target_transform, left_rect,
3109                                   root_pass.get(), gfx::RRectF());
3110     auto* color_quad = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
3111     color_quad->SetNew(shared_state, left_rect, left_rect, SK_ColorGREEN,
3112                        false);
3113 
3114     gfx::Rect right_rect =
3115         gfx::Rect(kGridWidth * 3 / 2, kGridHeight, kGridWidth, kGridHeight);
3116     shared_state =
3117         CreateTestSharedQuadState(identity_quad_to_target_transform, right_rect,
3118                                   root_pass.get(), gfx::RRectF());
3119     color_quad = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
3120     color_quad->SetNew(shared_state, right_rect, right_rect, SK_ColorRED,
3121                        false);
3122 
3123     shared_state = CreateTestSharedQuadState(identity_quad_to_target_transform,
3124                                              device_viewport_rect,
3125                                              root_pass.get(), gfx::RRectF());
3126     auto* background_quad =
3127         root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
3128     background_quad->SetNew(shared_state, device_viewport_rect,
3129                             device_viewport_rect, SK_ColorWHITE, false);
3130 
3131     pass_list_.push_back(std::move(filter_pass));
3132     pass_list_.push_back(std::move(root_pass));
3133   }
3134 
3135   AggregatedRenderPassList pass_list_;
3136   cc::FilterOperations backdrop_filters_;
3137   base::Optional<gfx::RRectF> backdrop_filter_bounds_;
3138   float backdrop_filter_quality_ = 1.0f;
3139   bool can_use_backdrop_filter_cache_ = false;
3140   gfx::Transform filter_pass_to_target_transform_;
3141   gfx::Rect filter_pass_layer_rect_;
3142 };
3143 
TEST_F(GLRendererPixelTestWithBackdropFilter,FilterQuality)3144 TEST_F(GLRendererPixelTestWithBackdropFilter, FilterQuality) {
3145   this->backdrop_filters_.Append(cc::FilterOperation::CreateBlurFilter(2.0f));
3146   this->filter_pass_layer_rect_ = gfx::Rect(this->device_viewport_size_);
3147   this->backdrop_filter_bounds_ =
3148       gfx::RRectF(gfx::RectF(this->filter_pass_layer_rect_));
3149   this->backdrop_filter_quality_ = 1.0f;
3150   this->SetUpRenderPassList();
3151   EXPECT_TRUE(this->RunPixelTest(
3152       &this->pass_list_,
3153       base::FilePath(FILE_PATH_LITERAL("gl_backdrop_filter_1.png")),
3154       cc::FuzzyPixelOffByOneComparator(true)));
3155   this->backdrop_filter_quality_ = 0.33f;
3156   this->SetUpRenderPassList();
3157   EXPECT_TRUE(this->RunPixelTest(
3158       &this->pass_list_,
3159       base::FilePath(FILE_PATH_LITERAL("gl_backdrop_filter_2.png")),
3160       cc::FuzzyPixelOffByOneComparator(true)));
3161 }
3162 
TEST_F(GLRendererPixelTestWithBackdropFilter,CachedResultOfBackdropFilter)3163 TEST_F(GLRendererPixelTestWithBackdropFilter, CachedResultOfBackdropFilter) {
3164   this->backdrop_filters_.Append(cc::FilterOperation::CreateBlurFilter(2.0f));
3165   this->filter_pass_layer_rect_ = gfx::Rect(this->device_viewport_size_);
3166   this->backdrop_filter_bounds_ =
3167       gfx::RRectF(gfx::RectF(this->filter_pass_layer_rect_));
3168   // Set the flag to use cached backdrop filtered texture. This makes the
3169   // GLRenderer cache backdrop filtered result.
3170   this->can_use_backdrop_filter_cache_ = true;
3171   this->SetUpRenderPassList();
3172 
3173   EXPECT_TRUE(this->RunPixelTest(
3174       &this->pass_list_,
3175       base::FilePath(FILE_PATH_LITERAL("gl_backdrop_filter_1.png")),
3176       cc::FuzzyPixelOffByOneComparator(true)));
3177 
3178   // Same render pass list makes the GLRenderer to skip backdrop filter
3179   // calculation and use cached texture. This should correctly produce the
3180   // same output image.
3181   this->SetUpRenderPassList();
3182   EXPECT_TRUE(this->RunPixelTest(
3183       &this->pass_list_,
3184       base::FilePath(FILE_PATH_LITERAL("gl_backdrop_filter_1.png")),
3185       cc::FuzzyPixelOffByOneComparator(true)));
3186 
3187   // To prove the cached texture is used, change a quad on the root pass which
3188   // is beneath the backdrop filter. The output image should still be the same
3189   // as before.
3190   this->SetUpRenderPassList();
3191   DrawQuad* background_quad = *pass_list_.back()->quad_list.rbegin();
3192   static_cast<SolidColorDrawQuad*>(background_quad)->color = SK_ColorYELLOW;
3193   EXPECT_TRUE(this->RunPixelTest(
3194       &this->pass_list_,
3195       base::FilePath(FILE_PATH_LITERAL("gl_backdrop_filter_1.png")),
3196       cc::FuzzyPixelOffByOneComparator(true)));
3197 
3198   // Set|can_use_backdrop_filter_cache_| to false to make GLRenderer re-run the
3199   // backdrop filter calculation
3200   this->can_use_backdrop_filter_cache_ = false;
3201   this->SetUpRenderPassList();
3202   background_quad = *pass_list_.back()->quad_list.rbegin();
3203   static_cast<SolidColorDrawQuad*>(background_quad)->color = SK_ColorYELLOW;
3204   EXPECT_TRUE(this->RunPixelTest(
3205       &this->pass_list_,
3206       base::FilePath(FILE_PATH_LITERAL("gl_backdrop_filter_3.png")),
3207       cc::FuzzyPixelOffByOneComparator(true)));
3208 }
3209 
3210 class ExternalStencilPixelTest : public VizPixelTestWithParam {
3211  protected:
ClearBackgroundToGreen()3212   void ClearBackgroundToGreen() {
3213     GLES2Interface* gl = this->output_surface_->context_provider()->ContextGL();
3214     this->output_surface_->EnsureBackbuffer();
3215     this->output_surface_->Reshape(this->device_viewport_size_, 1,
3216                                    gfx::ColorSpace(),
3217                                    gfx::BufferFormat::RGBA_8888, false);
3218     gl->ClearColor(0.f, 1.f, 0.f, 1.f);
3219     gl->Clear(GL_COLOR_BUFFER_BIT);
3220   }
3221 
PopulateStencilBuffer()3222   void PopulateStencilBuffer() {
3223     // Set two quadrants of the stencil buffer to 1.
3224     GLES2Interface* gl = this->output_surface_->context_provider()->ContextGL();
3225     this->output_surface_->EnsureBackbuffer();
3226     this->output_surface_->Reshape(this->device_viewport_size_, 1,
3227                                    gfx::ColorSpace(),
3228                                    gfx::BufferFormat::RGBA_8888, false);
3229     gl->ClearStencil(0);
3230     gl->Clear(GL_STENCIL_BUFFER_BIT);
3231     gl->Enable(GL_SCISSOR_TEST);
3232     gl->ClearStencil(1);
3233     gl->Scissor(0, 0, this->device_viewport_size_.width() / 2,
3234                 this->device_viewport_size_.height() / 2);
3235     gl->Clear(GL_STENCIL_BUFFER_BIT);
3236     gl->Scissor(this->device_viewport_size_.width() / 2,
3237                 this->device_viewport_size_.height() / 2,
3238                 this->device_viewport_size_.width(),
3239                 this->device_viewport_size_.height());
3240     gl->Clear(GL_STENCIL_BUFFER_BIT);
3241     gl->StencilFunc(GL_EQUAL, 1, 1);
3242   }
3243 };
3244 
3245 // TODO(crbug.com/939442): Enable these tests for SkiaRenderer.
3246 INSTANTIATE_TEST_SUITE_P(,
3247                          ExternalStencilPixelTest,
3248                          testing::Values(RendererType::kGL),
3249                          testing::PrintToStringParamName());
3250 
TEST_P(ExternalStencilPixelTest,StencilTestEnabled)3251 TEST_P(ExternalStencilPixelTest, StencilTestEnabled) {
3252   this->ClearBackgroundToGreen();
3253   this->PopulateStencilBuffer();
3254   this->EnableExternalStencilTest();
3255 
3256   // Draw a blue quad that covers the entire device viewport. It should be
3257   // clipped to the bottom left and top right corners by the external stencil.
3258   gfx::Rect rect(this->device_viewport_size_);
3259   AggregatedRenderPassId id{1};
3260   auto pass = CreateTestRootRenderPass(id, rect);
3261   SharedQuadState* blue_shared_state = CreateTestSharedQuadState(
3262       gfx::Transform(), rect, pass.get(), gfx::RRectF());
3263   auto* blue = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
3264   blue->SetNew(blue_shared_state, rect, rect, SK_ColorBLUE, false);
3265   pass->has_transparent_background = false;
3266   AggregatedRenderPassList pass_list;
3267   pass_list.push_back(std::move(pass));
3268 
3269   EXPECT_TRUE(this->RunPixelTest(
3270       &pass_list,
3271       base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")),
3272       cc::ExactPixelComparator(true)));
3273 }
3274 
TEST_P(ExternalStencilPixelTest,StencilTestDisabled)3275 TEST_P(ExternalStencilPixelTest, StencilTestDisabled) {
3276   this->PopulateStencilBuffer();
3277 
3278   // Draw a green quad that covers the entire device viewport. The stencil
3279   // buffer should be ignored.
3280   gfx::Rect rect(this->device_viewport_size_);
3281   AggregatedRenderPassId id{1};
3282   auto pass = CreateTestRootRenderPass(id, rect);
3283   SharedQuadState* green_shared_state = CreateTestSharedQuadState(
3284       gfx::Transform(), rect, pass.get(), gfx::RRectF());
3285   auto* green = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
3286   green->SetNew(green_shared_state, rect, rect, SK_ColorGREEN, false);
3287   AggregatedRenderPassList pass_list;
3288   pass_list.push_back(std::move(pass));
3289 
3290   EXPECT_TRUE(this->RunPixelTest(&pass_list,
3291                                  base::FilePath(FILE_PATH_LITERAL("green.png")),
3292                                  cc::ExactPixelComparator(true)));
3293 }
3294 
TEST_P(ExternalStencilPixelTest,RenderSurfacesIgnoreStencil)3295 TEST_P(ExternalStencilPixelTest, RenderSurfacesIgnoreStencil) {
3296   // The stencil test should apply only to the final render pass.
3297   this->ClearBackgroundToGreen();
3298   this->PopulateStencilBuffer();
3299   this->EnableExternalStencilTest();
3300 
3301   gfx::Rect viewport_rect(this->device_viewport_size_);
3302 
3303   AggregatedRenderPassId root_pass_id{1};
3304   auto root_pass = CreateTestRootRenderPass(root_pass_id, viewport_rect);
3305   root_pass->has_transparent_background = false;
3306 
3307   AggregatedRenderPassId child_pass_id{2};
3308   gfx::Rect pass_rect(this->device_viewport_size_);
3309   gfx::Transform transform_to_root;
3310   auto child_pass =
3311       CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
3312 
3313   gfx::Transform quad_to_target_transform;
3314   SharedQuadState* shared_state = CreateTestSharedQuadState(
3315       quad_to_target_transform, viewport_rect, child_pass.get(), gfx::RRectF());
3316 
3317   gfx::Rect blue_rect(0, 0, this->device_viewport_size_.width(),
3318                       this->device_viewport_size_.height());
3319   auto* blue = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
3320   blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
3321 
3322   SharedQuadState* pass_shared_state = CreateTestSharedQuadState(
3323       gfx::Transform(), pass_rect, root_pass.get(), gfx::RRectF());
3324   CreateTestRenderPassDrawQuad(pass_shared_state, pass_rect, child_pass_id,
3325                                root_pass.get());
3326   AggregatedRenderPassList pass_list;
3327   pass_list.push_back(std::move(child_pass));
3328   pass_list.push_back(std::move(root_pass));
3329 
3330   EXPECT_TRUE(this->RunPixelTest(
3331       &pass_list,
3332       base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")),
3333       cc::ExactPixelComparator(true)));
3334 }
3335 
3336 // Software renderer does not support anti-aliased edges.
TEST_P(GPURendererPixelTest,AntiAliasing)3337 TEST_P(GPURendererPixelTest, AntiAliasing) {
3338   gfx::Rect rect(this->device_viewport_size_);
3339 
3340   AggregatedRenderPassId id{1};
3341   auto pass = CreateTestRootRenderPass(id, rect);
3342 
3343   gfx::Transform red_quad_to_target_transform;
3344   red_quad_to_target_transform.Rotate(10);
3345   SharedQuadState* red_shared_state = CreateTestSharedQuadState(
3346       red_quad_to_target_transform, rect, pass.get(), gfx::RRectF());
3347 
3348   auto* red = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
3349   red->SetNew(red_shared_state, rect, rect, SK_ColorRED, false);
3350 
3351   gfx::Transform yellow_quad_to_target_transform;
3352   yellow_quad_to_target_transform.Rotate(5);
3353   SharedQuadState* yellow_shared_state = CreateTestSharedQuadState(
3354       yellow_quad_to_target_transform, rect, pass.get(), gfx::RRectF());
3355 
3356   auto* yellow = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
3357   yellow->SetNew(yellow_shared_state, rect, rect, SK_ColorYELLOW, false);
3358 
3359   gfx::Transform blue_quad_to_target_transform;
3360   SharedQuadState* blue_shared_state = CreateTestSharedQuadState(
3361       blue_quad_to_target_transform, rect, pass.get(), gfx::RRectF());
3362 
3363   auto* blue = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
3364   blue->SetNew(blue_shared_state, rect, rect, SK_ColorBLUE, false);
3365 
3366   AggregatedRenderPassList pass_list;
3367   pass_list.push_back(std::move(pass));
3368 
3369   EXPECT_TRUE(
3370       this->RunPixelTest(&pass_list,
3371                          base::FilePath(FILE_PATH_LITERAL("anti_aliasing_.png"))
3372                              .InsertBeforeExtensionASCII(this->renderer_str()),
3373                          cc::FuzzyPixelOffByOneComparator(true)));
3374 }
3375 
3376 // Software renderer does not support anti-aliased edges.
TEST_P(GPURendererPixelTest,AntiAliasingPerspective)3377 TEST_P(GPURendererPixelTest, AntiAliasingPerspective) {
3378   gfx::Rect rect(this->device_viewport_size_);
3379 
3380   auto pass = CreateTestRootRenderPass(AggregatedRenderPassId{1}, rect);
3381 
3382   gfx::Rect red_rect(0, 0, 180, 500);
3383   gfx::Transform red_quad_to_target_transform(
3384       1.0f, 2.4520f, 10.6206f, 19.0f, 0.0f, 0.3528f, 5.9737f, 9.5f, 0.0f,
3385       -0.2250f, -0.9744f, 0.0f, 0.0f, 0.0225f, 0.0974f, 1.0f);
3386   SharedQuadState* red_shared_state = CreateTestSharedQuadState(
3387       red_quad_to_target_transform, red_rect, pass.get(), gfx::RRectF());
3388   auto* red = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
3389   red->SetNew(red_shared_state, red_rect, red_rect, SK_ColorRED, false);
3390 
3391   gfx::Rect green_rect(19, 7, 180, 10);
3392   SharedQuadState* green_shared_state = CreateTestSharedQuadState(
3393       gfx::Transform(), green_rect, pass.get(), gfx::RRectF());
3394   auto* green = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
3395   green->SetNew(green_shared_state, green_rect, green_rect, SK_ColorGREEN,
3396                 false);
3397 
3398   SharedQuadState* blue_shared_state = CreateTestSharedQuadState(
3399       gfx::Transform(), rect, pass.get(), gfx::RRectF());
3400   auto* blue = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
3401   blue->SetNew(blue_shared_state, rect, rect, SK_ColorBLUE, false);
3402 
3403   AggregatedRenderPassList pass_list;
3404   pass_list.push_back(std::move(pass));
3405 
3406   EXPECT_TRUE(this->RunPixelTest(
3407       &pass_list,
3408       base::FilePath(FILE_PATH_LITERAL("anti_aliasing_perspective_.png"))
3409           .InsertBeforeExtensionASCII(this->renderer_str()),
3410       cc::FuzzyPixelOffByOneComparator(true)));
3411 }
3412 
3413 // This test tests that anti-aliasing works for axis aligned quads.
3414 // Anti-aliasing is only supported in the gl and skia renderers.
TEST_P(GPURendererPixelTest,AxisAligned)3415 TEST_P(GPURendererPixelTest, AxisAligned) {
3416   gfx::Rect rect(this->device_viewport_size_);
3417 
3418   AggregatedRenderPassId id{1};
3419   gfx::Transform transform_to_root;
3420   auto pass = CreateTestRenderPass(id, rect, transform_to_root);
3421 
3422   CreateTestAxisAlignedQuads(rect, SK_ColorRED, SK_ColorYELLOW, false, false,
3423                              pass.get());
3424 
3425   gfx::Transform blue_quad_to_target_transform;
3426   SharedQuadState* blue_shared_state = CreateTestSharedQuadState(
3427       blue_quad_to_target_transform, rect, pass.get(), gfx::RRectF());
3428 
3429   auto* blue = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
3430   blue->SetNew(blue_shared_state, rect, rect, SK_ColorBLUE, false);
3431 
3432   AggregatedRenderPassList pass_list;
3433   pass_list.push_back(std::move(pass));
3434 
3435   EXPECT_TRUE(this->RunPixelTest(
3436       &pass_list, base::FilePath(FILE_PATH_LITERAL("axis_aligned.png")),
3437       cc::FuzzyPixelOffByOneComparator(true)));
3438 }
3439 
3440 // This test tests that forcing anti-aliasing off works as expected for
3441 // solid color draw quads.
3442 // Anti-aliasing is only supported in the gl and skia renderers.
TEST_P(GPURendererPixelTest,SolidColorDrawQuadForceAntiAliasingOff)3443 TEST_P(GPURendererPixelTest, SolidColorDrawQuadForceAntiAliasingOff) {
3444   gfx::Rect rect(this->device_viewport_size_);
3445 
3446   AggregatedRenderPassId id{1};
3447   gfx::Transform transform_to_root;
3448   auto pass = CreateTestRenderPass(id, rect, transform_to_root);
3449   pass->has_transparent_background = false;
3450 
3451   gfx::Transform hole_quad_to_target_transform;
3452   hole_quad_to_target_transform.Translate(50, 50);
3453   hole_quad_to_target_transform.Scale(0.5f + 1.0f / (rect.width() * 2.0f),
3454                                       0.5f + 1.0f / (rect.height() * 2.0f));
3455   SharedQuadState* hole_shared_state = CreateTestSharedQuadState(
3456       hole_quad_to_target_transform, rect, pass.get(), gfx::RRectF());
3457 
3458   auto* hole = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
3459   hole->SetAll(hole_shared_state, rect, rect, false, SK_ColorTRANSPARENT, true);
3460 
3461   gfx::Transform green_quad_to_target_transform;
3462   SharedQuadState* green_shared_state = CreateTestSharedQuadState(
3463       green_quad_to_target_transform, rect, pass.get(), gfx::RRectF());
3464 
3465   auto* green = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
3466   green->SetNew(green_shared_state, rect, rect, SK_ColorGREEN, false);
3467 
3468   AggregatedRenderPassList pass_list;
3469   pass_list.push_back(std::move(pass));
3470 
3471   EXPECT_TRUE(this->RunPixelTest(
3472       &pass_list,
3473       base::FilePath(FILE_PATH_LITERAL("force_anti_aliasing_off.png")),
3474       cc::ExactPixelComparator(/*discard_alpha=*/true)));
3475 }
3476 
3477 // This test tests that forcing anti-aliasing off works as expected for
3478 // render pass draw quads.
3479 // Anti-aliasing is only supported in the gl and skia renderers.
TEST_P(GPURendererPixelTest,RenderPassDrawQuadForceAntiAliasingOff)3480 TEST_P(GPURendererPixelTest, RenderPassDrawQuadForceAntiAliasingOff) {
3481   gfx::Rect rect(this->device_viewport_size_);
3482 
3483   AggregatedRenderPassId root_pass_id{1};
3484   gfx::Transform transform_to_root;
3485   auto root_pass = CreateTestRenderPass(root_pass_id, rect, transform_to_root);
3486 
3487   AggregatedRenderPassId child_pass_id{2};
3488   gfx::Transform child_pass_transform;
3489   auto child_pass =
3490       CreateTestRenderPass(child_pass_id, rect, child_pass_transform);
3491 
3492   gfx::Transform quad_to_target_transform;
3493   SharedQuadState* hole_shared_state = CreateTestSharedQuadState(
3494       quad_to_target_transform, rect, child_pass.get(), gfx::RRectF());
3495   SolidColorDrawQuad* hole =
3496       child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
3497   hole->SetAll(hole_shared_state, rect, rect, false, SK_ColorTRANSPARENT,
3498                false);
3499 
3500   bool needs_blending = false;
3501   bool force_anti_aliasing_off = true;
3502   float backdrop_filter_quality = 1.0f;
3503   bool can_use_backdrop_filter_cache = false;
3504   gfx::Transform hole_pass_to_target_transform;
3505   hole_pass_to_target_transform.Translate(50, 50);
3506   hole_pass_to_target_transform.Scale(0.5f + 1.0f / (rect.width() * 2.0f),
3507                                       0.5f + 1.0f / (rect.height() * 2.0f));
3508   SharedQuadState* pass_shared_state = CreateTestSharedQuadState(
3509       hole_pass_to_target_transform, rect, root_pass.get(), gfx::RRectF());
3510   AggregatedRenderPassDrawQuad* pass_quad =
3511       root_pass->CreateAndAppendDrawQuad<AggregatedRenderPassDrawQuad>();
3512   pass_quad->SetAll(pass_shared_state, rect, rect, needs_blending,
3513                     child_pass_id, 0, gfx::RectF(), gfx::Size(),
3514                     gfx::Vector2dF(), gfx::PointF(), gfx::RectF(rect),
3515                     force_anti_aliasing_off, backdrop_filter_quality,
3516                     can_use_backdrop_filter_cache);
3517 
3518   gfx::Transform green_quad_to_target_transform;
3519   SharedQuadState* green_shared_state = CreateTestSharedQuadState(
3520       green_quad_to_target_transform, rect, root_pass.get(), gfx::RRectF());
3521 
3522   SolidColorDrawQuad* green =
3523       root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
3524   green->SetNew(green_shared_state, rect, rect, SK_ColorGREEN, false);
3525 
3526   AggregatedRenderPassList pass_list;
3527   pass_list.push_back(std::move(child_pass));
3528   pass_list.push_back(std::move(root_pass));
3529 
3530   EXPECT_TRUE(this->RunPixelTest(
3531       &pass_list,
3532       base::FilePath(FILE_PATH_LITERAL("force_anti_aliasing_off.png")),
3533       cc::ExactPixelComparator(/*discard_alpha=*/true)));
3534 }
3535 
3536 // This test tests that forcing anti-aliasing off works as expected for
3537 // tile draw quads.
3538 // Anti-aliasing is only supported in the gl and skia renderers.
TEST_P(GPURendererPixelTest,TileDrawQuadForceAntiAliasingOff)3539 TEST_P(GPURendererPixelTest, TileDrawQuadForceAntiAliasingOff) {
3540   gfx::Rect rect(this->device_viewport_size_);
3541 
3542   SkBitmap bitmap;
3543   bitmap.allocN32Pixels(32, 32);
3544   SkCanvas canvas(bitmap, SkSurfaceProps{});
3545   canvas.clear(SK_ColorTRANSPARENT);
3546 
3547   gfx::Size tile_size(32, 32);
3548   ResourceId resource;
3549   if (!is_software_renderer()) {
3550     resource = CreateGpuResource(
3551         this->child_context_provider_, this->child_resource_provider_.get(),
3552         tile_size, RGBA_8888, gfx::ColorSpace(), MakePixelSpan(bitmap));
3553   } else {
3554     resource = this->AllocateAndFillSoftwareResource(tile_size, bitmap);
3555   }
3556 
3557   // Return the mapped resource id.
3558   std::unordered_map<ResourceId, ResourceId> resource_map =
3559       cc::SendResourceAndGetChildToParentMap(
3560           {resource}, this->resource_provider_.get(),
3561           this->child_resource_provider_.get(),
3562           this->child_context_provider_.get());
3563   ResourceId mapped_resource = resource_map[resource];
3564 
3565   AggregatedRenderPassId id{1};
3566   gfx::Transform transform_to_root;
3567   auto pass = CreateTestRenderPass(id, rect, transform_to_root);
3568   pass->has_transparent_background = false;
3569 
3570   bool contents_premultiplied = true;
3571   bool needs_blending = false;
3572   bool nearest_neighbor = true;
3573   bool force_anti_aliasing_off = true;
3574   gfx::Transform hole_quad_to_target_transform;
3575   hole_quad_to_target_transform.Translate(50, 50);
3576   hole_quad_to_target_transform.Scale(0.5f + 1.0f / (rect.width() * 2.0f),
3577                                       0.5f + 1.0f / (rect.height() * 2.0f));
3578   SharedQuadState* hole_shared_state = CreateTestSharedQuadState(
3579       hole_quad_to_target_transform, rect, pass.get(), gfx::RRectF());
3580   TileDrawQuad* hole = pass->CreateAndAppendDrawQuad<TileDrawQuad>();
3581   hole->SetNew(hole_shared_state, rect, rect, needs_blending, mapped_resource,
3582                gfx::RectF(gfx::Rect(tile_size)), tile_size,
3583                contents_premultiplied, nearest_neighbor,
3584                force_anti_aliasing_off);
3585 
3586   gfx::Transform green_quad_to_target_transform;
3587   SharedQuadState* green_shared_state = CreateTestSharedQuadState(
3588       green_quad_to_target_transform, rect, pass.get(), gfx::RRectF());
3589 
3590   SolidColorDrawQuad* green =
3591       pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
3592   green->SetNew(green_shared_state, rect, rect, SK_ColorGREEN, false);
3593 
3594   AggregatedRenderPassList pass_list;
3595   pass_list.push_back(std::move(pass));
3596 
3597   EXPECT_TRUE(this->RunPixelTest(
3598       &pass_list,
3599       base::FilePath(FILE_PATH_LITERAL("force_anti_aliasing_off.png")),
3600       cc::ExactPixelComparator(/*discard_alpha=*/true)));
3601 }
3602 
3603 // This test tests that forcing anti-aliasing off works as expected while
3604 // blending is still enabled.
3605 // Anti-aliasing is only supported in the gl and skia renderers.
TEST_P(GPURendererPixelTest,BlendingWithoutAntiAliasing)3606 TEST_P(GPURendererPixelTest, BlendingWithoutAntiAliasing) {
3607   gfx::Rect rect(this->device_viewport_size_);
3608 
3609   AggregatedRenderPassId id{1};
3610   gfx::Transform transform_to_root;
3611   auto pass = CreateTestRenderPass(id, rect, transform_to_root);
3612   pass->has_transparent_background = false;
3613 
3614   CreateTestAxisAlignedQuads(rect, 0x800000FF, 0x8000FF00, true, true,
3615                              pass.get());
3616 
3617   SharedQuadState* background_quad_state = CreateTestSharedQuadState(
3618       gfx::Transform(), rect, pass.get(), gfx::RRectF());
3619   auto* background_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
3620   background_quad->SetNew(background_quad_state, rect, rect, SK_ColorBLACK,
3621                           false);
3622 
3623   AggregatedRenderPassList pass_list;
3624   pass_list.push_back(std::move(pass));
3625 
3626   EXPECT_TRUE(this->RunPixelTest(
3627       &pass_list,
3628       base::FilePath(FILE_PATH_LITERAL("translucent_quads_no_aa.png")),
3629       cc::ExactPixelComparator(/*discard_alpha=*/true)));
3630 }
3631 
3632 // Trilinear filtering is only supported in the gl renderer.
3633 // TODO(https://crbug.com/1044841): Flaky, especially on Linux/TSAN and Fuchsia.
TEST_P(GPURendererPixelTest,TrilinearFiltering)3634 TEST_P(GPURendererPixelTest, TrilinearFiltering) {
3635   gfx::Rect viewport_rect(this->device_viewport_size_);
3636 
3637   AggregatedRenderPassId root_pass_id{1};
3638   auto root_pass = CreateTestRootRenderPass(root_pass_id, viewport_rect);
3639   root_pass->has_transparent_background = false;
3640 
3641   AggregatedRenderPassId child_pass_id{2};
3642   gfx::Transform transform_to_root;
3643   gfx::Rect child_pass_rect(
3644       ScaleToCeiledSize(this->device_viewport_size_, 4.0f));
3645   bool generate_mipmap = true;
3646   auto child_pass = std::make_unique<AggregatedRenderPass>();
3647   child_pass->SetAll(
3648       child_pass_id, child_pass_rect, child_pass_rect, transform_to_root,
3649       cc::FilterOperations(), cc::FilterOperations(), gfx::RRectF(),
3650       gfx::ContentColorUsage::kSRGB, false, false, false, generate_mipmap);
3651 
3652   gfx::Rect red_rect(child_pass_rect);
3653   // Small enough red rect that linear filtering will miss it but large enough
3654   // that it makes a meaningful contribution when using trilinear filtering.
3655   red_rect.ClampToCenteredSize(gfx::Size(2, child_pass_rect.height()));
3656   SharedQuadState* red_shared_state = CreateTestSharedQuadState(
3657       gfx::Transform(), red_rect, child_pass.get(), gfx::RRectF());
3658   auto* red = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
3659   red->SetNew(red_shared_state, red_rect, red_rect, SK_ColorRED, false);
3660 
3661   SharedQuadState* blue_shared_state = CreateTestSharedQuadState(
3662       gfx::Transform(), child_pass_rect, child_pass.get(), gfx::RRectF());
3663   auto* blue = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
3664   blue->SetNew(blue_shared_state, child_pass_rect, child_pass_rect,
3665                SK_ColorBLUE, false);
3666 
3667   gfx::Transform child_to_root_transform(SkMatrix::MakeRectToRect(
3668       RectToSkRect(child_pass_rect), RectToSkRect(viewport_rect),
3669       SkMatrix::kFill_ScaleToFit));
3670   SharedQuadState* child_pass_shared_state = CreateTestSharedQuadState(
3671       child_to_root_transform, child_pass_rect, root_pass.get(), gfx::RRectF());
3672   auto* child_pass_quad =
3673       root_pass->CreateAndAppendDrawQuad<AggregatedRenderPassDrawQuad>();
3674   child_pass_quad->SetNew(child_pass_shared_state, child_pass_rect,
3675                           child_pass_rect, child_pass_id, 0, gfx::RectF(),
3676                           gfx::Size(), gfx::Vector2dF(), gfx::PointF(),
3677                           gfx::RectF(child_pass_rect), false, 1.0f);
3678 
3679   AggregatedRenderPassList pass_list;
3680   pass_list.push_back(std::move(child_pass));
3681   pass_list.push_back(std::move(root_pass));
3682 
3683   EXPECT_TRUE(this->RunPixelTest(
3684       &pass_list, base::FilePath(FILE_PATH_LITERAL("trilinear_filtering.png")),
3685       cc::ExactPixelComparator(true)));
3686 }
3687 
3688 class SoftwareRendererPixelTest : public VizPixelTest {
3689  public:
SoftwareRendererPixelTest()3690   SoftwareRendererPixelTest() : VizPixelTest(RendererType::kSoftware) {}
3691 };
3692 
TEST_F(SoftwareRendererPixelTest,PictureDrawQuadIdentityScale)3693 TEST_F(SoftwareRendererPixelTest, PictureDrawQuadIdentityScale) {
3694   gfx::Rect viewport(this->device_viewport_size_);
3695   // TODO(enne): the renderer should figure this out on its own.
3696   ResourceFormat texture_format = RGBA_8888;
3697   bool nearest_neighbor = false;
3698 
3699   AggregatedRenderPassId id{1};
3700   gfx::Transform transform_to_root;
3701   auto pass = CreateTestRenderPass(id, viewport, transform_to_root);
3702 
3703   // One clipped blue quad in the lower right corner.  Outside the clip
3704   // is red, which should not appear.
3705   gfx::Rect blue_rect(gfx::Size(100, 100));
3706   gfx::Rect blue_clip_rect(gfx::Point(50, 50), gfx::Size(50, 50));
3707 
3708   std::unique_ptr<cc::FakeRecordingSource> blue_recording =
3709       cc::FakeRecordingSource::CreateFilledRecordingSource(blue_rect.size());
3710   cc::PaintFlags red_flags;
3711   red_flags.setColor(SK_ColorRED);
3712   blue_recording->add_draw_rect_with_flags(blue_rect, red_flags);
3713   cc::PaintFlags blue_flags;
3714   blue_flags.setColor(SK_ColorBLUE);
3715   blue_recording->add_draw_rect_with_flags(blue_clip_rect, blue_flags);
3716   blue_recording->Rerecord();
3717 
3718   scoped_refptr<cc::RasterSource> blue_raster_source =
3719       blue_recording->CreateRasterSource();
3720 
3721   gfx::Vector2d offset(viewport.bottom_right() - blue_rect.bottom_right());
3722   bool needs_blending = true;
3723   gfx::Transform blue_quad_to_target_transform;
3724   blue_quad_to_target_transform.Translate(offset.x(), offset.y());
3725   gfx::Rect blue_target_clip_rect = cc::MathUtil::MapEnclosingClippedRect(
3726       blue_quad_to_target_transform, blue_clip_rect);
3727   SharedQuadState* blue_shared_state =
3728       CreateTestSharedQuadStateClipped(blue_quad_to_target_transform, blue_rect,
3729                                        blue_target_clip_rect, pass.get());
3730 
3731   auto* blue_quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
3732 
3733   blue_quad->SetNew(blue_shared_state,
3734                     viewport,  // Intentionally bigger than clip.
3735                     viewport, needs_blending, gfx::RectF(viewport),
3736                     viewport.size(), nearest_neighbor, texture_format, viewport,
3737                     1.f, {}, blue_raster_source->GetDisplayItemList());
3738 
3739   // One viewport-filling green quad.
3740   std::unique_ptr<cc::FakeRecordingSource> green_recording =
3741       cc::FakeRecordingSource::CreateFilledRecordingSource(viewport.size());
3742   cc::PaintFlags green_flags;
3743   green_flags.setColor(SK_ColorGREEN);
3744   green_recording->add_draw_rect_with_flags(viewport, green_flags);
3745   green_recording->Rerecord();
3746   scoped_refptr<cc::RasterSource> green_raster_source =
3747       green_recording->CreateRasterSource();
3748 
3749   gfx::Transform green_quad_to_target_transform;
3750   SharedQuadState* green_shared_state = CreateTestSharedQuadState(
3751       green_quad_to_target_transform, viewport, pass.get(), gfx::RRectF());
3752 
3753   auto* green_quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
3754   green_quad->SetNew(green_shared_state, viewport, viewport, needs_blending,
3755                      gfx::RectF(0.f, 0.f, 1.f, 1.f), viewport.size(),
3756                      nearest_neighbor, texture_format, viewport, 1.f, {},
3757                      green_raster_source->GetDisplayItemList());
3758 
3759   AggregatedRenderPassList pass_list;
3760   pass_list.push_back(std::move(pass));
3761 
3762   EXPECT_TRUE(this->RunPixelTest(
3763       &pass_list,
3764       base::FilePath(FILE_PATH_LITERAL("green_with_blue_corner.png")),
3765       cc::ExactPixelComparator(true)));
3766 }
3767 
3768 // Not WithSkiaGPUBackend since that path currently requires tiles for opacity.
TEST_F(SoftwareRendererPixelTest,PictureDrawQuadOpacity)3769 TEST_F(SoftwareRendererPixelTest, PictureDrawQuadOpacity) {
3770   gfx::Rect viewport(this->device_viewport_size_);
3771   bool needs_blending = true;
3772   ResourceFormat texture_format = RGBA_8888;
3773   bool nearest_neighbor = false;
3774 
3775   AggregatedRenderPassId id{1};
3776   gfx::Transform transform_to_root;
3777   auto pass = CreateTestRenderPass(id, viewport, transform_to_root);
3778 
3779   // One viewport-filling 0.5-opacity green quad.
3780   std::unique_ptr<cc::FakeRecordingSource> green_recording =
3781       cc::FakeRecordingSource::CreateFilledRecordingSource(viewport.size());
3782   cc::PaintFlags green_flags;
3783   green_flags.setColor(SK_ColorGREEN);
3784   green_recording->add_draw_rect_with_flags(viewport, green_flags);
3785   green_recording->Rerecord();
3786   scoped_refptr<cc::RasterSource> green_raster_source =
3787       green_recording->CreateRasterSource();
3788 
3789   gfx::Transform green_quad_to_target_transform;
3790   SharedQuadState* green_shared_state = CreateTestSharedQuadState(
3791       green_quad_to_target_transform, viewport, pass.get(), gfx::RRectF());
3792   green_shared_state->opacity = 0.5f;
3793 
3794   auto* green_quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
3795   green_quad->SetNew(green_shared_state, viewport, viewport, needs_blending,
3796                      gfx::RectF(0, 0, 1, 1), viewport.size(), nearest_neighbor,
3797                      texture_format, viewport, 1.f, {},
3798                      green_raster_source->GetDisplayItemList());
3799 
3800   // One viewport-filling white quad.
3801   std::unique_ptr<cc::FakeRecordingSource> white_recording =
3802       cc::FakeRecordingSource::CreateFilledRecordingSource(viewport.size());
3803   cc::PaintFlags white_flags;
3804   white_flags.setColor(SK_ColorWHITE);
3805   white_recording->add_draw_rect_with_flags(viewport, white_flags);
3806   white_recording->Rerecord();
3807   scoped_refptr<cc::RasterSource> white_raster_source =
3808       white_recording->CreateRasterSource();
3809 
3810   gfx::Transform white_quad_to_target_transform;
3811   SharedQuadState* white_shared_state = CreateTestSharedQuadState(
3812       white_quad_to_target_transform, viewport, pass.get(), gfx::RRectF());
3813 
3814   auto* white_quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
3815   white_quad->SetNew(white_shared_state, viewport, viewport, needs_blending,
3816                      gfx::RectF(0, 0, 1, 1), viewport.size(), nearest_neighbor,
3817                      texture_format, viewport, 1.f, {},
3818                      white_raster_source->GetDisplayItemList());
3819 
3820   AggregatedRenderPassList pass_list;
3821   pass_list.push_back(std::move(pass));
3822 
3823   EXPECT_TRUE(this->RunPixelTest(
3824       &pass_list, base::FilePath(FILE_PATH_LITERAL("green_alpha.png")),
3825       cc::FuzzyPixelOffByOneComparator(true)));
3826 }
3827 
TEST_F(SoftwareRendererPixelTest,PictureDrawQuadOpacityWithAlpha)3828 TEST_F(SoftwareRendererPixelTest, PictureDrawQuadOpacityWithAlpha) {
3829   gfx::Rect viewport(this->device_viewport_size_);
3830   bool needs_blending = true;
3831   ResourceFormat texture_format = RGBA_8888;
3832   bool nearest_neighbor = false;
3833 
3834   AggregatedRenderPassId id{1};
3835   gfx::Transform transform_to_root;
3836   auto pass = CreateTestRenderPass(id, viewport, transform_to_root);
3837 
3838   // One viewport-filling 0.5-opacity transparent quad.
3839   std::unique_ptr<cc::FakeRecordingSource> transparent_recording =
3840       cc::FakeRecordingSource::CreateFilledRecordingSource(viewport.size());
3841   cc::PaintFlags transparent_flags;
3842   transparent_flags.setColor(SK_ColorTRANSPARENT);
3843   transparent_recording->add_draw_rect_with_flags(viewport, transparent_flags);
3844   transparent_recording->Rerecord();
3845   scoped_refptr<cc::RasterSource> transparent_raster_source =
3846       transparent_recording->CreateRasterSource();
3847 
3848   gfx::Transform transparent_quad_to_target_transform;
3849   SharedQuadState* transparent_shared_state =
3850       CreateTestSharedQuadState(transparent_quad_to_target_transform, viewport,
3851                                 pass.get(), gfx::RRectF());
3852   transparent_shared_state->opacity = 0.5f;
3853 
3854   auto* transparent_quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
3855   transparent_quad->SetNew(
3856       transparent_shared_state, viewport, viewport, needs_blending,
3857       gfx::RectF(0, 0, 1, 1), viewport.size(), nearest_neighbor, texture_format,
3858       viewport, 1.f, {}, transparent_raster_source->GetDisplayItemList());
3859 
3860   // One viewport-filling white quad.
3861   std::unique_ptr<cc::FakeRecordingSource> white_recording =
3862       cc::FakeRecordingSource::CreateFilledRecordingSource(viewport.size());
3863   cc::PaintFlags white_flags;
3864   white_flags.setColor(SK_ColorWHITE);
3865   white_recording->add_draw_rect_with_flags(viewport, white_flags);
3866   white_recording->Rerecord();
3867   scoped_refptr<cc::RasterSource> white_raster_source =
3868       white_recording->CreateRasterSource();
3869 
3870   gfx::Transform white_quad_to_target_transform;
3871   SharedQuadState* white_shared_state = CreateTestSharedQuadState(
3872       white_quad_to_target_transform, viewport, pass.get(), gfx::RRectF());
3873 
3874   auto* white_quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
3875   white_quad->SetNew(white_shared_state, viewport, viewport, needs_blending,
3876                      gfx::RectF(0, 0, 1, 1), viewport.size(), nearest_neighbor,
3877                      texture_format, viewport, 1.f, {},
3878                      white_raster_source->GetDisplayItemList());
3879 
3880   AggregatedRenderPassList pass_list;
3881   pass_list.push_back(std::move(pass));
3882 
3883   EXPECT_TRUE(this->RunPixelTest(&pass_list,
3884                                  base::FilePath(FILE_PATH_LITERAL("white.png")),
3885                                  cc::FuzzyPixelOffByOneComparator(true)));
3886 }
3887 
draw_point_color(SkCanvas * canvas,SkScalar x,SkScalar y,SkColor color)3888 void draw_point_color(SkCanvas* canvas, SkScalar x, SkScalar y, SkColor color) {
3889   SkPaint paint;
3890   paint.setColor(color);
3891   canvas->drawPoint(x, y, paint);
3892 }
3893 
3894 // If we disable image filtering, then a 2x2 bitmap should appear as four
3895 // huge sharp squares.
TEST_F(SoftwareRendererPixelTest,PictureDrawQuadDisableImageFiltering)3896 TEST_F(SoftwareRendererPixelTest, PictureDrawQuadDisableImageFiltering) {
3897   gfx::Rect viewport(this->device_viewport_size_);
3898   ResourceFormat texture_format = RGBA_8888;
3899   bool needs_blending = true;
3900   bool nearest_neighbor = false;
3901 
3902   AggregatedRenderPassId id{1};
3903   gfx::Transform transform_to_root;
3904   auto pass = CreateTestRenderPass(id, viewport, transform_to_root);
3905 
3906   sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(2, 2);
3907   ASSERT_NE(surface, nullptr);
3908   SkCanvas* canvas = surface->getCanvas();
3909   draw_point_color(canvas, 0, 0, SK_ColorGREEN);
3910   draw_point_color(canvas, 0, 1, SK_ColorBLUE);
3911   draw_point_color(canvas, 1, 0, SK_ColorBLUE);
3912   draw_point_color(canvas, 1, 1, SK_ColorGREEN);
3913 
3914   std::unique_ptr<cc::FakeRecordingSource> recording =
3915       cc::FakeRecordingSource::CreateFilledRecordingSource(viewport.size());
3916   cc::PaintFlags flags;
3917   flags.setFilterQuality(kLow_SkFilterQuality);
3918   recording->add_draw_image_with_flags(surface->makeImageSnapshot(),
3919                                        gfx::Point(), flags);
3920   recording->Rerecord();
3921   scoped_refptr<cc::RasterSource> raster_source =
3922       recording->CreateRasterSource();
3923 
3924   gfx::Transform quad_to_target_transform;
3925   SharedQuadState* shared_state = CreateTestSharedQuadState(
3926       quad_to_target_transform, viewport, pass.get(), gfx::RRectF());
3927 
3928   auto* quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
3929   quad->SetNew(shared_state, viewport, viewport, needs_blending,
3930                gfx::RectF(0, 0, 2, 2), viewport.size(), nearest_neighbor,
3931                texture_format, viewport, 1.f, {},
3932                raster_source->GetDisplayItemList());
3933 
3934   AggregatedRenderPassList pass_list;
3935   pass_list.push_back(std::move(pass));
3936 
3937   this->disable_picture_quad_image_filtering_ = true;
3938 
3939   EXPECT_TRUE(this->RunPixelTest(
3940       &pass_list,
3941       base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")),
3942       cc::ExactPixelComparator(true)));
3943 }
3944 
3945 // This disables filtering by setting |nearest_neighbor| on the
3946 // PictureDrawQuad.
TEST_F(SoftwareRendererPixelTest,PictureDrawQuadNearestNeighbor)3947 TEST_F(SoftwareRendererPixelTest, PictureDrawQuadNearestNeighbor) {
3948   gfx::Rect viewport(this->device_viewport_size_);
3949   ResourceFormat texture_format = RGBA_8888;
3950   bool needs_blending = true;
3951   bool nearest_neighbor = true;
3952 
3953   AggregatedRenderPassId id{1};
3954   gfx::Transform transform_to_root;
3955   auto pass = CreateTestRenderPass(id, viewport, transform_to_root);
3956 
3957   sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(2, 2);
3958   ASSERT_NE(surface, nullptr);
3959   SkCanvas* canvas = surface->getCanvas();
3960   draw_point_color(canvas, 0, 0, SK_ColorGREEN);
3961   draw_point_color(canvas, 0, 1, SK_ColorBLUE);
3962   draw_point_color(canvas, 1, 0, SK_ColorBLUE);
3963   draw_point_color(canvas, 1, 1, SK_ColorGREEN);
3964 
3965   std::unique_ptr<cc::FakeRecordingSource> recording =
3966       cc::FakeRecordingSource::CreateFilledRecordingSource(viewport.size());
3967   cc::PaintFlags flags;
3968   flags.setFilterQuality(kLow_SkFilterQuality);
3969   recording->add_draw_image_with_flags(surface->makeImageSnapshot(),
3970                                        gfx::Point(), flags);
3971   recording->Rerecord();
3972   scoped_refptr<cc::RasterSource> raster_source =
3973       recording->CreateRasterSource();
3974 
3975   gfx::Transform quad_to_target_transform;
3976   SharedQuadState* shared_state = CreateTestSharedQuadState(
3977       quad_to_target_transform, viewport, pass.get(), gfx::RRectF());
3978 
3979   auto* quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
3980   quad->SetNew(shared_state, viewport, viewport, needs_blending,
3981                gfx::RectF(0, 0, 2, 2), viewport.size(), nearest_neighbor,
3982                texture_format, viewport, 1.f, {},
3983                raster_source->GetDisplayItemList());
3984 
3985   AggregatedRenderPassList pass_list;
3986   pass_list.push_back(std::move(pass));
3987 
3988   EXPECT_TRUE(this->RunPixelTest(
3989       &pass_list,
3990       base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")),
3991       cc::ExactPixelComparator(true)));
3992 }
3993 
3994 // This disables filtering by setting |nearest_neighbor| on the
3995 // TileDrawQuad.
TEST_P(RendererPixelTest,TileDrawQuadNearestNeighbor)3996 TEST_P(RendererPixelTest, TileDrawQuadNearestNeighbor) {
3997   constexpr bool contents_premultiplied = true;
3998   constexpr bool needs_blending = true;
3999   constexpr bool nearest_neighbor = true;
4000   constexpr bool force_anti_aliasing_off = false;
4001   constexpr ResourceFormat resource_format = RGBA_8888;
4002   gfx::Rect viewport(this->device_viewport_size_);
4003 
4004   SkColorType ct = ResourceFormatToClosestSkColorType(!is_software_renderer(),
4005                                                       resource_format);
4006   SkImageInfo info = SkImageInfo::Make(2, 2, ct, kPremul_SkAlphaType);
4007   SkBitmap bitmap;
4008   bitmap.allocPixels(info);
4009   SkCanvas canvas(bitmap, SkSurfaceProps{});
4010   draw_point_color(&canvas, 0, 0, SK_ColorGREEN);
4011   draw_point_color(&canvas, 0, 1, SK_ColorBLUE);
4012   draw_point_color(&canvas, 1, 0, SK_ColorBLUE);
4013   draw_point_color(&canvas, 1, 1, SK_ColorGREEN);
4014 
4015   gfx::Size tile_size(2, 2);
4016   ResourceId resource;
4017   if (!is_software_renderer()) {
4018     resource = CreateGpuResource(
4019         this->child_context_provider_, this->child_resource_provider_.get(),
4020         tile_size, RGBA_8888, gfx::ColorSpace(), MakePixelSpan(bitmap));
4021   } else {
4022     resource = this->AllocateAndFillSoftwareResource(tile_size, bitmap);
4023   }
4024   // Return the mapped resource id.
4025   std::unordered_map<ResourceId, ResourceId> resource_map =
4026       cc::SendResourceAndGetChildToParentMap(
4027           {resource}, this->resource_provider_.get(),
4028           this->child_resource_provider_.get(),
4029           this->child_context_provider_.get());
4030   ResourceId mapped_resource = resource_map[resource];
4031 
4032   AggregatedRenderPassId id{1};
4033   gfx::Transform transform_to_root;
4034   auto pass = CreateTestRenderPass(id, viewport, transform_to_root);
4035 
4036   gfx::Transform quad_to_target_transform;
4037   SharedQuadState* shared_state = CreateTestSharedQuadState(
4038       quad_to_target_transform, viewport, pass.get(), gfx::RRectF());
4039 
4040   auto* quad = pass->CreateAndAppendDrawQuad<TileDrawQuad>();
4041   quad->SetNew(shared_state, viewport, viewport, needs_blending,
4042                mapped_resource, gfx::RectF(gfx::Rect(tile_size)), tile_size,
4043                contents_premultiplied, nearest_neighbor,
4044                force_anti_aliasing_off);
4045 
4046   AggregatedRenderPassList pass_list;
4047   pass_list.push_back(std::move(pass));
4048 
4049   EXPECT_TRUE(this->RunPixelTest(
4050       &pass_list,
4051       base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")),
4052       cc::ExactPixelComparator(true)));
4053 }
4054 
4055 // This disables filtering by setting |nearest_neighbor| to true on the
4056 // TextureDrawQuad.
TEST_F(SoftwareRendererPixelTest,TextureDrawQuadNearestNeighbor)4057 TEST_F(SoftwareRendererPixelTest, TextureDrawQuadNearestNeighbor) {
4058   gfx::Rect viewport(this->device_viewport_size_);
4059   bool needs_blending = true;
4060   bool nearest_neighbor = true;
4061 
4062   SkBitmap bitmap;
4063   bitmap.allocN32Pixels(2, 2);
4064   SkCanvas canvas(bitmap, SkSurfaceProps{});
4065   draw_point_color(&canvas, 0, 0, SK_ColorGREEN);
4066   draw_point_color(&canvas, 0, 1, SK_ColorBLUE);
4067   draw_point_color(&canvas, 1, 0, SK_ColorBLUE);
4068   draw_point_color(&canvas, 1, 1, SK_ColorGREEN);
4069 
4070   gfx::Size tile_size(2, 2);
4071   ResourceId resource =
4072       this->AllocateAndFillSoftwareResource(tile_size, bitmap);
4073 
4074   // Return the mapped resource id.
4075   std::unordered_map<ResourceId, ResourceId> resource_map =
4076       cc::SendResourceAndGetChildToParentMap(
4077           {resource}, this->resource_provider_.get(),
4078           this->child_resource_provider_.get(),
4079           this->child_context_provider_.get());
4080   ResourceId mapped_resource = resource_map[resource];
4081 
4082   AggregatedRenderPassId id{1};
4083   gfx::Transform transform_to_root;
4084   auto pass = CreateTestRenderPass(id, viewport, transform_to_root);
4085 
4086   gfx::Transform quad_to_target_transform;
4087   SharedQuadState* shared_state = CreateTestSharedQuadState(
4088       quad_to_target_transform, viewport, pass.get(), gfx::RRectF());
4089 
4090   float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
4091   auto* quad = pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
4092   quad->SetNew(shared_state, viewport, viewport, needs_blending,
4093                mapped_resource, false, gfx::PointF(0, 0), gfx::PointF(1, 1),
4094                SK_ColorBLACK, vertex_opacity, false, nearest_neighbor,
4095                /*secure_output_only=*/false, gfx::ProtectedVideoType::kClear);
4096 
4097   AggregatedRenderPassList pass_list;
4098   pass_list.push_back(std::move(pass));
4099 
4100   EXPECT_TRUE(this->RunPixelTest(
4101       &pass_list,
4102       base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")),
4103       cc::FuzzyPixelComparator(false, 2.f, 0.f, 256.f, 256, 0.f)));
4104 }
4105 
4106 // This ensures filtering is enabled by setting |nearest_neighbor| to false on
4107 // the TextureDrawQuad.
TEST_F(SoftwareRendererPixelTest,TextureDrawQuadLinear)4108 TEST_F(SoftwareRendererPixelTest, TextureDrawQuadLinear) {
4109   gfx::Rect viewport(this->device_viewport_size_);
4110   bool needs_blending = true;
4111   bool nearest_neighbor = false;
4112 
4113   SkBitmap bitmap;
4114   bitmap.allocN32Pixels(2, 2);
4115   {
4116     SkCanvas canvas(bitmap, SkSurfaceProps{});
4117     draw_point_color(&canvas, 0, 0, SK_ColorGREEN);
4118     draw_point_color(&canvas, 0, 1, SK_ColorBLUE);
4119     draw_point_color(&canvas, 1, 0, SK_ColorBLUE);
4120     draw_point_color(&canvas, 1, 1, SK_ColorGREEN);
4121   }
4122 
4123   gfx::Size tile_size(2, 2);
4124   ResourceId resource =
4125       this->AllocateAndFillSoftwareResource(tile_size, bitmap);
4126 
4127   // Return the mapped resource id.
4128   std::unordered_map<ResourceId, ResourceId> resource_map =
4129       cc::SendResourceAndGetChildToParentMap(
4130           {resource}, this->resource_provider_.get(),
4131           this->child_resource_provider_.get(),
4132           this->child_context_provider_.get());
4133   ResourceId mapped_resource = resource_map[resource];
4134 
4135   AggregatedRenderPassId id{1};
4136   gfx::Transform transform_to_root;
4137   auto pass = CreateTestRenderPass(id, viewport, transform_to_root);
4138 
4139   gfx::Transform quad_to_target_transform;
4140   SharedQuadState* shared_state = CreateTestSharedQuadState(
4141       quad_to_target_transform, viewport, pass.get(), gfx::RRectF());
4142 
4143   float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
4144   auto* quad = pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
4145   quad->SetNew(shared_state, viewport, viewport, needs_blending,
4146                mapped_resource, false, gfx::PointF(0, 0), gfx::PointF(1, 1),
4147                SK_ColorBLACK, vertex_opacity, false, nearest_neighbor,
4148                /*secure_output_only=*/false, gfx::ProtectedVideoType::kClear);
4149 
4150   AggregatedRenderPassList pass_list;
4151   pass_list.push_back(std::move(pass));
4152 
4153   // Allow for a small amount of error as the blending alogrithm used by Skia is
4154   // affected by the offset in the expanded rect.
4155   EXPECT_TRUE(this->RunPixelTest(
4156       &pass_list,
4157       base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers_linear.png")),
4158       cc::FuzzyPixelComparator(false, 100.f, 0.f, 16.f, 16.f, 0.f)));
4159 }
4160 
TEST_F(SoftwareRendererPixelTest,PictureDrawQuadNonIdentityScale)4161 TEST_F(SoftwareRendererPixelTest, PictureDrawQuadNonIdentityScale) {
4162   gfx::Rect viewport(this->device_viewport_size_);
4163   // TODO(enne): the renderer should figure this out on its own.
4164   ResourceFormat texture_format = RGBA_8888;
4165   bool needs_blending = true;
4166   bool nearest_neighbor = false;
4167 
4168   AggregatedRenderPassId id{1};
4169   gfx::Transform transform_to_root;
4170   auto pass = CreateTestRenderPass(id, viewport, transform_to_root);
4171 
4172   // As scaling up the blue checkerboards will cause sampling on the GPU,
4173   // a few extra "cleanup rects" need to be added to clobber the blending
4174   // to make the output image more clean.  This will also test subrects
4175   // of the layer.
4176   gfx::Transform green_quad_to_target_transform;
4177   gfx::Rect green_rect1(gfx::Point(80, 0), gfx::Size(20, 100));
4178   gfx::Rect green_rect2(gfx::Point(0, 80), gfx::Size(100, 20));
4179 
4180   std::unique_ptr<cc::FakeRecordingSource> green_recording =
4181       cc::FakeRecordingSource::CreateFilledRecordingSource(viewport.size());
4182 
4183   cc::PaintFlags red_flags;
4184   red_flags.setColor(SK_ColorRED);
4185   green_recording->add_draw_rect_with_flags(viewport, red_flags);
4186   cc::PaintFlags green_flags;
4187   green_flags.setColor(SK_ColorGREEN);
4188   green_recording->add_draw_rect_with_flags(green_rect1, green_flags);
4189   green_recording->add_draw_rect_with_flags(green_rect2, green_flags);
4190   green_recording->Rerecord();
4191   scoped_refptr<cc::RasterSource> green_raster_source =
4192       green_recording->CreateRasterSource();
4193 
4194   SharedQuadState* top_right_green_shared_quad_state =
4195       CreateTestSharedQuadState(green_quad_to_target_transform, viewport,
4196                                 pass.get(), gfx::RRectF());
4197 
4198   auto* green_quad1 = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
4199   green_quad1->SetNew(
4200       top_right_green_shared_quad_state, green_rect1, green_rect1,
4201       needs_blending, gfx::RectF(gfx::SizeF(green_rect1.size())),
4202       green_rect1.size(), nearest_neighbor, texture_format, green_rect1, 1.f,
4203       {}, green_raster_source->GetDisplayItemList());
4204 
4205   auto* green_quad2 = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
4206   green_quad2->SetNew(
4207       top_right_green_shared_quad_state, green_rect2, green_rect2,
4208       needs_blending, gfx::RectF(gfx::SizeF(green_rect2.size())),
4209       green_rect2.size(), nearest_neighbor, texture_format, green_rect2, 1.f,
4210       {}, green_raster_source->GetDisplayItemList());
4211 
4212   // Add a green clipped checkerboard in the bottom right to help test
4213   // interleaving picture quad content and solid color content.
4214   gfx::Rect bottom_right_rect(
4215       gfx::Point(viewport.width() / 2, viewport.height() / 2),
4216       gfx::Size(viewport.width() / 2, viewport.height() / 2));
4217   SharedQuadState* bottom_right_green_shared_state =
4218       CreateTestSharedQuadStateClipped(green_quad_to_target_transform, viewport,
4219                                        bottom_right_rect, pass.get());
4220   auto* bottom_right_color_quad =
4221       pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4222   bottom_right_color_quad->SetNew(bottom_right_green_shared_state, viewport,
4223                                   viewport, SK_ColorGREEN, false);
4224 
4225   // Add two blue checkerboards taking up the bottom left and top right,
4226   // but use content scales as content rects to make this happen.
4227   // The content is at a 4x content scale.
4228   gfx::Rect layer_rect(gfx::Size(20, 30));
4229   float contents_scale = 4.f;
4230   // Two rects that touch at their corners, arbitrarily placed in the layer.
4231   gfx::RectF blue_layer_rect1(gfx::PointF(5.5f, 9.0f), gfx::SizeF(2.5f, 2.5f));
4232   gfx::RectF blue_layer_rect2(gfx::PointF(8.0f, 6.5f), gfx::SizeF(2.5f, 2.5f));
4233   gfx::RectF union_layer_rect = blue_layer_rect1;
4234   union_layer_rect.Union(blue_layer_rect2);
4235 
4236   // Because scaling up will cause sampling outside the rects, add one extra
4237   // pixel of buffer at the final content scale.
4238   float inset = -1.f / contents_scale;
4239   blue_layer_rect1.Inset(inset, inset, inset, inset);
4240   blue_layer_rect2.Inset(inset, inset, inset, inset);
4241 
4242   std::unique_ptr<cc::FakeRecordingSource> recording =
4243       cc::FakeRecordingSource::CreateFilledRecordingSource(layer_rect.size());
4244 
4245   cc::Region outside(layer_rect);
4246   outside.Subtract(gfx::ToEnclosingRect(union_layer_rect));
4247   for (gfx::Rect rect : outside) {
4248     recording->add_draw_rect_with_flags(rect, red_flags);
4249   }
4250 
4251   cc::PaintFlags blue_flags;
4252   blue_flags.setColor(SK_ColorBLUE);
4253   recording->add_draw_rectf_with_flags(blue_layer_rect1, blue_flags);
4254   recording->add_draw_rectf_with_flags(blue_layer_rect2, blue_flags);
4255   recording->Rerecord();
4256   scoped_refptr<cc::RasterSource> raster_source =
4257       recording->CreateRasterSource();
4258 
4259   gfx::Rect content_union_rect(
4260       gfx::ToEnclosingRect(gfx::ScaleRect(union_layer_rect, contents_scale)));
4261 
4262   // At a scale of 4x the rectangles with a width of 2.5 will take up 10 pixels,
4263   // so scale an additional 10x to make them 100x100.
4264   gfx::Transform quad_to_target_transform;
4265   quad_to_target_transform.Scale(10.0, 10.0);
4266   gfx::Rect quad_content_rect(gfx::Size(20, 20));
4267   SharedQuadState* blue_shared_state = CreateTestSharedQuadState(
4268       quad_to_target_transform, quad_content_rect, pass.get(), gfx::RRectF());
4269 
4270   auto* blue_quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
4271   blue_quad->SetNew(blue_shared_state, quad_content_rect, quad_content_rect,
4272                     needs_blending, gfx::RectF(quad_content_rect),
4273                     content_union_rect.size(), nearest_neighbor, texture_format,
4274                     content_union_rect, contents_scale, {},
4275                     raster_source->GetDisplayItemList());
4276 
4277   // Fill left half of viewport with green.
4278   gfx::Transform half_green_quad_to_target_transform;
4279   gfx::Rect half_green_rect(gfx::Size(viewport.width() / 2, viewport.height()));
4280   SharedQuadState* half_green_shared_state =
4281       CreateTestSharedQuadState(half_green_quad_to_target_transform,
4282                                 half_green_rect, pass.get(), gfx::RRectF());
4283   auto* half_color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4284   half_color_quad->SetNew(half_green_shared_state, half_green_rect,
4285                           half_green_rect, SK_ColorGREEN, false);
4286 
4287   AggregatedRenderPassList pass_list;
4288   pass_list.push_back(std::move(pass));
4289 
4290   EXPECT_TRUE(this->RunPixelTest(
4291       &pass_list,
4292       base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")),
4293       cc::ExactPixelComparator(true)));
4294 }
4295 
4296 class RendererPixelTestWithFlippedOutputSurface : public VizPixelTestWithParam {
4297  protected:
GetSurfaceOrigin() const4298   gfx::SurfaceOrigin GetSurfaceOrigin() const override {
4299     return gfx::SurfaceOrigin::kTopLeft;
4300   }
4301 };
4302 
4303 INSTANTIATE_TEST_SUITE_P(,
4304                          RendererPixelTestWithFlippedOutputSurface,
4305                          testing::ValuesIn(GetGpuRendererTypes()),
4306                          testing::PrintToStringParamName());
4307 
TEST_P(RendererPixelTestWithFlippedOutputSurface,ExplicitFlipTest)4308 TEST_P(RendererPixelTestWithFlippedOutputSurface, ExplicitFlipTest) {
4309   // This draws a blue rect above a yellow rect with an inverted output surface.
4310   gfx::Rect viewport_rect(this->device_viewport_size_);
4311 
4312   AggregatedRenderPassId root_pass_id{1};
4313   auto root_pass = CreateTestRootRenderPass(root_pass_id, viewport_rect);
4314 
4315   AggregatedRenderPassId child_pass_id{2};
4316   gfx::Rect pass_rect(this->device_viewport_size_);
4317   gfx::Transform transform_to_root;
4318   auto child_pass =
4319       CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
4320 
4321   gfx::Transform quad_to_target_transform;
4322   SharedQuadState* shared_state = CreateTestSharedQuadState(
4323       quad_to_target_transform, viewport_rect, child_pass.get(), gfx::RRectF());
4324 
4325   gfx::Rect blue_rect(0, 0, this->device_viewport_size_.width(),
4326                       this->device_viewport_size_.height() / 2);
4327   auto* blue = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4328   blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
4329   gfx::Rect yellow_rect(0, this->device_viewport_size_.height() / 2,
4330                         this->device_viewport_size_.width(),
4331                         this->device_viewport_size_.height() / 2);
4332   auto* yellow = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4333   yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false);
4334 
4335   SharedQuadState* pass_shared_state = CreateTestSharedQuadState(
4336       gfx::Transform(), pass_rect, root_pass.get(), gfx::RRectF());
4337   CreateTestRenderPassDrawQuad(pass_shared_state, pass_rect, child_pass_id,
4338                                root_pass.get());
4339 
4340   AggregatedRenderPassList pass_list;
4341   pass_list.push_back(std::move(child_pass));
4342   pass_list.push_back(std::move(root_pass));
4343 
4344   // Note: RunPixelTest() will issue a CopyOutputRequest on the root pass. The
4345   // implementation should realize the output surface is flipped, and return a
4346   // right-side up result regardless (i.e., NOT blue_yellow_flipped.png).
4347   EXPECT_TRUE(this->RunPixelTest(
4348       &pass_list, base::FilePath(FILE_PATH_LITERAL("blue_yellow.png")),
4349       cc::FuzzyPixelOffByOneComparator(true)));
4350 }
4351 
TEST_P(RendererPixelTestWithFlippedOutputSurface,CheckChildPassUnflipped)4352 TEST_P(RendererPixelTestWithFlippedOutputSurface, CheckChildPassUnflipped) {
4353   // This draws a blue rect above a yellow rect with an inverted output surface.
4354   gfx::Rect viewport_rect(this->device_viewport_size_);
4355 
4356   AggregatedRenderPassId root_pass_id{1};
4357   auto root_pass = CreateTestRootRenderPass(root_pass_id, viewport_rect);
4358 
4359   AggregatedRenderPassId child_pass_id{2};
4360   gfx::Rect pass_rect(this->device_viewport_size_);
4361   gfx::Transform transform_to_root;
4362   auto child_pass =
4363       CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
4364 
4365   gfx::Transform quad_to_target_transform;
4366   SharedQuadState* shared_state = CreateTestSharedQuadState(
4367       quad_to_target_transform, viewport_rect, child_pass.get(), gfx::RRectF());
4368 
4369   gfx::Rect blue_rect(0, 0, this->device_viewport_size_.width(),
4370                       this->device_viewport_size_.height() / 2);
4371   auto* blue = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4372   blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
4373   gfx::Rect yellow_rect(0, this->device_viewport_size_.height() / 2,
4374                         this->device_viewport_size_.width(),
4375                         this->device_viewport_size_.height() / 2);
4376   auto* yellow = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4377   yellow->SetNew(shared_state, yellow_rect, yellow_rect, SK_ColorYELLOW, false);
4378 
4379   SharedQuadState* pass_shared_state = CreateTestSharedQuadState(
4380       gfx::Transform(), pass_rect, root_pass.get(), gfx::RRectF());
4381   CreateTestRenderPassDrawQuad(pass_shared_state, pass_rect, child_pass_id,
4382                                root_pass.get());
4383 
4384   AggregatedRenderPassList pass_list;
4385   pass_list.push_back(std::move(child_pass));
4386   pass_list.push_back(std::move(root_pass));
4387 
4388   // Check that the child pass remains unflipped.
4389   EXPECT_TRUE(this->RunPixelTestWithReadbackTarget(
4390       &pass_list, pass_list.front().get(),
4391       base::FilePath(FILE_PATH_LITERAL("blue_yellow.png")),
4392       cc::ExactPixelComparator(true)));
4393 }
4394 
TEST_P(GPURendererPixelTest,CheckReadbackSubset)4395 TEST_P(GPURendererPixelTest, CheckReadbackSubset) {
4396   gfx::Rect viewport_rect(this->device_viewport_size_);
4397 
4398   AggregatedRenderPassId root_pass_id{1};
4399   auto root_pass = CreateTestRootRenderPass(root_pass_id, viewport_rect);
4400 
4401   AggregatedRenderPassId child_pass_id{2};
4402   gfx::Rect pass_rect(this->device_viewport_size_);
4403   gfx::Transform transform_to_root;
4404   auto child_pass =
4405       CreateTestRenderPass(child_pass_id, pass_rect, transform_to_root);
4406 
4407   gfx::Transform quad_to_target_transform;
4408   SharedQuadState* shared_state = CreateTestSharedQuadState(
4409       quad_to_target_transform, viewport_rect, child_pass.get(), gfx::RRectF());
4410 
4411   // Draw a green quad full-size with a blue quad in the lower-right corner.
4412   gfx::Rect blue_rect(this->device_viewport_size_.width() * 3 / 4,
4413                       this->device_viewport_size_.height() * 3 / 4,
4414                       this->device_viewport_size_.width() * 3 / 4,
4415                       this->device_viewport_size_.height() * 3 / 4);
4416   auto* blue = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4417   blue->SetNew(shared_state, blue_rect, blue_rect, SK_ColorBLUE, false);
4418   gfx::Rect green_rect(0, 0, this->device_viewport_size_.width(),
4419                        this->device_viewport_size_.height());
4420   auto* green = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4421   green->SetNew(shared_state, green_rect, green_rect, SK_ColorGREEN, false);
4422 
4423   SharedQuadState* pass_shared_state = CreateTestSharedQuadState(
4424       gfx::Transform(), pass_rect, root_pass.get(), gfx::RRectF());
4425   CreateTestRenderPassDrawQuad(pass_shared_state, pass_rect, child_pass_id,
4426                                root_pass.get());
4427 
4428   AggregatedRenderPassList pass_list;
4429   pass_list.push_back(std::move(child_pass));
4430   pass_list.push_back(std::move(root_pass));
4431 
4432   // Check that the child pass remains unflipped.
4433   gfx::Rect capture_rect(this->device_viewport_size_.width() / 2,
4434                          this->device_viewport_size_.height() / 2,
4435                          this->device_viewport_size_.width() / 2,
4436                          this->device_viewport_size_.height() / 2);
4437   EXPECT_TRUE(this->RunPixelTestWithReadbackTargetAndArea(
4438       &pass_list, pass_list.front().get(),
4439       base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")),
4440       cc::ExactPixelComparator(true), &capture_rect));
4441 }
4442 
TEST_P(GPURendererPixelTest,TextureQuadBatching)4443 TEST_P(GPURendererPixelTest, TextureQuadBatching) {
4444   // This test verifies that multiple texture quads using the same resource
4445   // get drawn correctly.  It implicitly is trying to test that the
4446   // GLRenderer does the right thing with its draw quad cache.
4447 
4448   gfx::Rect rect(this->device_viewport_size_);
4449   bool needs_blending = false;
4450 
4451   AggregatedRenderPassId id{1};
4452   auto pass = CreateTestRootRenderPass(id, rect);
4453 
4454   SharedQuadState* shared_state = CreateTestSharedQuadState(
4455       gfx::Transform(), rect, pass.get(), gfx::RRectF());
4456 
4457   // Make a mask.
4458   gfx::Rect mask_rect = rect;
4459   SkBitmap bitmap;
4460   bitmap.allocPixels(
4461       SkImageInfo::MakeN32Premul(mask_rect.width(), mask_rect.height()));
4462   SkCanvas canvas(bitmap, SkSurfaceProps{});
4463   SkPaint paint;
4464   paint.setStyle(SkPaint::kStroke_Style);
4465   paint.setStrokeWidth(SkIntToScalar(4));
4466   paint.setColor(SK_ColorGREEN);
4467   canvas.clear(SK_ColorWHITE);
4468   gfx::Rect inset_rect = rect;
4469   while (!inset_rect.IsEmpty()) {
4470     inset_rect.Inset(6, 6, 4, 4);
4471     canvas.drawRect(SkRect::MakeXYWH(inset_rect.x(), inset_rect.y(),
4472                                      inset_rect.width(), inset_rect.height()),
4473                     paint);
4474     inset_rect.Inset(6, 6, 4, 4);
4475   }
4476 
4477   ResourceId resource = CreateGpuResource(
4478       this->child_context_provider_, this->child_resource_provider_.get(),
4479       mask_rect.size(), RGBA_8888, gfx::ColorSpace(), MakePixelSpan(bitmap));
4480 
4481   // Return the mapped resource id.
4482   std::unordered_map<ResourceId, ResourceId> resource_map =
4483       cc::SendResourceAndGetChildToParentMap(
4484           {resource}, this->resource_provider_.get(),
4485           this->child_resource_provider_.get(),
4486           this->child_context_provider_.get());
4487   ResourceId mapped_resource = resource_map[resource];
4488 
4489   // Arbitrary dividing lengths to divide up the resource into 16 quads.
4490   int widths[] = {
4491       0, 60, 50, 40,
4492   };
4493   int heights[] = {
4494       0, 10, 80, 50,
4495   };
4496   size_t num_quads = 4;
4497   for (size_t i = 0; i < num_quads; ++i) {
4498     int x_start = widths[i];
4499     int x_end = i == num_quads - 1 ? rect.width() : widths[i + 1];
4500     DCHECK_LE(x_end, rect.width());
4501     for (size_t j = 0; j < num_quads; ++j) {
4502       int y_start = heights[j];
4503       int y_end = j == num_quads - 1 ? rect.height() : heights[j + 1];
4504       DCHECK_LE(y_end, rect.height());
4505 
4506       float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
4507       gfx::Rect layer_rect(x_start, y_start, x_end - x_start, y_end - y_start);
4508       gfx::RectF uv_rect = gfx::ScaleRect(
4509           gfx::RectF(layer_rect), 1.f / rect.width(), 1.f / rect.height());
4510 
4511       auto* texture_quad = pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
4512       texture_quad->SetNew(
4513           shared_state, layer_rect, layer_rect, needs_blending, mapped_resource,
4514           true, uv_rect.origin(), uv_rect.bottom_right(), SK_ColorWHITE,
4515           vertex_opacity, false, false, /*secure_output_only=*/false,
4516           gfx::ProtectedVideoType::kClear);
4517     }
4518   }
4519 
4520   AggregatedRenderPassList pass_list;
4521   pass_list.push_back(std::move(pass));
4522 
4523   EXPECT_TRUE(this->RunPixelTest(
4524       &pass_list, base::FilePath(FILE_PATH_LITERAL("spiral.png")),
4525       cc::FuzzyPixelOffByOneComparator(true)));
4526 }
4527 
TEST_P(GPURendererPixelTest,TileQuadClamping)4528 TEST_P(GPURendererPixelTest, TileQuadClamping) {
4529   gfx::Rect viewport(this->device_viewport_size_);
4530   bool contents_premultiplied = true;
4531   bool needs_blending = true;
4532   bool nearest_neighbor = false;
4533   bool use_aa = false;
4534 
4535   gfx::Size layer_size(4, 4);
4536   gfx::Size tile_size(20, 20);
4537   gfx::Rect quad_rect(layer_size);
4538   gfx::RectF tex_coord_rect(quad_rect);
4539 
4540   // tile sized bitmap, with valid contents green and contents outside the
4541   // layer rect red.
4542   SkBitmap bitmap;
4543   bitmap.allocN32Pixels(tile_size.width(), tile_size.height());
4544   SkCanvas canvas(bitmap, SkSurfaceProps{});
4545   SkPaint red;
4546   red.setColor(SK_ColorRED);
4547   canvas.drawRect(SkRect::MakeWH(tile_size.width(), tile_size.height()), red);
4548   SkPaint green;
4549   green.setColor(SK_ColorGREEN);
4550   canvas.drawRect(SkRect::MakeWH(layer_size.width(), layer_size.height()),
4551                   green);
4552 
4553   ResourceId resource;
4554   if (!is_software_renderer()) {
4555     resource = CreateGpuResource(
4556         this->child_context_provider_, this->child_resource_provider_.get(),
4557         tile_size, RGBA_8888, gfx::ColorSpace(), MakePixelSpan(bitmap));
4558   } else {
4559     resource = this->AllocateAndFillSoftwareResource(tile_size, bitmap);
4560   }
4561   // Return the mapped resource id.
4562   std::unordered_map<ResourceId, ResourceId> resource_map =
4563       cc::SendResourceAndGetChildToParentMap(
4564           {resource}, this->resource_provider_.get(),
4565           this->child_resource_provider_.get(),
4566           this->child_context_provider_.get());
4567   ResourceId mapped_resource = resource_map[resource];
4568 
4569   AggregatedRenderPassId id{1};
4570   gfx::Transform transform_to_root;
4571   auto pass = CreateTestRenderPass(id, viewport, transform_to_root);
4572 
4573   // Green quad that should not show any red pixels from outside the
4574   // tex coord rect.
4575   gfx::Transform transform;
4576   transform.Scale(40, 40);
4577   SharedQuadState* quad_shared = CreateTestSharedQuadState(
4578       transform, gfx::Rect(layer_size), pass.get(), gfx::RRectF());
4579   auto* quad = pass->CreateAndAppendDrawQuad<TileDrawQuad>();
4580   quad->SetNew(quad_shared, gfx::Rect(layer_size), gfx::Rect(layer_size),
4581                needs_blending, mapped_resource, tex_coord_rect, tile_size,
4582                contents_premultiplied, nearest_neighbor, use_aa);
4583 
4584   // Green background.
4585   SharedQuadState* background_shared = CreateTestSharedQuadState(
4586       gfx::Transform(), viewport, pass.get(), gfx::RRectF());
4587   auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4588   color_quad->SetNew(background_shared, viewport, viewport, SK_ColorGREEN,
4589                      false);
4590 
4591   AggregatedRenderPassList pass_list;
4592   pass_list.push_back(std::move(pass));
4593 
4594   EXPECT_TRUE(this->RunPixelTest(&pass_list,
4595                                  base::FilePath(FILE_PATH_LITERAL("green.png")),
4596                                  cc::ExactPixelComparator(true)));
4597 }
4598 
TEST_P(RendererPixelTest,RoundedCornerSimpleSolidDrawQuad)4599 TEST_P(RendererPixelTest, RoundedCornerSimpleSolidDrawQuad) {
4600   gfx::Rect viewport_rect(this->device_viewport_size_);
4601   constexpr int kInset = 20;
4602   constexpr int kCornerRadius = 20;
4603 
4604   AggregatedRenderPassId root_pass_id{1};
4605   auto root_pass = CreateTestRootRenderPass(root_pass_id, viewport_rect);
4606 
4607   gfx::Transform quad_to_target_transform;
4608   gfx::Rect blue_rect(0, 0, this->device_viewport_size_.width(),
4609                       this->device_viewport_size_.height());
4610   gfx::Rect red_rect = blue_rect;
4611   blue_rect.Inset(kInset, kInset);
4612 
4613   gfx::RRectF rounded_corner_rrect(gfx::RectF(blue_rect), kCornerRadius);
4614   SharedQuadState* shared_state_rounded =
4615       CreateTestSharedQuadState(quad_to_target_transform, viewport_rect,
4616                                 root_pass.get(), rounded_corner_rrect);
4617 
4618   auto* blue = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4619   blue->SetNew(shared_state_rounded, blue_rect, blue_rect, SK_ColorBLUE, false);
4620 
4621   SharedQuadState* shared_state_normal = CreateTestSharedQuadState(
4622       quad_to_target_transform, viewport_rect, root_pass.get(), gfx::RRectF());
4623 
4624   auto* white = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4625   white->SetNew(shared_state_normal, red_rect, red_rect, SK_ColorWHITE, false);
4626 
4627   AggregatedRenderPassList pass_list;
4628   pass_list.push_back(std::move(root_pass));
4629 
4630   if (is_gl_renderer()) {
4631     // GL Renderer should have an exact match as that is the reference point.
4632     EXPECT_TRUE(this->RunPixelTest(
4633         &pass_list,
4634         base::FilePath(FILE_PATH_LITERAL("rounded_corner_simple.png")),
4635         cc::ExactPixelComparator(true)));
4636   } else {
4637     // Software/skia renderer uses skia rrect to create rounded corner clip.
4638     // This results in a different corner path due to a different anti aliasing
4639     // approach than the fragment shader in gl renderer.
4640     EXPECT_TRUE(this->RunPixelTest(
4641         &pass_list,
4642         base::FilePath(FILE_PATH_LITERAL("rounded_corner_simple.png")),
4643         cc::FuzzyPixelComparator(true, 0.55f, 0.f, 255.f, 255, 0)));
4644   }
4645 }
4646 
TEST_P(GPURendererPixelTest,RoundedCornerSimpleTextureDrawQuad)4647 TEST_P(GPURendererPixelTest, RoundedCornerSimpleTextureDrawQuad) {
4648   gfx::Rect viewport_rect(this->device_viewport_size_);
4649   constexpr int kInset = 20;
4650   constexpr int kCornerRadius = 20;
4651 
4652   AggregatedRenderPassId root_pass_id{1};
4653   auto root_pass = CreateTestRootRenderPass(root_pass_id, viewport_rect);
4654 
4655   gfx::Transform quad_to_target_transform;
4656   gfx::Rect blue_rect(0, 0, this->device_viewport_size_.width(),
4657                       this->device_viewport_size_.height());
4658   gfx::Rect red_rect = blue_rect;
4659   blue_rect.Inset(kInset, kInset);
4660 
4661   gfx::RRectF rounded_corner_rrect(gfx::RectF(blue_rect), kCornerRadius);
4662   SharedQuadState* shared_state_rounded =
4663       CreateTestSharedQuadState(quad_to_target_transform, viewport_rect,
4664                                 root_pass.get(), rounded_corner_rrect);
4665 
4666   const uint8_t colors[] = {0, 0, 255, 255, 0, 0, 255, 255,
4667                             0, 0, 255, 255, 0, 0, 255, 255};
4668   ResourceId resource = CreateGpuResource(
4669       this->child_context_provider_, this->child_resource_provider_.get(),
4670       gfx::Size(2, 2), RGBA_8888, gfx::ColorSpace(), colors);
4671 
4672   std::unordered_map<ResourceId, ResourceId> resource_map =
4673       cc::SendResourceAndGetChildToParentMap(
4674           {resource}, this->resource_provider_.get(),
4675           this->child_resource_provider_.get(),
4676           this->child_context_provider_.get());
4677   ResourceId mapped_resource = resource_map[resource];
4678   bool needs_blending = true;
4679   const gfx::PointF uv_top_left(0.0f, 0.0f);
4680   const gfx::PointF uv_bottom_right(1.0f, 1.0f);
4681   const bool flipped = false;
4682   const bool nearest_neighbor = false;
4683   auto* blue = root_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
4684   float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
4685   blue->SetNew(shared_state_rounded, blue_rect, blue_rect, needs_blending,
4686                mapped_resource, true, uv_top_left, uv_bottom_right,
4687                SK_ColorBLACK, vertex_opacity, flipped, nearest_neighbor,
4688                /*secure_output_only=*/false, gfx::ProtectedVideoType::kClear);
4689 
4690   SharedQuadState* shared_state_normal = CreateTestSharedQuadState(
4691       quad_to_target_transform, viewport_rect, root_pass.get(), gfx::RRectF());
4692 
4693   auto* white = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4694   white->SetNew(shared_state_normal, red_rect, red_rect, SK_ColorWHITE, false);
4695 
4696   AggregatedRenderPassList pass_list;
4697   pass_list.push_back(std::move(root_pass));
4698 
4699   if (is_gl_renderer()) {
4700     // GL Renderer should have an exact match as that is the reference point.
4701     EXPECT_TRUE(this->RunPixelTest(
4702         &pass_list,
4703         base::FilePath(FILE_PATH_LITERAL("rounded_corner_simple.png")),
4704         cc::ExactPixelComparator(true)));
4705   } else {
4706     // SkiaRenderer uses skia rrect to create rounded corner clip. This results
4707     // in a different corner path due to a different anti aliasing approach than
4708     // the fragment shader in gl renderer.
4709     EXPECT_TRUE(this->RunPixelTest(
4710         &pass_list,
4711         base::FilePath(FILE_PATH_LITERAL("rounded_corner_simple.png")),
4712         cc::FuzzyPixelComparator(true, 0.6f, 0.f, 255.f, 255, 0)));
4713   }
4714 }
4715 
4716 // TODO(https://crbug.com/1044841): Flaky, especially on Linux/TSAN and Fuchsia.
TEST_P(RendererPixelTest,DISABLED_RoundedCornerOnRenderPass)4717 TEST_P(RendererPixelTest, DISABLED_RoundedCornerOnRenderPass) {
4718   gfx::Rect viewport_rect(this->device_viewport_size_);
4719   constexpr int kInset = 20;
4720   constexpr int kCornerRadius = 20;
4721   constexpr int kBlueCornerRadius = 10;
4722 
4723   AggregatedRenderPassId root_pass_id{1};
4724   auto root_pass = CreateTestRootRenderPass(root_pass_id, viewport_rect);
4725 
4726   AggregatedRenderPassId child_pass_id{2};
4727   gfx::Rect pass_rect(this->device_viewport_size_);
4728   pass_rect.Inset(kInset, kInset);
4729   gfx::Rect child_pass_local_rect = gfx::Rect(pass_rect.size());
4730   gfx::Transform transform_to_root;
4731   transform_to_root.Translate(pass_rect.OffsetFromOrigin());
4732   auto child_pass = CreateTestRenderPass(child_pass_id, child_pass_local_rect,
4733                                          transform_to_root);
4734 
4735   gfx::Rect blue_rect = child_pass_local_rect;
4736   gfx::Vector2dF blue_offset_from_target(-30, 40);
4737   gfx::RRectF blue_rrect(gfx::RectF(blue_rect), kBlueCornerRadius);
4738   blue_rrect.Offset(blue_offset_from_target);
4739   gfx::Transform quad_to_target_transform;
4740   quad_to_target_transform.Translate(blue_offset_from_target);
4741   SharedQuadState* shared_state_with_rrect =
4742       CreateTestSharedQuadState(quad_to_target_transform, child_pass_local_rect,
4743                                 child_pass.get(), blue_rrect);
4744   auto* blue = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4745   blue->SetNew(shared_state_with_rrect, blue_rect, blue_rect, SK_ColorBLUE,
4746                false);
4747 
4748   SharedQuadState* shared_state_without_rrect = CreateTestSharedQuadState(
4749       gfx::Transform(), child_pass_local_rect, child_pass.get(), gfx::RRectF());
4750   gfx::Rect yellow_rect = child_pass_local_rect;
4751   yellow_rect.Offset(30, -60);
4752   auto* yellow = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4753   yellow->SetNew(shared_state_without_rrect, yellow_rect, yellow_rect,
4754                  SK_ColorYELLOW, false);
4755 
4756   gfx::Rect white_rect = child_pass_local_rect;
4757   auto* white = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4758   white->SetNew(shared_state_without_rrect, white_rect, white_rect,
4759                 SK_ColorWHITE, false);
4760 
4761   gfx::RRectF rounded_corner_bounds(gfx::RectF(pass_rect), kCornerRadius);
4762   SharedQuadState* pass_shared_state = CreateTestSharedQuadState(
4763       gfx::Transform(), pass_rect, root_pass.get(), rounded_corner_bounds);
4764   CreateTestRenderPassDrawQuad(pass_shared_state, pass_rect, child_pass_id,
4765                                root_pass.get());
4766 
4767   AggregatedRenderPassList pass_list;
4768   pass_list.push_back(std::move(child_pass));
4769   pass_list.push_back(std::move(root_pass));
4770 
4771   base::FilePath path(FILE_PATH_LITERAL("rounded_corner_render_pass_.png"));
4772   path = path.InsertBeforeExtensionASCII(this->renderer_str());
4773   EXPECT_TRUE(this->RunPixelTest(&pass_list, path,
4774                                  cc::FuzzyPixelOffByOneComparator(true)));
4775 }
4776 
4777 // TODO(https://crbug.com/1044841): Flaky, especially on Linux/TSAN and Fuchsia.
TEST_P(RendererPixelTest,DISABLED_RoundedCornerMultiRadii)4778 TEST_P(RendererPixelTest, DISABLED_RoundedCornerMultiRadii) {
4779   gfx::Rect viewport_rect(this->device_viewport_size_);
4780   constexpr gfx::RoundedCornersF kCornerRadii(5, 15, 25, 35);
4781   constexpr int kInset = 20;
4782 
4783   AggregatedRenderPassId root_pass_id{1};
4784   auto root_pass = CreateTestRootRenderPass(root_pass_id, viewport_rect);
4785 
4786   gfx::Rect pass_rect(this->device_viewport_size_);
4787   pass_rect.Inset(kInset, kInset);
4788   gfx::RRectF rounded_corner_bounds(gfx::RectF(pass_rect), kCornerRadii);
4789   gfx::Rect blue_rect = pass_rect;
4790   blue_rect.set_height(blue_rect.height() / 2);
4791 
4792   gfx::Transform quad_to_target_transform;
4793   SharedQuadState* shared_state_normal =
4794       CreateTestSharedQuadState(quad_to_target_transform, pass_rect,
4795                                 root_pass.get(), rounded_corner_bounds);
4796   auto* blue = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4797   blue->SetNew(shared_state_normal, blue_rect, blue_rect, SK_ColorBLUE, false);
4798 
4799   gfx::Rect yellow_rect = blue_rect;
4800   yellow_rect.Offset(0, blue_rect.height());
4801 
4802   auto* yellow = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4803   yellow->SetNew(shared_state_normal, yellow_rect, yellow_rect, SK_ColorYELLOW,
4804                  false);
4805 
4806   SharedQuadState* sqs_white = CreateTestSharedQuadState(
4807       quad_to_target_transform, viewport_rect, root_pass.get(), gfx::RRectF());
4808   gfx::Rect white_rect = gfx::Rect(this->device_viewport_size_);
4809   auto* white = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4810   white->SetNew(sqs_white, white_rect, white_rect, SK_ColorWHITE, false);
4811 
4812   AggregatedRenderPassList pass_list;
4813   pass_list.push_back(std::move(root_pass));
4814 
4815   if (is_gl_renderer()) {
4816     // GL Renderer should have an exact match as that is the reference point.
4817     EXPECT_TRUE(this->RunPixelTest(
4818         &pass_list,
4819         base::FilePath(FILE_PATH_LITERAL("rounded_corner_multi_radii.png")),
4820         cc::ExactPixelComparator(true)));
4821   } else {
4822     // Software/skia renderer uses skia rrect to create rounded corner clip.
4823     // This results in a different corner path due to a different anti aliasing
4824     // approach than the fragment shader in gl renderer.
4825     EXPECT_TRUE(this->RunPixelTest(
4826         &pass_list,
4827         base::FilePath(FILE_PATH_LITERAL("rounded_corner_multi_radii.png")),
4828         cc::FuzzyPixelComparator(true, 0.55f, 0.f, 255.f, 255, 0)));
4829   }
4830 }
4831 
4832 // TODO(https://crbug.com/1044841): Flaky, especially on Linux/TSAN and Fuchsia.
TEST_P(RendererPixelTest,DISABLED_RoundedCornerMultipleQads)4833 TEST_P(RendererPixelTest, DISABLED_RoundedCornerMultipleQads) {
4834   const gfx::Rect viewport_rect(this->device_viewport_size_);
4835   constexpr gfx::RoundedCornersF kCornerRadiiUL(5, 0, 0, 0);
4836   constexpr gfx::RoundedCornersF kCornerRadiiUR(0, 15, 0, 0);
4837   constexpr gfx::RoundedCornersF kCornerRadiiLR(0, 0, 25, 0);
4838   constexpr gfx::RoundedCornersF kCornerRadiiLL(0, 0, 0, 35);
4839   constexpr int kInset = 20;
4840 
4841   AggregatedRenderPassId root_pass_id{1};
4842   auto root_pass = CreateTestRootRenderPass(root_pass_id, viewport_rect);
4843 
4844   gfx::Rect pass_rect(this->device_viewport_size_);
4845   pass_rect.Inset(kInset, kInset);
4846   gfx::RRectF rounded_corner_bounds_ul(gfx::RectF(pass_rect), kCornerRadiiUL);
4847   gfx::RRectF rounded_corner_bounds_ur(gfx::RectF(pass_rect), kCornerRadiiUR);
4848   gfx::RRectF rounded_corner_bounds_lr(gfx::RectF(pass_rect), kCornerRadiiLR);
4849   gfx::RRectF rounded_corner_bounds_ll(gfx::RectF(pass_rect), kCornerRadiiLL);
4850 
4851   gfx::Rect ul_rect = pass_rect;
4852   ul_rect.set_height(ul_rect.height() / 2);
4853   ul_rect.set_width(ul_rect.width() / 2);
4854 
4855   gfx::Rect ur_rect = pass_rect;
4856   ur_rect.set_x(ul_rect.right());
4857   ur_rect.set_width(pass_rect.right() - ur_rect.x());
4858   ur_rect.set_height(ul_rect.height());
4859 
4860   gfx::Rect lr_rect = pass_rect;
4861   lr_rect.set_y(ur_rect.bottom());
4862   lr_rect.set_x(ur_rect.x());
4863   lr_rect.set_width(ur_rect.width());
4864   lr_rect.set_height(pass_rect.bottom() - lr_rect.y());
4865 
4866   gfx::Rect ll_rect = pass_rect;
4867   ll_rect.set_y(lr_rect.y());
4868   ll_rect.set_width(ul_rect.width());
4869   ll_rect.set_height(lr_rect.height());
4870 
4871   SharedQuadState* shared_state_normal_ul = CreateTestSharedQuadState(
4872       gfx::Transform(), pass_rect, root_pass.get(), rounded_corner_bounds_ul);
4873 
4874   SharedQuadState* shared_state_normal_ur = CreateTestSharedQuadState(
4875       gfx::Transform(), pass_rect, root_pass.get(), rounded_corner_bounds_ur);
4876 
4877   SharedQuadState* shared_state_normal_lr = CreateTestSharedQuadState(
4878       gfx::Transform(), pass_rect, root_pass.get(), rounded_corner_bounds_lr);
4879 
4880   SharedQuadState* shared_state_normal_ll = CreateTestSharedQuadState(
4881       gfx::Transform(), pass_rect, root_pass.get(), rounded_corner_bounds_ll);
4882 
4883   auto* ul = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4884   auto* ur = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4885   auto* lr = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4886   auto* ll = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4887 
4888   ul->SetNew(shared_state_normal_ul, ul_rect, ul_rect, SK_ColorRED, false);
4889   ur->SetNew(shared_state_normal_ur, ur_rect, ur_rect, SK_ColorGREEN, false);
4890   lr->SetNew(shared_state_normal_lr, lr_rect, lr_rect, SK_ColorBLUE, false);
4891   ll->SetNew(shared_state_normal_ll, ll_rect, ll_rect, SK_ColorYELLOW, false);
4892 
4893   SharedQuadState* sqs_white = CreateTestSharedQuadState(
4894       gfx::Transform(), viewport_rect, root_pass.get(), gfx::RRectF());
4895   gfx::Rect white_rect = gfx::Rect(this->device_viewport_size_);
4896   auto* white = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4897   white->SetNew(sqs_white, white_rect, white_rect, SK_ColorWHITE, false);
4898 
4899   AggregatedRenderPassList pass_list;
4900   pass_list.push_back(std::move(root_pass));
4901 
4902   // GL Renderer should have an exact match as that is the reference point.
4903   // Software/skia renderer use skia rrect to create rounded corner clip.
4904   // This results in a different corner path due to a different anti aliasing
4905   // approach than the fragment shader in gl renderer.
4906   std::unique_ptr<cc::PixelComparator> comparator;
4907   comparator.reset(
4908       is_gl_renderer()
4909           ? static_cast<cc::PixelComparator*>(
4910                 new cc::ExactPixelComparator(true))
4911           : static_cast<cc::PixelComparator*>(
4912                 new cc::FuzzyPixelComparator(true, 0.55f, 0.f, 255.f, 255, 0)));
4913   EXPECT_TRUE(this->RunPixelTest(
4914       &pass_list,
4915       base::FilePath(FILE_PATH_LITERAL("rounded_corner_multi_quad.png")),
4916       *comparator));
4917 }
4918 
4919 class RendererPixelTestWithOverdrawFeedback : public VizPixelTestWithParam {
4920  protected:
SetUp()4921   void SetUp() override {
4922     this->debug_settings_.show_overdraw_feedback = true;
4923     VizPixelTestWithParam::SetUp();
4924   }
4925 };
4926 
TEST_P(RendererPixelTestWithOverdrawFeedback,TranslucentRectangles)4927 TEST_P(RendererPixelTestWithOverdrawFeedback, TranslucentRectangles) {
4928   gfx::Rect rect(this->device_viewport_size_);
4929 
4930   AggregatedRenderPassId id{1};
4931   gfx::Transform transform_to_root;
4932   auto pass = CreateTestRenderPass(id, rect, transform_to_root);
4933 
4934   CreateTestAxisAlignedQuads(rect, 0x10444444, 0x10CCCCCC, true, false,
4935                              pass.get());
4936 
4937   gfx::Transform bg_quad_to_target_transform;
4938   SharedQuadState* bg_shared_state = CreateTestSharedQuadState(
4939       bg_quad_to_target_transform, rect, pass.get(), gfx::RRectF());
4940 
4941   auto* bg = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
4942   bg->SetNew(bg_shared_state, rect, rect, SK_ColorBLACK, false);
4943 
4944   AggregatedRenderPassList pass_list;
4945   pass_list.push_back(std::move(pass));
4946 
4947   if (is_gl_renderer()) {
4948     EXPECT_TRUE(this->RunPixelTest(
4949         &pass_list,
4950         base::FilePath(FILE_PATH_LITERAL("translucent_rectangles.png")),
4951         cc::ExactPixelComparator(true)));
4952   } else {
4953     // TODO(xing.xu): investigate why overdraw feedback has small difference
4954     // (http://crbug.com/909971)
4955     EXPECT_TRUE(this->RunPixelTest(
4956         &pass_list,
4957         base::FilePath(FILE_PATH_LITERAL("skia_translucent_rectangles.png")),
4958         cc::FuzzyPixelComparator(false, 2.f, 0.f, 256.f, 256, 0.f)));
4959   }
4960 }
4961 
4962 INSTANTIATE_TEST_SUITE_P(,
4963                          RendererPixelTestWithOverdrawFeedback,
4964                          testing::ValuesIn(GetGpuRendererTypes()),
4965                          testing::PrintToStringParamName());
4966 
4967 using PrimaryID = gfx::ColorSpace::PrimaryID;
4968 using TransferID = gfx::ColorSpace::TransferID;
4969 
4970 class ColorTransformPixelTest
4971     : public VizPixelTest,
4972       public testing::WithParamInterface<
4973           std::tuple<RendererType, gfx::ColorSpace, gfx::ColorSpace, bool>> {
4974  public:
ColorTransformPixelTest()4975   ColorTransformPixelTest() : VizPixelTest(std::get<0>(GetParam())) {
4976     // Note that this size of 17 is not random -- it is chosen to match the
4977     // size of LUTs that are created. If we did not match the LUT size exactly,
4978     // then the error for LUT based transforms is much larger.
4979     this->device_viewport_size_ = gfx::Size(17, 5);
4980     this->src_color_space_ = std::get<1>(GetParam());
4981     this->dst_color_space_ = std::get<2>(GetParam());
4982     if (!this->src_color_space_.IsValid()) {
4983       this->src_color_space_ =
4984           gfx::ICCProfileForTestingNoAnalyticTrFn().GetColorSpace();
4985     }
4986     if (!this->dst_color_space_.IsValid()) {
4987       this->dst_color_space_ =
4988           gfx::ICCProfileForTestingNoAnalyticTrFn().GetColorSpace();
4989     }
4990     this->display_color_spaces_ =
4991         gfx::DisplayColorSpaces(this->dst_color_space_);
4992     this->premultiplied_alpha_ = std::get<3>(GetParam());
4993   }
4994 
Basic()4995   void Basic() {
4996     // Skip piecewise transfer functions because SkColorSpace (needed for
4997     // CopyOutputResult::AsSkBitmap) doesn't support them..
4998     if ((src_color_space_.GetTransferID() == TransferID::PIECEWISE_HDR ||
4999          dst_color_space_.GetTransferID() == TransferID::PIECEWISE_HDR)) {
5000       LOG(ERROR) << "Skipping piecewise HDR function";
5001       return;
5002     }
5003 
5004     gfx::Rect rect(this->device_viewport_size_);
5005     std::vector<uint8_t> input_colors(4 * rect.width() * rect.height(), 0);
5006     std::vector<SkColor> expected_output_colors(rect.width() * rect.height());
5007 
5008     // Set the input data to be:
5009     //   Row 0: Gradient of red from 0 to 255
5010     //   Row 1: Gradient of green from 0 to 255
5011     //   Row 2: Gradient of blue from 0 to 255
5012     //   Row 3: Gradient of grey from 0 to 255
5013     //   Row 4: Gradient of alpha from 0 to 255 with mixed colors.
5014     for (int x = 0; x < rect.width(); ++x) {
5015       int gradient_value = (x * 255) / (rect.width() - 1);
5016       for (int y = 0; y < rect.height(); ++y) {
5017         uint8_t* pixel = &input_colors[4 * (x + rect.width() * y)];
5018         pixel[3] = 255;
5019         if (y < 3) {
5020           pixel[y] = gradient_value;
5021         } else if (y == 3) {
5022           pixel[0] = pixel[1] = pixel[2] = gradient_value;
5023         } else {
5024           if (this->premultiplied_alpha_) {
5025             pixel[x % 3] = gradient_value;
5026             pixel[3] = gradient_value;
5027           } else {
5028             pixel[x % 3] = 0xFF;
5029             pixel[3] = gradient_value;
5030           }
5031         }
5032       }
5033     }
5034 
5035     std::unique_ptr<gfx::ColorTransform> transform =
5036         gfx::ColorTransform::NewColorTransform(
5037             this->src_color_space_, this->dst_color_space_,
5038             gfx::ColorTransform::Intent::INTENT_PERCEPTUAL);
5039 
5040     for (size_t i = 0; i < expected_output_colors.size(); ++i) {
5041       gfx::ColorTransform::TriStim color;
5042       color.set_x(input_colors[4 * i + 0] / 255.f);
5043       color.set_y(input_colors[4 * i + 1] / 255.f);
5044       color.set_z(input_colors[4 * i + 2] / 255.f);
5045       float alpha = input_colors[4 * i + 3] / 255.f;
5046       if (this->premultiplied_alpha_ && alpha > 0.0) {
5047         color.Scale(1.0f / alpha);
5048       }
5049       transform->Transform(&color, 1);
5050       color.Scale(alpha);
5051       color.set_x(base::ClampToRange(color.x(), 0.0f, 1.0f));
5052       color.set_y(base::ClampToRange(color.y(), 0.0f, 1.0f));
5053       color.set_z(base::ClampToRange(color.z(), 0.0f, 1.0f));
5054       expected_output_colors[i] =
5055           SkColorSetARGB(255, static_cast<size_t>(255.f * color.x() + 0.5f),
5056                          static_cast<size_t>(255.f * color.y() + 0.5f),
5057                          static_cast<size_t>(255.f * color.z() + 0.5f));
5058     }
5059 
5060     AggregatedRenderPassId id{1};
5061     auto pass = CreateTestRootRenderPass(id, rect);
5062 
5063     // Append a quad to execute the transform.
5064     {
5065       SharedQuadState* shared_state = CreateTestSharedQuadState(
5066           gfx::Transform(), rect, pass.get(), gfx::RRectF());
5067 
5068       ResourceId resource = CreateGpuResource(
5069           this->child_context_provider_, this->child_resource_provider_.get(),
5070           rect.size(), RGBA_8888, this->src_color_space_, input_colors);
5071 
5072       // Return the mapped resource id.
5073       std::unordered_map<ResourceId, ResourceId> resource_map =
5074           cc::SendResourceAndGetChildToParentMap(
5075               {resource}, this->resource_provider_.get(),
5076               this->child_resource_provider_.get(),
5077               this->child_context_provider_.get());
5078       ResourceId mapped_resource = resource_map[resource];
5079 
5080       bool needs_blending = true;
5081       const gfx::PointF uv_top_left(0.0f, 0.0f);
5082       const gfx::PointF uv_bottom_right(1.0f, 1.0f);
5083       const bool flipped = false;
5084       const bool nearest_neighbor = false;
5085       auto* quad = pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
5086 
5087       float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
5088       quad->SetNew(shared_state, rect, rect, needs_blending, mapped_resource,
5089                    this->premultiplied_alpha_, uv_top_left, uv_bottom_right,
5090                    SK_ColorBLACK, vertex_opacity, flipped, nearest_neighbor,
5091                    /*secure_output_only=*/false,
5092                    gfx::ProtectedVideoType::kClear);
5093 
5094       auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
5095       color_quad->SetNew(shared_state, rect, rect, SK_ColorBLACK, false);
5096     }
5097 
5098     AggregatedRenderPassList pass_list;
5099     pass_list.push_back(std::move(pass));
5100 
5101     // Allow a difference of 2 bytes in comparison for shader-based transforms,
5102     // and 4 bytes for LUT-based transforms (determined empirically).
5103     cc::FuzzyPixelComparator comparator(false, 100.f, 0.f, 2.f, 2, 0);
5104     EXPECT_TRUE(
5105         this->RunPixelTest(&pass_list, &expected_output_colors, comparator))
5106         << " src:" << src_color_space_ << ", dst:" << dst_color_space_;
5107   }
5108 
5109   gfx::ColorSpace src_color_space_;
5110   gfx::ColorSpace dst_color_space_;
5111   bool premultiplied_alpha_ = false;
5112 };
5113 
TEST_P(ColorTransformPixelTest,Basic)5114 TEST_P(ColorTransformPixelTest, Basic) {
5115   Basic();
5116 }
5117 
5118 gfx::ColorSpace src_color_spaces[] = {
5119     // This will be replaced by an ICC-based space (which can't be initialized
5120     // here).
5121     gfx::ColorSpace(),
5122     gfx::ColorSpace(PrimaryID::BT709, TransferID::BT709),
5123     gfx::ColorSpace(PrimaryID::BT709, TransferID::GAMMA28),
5124     gfx::ColorSpace(PrimaryID::BT709, TransferID::SMPTE240M),
5125     gfx::ColorSpace(PrimaryID::BT709, TransferID::LINEAR),
5126     gfx::ColorSpace(PrimaryID::BT709, TransferID::IEC61966_2_1),
5127     gfx::ColorSpace(PrimaryID::BT709, TransferID::SMPTEST428_1),
5128     gfx::ColorSpace(PrimaryID::BT709, TransferID::IEC61966_2_1_HDR),
5129     gfx::ColorSpace(PrimaryID::BT709, TransferID::LINEAR_HDR),
5130     // Piecewise HDR transfer functions skipped with SkiaRenderer.
5131     gfx::ColorSpace::CreatePiecewiseHDR(PrimaryID::BT709, 0.5, 1.5),
5132     gfx::ColorSpace::CreateHDR10(50.f),
5133     gfx::ColorSpace::CreateHDR10(250.f),
5134 };
5135 
5136 gfx::ColorSpace dst_color_spaces[] = {
5137     // This will be replaced by an ICC-based space (which can't be initialized
5138     // here).
5139     gfx::ColorSpace(),
5140     gfx::ColorSpace(PrimaryID::BT709, TransferID::BT709),
5141     gfx::ColorSpace(PrimaryID::BT709, TransferID::GAMMA28),
5142     gfx::ColorSpace(PrimaryID::BT709, TransferID::SMPTE240M),
5143     gfx::ColorSpace(PrimaryID::BT709, TransferID::LINEAR),
5144     gfx::ColorSpace(PrimaryID::BT709, TransferID::IEC61966_2_1),
5145     gfx::ColorSpace(PrimaryID::BT709, TransferID::IEC61966_2_1_HDR),
5146     gfx::ColorSpace(PrimaryID::BT709, TransferID::LINEAR_HDR),
5147     // Piecewise HDR transfer functions are skipped with SkiaRenderer.
5148     gfx::ColorSpace::CreatePiecewiseHDR(PrimaryID::BT709, 0.25, 2.5),
5149 };
5150 
5151 gfx::ColorSpace intermediate_color_spaces[] = {
5152     gfx::ColorSpace(PrimaryID::XYZ_D50, TransferID::LINEAR),
5153     gfx::ColorSpace(PrimaryID::XYZ_D50, TransferID::IEC61966_2_1_HDR),
5154 };
5155 
5156 INSTANTIATE_TEST_SUITE_P(
5157     FromColorSpace,
5158     ColorTransformPixelTest,
5159     testing::Combine(testing::ValuesIn(GetGpuRendererTypesNoDawn()),
5160                      testing::ValuesIn(src_color_spaces),
5161                      testing::ValuesIn(intermediate_color_spaces),
5162                      testing::Bool()));
5163 
5164 INSTANTIATE_TEST_SUITE_P(
5165     ToColorSpace,
5166     ColorTransformPixelTest,
5167     testing::Combine(testing::ValuesIn(GetGpuRendererTypesNoDawn()),
5168                      testing::ValuesIn(intermediate_color_spaces),
5169                      testing::ValuesIn(dst_color_spaces),
5170                      testing::Bool()));
5171 
5172 class DelegatedInkTest : public VizPixelTestWithParam,
5173                          public DelegatedInkPointPixelTestHelper {
5174  public:
SetUp()5175   void SetUp() override {
5176     // Partial swap must be enabled or else the test will pass even if the
5177     // delegated ink trail damage rect is wrong, because the whole frame is
5178     // always redrawn otherwise.
5179     renderer_settings_.partial_swap_enabled = true;
5180     VizPixelTestWithParam::SetUp();
5181     EXPECT_TRUE(VizPixelTestWithParam::renderer_->use_partial_swap());
5182 
5183     SetRendererAndCreateInkRenderer(VizPixelTestWithParam::renderer_.get());
5184   }
5185 
CreateTestRootRenderPass(AggregatedRenderPassId id,const gfx::Rect & output_rect,const gfx::Rect & damage_rect)5186   std::unique_ptr<AggregatedRenderPass> CreateTestRootRenderPass(
5187       AggregatedRenderPassId id,
5188       const gfx::Rect& output_rect,
5189       const gfx::Rect& damage_rect) {
5190     auto pass = std::make_unique<AggregatedRenderPass>();
5191     const gfx::Transform transform_to_root_target;
5192     pass->SetNew(id, output_rect, damage_rect, transform_to_root_target);
5193     return pass;
5194   }
5195 
DrawAndTestTrail(base::FilePath::StringPieceType file)5196   bool DrawAndTestTrail(base::FilePath::StringPieceType file) {
5197     gfx::Rect rect(this->device_viewport_size_);
5198 
5199     // Minimize the root render pass damage rect so that it has to be expanded
5200     // by the delegated ink trail damage rect to confirm that it is the right
5201     // size to remove old trails and add new ones.
5202     gfx::Rect damage_rect(0, 0, 1, 1);
5203     AggregatedRenderPassId id{1};
5204     std::unique_ptr<AggregatedRenderPass> pass =
5205         CreateTestRootRenderPass(id, rect, damage_rect);
5206 
5207     SharedQuadState* shared_state = CreateTestSharedQuadState(
5208         gfx::Transform(), rect, pass.get(), gfx::RRectF());
5209 
5210     SolidColorDrawQuad* color_quad =
5211         pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
5212     color_quad->SetNew(shared_state, rect, rect, SK_ColorWHITE, false);
5213 
5214     AggregatedRenderPassList pass_list;
5215     pass_list.push_back(std::move(pass));
5216 
5217     return this->RunPixelTest(&pass_list, base::FilePath(file),
5218                               cc::FuzzyPixelOffByOneComparator(true));
5219   }
5220 };
5221 
5222 INSTANTIATE_TEST_SUITE_P(,
5223                          DelegatedInkTest,
5224                          testing::ValuesIn(GetRendererTypesSkiaOnly()),
5225                          testing::PrintToStringParamName());
5226 
5227 // Draw a single trail and erase it, making sure that no bits of trail are left
5228 // behind.
TEST_P(DelegatedInkTest,DrawOneTrailAndErase)5229 TEST_P(DelegatedInkTest, DrawOneTrailAndErase) {
5230   // First provide the metadata required to draw the trail, numbers arbitrary.
5231   CreateAndSendMetadata(gfx::PointF(10, 10), 3.5f, SK_ColorBLACK,
5232                         gfx::RectF(0, 0, 175, 172));
5233 
5234   // Then provide some points for the trail to draw. Numbers chosen arbitrarily
5235   // after the first point, which must match the metadata. This will predict no
5236   // points, so a trail made of 3 points will be drawn.
5237   CreateAndSendPointFromMetadata();
5238   CreateAndSendPointFromLastPoint(gfx::PointF(75, 62));
5239   CreateAndSendPointFromLastPoint(gfx::PointF(124, 45));
5240 
5241   // Confirm that the trail was drawn.
5242   EXPECT_TRUE(
5243       DrawAndTestTrail(FILE_PATH_LITERAL("delegated_ink_one_trail.png")));
5244 
5245   // The metadata should have been cleared after drawing, so confirm that there
5246   // is no trail after another draw.
5247   EXPECT_TRUE(DrawAndTestTrail(FILE_PATH_LITERAL("white.png")));
5248 }
5249 
5250 // Confirm that drawing a second trail completely removes the first trail.
TEST_P(DelegatedInkTest,DrawTwoTrailsAndErase)5251 TEST_P(DelegatedInkTest, DrawTwoTrailsAndErase) {
5252   // TODO(crbug.com/1021566): Enable this test for SkiaRenderer Dawn.
5253   if (renderer_type() == RendererType::kSkiaDawn)
5254     return;
5255 
5256   // First provide the metadata required to draw the trail, numbers arbitrary.
5257   CreateAndSendMetadata(gfx::PointF(140, 48), 8.2f, SK_ColorMAGENTA,
5258                         gfx::RectF(0, 0, 200, 200));
5259 
5260   // Then provide some points for the trail to draw. Numbers chosen arbitrarily
5261   // after the first point, which must match the metadata. No points will be
5262   // predicted, so a trail made of 2 points will be drawn.
5263   CreateAndSendPointFromMetadata();
5264   CreateAndSendPointFromLastPoint(gfx::PointF(115, 85));
5265 
5266   // Confirm that the trail was drawn correctly.
5267   EXPECT_TRUE(DrawAndTestTrail(
5268       FILE_PATH_LITERAL("delegated_ink_two_trails_first.png")));
5269 
5270   // Now provide new metadata and points to draw a new trail. Just use the last
5271   // point draw above as the starting point for the new trail. One point will
5272   // be predicted, so a trail consisting of 4 points will be drawn.
5273   CreateAndSendMetadataFromLastPoint();
5274   CreateAndSendPointFromLastPoint(gfx::PointF(134, 100));
5275   CreateAndSendPointFromLastPoint(gfx::PointF(150, 81.44f));
5276 
5277   // Confirm the first trail is gone and only the second remains.
5278   EXPECT_TRUE(DrawAndTestTrail(
5279       FILE_PATH_LITERAL("delegated_ink_two_trails_second.png")));
5280 
5281   // Confirm all trails are gone.
5282   EXPECT_TRUE(DrawAndTestTrail(FILE_PATH_LITERAL("white.png")));
5283 }
5284 
5285 // Confirm that the trail can't be drawn beyond the presentation area.
TEST_P(DelegatedInkTest,TrailExtendsBeyondPresentationArea)5286 TEST_P(DelegatedInkTest, TrailExtendsBeyondPresentationArea) {
5287   // TODO(crbug.com/1021566): Enable this test for SkiaRenderer Dawn.
5288   if (renderer_type() == RendererType::kSkiaDawn)
5289     return;
5290 
5291   const gfx::RectF kPresentationArea(30, 30, 100, 100);
5292   CreateAndSendMetadata(gfx::PointF(50.2f, 89.999f), 15.22f, SK_ColorCYAN,
5293                         kPresentationArea);
5294 
5295   // Send points such that some extend beyond the presentation area to confirm
5296   // that the trail is clipped correctly. One point will be predicted, so the
5297   // trail will be made of 9 points.
5298   CreateAndSendPointFromMetadata();
5299   CreateAndSendPointFromLastPoint(gfx::PointF(80.7f, 149.6f));
5300   CreateAndSendPointFromLastPoint(gfx::PointF(128.999f, 110.01f));
5301   CreateAndSendPointFromLastPoint(gfx::PointF(50, 50));
5302   CreateAndSendPointFromLastPoint(gfx::PointF(10.1f, 30.3f));
5303   CreateAndSendPointFromLastPoint(gfx::PointF(29.98f, 66));
5304   CreateAndSendPointFromLastPoint(gfx::PointF(52.3456f, 2.31f));
5305   CreateAndSendPointFromLastPoint(gfx::PointF(97, 36.9f));
5306   EXPECT_TRUE(DrawAndTestTrail(FILE_PATH_LITERAL(
5307       "delegated_ink_trail_clipped_by_presentation_area.png")));
5308 }
5309 
5310 // Confirm that the trail appears on top of everything, including batched quads
5311 // that are drawn as part of the call to FinishDrawingQuadList.
TEST_P(DelegatedInkTest,DelegatedInkTrailAfterBatchedQuads)5312 TEST_P(DelegatedInkTest, DelegatedInkTrailAfterBatchedQuads) {
5313   gfx::Rect rect(this->device_viewport_size_);
5314 
5315   AggregatedRenderPassId id{1};
5316   auto pass = CreateTestRootRenderPass(id, rect, rect);
5317 
5318   SharedQuadState* shared_state = CreateTestSharedQuadState(
5319       gfx::Transform(), rect, pass.get(), gfx::RRectF());
5320 
5321   CreateTestTextureDrawQuad(
5322       !is_software_renderer(), gfx::Rect(this->device_viewport_size_),
5323       SkColorSetARGB(128, 0, 255, 0),  // Texel color.
5324       SK_ColorTRANSPARENT,             // Background color.
5325       true,                            // Premultiplied alpha.
5326       shared_state, this->resource_provider_.get(),
5327       this->child_resource_provider_.get(), this->shared_bitmap_manager_.get(),
5328       this->child_context_provider_, pass.get());
5329 
5330   auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
5331   color_quad->SetNew(shared_state, rect, rect, SK_ColorWHITE, false);
5332 
5333   AggregatedRenderPassList pass_list;
5334   pass_list.push_back(std::move(pass));
5335 
5336   const gfx::RectF kPresentationArea(0, 0, 200, 200);
5337   CreateAndSendMetadata(gfx::PointF(34.f, 72.f), 7.77f, SK_ColorDKGRAY,
5338                         kPresentationArea);
5339   CreateAndSendPointFromMetadata();
5340   CreateAndSendPointFromLastPoint(gfx::PointF(79, 101));
5341   CreateAndSendPointFromLastPoint(gfx::PointF(134, 114));
5342 
5343   EXPECT_TRUE(this->RunPixelTest(
5344       &pass_list,
5345       base::FilePath(
5346           FILE_PATH_LITERAL("delegated_ink_trail_on_batched_quads.png")),
5347       cc::FuzzyPixelOffByOneComparator(true)));
5348 }
5349 
5350 // Confirm that delegated ink trails are not drawn on non-root render passes.
TEST_P(DelegatedInkTest,SimpleTrailNonRootRenderPass)5351 TEST_P(DelegatedInkTest, SimpleTrailNonRootRenderPass) {
5352   gfx::Rect rect(this->device_viewport_size_);
5353 
5354   AggregatedRenderPassId child_id{2};
5355   auto child_pass = CreateTestRenderPass(child_id, rect, gfx::Transform());
5356 
5357   SharedQuadState* child_shared_state = CreateTestSharedQuadState(
5358       gfx::Transform(), rect, child_pass.get(), gfx::RRectF());
5359 
5360   auto* color_quad = child_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
5361   color_quad->SetNew(child_shared_state, rect, rect, SK_ColorGREEN, false);
5362 
5363   AggregatedRenderPassId root_id{1};
5364   auto root_pass = CreateTestRootRenderPass(root_id, rect, rect);
5365 
5366   SharedQuadState* root_shared_state = CreateTestSharedQuadState(
5367       gfx::Transform(), rect, root_pass.get(), gfx::RRectF());
5368 
5369   CreateTestRenderPassDrawQuad(root_shared_state, rect, child_id,
5370                                root_pass.get());
5371 
5372   auto* child_pass_ptr = child_pass.get();
5373 
5374   AggregatedRenderPassList pass_list;
5375   pass_list.push_back(std::move(child_pass));
5376   pass_list.push_back(std::move(root_pass));
5377 
5378   // Values for a simple delegated ink trail, numbers chosen arbitrarily.
5379   const gfx::RectF kPresentationArea(0, 0, 200, 200);
5380   CreateAndSendMetadata(gfx::PointF(156.f, 111.f), 19.177f, SK_ColorRED,
5381                         kPresentationArea);
5382   CreateAndSendPointFromMetadata();
5383   CreateAndSendPointFromLastPoint(gfx::PointF(119, 87.23f));
5384   CreateAndSendPointFromLastPoint(gfx::PointF(74.222f, 95.4f));
5385 
5386   // This will only check what was drawn in the child pass, which should never
5387   // contain a delegated ink trail, so it should be solid green.
5388   EXPECT_TRUE(this->RunPixelTestWithReadbackTarget(
5389       &pass_list, child_pass_ptr,
5390       base::FilePath(FILE_PATH_LITERAL("green.png")),
5391       cc::ExactPixelComparator(true)));
5392 }
5393 #endif  // !defined(OS_ANDROID)
5394 
5395 }  // namespace
5396 }  // namespace viz
5397