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 "components/viz/common/quads/draw_quad.h"
6 
7 #include <stddef.h>
8 
9 #include <algorithm>
10 #include <memory>
11 
12 #include "base/bind.h"
13 #include "base/compiler_specific.h"
14 #include "base/logging.h"
15 #include "base/unguessable_token.h"
16 #include "cc/base/math_util.h"
17 #include "cc/paint/filter_operations.h"
18 #include "cc/test/fake_raster_source.h"
19 #include "cc/test/geometry_test_utils.h"
20 #include "components/viz/common/quads/aggregated_render_pass.h"
21 #include "components/viz/common/quads/aggregated_render_pass_draw_quad.h"
22 #include "components/viz/common/quads/compositor_render_pass.h"
23 #include "components/viz/common/quads/compositor_render_pass_draw_quad.h"
24 #include "components/viz/common/quads/debug_border_draw_quad.h"
25 #include "components/viz/common/quads/largest_draw_quad.h"
26 #include "components/viz/common/quads/picture_draw_quad.h"
27 #include "components/viz/common/quads/solid_color_draw_quad.h"
28 #include "components/viz/common/quads/stream_video_draw_quad.h"
29 #include "components/viz/common/quads/surface_draw_quad.h"
30 #include "components/viz/common/quads/texture_draw_quad.h"
31 #include "components/viz/common/quads/tile_draw_quad.h"
32 #include "components/viz/common/quads/video_hole_draw_quad.h"
33 #include "components/viz/common/quads/yuv_video_draw_quad.h"
34 #include "testing/gtest/include/gtest/gtest.h"
35 #include "third_party/skia/include/effects/SkBlurImageFilter.h"
36 #include "ui/gfx/hdr_metadata.h"
37 #include "ui/gfx/transform.h"
38 
39 namespace viz {
40 namespace {
41 
42 static constexpr FrameSinkId kArbitraryFrameSinkId(1, 1);
43 
TEST(DrawQuadTest,CopySharedQuadState)44 TEST(DrawQuadTest, CopySharedQuadState) {
45   gfx::Transform quad_transform = gfx::Transform(1.0, 0.0, 0.5, 1.0, 0.5, 0.0);
46   gfx::Rect layer_rect(26, 28);
47   gfx::Rect visible_layer_rect(10, 12, 14, 16);
48   gfx::Rect clip_rect(19, 21, 23, 25);
49   bool is_clipped = true;
50   bool are_contents_opaque = true;
51   float opacity = 0.25f;
52   SkBlendMode blend_mode = SkBlendMode::kMultiply;
53   int sorting_context_id = 65536;
54 
55   auto state = std::make_unique<SharedQuadState>();
56   state->SetAll(quad_transform, layer_rect, visible_layer_rect,
57                 gfx::MaskFilterInfo(), clip_rect, is_clipped,
58                 are_contents_opaque, opacity, blend_mode, sorting_context_id);
59 
60   auto copy = std::make_unique<SharedQuadState>(*state);
61   EXPECT_EQ(quad_transform, copy->quad_to_target_transform);
62   EXPECT_EQ(visible_layer_rect, copy->visible_quad_layer_rect);
63   EXPECT_EQ(opacity, copy->opacity);
64   EXPECT_EQ(clip_rect, copy->clip_rect);
65   EXPECT_EQ(is_clipped, copy->is_clipped);
66   EXPECT_EQ(are_contents_opaque, copy->are_contents_opaque);
67   EXPECT_EQ(blend_mode, copy->blend_mode);
68 }
69 
CreateSharedQuadState(CompositorRenderPass * render_pass)70 SharedQuadState* CreateSharedQuadState(CompositorRenderPass* render_pass) {
71   gfx::Transform quad_transform = gfx::Transform(1.0, 0.0, 0.5, 1.0, 0.5, 0.0);
72   gfx::Rect layer_rect(26, 28);
73   gfx::Rect visible_layer_rect(10, 12, 14, 16);
74   gfx::Rect clip_rect(19, 21, 23, 25);
75   bool is_clipped = false;
76   bool are_contents_opaque = true;
77   float opacity = 1.f;
78   int sorting_context_id = 65536;
79   SkBlendMode blend_mode = SkBlendMode::kSrcOver;
80 
81   SharedQuadState* state = render_pass->CreateAndAppendSharedQuadState();
82   state->SetAll(quad_transform, layer_rect, visible_layer_rect,
83                 gfx::MaskFilterInfo(), clip_rect, is_clipped,
84                 are_contents_opaque, opacity, blend_mode, sorting_context_id);
85   return state;
86 }
87 
CompareSharedQuadState(const SharedQuadState * source_sqs,const SharedQuadState * copy_sqs)88 void CompareSharedQuadState(const SharedQuadState* source_sqs,
89                             const SharedQuadState* copy_sqs) {
90   EXPECT_EQ(source_sqs->quad_to_target_transform,
91             copy_sqs->quad_to_target_transform);
92   EXPECT_EQ(source_sqs->quad_layer_rect, copy_sqs->quad_layer_rect);
93   EXPECT_EQ(source_sqs->visible_quad_layer_rect,
94             copy_sqs->visible_quad_layer_rect);
95   EXPECT_EQ(source_sqs->clip_rect, copy_sqs->clip_rect);
96   EXPECT_EQ(source_sqs->is_clipped, copy_sqs->is_clipped);
97   EXPECT_EQ(source_sqs->opacity, copy_sqs->opacity);
98   EXPECT_EQ(source_sqs->blend_mode, copy_sqs->blend_mode);
99   EXPECT_EQ(source_sqs->sorting_context_id, copy_sqs->sorting_context_id);
100 }
101 
CompareDrawQuad(DrawQuad * quad,DrawQuad * copy)102 void CompareDrawQuad(DrawQuad* quad, DrawQuad* copy) {
103   EXPECT_EQ(quad->material, copy->material);
104   EXPECT_EQ(quad->rect, copy->rect);
105   EXPECT_EQ(quad->visible_rect, copy->visible_rect);
106   EXPECT_EQ(quad->needs_blending, copy->needs_blending);
107   CompareSharedQuadState(quad->shared_quad_state, copy->shared_quad_state);
108 }
109 
110 #define CREATE_SHARED_STATE()                                              \
111   auto render_pass = CompositorRenderPass::Create();                       \
112   SharedQuadState* shared_state(CreateSharedQuadState(render_pass.get())); \
113   SharedQuadState* copy_shared_state =                                     \
114       render_pass->CreateAndAppendSharedQuadState();                       \
115   *copy_shared_state = *shared_state;
116 
117 #define QUAD_DATA                              \
118   gfx::Rect quad_rect(30, 40, 50, 60);         \
119   gfx::Rect quad_visible_rect(40, 50, 30, 20); \
120   ALLOW_UNUSED_LOCAL(quad_visible_rect);       \
121   bool needs_blending = true;                  \
122   ALLOW_UNUSED_LOCAL(needs_blending);
123 
124 #define SETUP_AND_COPY_QUAD_NEW(Type, quad)                              \
125   DrawQuad* copy_new = render_pass->CopyFromAndAppendDrawQuad(quad_new); \
126   CompareDrawQuad(quad_new, copy_new);                                   \
127   const Type* copy_quad = Type::MaterialCast(copy_new);                  \
128   ALLOW_UNUSED_LOCAL(copy_quad);
129 
130 #define SETUP_AND_COPY_QUAD_ALL(Type, quad)                              \
131   DrawQuad* copy_all = render_pass->CopyFromAndAppendDrawQuad(quad_all); \
132   CompareDrawQuad(quad_all, copy_all);                                   \
133   copy_quad = Type::MaterialCast(copy_all);
134 
135 #define SETUP_AND_COPY_QUAD_NEW_RP(Type, quad, a)                    \
136   DrawQuad* copy_new =                                               \
137       render_pass->CopyFromAndAppendRenderPassDrawQuad(quad_new, a); \
138   CompareDrawQuad(quad_new, copy_new);                               \
139   const Type* copy_quad = Type::MaterialCast(copy_new);              \
140   ALLOW_UNUSED_LOCAL(copy_quad);
141 
142 #define SETUP_AND_COPY_QUAD_ALL_RP(Type, quad, a)                    \
143   DrawQuad* copy_all =                                               \
144       render_pass->CopyFromAndAppendRenderPassDrawQuad(quad_all, a); \
145   CompareDrawQuad(quad_all, copy_all);                               \
146   const Type* copy_quad = Type::MaterialCast(copy_all);
147 
148 #define CREATE_QUAD_ALL(Type, ...)                                         \
149   Type* quad_all = render_pass->CreateAndAppendDrawQuad<Type>();           \
150   {                                                                        \
151     QUAD_DATA quad_all->SetAll(shared_state, quad_rect, quad_visible_rect, \
152                                needs_blending, __VA_ARGS__);               \
153   }                                                                        \
154   SETUP_AND_COPY_QUAD_ALL(Type, quad_all);
155 
156 #define CREATE_QUAD_NEW(Type, ...)                                      \
157   Type* quad_new = render_pass->CreateAndAppendDrawQuad<Type>();        \
158   { QUAD_DATA quad_new->SetNew(shared_state, quad_rect, __VA_ARGS__); } \
159   SETUP_AND_COPY_QUAD_NEW(Type, quad_new);
160 
161 #define CREATE_QUAD_ALL_RP(Type, a, b, c, d, e, f, g, h, i, j, k, copy_a)     \
162   Type* quad_all = render_pass->CreateAndAppendDrawQuad<Type>();              \
163   {                                                                           \
164     QUAD_DATA quad_all->SetAll(shared_state, quad_rect, a, needs_blending, b, \
165                                c, d, e, f, g, h, i, j, k);                    \
166   }                                                                           \
167   SETUP_AND_COPY_QUAD_ALL_RP(Type, quad_all, copy_a);
168 
169 #define CREATE_QUAD_NEW_RP(Type, a, b, c, d, e, f, g, h, i, j, copy_a)       \
170   Type* quad_new = render_pass->CreateAndAppendDrawQuad<Type>();             \
171   {                                                                          \
172     QUAD_DATA quad_new->SetNew(shared_state, quad_rect, a, b, c, d, e, f, g, \
173                                h, i, j);                                     \
174   }                                                                          \
175   SETUP_AND_COPY_QUAD_NEW_RP(Type, quad_new, copy_a);
176 
TEST(DrawQuadTest,CopyDebugBorderDrawQuad)177 TEST(DrawQuadTest, CopyDebugBorderDrawQuad) {
178   gfx::Rect visible_rect(40, 50, 30, 20);
179   SkColor color = 0xfabb0011;
180   int width = 99;
181   CREATE_SHARED_STATE();
182 
183   CREATE_QUAD_NEW(DebugBorderDrawQuad, visible_rect, color, width);
184   EXPECT_EQ(DrawQuad::Material::kDebugBorder, copy_quad->material);
185   EXPECT_EQ(visible_rect, copy_quad->visible_rect);
186   EXPECT_EQ(color, copy_quad->color);
187   EXPECT_EQ(width, copy_quad->width);
188 
189   CREATE_QUAD_ALL(DebugBorderDrawQuad, color, width);
190   EXPECT_EQ(DrawQuad::Material::kDebugBorder, copy_quad->material);
191   EXPECT_EQ(color, copy_quad->color);
192   EXPECT_EQ(width, copy_quad->width);
193 }
194 
TEST(DrawQuadTest,CopyRenderPassDrawQuad)195 TEST(DrawQuadTest, CopyRenderPassDrawQuad) {
196   gfx::Rect visible_rect(40, 50, 30, 20);
197   CompositorRenderPassId render_pass_id{61};
198   ResourceId mask_resource_id = 78;
199   gfx::RectF mask_uv_rect(0, 0, 33.f, 19.f);
200   gfx::Size mask_texture_size(128, 134);
201   gfx::Vector2dF filters_scale;
202   gfx::PointF filters_origin;
203   gfx::RectF tex_coord_rect(1, 1, 255, 254);
204   bool force_anti_aliasing_off = false;
205   float backdrop_filter_quality = 1.0f;
206   bool can_use_backdrop_filter_cache = true;
207 
208   CompositorRenderPassId copied_render_pass_id{235};
209   CREATE_SHARED_STATE();
210 
211   CREATE_QUAD_ALL_RP(CompositorRenderPassDrawQuad, visible_rect, render_pass_id,
212                      mask_resource_id, mask_uv_rect, mask_texture_size,
213                      filters_scale, filters_origin, tex_coord_rect,
214                      force_anti_aliasing_off, backdrop_filter_quality,
215                      can_use_backdrop_filter_cache, copied_render_pass_id);
216   EXPECT_EQ(DrawQuad::Material::kCompositorRenderPass, copy_quad->material);
217   EXPECT_EQ(visible_rect, copy_quad->visible_rect);
218   EXPECT_EQ(copied_render_pass_id, copy_quad->render_pass_id);
219   EXPECT_EQ(mask_resource_id, copy_quad->mask_resource_id());
220   EXPECT_EQ(mask_uv_rect.ToString(), copy_quad->mask_uv_rect.ToString());
221   EXPECT_EQ(mask_texture_size.ToString(),
222             copy_quad->mask_texture_size.ToString());
223   EXPECT_EQ(filters_scale, copy_quad->filters_scale);
224   EXPECT_EQ(filters_origin, copy_quad->filters_origin);
225   EXPECT_EQ(tex_coord_rect.ToString(), copy_quad->tex_coord_rect.ToString());
226   EXPECT_EQ(force_anti_aliasing_off, copy_quad->force_anti_aliasing_off);
227   EXPECT_EQ(backdrop_filter_quality, copy_quad->backdrop_filter_quality);
228   EXPECT_EQ(can_use_backdrop_filter_cache,
229             copy_quad->can_use_backdrop_filter_cache);
230 }
231 
TEST(DrawQuadTest,CopySolidColorDrawQuad)232 TEST(DrawQuadTest, CopySolidColorDrawQuad) {
233   gfx::Rect visible_rect(40, 50, 30, 20);
234   SkColor color = 0x49494949;
235   bool force_anti_aliasing_off = false;
236   CREATE_SHARED_STATE();
237 
238   CREATE_QUAD_NEW(SolidColorDrawQuad, visible_rect, color,
239                   force_anti_aliasing_off);
240   EXPECT_EQ(DrawQuad::Material::kSolidColor, copy_quad->material);
241   EXPECT_EQ(visible_rect, copy_quad->visible_rect);
242   EXPECT_EQ(color, copy_quad->color);
243   EXPECT_EQ(force_anti_aliasing_off, copy_quad->force_anti_aliasing_off);
244 
245   CREATE_QUAD_ALL(SolidColorDrawQuad, color, force_anti_aliasing_off);
246   EXPECT_EQ(DrawQuad::Material::kSolidColor, copy_quad->material);
247   EXPECT_EQ(color, copy_quad->color);
248   EXPECT_EQ(force_anti_aliasing_off, copy_quad->force_anti_aliasing_off);
249 }
250 
TEST(DrawQuadTest,CopyStreamVideoDrawQuad)251 TEST(DrawQuadTest, CopyStreamVideoDrawQuad) {
252   gfx::Rect visible_rect(40, 50, 30, 20);
253   bool needs_blending = true;
254   ResourceId resource_id = 64;
255   gfx::Size resource_size_in_pixels = gfx::Size(40, 41);
256   gfx::PointF uv_top_left(0.25f, 0.3f);
257   gfx::PointF uv_bottom_right(0.75f, 0.7f);
258   CREATE_SHARED_STATE();
259 
260   CREATE_QUAD_NEW(StreamVideoDrawQuad, visible_rect, needs_blending,
261                   resource_id, resource_size_in_pixels, uv_top_left,
262                   uv_bottom_right);
263   EXPECT_EQ(DrawQuad::Material::kStreamVideoContent, copy_quad->material);
264   EXPECT_EQ(visible_rect, copy_quad->visible_rect);
265   EXPECT_EQ(needs_blending, copy_quad->needs_blending);
266   EXPECT_EQ(resource_id, copy_quad->resource_id());
267   EXPECT_EQ(resource_size_in_pixels, copy_quad->resource_size_in_pixels());
268   EXPECT_EQ(uv_top_left, copy_quad->uv_top_left);
269   EXPECT_EQ(uv_bottom_right, copy_quad->uv_bottom_right);
270 
271   CREATE_QUAD_ALL(StreamVideoDrawQuad, resource_id, resource_size_in_pixels,
272                   uv_top_left, uv_bottom_right);
273   EXPECT_EQ(DrawQuad::Material::kStreamVideoContent, copy_quad->material);
274   EXPECT_EQ(resource_id, copy_quad->resource_id());
275   EXPECT_EQ(resource_size_in_pixels, copy_quad->resource_size_in_pixels());
276   EXPECT_EQ(uv_top_left, copy_quad->uv_top_left);
277   EXPECT_EQ(uv_bottom_right, copy_quad->uv_bottom_right);
278 }
279 
TEST(DrawQuadTest,CopySurfaceDrawQuad)280 TEST(DrawQuadTest, CopySurfaceDrawQuad) {
281   gfx::Rect visible_rect(40, 50, 30, 20);
282   SurfaceId primary_surface_id(
283       kArbitraryFrameSinkId,
284       LocalSurfaceId(1234, base::UnguessableToken::Create()));
285   SurfaceId fallback_surface_id(
286       kArbitraryFrameSinkId,
287       LocalSurfaceId(5678, base::UnguessableToken::Create()));
288   CREATE_SHARED_STATE();
289 
290   CREATE_QUAD_NEW(SurfaceDrawQuad, visible_rect,
291                   SurfaceRange(fallback_surface_id, primary_surface_id),
292                   SK_ColorWHITE, /*stretch_content_to_fill_bounds=*/true);
293   EXPECT_EQ(DrawQuad::Material::kSurfaceContent, copy_quad->material);
294   EXPECT_EQ(visible_rect, copy_quad->visible_rect);
295   EXPECT_EQ(primary_surface_id, copy_quad->surface_range.end());
296   EXPECT_EQ(fallback_surface_id, *copy_quad->surface_range.start());
297   EXPECT_TRUE(copy_quad->stretch_content_to_fill_bounds);
298 
299   CREATE_QUAD_ALL(SurfaceDrawQuad,
300                   SurfaceRange(fallback_surface_id, primary_surface_id),
301                   SK_ColorWHITE, /*stretch_content_to_fill_bounds=*/false,
302                   /*is_reflection=*/false, /*allow_merge=*/true);
303   EXPECT_EQ(DrawQuad::Material::kSurfaceContent, copy_quad->material);
304   EXPECT_EQ(primary_surface_id, copy_quad->surface_range.end());
305   EXPECT_EQ(fallback_surface_id, *copy_quad->surface_range.start());
306   EXPECT_FALSE(copy_quad->stretch_content_to_fill_bounds);
307   EXPECT_FALSE(copy_quad->is_reflection);
308 }
309 
TEST(DrawQuadTest,CopyTextureDrawQuad)310 TEST(DrawQuadTest, CopyTextureDrawQuad) {
311   gfx::Rect visible_rect(40, 50, 30, 20);
312   bool needs_blending = true;
313   unsigned resource_id = 82;
314   gfx::Size resource_size_in_pixels = gfx::Size(40, 41);
315   bool premultiplied_alpha = true;
316   gfx::PointF uv_top_left(0.5f, 224.f);
317   gfx::PointF uv_bottom_right(51.5f, 260.f);
318   const float vertex_opacity[] = {1.0f, 1.0f, 1.0f, 1.0f};
319   bool y_flipped = true;
320   bool nearest_neighbor = true;
321   bool secure_output_only = true;
322   gfx::ProtectedVideoType protected_video_type =
323       gfx::ProtectedVideoType::kSoftwareProtected;
324   CREATE_SHARED_STATE();
325 
326   CREATE_QUAD_NEW(TextureDrawQuad, visible_rect, needs_blending, resource_id,
327                   premultiplied_alpha, uv_top_left, uv_bottom_right,
328                   SK_ColorTRANSPARENT, vertex_opacity, y_flipped,
329                   nearest_neighbor, secure_output_only, protected_video_type);
330   EXPECT_EQ(DrawQuad::Material::kTextureContent, copy_quad->material);
331   EXPECT_EQ(visible_rect, copy_quad->visible_rect);
332   EXPECT_EQ(needs_blending, copy_quad->needs_blending);
333   EXPECT_EQ(resource_id, copy_quad->resource_id());
334   EXPECT_EQ(premultiplied_alpha, copy_quad->premultiplied_alpha);
335   EXPECT_EQ(uv_top_left, copy_quad->uv_top_left);
336   EXPECT_EQ(uv_bottom_right, copy_quad->uv_bottom_right);
337   EXPECT_FLOAT_ARRAY_EQ(vertex_opacity, copy_quad->vertex_opacity, 4);
338   EXPECT_EQ(y_flipped, copy_quad->y_flipped);
339   EXPECT_EQ(nearest_neighbor, copy_quad->nearest_neighbor);
340   EXPECT_EQ(secure_output_only, copy_quad->secure_output_only);
341   EXPECT_EQ(protected_video_type, copy_quad->protected_video_type);
342 
343   CREATE_QUAD_ALL(TextureDrawQuad, resource_id, resource_size_in_pixels,
344                   premultiplied_alpha, uv_top_left, uv_bottom_right,
345                   SK_ColorTRANSPARENT, vertex_opacity, y_flipped,
346                   nearest_neighbor, secure_output_only, protected_video_type);
347   EXPECT_EQ(DrawQuad::Material::kTextureContent, copy_quad->material);
348   EXPECT_EQ(resource_id, copy_quad->resource_id());
349   EXPECT_EQ(resource_size_in_pixels, copy_quad->resource_size_in_pixels());
350   EXPECT_EQ(premultiplied_alpha, copy_quad->premultiplied_alpha);
351   EXPECT_EQ(uv_top_left, copy_quad->uv_top_left);
352   EXPECT_EQ(uv_bottom_right, copy_quad->uv_bottom_right);
353   EXPECT_FLOAT_ARRAY_EQ(vertex_opacity, copy_quad->vertex_opacity, 4);
354   EXPECT_EQ(y_flipped, copy_quad->y_flipped);
355   EXPECT_EQ(nearest_neighbor, copy_quad->nearest_neighbor);
356   EXPECT_EQ(secure_output_only, copy_quad->secure_output_only);
357   EXPECT_EQ(protected_video_type, copy_quad->protected_video_type);
358 }
359 
TEST(DrawQuadTest,CopyTileDrawQuad)360 TEST(DrawQuadTest, CopyTileDrawQuad) {
361   gfx::Rect visible_rect(40, 50, 30, 20);
362   bool needs_blending = true;
363   unsigned resource_id = 104;
364   gfx::RectF tex_coord_rect(31.f, 12.f, 54.f, 20.f);
365   gfx::Size texture_size(85, 32);
366   bool contents_premultiplied = true;
367   bool nearest_neighbor = true;
368   bool force_anti_aliasing_off = false;
369   CREATE_SHARED_STATE();
370 
371   CREATE_QUAD_NEW(TileDrawQuad, visible_rect, needs_blending, resource_id,
372                   tex_coord_rect, texture_size, contents_premultiplied,
373                   nearest_neighbor, force_anti_aliasing_off);
374   EXPECT_EQ(DrawQuad::Material::kTiledContent, copy_quad->material);
375   EXPECT_EQ(visible_rect, copy_quad->visible_rect);
376   EXPECT_EQ(needs_blending, copy_quad->needs_blending);
377   EXPECT_EQ(resource_id, copy_quad->resource_id());
378   EXPECT_EQ(tex_coord_rect, copy_quad->tex_coord_rect);
379   EXPECT_EQ(texture_size, copy_quad->texture_size);
380   EXPECT_EQ(nearest_neighbor, copy_quad->nearest_neighbor);
381 
382   CREATE_QUAD_ALL(TileDrawQuad, resource_id, tex_coord_rect, texture_size,
383                   contents_premultiplied, nearest_neighbor,
384                   force_anti_aliasing_off);
385   EXPECT_EQ(DrawQuad::Material::kTiledContent, copy_quad->material);
386   EXPECT_EQ(resource_id, copy_quad->resource_id());
387   EXPECT_EQ(tex_coord_rect, copy_quad->tex_coord_rect);
388   EXPECT_EQ(texture_size, copy_quad->texture_size);
389   EXPECT_EQ(nearest_neighbor, copy_quad->nearest_neighbor);
390 }
391 
TEST(DrawQuadTest,CopyVideoHoleDrawQuad)392 TEST(DrawQuadTest, CopyVideoHoleDrawQuad) {
393   gfx::Rect visible_rect(40, 50, 30, 20);
394   base::UnguessableToken overlay_plane_id = base::UnguessableToken::Create();
395   CREATE_SHARED_STATE();
396 
397   CREATE_QUAD_NEW(VideoHoleDrawQuad, visible_rect, overlay_plane_id);
398   EXPECT_EQ(DrawQuad::Material::kVideoHole, copy_quad->material);
399   EXPECT_EQ(visible_rect, copy_quad->visible_rect);
400   EXPECT_EQ(overlay_plane_id, copy_quad->overlay_plane_id);
401 
402   CREATE_QUAD_ALL(VideoHoleDrawQuad, overlay_plane_id);
403   EXPECT_EQ(DrawQuad::Material::kVideoHole, copy_quad->material);
404   EXPECT_EQ(overlay_plane_id, copy_quad->overlay_plane_id);
405 }
406 
TEST(DrawQuadTest,CopyYUVVideoDrawQuad)407 TEST(DrawQuadTest, CopyYUVVideoDrawQuad) {
408   gfx::Rect visible_rect(40, 50, 30, 20);
409   bool needs_blending = true;
410   gfx::RectF ya_tex_coord_rect(40, 50, 30, 20);
411   gfx::RectF uv_tex_coord_rect(20, 25, 15, 10);
412   gfx::Size ya_tex_size(32, 68);
413   gfx::Size uv_tex_size(41, 51);
414   ResourceId y_plane_resource_id = 45;
415   ResourceId u_plane_resource_id = 532;
416   ResourceId v_plane_resource_id = 4;
417   ResourceId a_plane_resource_id = 63;
418   float resource_offset = 0.5f;
419   float resource_multiplier = 2.001f;
420   uint32_t bits_per_channel = 5;
421   gfx::ProtectedVideoType protected_video_type =
422       gfx::ProtectedVideoType::kHardwareProtected;
423   gfx::ColorSpace video_color_space = gfx::ColorSpace::CreateJpeg();
424   gfx::HDRMetadata hdr_metadata = gfx::HDRMetadata();
425   hdr_metadata.max_content_light_level = 1000;
426   hdr_metadata.max_frame_average_light_level = 100;
427 
428   CREATE_SHARED_STATE();
429 
430   CREATE_QUAD_NEW(YUVVideoDrawQuad, visible_rect, needs_blending,
431                   ya_tex_coord_rect, uv_tex_coord_rect, ya_tex_size,
432                   uv_tex_size, y_plane_resource_id, u_plane_resource_id,
433                   v_plane_resource_id, a_plane_resource_id, video_color_space,
434                   resource_offset, resource_multiplier, bits_per_channel);
435   EXPECT_EQ(DrawQuad::Material::kYuvVideoContent, copy_quad->material);
436   EXPECT_EQ(visible_rect, copy_quad->visible_rect);
437   EXPECT_EQ(needs_blending, copy_quad->needs_blending);
438   EXPECT_EQ(ya_tex_coord_rect, copy_quad->ya_tex_coord_rect);
439   EXPECT_EQ(uv_tex_coord_rect, copy_quad->uv_tex_coord_rect);
440   EXPECT_EQ(ya_tex_size, copy_quad->ya_tex_size);
441   EXPECT_EQ(uv_tex_size, copy_quad->uv_tex_size);
442   EXPECT_EQ(y_plane_resource_id, copy_quad->y_plane_resource_id());
443   EXPECT_EQ(u_plane_resource_id, copy_quad->u_plane_resource_id());
444   EXPECT_EQ(v_plane_resource_id, copy_quad->v_plane_resource_id());
445   EXPECT_EQ(a_plane_resource_id, copy_quad->a_plane_resource_id());
446   EXPECT_EQ(resource_offset, copy_quad->resource_offset);
447   EXPECT_EQ(resource_multiplier, copy_quad->resource_multiplier);
448   EXPECT_EQ(bits_per_channel, copy_quad->bits_per_channel);
449   EXPECT_EQ(gfx::ProtectedVideoType::kClear, copy_quad->protected_video_type);
450   EXPECT_EQ(gfx::HDRMetadata(), copy_quad->hdr_metadata);
451 
452   CREATE_QUAD_ALL(YUVVideoDrawQuad, ya_tex_coord_rect, uv_tex_coord_rect,
453                   ya_tex_size, uv_tex_size, y_plane_resource_id,
454                   u_plane_resource_id, v_plane_resource_id, a_plane_resource_id,
455                   video_color_space, resource_offset, resource_multiplier,
456                   bits_per_channel, protected_video_type, hdr_metadata);
457   EXPECT_EQ(DrawQuad::Material::kYuvVideoContent, copy_quad->material);
458   EXPECT_EQ(ya_tex_coord_rect, copy_quad->ya_tex_coord_rect);
459   EXPECT_EQ(uv_tex_coord_rect, copy_quad->uv_tex_coord_rect);
460   EXPECT_EQ(ya_tex_size, copy_quad->ya_tex_size);
461   EXPECT_EQ(uv_tex_size, copy_quad->uv_tex_size);
462   EXPECT_EQ(y_plane_resource_id, copy_quad->y_plane_resource_id());
463   EXPECT_EQ(u_plane_resource_id, copy_quad->u_plane_resource_id());
464   EXPECT_EQ(v_plane_resource_id, copy_quad->v_plane_resource_id());
465   EXPECT_EQ(a_plane_resource_id, copy_quad->a_plane_resource_id());
466   EXPECT_EQ(resource_offset, copy_quad->resource_offset);
467   EXPECT_EQ(resource_multiplier, copy_quad->resource_multiplier);
468   EXPECT_EQ(bits_per_channel, copy_quad->bits_per_channel);
469   EXPECT_EQ(protected_video_type, copy_quad->protected_video_type);
470   EXPECT_EQ(hdr_metadata, copy_quad->hdr_metadata);
471 }
472 
TEST(DrawQuadTest,CopyPictureDrawQuad)473 TEST(DrawQuadTest, CopyPictureDrawQuad) {
474   gfx::Rect visible_rect(40, 50, 30, 20);
475   bool needs_blending = true;
476   gfx::RectF tex_coord_rect(31.f, 12.f, 54.f, 20.f);
477   gfx::Size texture_size(85, 32);
478   bool nearest_neighbor = true;
479   ResourceFormat texture_format = RGBA_8888;
480   gfx::Rect content_rect(30, 40, 20, 30);
481   float contents_scale = 3.141592f;
482   scoped_refptr<cc::DisplayItemList> display_item_list =
483       cc::FakeRasterSource::CreateEmpty(gfx::Size(100, 100))
484           ->GetDisplayItemList();
485   CREATE_SHARED_STATE();
486 
487   CREATE_QUAD_NEW(PictureDrawQuad, visible_rect, needs_blending, tex_coord_rect,
488                   texture_size, nearest_neighbor, texture_format, content_rect,
489                   contents_scale, {}, display_item_list);
490   EXPECT_EQ(DrawQuad::Material::kPictureContent, copy_quad->material);
491   EXPECT_EQ(visible_rect, copy_quad->visible_rect);
492   EXPECT_EQ(needs_blending, copy_quad->needs_blending);
493   EXPECT_EQ(tex_coord_rect, copy_quad->tex_coord_rect);
494   EXPECT_EQ(texture_size, copy_quad->texture_size);
495   EXPECT_EQ(nearest_neighbor, copy_quad->nearest_neighbor);
496   EXPECT_EQ(texture_format, copy_quad->texture_format);
497   EXPECT_EQ(content_rect, copy_quad->content_rect);
498   EXPECT_EQ(contents_scale, copy_quad->contents_scale);
499   EXPECT_EQ(display_item_list, copy_quad->display_item_list);
500 
501   CREATE_QUAD_ALL(PictureDrawQuad, tex_coord_rect, texture_size,
502                   nearest_neighbor, texture_format, content_rect,
503                   contents_scale, {}, display_item_list);
504   EXPECT_EQ(DrawQuad::Material::kPictureContent, copy_quad->material);
505   EXPECT_EQ(tex_coord_rect, copy_quad->tex_coord_rect);
506   EXPECT_EQ(texture_size, copy_quad->texture_size);
507   EXPECT_EQ(nearest_neighbor, copy_quad->nearest_neighbor);
508   EXPECT_EQ(texture_format, copy_quad->texture_format);
509   EXPECT_EQ(content_rect, copy_quad->content_rect);
510   EXPECT_EQ(contents_scale, copy_quad->contents_scale);
511   EXPECT_EQ(display_item_list, copy_quad->display_item_list);
512 }
513 
514 class DrawQuadIteratorTest : public testing::Test {
515  protected:
IterateAndCount(DrawQuad * quad)516   int IterateAndCount(DrawQuad* quad) {
517     num_resources_ = 0;
518     for (ResourceId& resource_id : quad->resources) {
519       ++num_resources_;
520       ++resource_id;
521     }
522     return num_resources_;
523   }
524 
525  private:
526   int num_resources_;
527 };
528 
TEST_F(DrawQuadIteratorTest,DebugBorderDrawQuad)529 TEST_F(DrawQuadIteratorTest, DebugBorderDrawQuad) {
530   gfx::Rect visible_rect(40, 50, 30, 20);
531   SkColor color = 0xfabb0011;
532   int width = 99;
533 
534   CREATE_SHARED_STATE();
535   CREATE_QUAD_NEW(DebugBorderDrawQuad, visible_rect, color, width);
536   EXPECT_EQ(0, IterateAndCount(quad_new));
537 }
538 
TEST_F(DrawQuadIteratorTest,CompositorRenderPassDrawQuad)539 TEST_F(DrawQuadIteratorTest, CompositorRenderPassDrawQuad) {
540   gfx::Rect visible_rect(40, 50, 30, 20);
541   CompositorRenderPassId render_pass_id{61};
542   ResourceId mask_resource_id = 78;
543   gfx::RectF mask_uv_rect(0.f, 0.f, 33.f, 19.f);
544   gfx::Size mask_texture_size(128, 134);
545   gfx::Vector2dF filters_scale(2.f, 3.f);
546   gfx::PointF filters_origin(0.f, 0.f);
547   gfx::RectF tex_coord_rect(1.f, 1.f, 33.f, 19.f);
548   bool force_anti_aliasing_off = false;
549   float backdrop_filter_quality = 1.0f;
550   CompositorRenderPassId copied_render_pass_id{235};
551 
552   CREATE_SHARED_STATE();
553   CREATE_QUAD_NEW_RP(CompositorRenderPassDrawQuad, visible_rect, render_pass_id,
554                      mask_resource_id, mask_uv_rect, mask_texture_size,
555                      filters_scale, filters_origin, tex_coord_rect,
556                      force_anti_aliasing_off, backdrop_filter_quality,
557                      copied_render_pass_id);
558   EXPECT_EQ(mask_resource_id, quad_new->mask_resource_id());
559   EXPECT_EQ(1, IterateAndCount(quad_new));
560   EXPECT_EQ(mask_resource_id + 1, quad_new->mask_resource_id());
561 
562   ResourceId new_mask_resource_id = 0;
563   gfx::Rect quad_rect(30, 40, 50, 60);
564   quad_new->SetNew(shared_state, quad_rect, visible_rect, render_pass_id,
565                    new_mask_resource_id, mask_uv_rect, mask_texture_size,
566                    filters_scale, filters_origin, tex_coord_rect,
567                    force_anti_aliasing_off, backdrop_filter_quality);
568   EXPECT_EQ(0, IterateAndCount(quad_new));
569   EXPECT_EQ(0u, quad_new->mask_resource_id());
570 }
571 
TEST_F(DrawQuadIteratorTest,SolidColorDrawQuad)572 TEST_F(DrawQuadIteratorTest, SolidColorDrawQuad) {
573   gfx::Rect visible_rect(40, 50, 30, 20);
574   SkColor color = 0x49494949;
575   bool force_anti_aliasing_off = false;
576 
577   CREATE_SHARED_STATE();
578   CREATE_QUAD_NEW(SolidColorDrawQuad, visible_rect, color,
579                   force_anti_aliasing_off);
580   EXPECT_EQ(0, IterateAndCount(quad_new));
581 }
582 
TEST_F(DrawQuadIteratorTest,StreamVideoDrawQuad)583 TEST_F(DrawQuadIteratorTest, StreamVideoDrawQuad) {
584   gfx::Rect visible_rect(40, 50, 30, 20);
585   ResourceId resource_id = 64;
586   gfx::Size resource_size_in_pixels = gfx::Size(40, 41);
587   gfx::PointF uv_top_left(0.25f, 0.3f);
588   gfx::PointF uv_bottom_right(0.75f, 0.7f);
589 
590   CREATE_SHARED_STATE();
591   CREATE_QUAD_NEW(StreamVideoDrawQuad, visible_rect, needs_blending,
592                   resource_id, resource_size_in_pixels, uv_top_left,
593                   uv_bottom_right);
594   EXPECT_EQ(resource_id, quad_new->resource_id());
595   EXPECT_EQ(resource_size_in_pixels, quad_new->resource_size_in_pixels());
596   EXPECT_EQ(1, IterateAndCount(quad_new));
597   EXPECT_EQ(resource_id + 1, quad_new->resource_id());
598 }
599 
TEST_F(DrawQuadIteratorTest,SurfaceDrawQuad)600 TEST_F(DrawQuadIteratorTest, SurfaceDrawQuad) {
601   gfx::Rect visible_rect(40, 50, 30, 20);
602   SurfaceId surface_id(kArbitraryFrameSinkId,
603                        LocalSurfaceId(4321, base::UnguessableToken::Create()));
604 
605   CREATE_SHARED_STATE();
606   CREATE_QUAD_NEW(SurfaceDrawQuad, visible_rect,
607                   SurfaceRange(base::nullopt, surface_id), SK_ColorWHITE,
608                   /*stretch_content_to_fill_bounds=*/false);
609   EXPECT_EQ(0, IterateAndCount(quad_new));
610 }
611 
TEST_F(DrawQuadIteratorTest,TextureDrawQuad)612 TEST_F(DrawQuadIteratorTest, TextureDrawQuad) {
613   gfx::Rect visible_rect(40, 50, 30, 20);
614   unsigned resource_id = 82;
615   bool premultiplied_alpha = true;
616   gfx::PointF uv_top_left(0.5f, 224.f);
617   gfx::PointF uv_bottom_right(51.5f, 260.f);
618   const float vertex_opacity[] = {1.0f, 1.0f, 1.0f, 1.0f};
619   bool y_flipped = true;
620   bool nearest_neighbor = true;
621   bool secure_output_only = true;
622   gfx::ProtectedVideoType protected_video_type =
623       gfx::ProtectedVideoType::kClear;
624 
625   CREATE_SHARED_STATE();
626   CREATE_QUAD_NEW(TextureDrawQuad, visible_rect, needs_blending, resource_id,
627                   premultiplied_alpha, uv_top_left, uv_bottom_right,
628                   SK_ColorTRANSPARENT, vertex_opacity, y_flipped,
629                   nearest_neighbor, secure_output_only, protected_video_type);
630   EXPECT_EQ(resource_id, quad_new->resource_id());
631   EXPECT_EQ(1, IterateAndCount(quad_new));
632   EXPECT_EQ(resource_id + 1, quad_new->resource_id());
633 }
634 
TEST_F(DrawQuadIteratorTest,TileDrawQuad)635 TEST_F(DrawQuadIteratorTest, TileDrawQuad) {
636   gfx::Rect visible_rect(40, 50, 30, 20);
637   unsigned resource_id = 104;
638   gfx::RectF tex_coord_rect(31.f, 12.f, 54.f, 20.f);
639   gfx::Size texture_size(85, 32);
640   bool contents_premultiplied = true;
641   bool nearest_neighbor = true;
642   bool force_anti_aliasing_off = false;
643 
644   CREATE_SHARED_STATE();
645   CREATE_QUAD_NEW(TileDrawQuad, visible_rect, needs_blending, resource_id,
646                   tex_coord_rect, texture_size, contents_premultiplied,
647                   nearest_neighbor, force_anti_aliasing_off);
648   EXPECT_EQ(resource_id, quad_new->resource_id());
649   EXPECT_EQ(1, IterateAndCount(quad_new));
650   EXPECT_EQ(resource_id + 1, quad_new->resource_id());
651 }
652 
TEST_F(DrawQuadIteratorTest,VideoHoleDrawQuad)653 TEST_F(DrawQuadIteratorTest, VideoHoleDrawQuad) {
654   gfx::Rect visible_rect(40, 50, 30, 20);
655   base::UnguessableToken overlay_plane_id = base::UnguessableToken::Create();
656 
657   CREATE_SHARED_STATE();
658   CREATE_QUAD_NEW(VideoHoleDrawQuad, visible_rect, overlay_plane_id);
659   EXPECT_EQ(0, IterateAndCount(quad_new));
660 }
661 
TEST_F(DrawQuadIteratorTest,YUVVideoDrawQuad)662 TEST_F(DrawQuadIteratorTest, YUVVideoDrawQuad) {
663   gfx::Rect visible_rect(40, 50, 30, 20);
664   gfx::RectF ya_tex_coord_rect(0.0f, 0.0f, 0.75f, 0.5f);
665   gfx::RectF uv_tex_coord_rect(0.0f, 0.0f, 0.375f, 0.25f);
666   gfx::Size ya_tex_size(32, 68);
667   gfx::Size uv_tex_size(41, 51);
668   ResourceId y_plane_resource_id = 45;
669   ResourceId u_plane_resource_id = 532;
670   ResourceId v_plane_resource_id = 4;
671   ResourceId a_plane_resource_id = 63;
672   gfx::ColorSpace video_color_space = gfx::ColorSpace::CreateJpeg();
673 
674   CREATE_SHARED_STATE();
675   CREATE_QUAD_NEW(YUVVideoDrawQuad, visible_rect, needs_blending,
676                   ya_tex_coord_rect, uv_tex_coord_rect, ya_tex_size,
677                   uv_tex_size, y_plane_resource_id, u_plane_resource_id,
678                   v_plane_resource_id, a_plane_resource_id, video_color_space,
679                   0.0, 1.0, 5);
680   EXPECT_EQ(DrawQuad::Material::kYuvVideoContent, copy_quad->material);
681   EXPECT_EQ(y_plane_resource_id, quad_new->y_plane_resource_id());
682   EXPECT_EQ(u_plane_resource_id, quad_new->u_plane_resource_id());
683   EXPECT_EQ(v_plane_resource_id, quad_new->v_plane_resource_id());
684   EXPECT_EQ(a_plane_resource_id, quad_new->a_plane_resource_id());
685   EXPECT_EQ(4, IterateAndCount(quad_new));
686   EXPECT_EQ(y_plane_resource_id + 1, quad_new->y_plane_resource_id());
687   EXPECT_EQ(u_plane_resource_id + 1, quad_new->u_plane_resource_id());
688   EXPECT_EQ(v_plane_resource_id + 1, quad_new->v_plane_resource_id());
689   EXPECT_EQ(a_plane_resource_id + 1, quad_new->a_plane_resource_id());
690 }
691 
TEST(DrawQuadTest,LargestQuadType)692 TEST(DrawQuadTest, LargestQuadType) {
693   size_t largest = 0;
694 
695   for (int i = 0; i <= static_cast<int>(DrawQuad::Material::kMaxValue); ++i) {
696     switch (static_cast<DrawQuad::Material>(i)) {
697       case DrawQuad::Material::kAggregatedRenderPass:
698         largest = std::max(largest, sizeof(AggregatedRenderPassDrawQuad));
699         break;
700       case DrawQuad::Material::kDebugBorder:
701         largest = std::max(largest, sizeof(DebugBorderDrawQuad));
702         break;
703       case DrawQuad::Material::kPictureContent:
704         largest = std::max(largest, sizeof(PictureDrawQuad));
705         break;
706       case DrawQuad::Material::kTextureContent:
707         largest = std::max(largest, sizeof(TextureDrawQuad));
708         break;
709       case DrawQuad::Material::kCompositorRenderPass:
710         largest = std::max(largest, sizeof(CompositorRenderPassDrawQuad));
711         break;
712       case DrawQuad::Material::kSolidColor:
713         largest = std::max(largest, sizeof(SolidColorDrawQuad));
714         break;
715       case DrawQuad::Material::kSurfaceContent:
716         largest = std::max(largest, sizeof(SurfaceDrawQuad));
717         break;
718       case DrawQuad::Material::kTiledContent:
719         largest = std::max(largest, sizeof(TileDrawQuad));
720         break;
721       case DrawQuad::Material::kStreamVideoContent:
722         largest = std::max(largest, sizeof(StreamVideoDrawQuad));
723         break;
724       case DrawQuad::Material::kYuvVideoContent:
725         largest = std::max(largest, sizeof(YUVVideoDrawQuad));
726         break;
727       case DrawQuad::Material::kVideoHole:
728         largest = std::max(largest, sizeof(VideoHoleDrawQuad));
729         break;
730       case DrawQuad::Material::kInvalid:
731         break;
732     }
733   }
734   EXPECT_EQ(LargestDrawQuadSize(), largest);
735 
736   if (!HasFailure())
737     return;
738 
739   // On failure, output the size of all quads for debugging.
740   LOG(ERROR) << "largest " << largest;
741   LOG(ERROR) << "kLargestDrawQuad " << LargestDrawQuadSize();
742   for (int i = 0; i <= static_cast<int>(DrawQuad::Material::kMaxValue); ++i) {
743     switch (static_cast<DrawQuad::Material>(i)) {
744       case DrawQuad::Material::kAggregatedRenderPass:
745         LOG(ERROR) << "AggregatedRenderPass " << sizeof(AggregatedRenderPass);
746         break;
747       case DrawQuad::Material::kDebugBorder:
748         LOG(ERROR) << "DebugBorderDrawQuad " << sizeof(DebugBorderDrawQuad);
749         break;
750       case DrawQuad::Material::kPictureContent:
751         LOG(ERROR) << "PictureDrawQuad " << sizeof(PictureDrawQuad);
752         break;
753       case DrawQuad::Material::kTextureContent:
754         LOG(ERROR) << "TextureDrawQuad " << sizeof(TextureDrawQuad);
755         break;
756       case DrawQuad::Material::kCompositorRenderPass:
757         LOG(ERROR) << "CompositorRenderPassDrawQuad "
758                    << sizeof(CompositorRenderPassDrawQuad);
759         break;
760       case DrawQuad::Material::kSolidColor:
761         LOG(ERROR) << "SolidColorDrawQuad " << sizeof(SolidColorDrawQuad);
762         break;
763       case DrawQuad::Material::kSurfaceContent:
764         LOG(ERROR) << "SurfaceDrawQuad " << sizeof(SurfaceDrawQuad);
765         break;
766       case DrawQuad::Material::kTiledContent:
767         LOG(ERROR) << "TileDrawQuad " << sizeof(TileDrawQuad);
768         break;
769       case DrawQuad::Material::kStreamVideoContent:
770         LOG(ERROR) << "StreamVideoDrawQuad " << sizeof(StreamVideoDrawQuad);
771         break;
772       case DrawQuad::Material::kYuvVideoContent:
773         LOG(ERROR) << "YUVVideoDrawQuad " << sizeof(YUVVideoDrawQuad);
774         break;
775       case DrawQuad::Material::kVideoHole:
776         LOG(ERROR) << "VideoHoleDrawQuad " << sizeof(VideoHoleDrawQuad);
777         break;
778       case DrawQuad::Material::kInvalid:
779         break;
780     }
781   }
782 }
783 
784 }  // namespace
785 }  // namespace viz
786