1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "build/build_config.h"
6 #include "cc/layers/content_layer_client.h"
7 #include "cc/layers/picture_image_layer.h"
8 #include "cc/layers/picture_layer.h"
9 #include "cc/layers/solid_color_layer.h"
10 #include "cc/test/layer_tree_pixel_resource_test.h"
11 #include "cc/test/pixel_comparator.h"
13 #if !defined(OS_ANDROID)
18 typedef ParameterizedPixelResourceTest LayerTreeHostMasksPixelTest
;
20 INSTANTIATE_PIXEL_RESOURCE_TEST_CASE_P(LayerTreeHostMasksPixelTest
);
22 class MaskContentLayerClient
: public ContentLayerClient
{
24 explicit MaskContentLayerClient(const gfx::Size
& bounds
) : bounds_(bounds
) {}
25 ~MaskContentLayerClient() override
{}
27 bool FillsBoundsCompletely() const override
{ return false; }
29 void PaintContents(SkCanvas
* canvas
,
30 const gfx::Rect
& rect
,
31 PaintingControlSetting picture_control
) override
{
33 paint
.setStyle(SkPaint::kStroke_Style
);
34 paint
.setStrokeWidth(SkIntToScalar(2));
35 paint
.setColor(SK_ColorWHITE
);
37 canvas
->clear(SK_ColorTRANSPARENT
);
38 gfx::Rect
inset_rect(bounds_
);
39 while (!inset_rect
.IsEmpty()) {
40 inset_rect
.Inset(3, 3, 2, 2);
42 SkRect::MakeXYWH(inset_rect
.x(), inset_rect
.y(),
43 inset_rect
.width(), inset_rect
.height()),
45 inset_rect
.Inset(3, 3, 2, 2);
49 void PaintContentsToDisplayList(
50 DisplayItemList
* display_list
,
51 const gfx::Rect
& clip
,
52 PaintingControlSetting picture_control
) override
{
60 TEST_P(LayerTreeHostMasksPixelTest
, MaskOfLayer
) {
61 scoped_refptr
<SolidColorLayer
> background
= CreateSolidColorLayer(
62 gfx::Rect(100, 100), SK_ColorWHITE
);
64 scoped_refptr
<SolidColorLayer
> green
= CreateSolidColorLayerWithBorder(
65 gfx::Rect(25, 25, 50, 50), kCSSGreen
, 1, SK_ColorBLACK
);
66 background
->AddChild(green
);
68 gfx::Size
mask_bounds(50, 50);
69 MaskContentLayerClient
client(mask_bounds
);
70 scoped_refptr
<PictureLayer
> mask
=
71 PictureLayer::Create(layer_settings(), &client
);
72 mask
->SetBounds(mask_bounds
);
73 mask
->SetIsDrawable(true);
74 mask
->SetIsMask(true);
75 green
->SetMaskLayer(mask
.get());
77 RunPixelResourceTest(background
,
78 base::FilePath(FILE_PATH_LITERAL("mask_of_layer.png")));
81 TEST_P(LayerTreeHostMasksPixelTest
, ImageMaskOfLayer
) {
82 scoped_refptr
<SolidColorLayer
> background
= CreateSolidColorLayer(
83 gfx::Rect(100, 100), SK_ColorWHITE
);
85 gfx::Size
mask_bounds(50, 50);
87 scoped_refptr
<PictureImageLayer
> mask
=
88 PictureImageLayer::Create(layer_settings());
89 mask
->SetIsDrawable(true);
90 mask
->SetIsMask(true);
91 mask
->SetBounds(mask_bounds
);
94 bitmap
.allocN32Pixels(200, 200);
95 SkCanvas
canvas(bitmap
);
96 canvas
.scale(SkIntToScalar(4), SkIntToScalar(4));
97 MaskContentLayerClient
client(mask_bounds
);
98 client
.PaintContents(&canvas
, gfx::Rect(mask_bounds
),
99 ContentLayerClient::PAINTING_BEHAVIOR_NORMAL
);
100 mask
->SetBitmap(bitmap
);
102 scoped_refptr
<SolidColorLayer
> green
= CreateSolidColorLayerWithBorder(
103 gfx::Rect(25, 25, 50, 50), kCSSGreen
, 1, SK_ColorBLACK
);
104 green
->SetMaskLayer(mask
.get());
105 background
->AddChild(green
);
107 RunPixelResourceTest(
108 background
, base::FilePath(FILE_PATH_LITERAL("image_mask_of_layer.png")));
111 TEST_P(LayerTreeHostMasksPixelTest
, MaskOfClippedLayer
) {
112 scoped_refptr
<SolidColorLayer
> background
= CreateSolidColorLayer(
113 gfx::Rect(100, 100), SK_ColorWHITE
);
115 // Clip to the top half of the green layer.
116 scoped_refptr
<Layer
> clip
= Layer::Create(layer_settings());
117 clip
->SetPosition(gfx::Point(0, 0));
118 clip
->SetBounds(gfx::Size(100, 50));
119 clip
->SetMasksToBounds(true);
120 background
->AddChild(clip
);
122 scoped_refptr
<SolidColorLayer
> green
= CreateSolidColorLayerWithBorder(
123 gfx::Rect(25, 25, 50, 50), kCSSGreen
, 1, SK_ColorBLACK
);
124 clip
->AddChild(green
);
126 gfx::Size
mask_bounds(50, 50);
127 MaskContentLayerClient
client(mask_bounds
);
128 scoped_refptr
<PictureLayer
> mask
=
129 PictureLayer::Create(layer_settings(), &client
);
130 mask
->SetBounds(mask_bounds
);
131 mask
->SetIsDrawable(true);
132 mask
->SetIsMask(true);
133 green
->SetMaskLayer(mask
.get());
135 RunPixelResourceTest(
137 base::FilePath(FILE_PATH_LITERAL("mask_of_clipped_layer.png")));
140 TEST_P(LayerTreeHostMasksPixelTest
, MaskWithReplica
) {
141 scoped_refptr
<SolidColorLayer
> background
= CreateSolidColorLayer(
142 gfx::Rect(100, 100), SK_ColorWHITE
);
144 gfx::Size
mask_bounds(50, 50);
145 MaskContentLayerClient
client(mask_bounds
);
146 scoped_refptr
<PictureLayer
> mask
=
147 PictureLayer::Create(layer_settings(), &client
);
148 mask
->SetBounds(mask_bounds
);
149 mask
->SetIsDrawable(true);
150 mask
->SetIsMask(true);
152 scoped_refptr
<SolidColorLayer
> green
= CreateSolidColorLayerWithBorder(
153 gfx::Rect(0, 0, 50, 50), kCSSGreen
, 1, SK_ColorBLACK
);
154 background
->AddChild(green
);
155 green
->SetMaskLayer(mask
.get());
157 gfx::Transform replica_transform
;
158 replica_transform
.Rotate(-90.0);
160 scoped_refptr
<Layer
> replica
= Layer::Create(layer_settings());
161 replica
->SetTransformOrigin(gfx::Point3F(25.f
, 25.f
, 0.f
));
162 replica
->SetPosition(gfx::Point(50, 50));
163 replica
->SetTransform(replica_transform
);
164 green
->SetReplicaLayer(replica
.get());
166 RunPixelResourceTest(
167 background
, base::FilePath(FILE_PATH_LITERAL("mask_with_replica.png")));
170 TEST_P(LayerTreeHostMasksPixelTest
, MaskWithReplicaOfClippedLayer
) {
171 scoped_refptr
<SolidColorLayer
> background
= CreateSolidColorLayer(
172 gfx::Rect(100, 100), SK_ColorWHITE
);
174 gfx::Size
mask_bounds(50, 50);
175 MaskContentLayerClient
client(mask_bounds
);
176 scoped_refptr
<PictureLayer
> mask
=
177 PictureLayer::Create(layer_settings(), &client
);
178 mask
->SetBounds(mask_bounds
);
179 mask
->SetIsDrawable(true);
180 mask
->SetIsMask(true);
182 // Clip to the bottom half of the green layer, and the left half of the
184 scoped_refptr
<Layer
> clip
= Layer::Create(layer_settings());
185 clip
->SetPosition(gfx::Point(0, 25));
186 clip
->SetBounds(gfx::Size(75, 75));
187 clip
->SetMasksToBounds(true);
188 background
->AddChild(clip
);
190 scoped_refptr
<SolidColorLayer
> green
= CreateSolidColorLayerWithBorder(
191 gfx::Rect(0, -25, 50, 50), kCSSGreen
, 1, SK_ColorBLACK
);
192 clip
->AddChild(green
);
193 green
->SetMaskLayer(mask
.get());
195 gfx::Transform replica_transform
;
196 replica_transform
.Rotate(-90.0);
198 scoped_refptr
<Layer
> replica
= Layer::Create(layer_settings());
199 replica
->SetTransformOrigin(gfx::Point3F(25.f
, 25.f
, 0.f
));
200 replica
->SetPosition(gfx::Point(50, 50));
201 replica
->SetTransform(replica_transform
);
202 green
->SetReplicaLayer(replica
.get());
204 RunPixelResourceTest(background
,
205 base::FilePath(FILE_PATH_LITERAL(
206 "mask_with_replica_of_clipped_layer.png")));
209 TEST_P(LayerTreeHostMasksPixelTest
, MaskOfReplica
) {
210 scoped_refptr
<SolidColorLayer
> background
= CreateSolidColorLayer(
211 gfx::Rect(100, 100), SK_ColorWHITE
);
213 gfx::Size
mask_bounds(50, 50);
214 MaskContentLayerClient
client(mask_bounds
);
215 scoped_refptr
<PictureLayer
> mask
=
216 PictureLayer::Create(layer_settings(), &client
);
217 mask
->SetBounds(mask_bounds
);
218 mask
->SetIsDrawable(true);
219 mask
->SetIsMask(true);
221 scoped_refptr
<SolidColorLayer
> green
= CreateSolidColorLayerWithBorder(
222 gfx::Rect(25, 0, 50, 50), kCSSGreen
, 1, SK_ColorBLACK
);
223 background
->AddChild(green
);
225 scoped_refptr
<SolidColorLayer
> orange
= CreateSolidColorLayer(
226 gfx::Rect(-25, 25, 25, 25), kCSSOrange
);
227 green
->AddChild(orange
);
229 gfx::Transform replica_transform
;
230 replica_transform
.Rotate(180.0);
231 replica_transform
.Translate(50.0, 0.0);
233 scoped_refptr
<Layer
> replica
= Layer::Create(layer_settings());
234 replica
->SetTransformOrigin(gfx::Point3F(50.f
, 50.f
, 0.f
));
235 replica
->SetPosition(gfx::Point());
236 replica
->SetTransform(replica_transform
);
237 replica
->SetMaskLayer(mask
.get());
238 green
->SetReplicaLayer(replica
.get());
240 RunPixelResourceTest(
241 background
, base::FilePath(FILE_PATH_LITERAL("mask_of_replica.png")));
244 TEST_P(LayerTreeHostMasksPixelTest
, MaskOfReplicaOfClippedLayer
) {
245 scoped_refptr
<SolidColorLayer
> background
= CreateSolidColorLayer(
246 gfx::Rect(100, 100), SK_ColorWHITE
);
248 gfx::Size
mask_bounds(50, 50);
249 MaskContentLayerClient
client(mask_bounds
);
250 scoped_refptr
<PictureLayer
> mask
=
251 PictureLayer::Create(layer_settings(), &client
);
252 mask
->SetBounds(mask_bounds
);
253 mask
->SetIsDrawable(true);
254 mask
->SetIsMask(true);
256 // Clip to the bottom 3/4 of the green layer, and the top 3/4 of the replica.
257 scoped_refptr
<Layer
> clip
= Layer::Create(layer_settings());
258 clip
->SetPosition(gfx::Point(0, 12));
259 clip
->SetBounds(gfx::Size(100, 75));
260 clip
->SetMasksToBounds(true);
261 background
->AddChild(clip
);
263 scoped_refptr
<SolidColorLayer
> green
= CreateSolidColorLayerWithBorder(
264 gfx::Rect(25, -12, 50, 50), kCSSGreen
, 1, SK_ColorBLACK
);
265 clip
->AddChild(green
);
267 scoped_refptr
<SolidColorLayer
> orange
= CreateSolidColorLayer(
268 gfx::Rect(-25, 25, 25, 25), kCSSOrange
);
269 green
->AddChild(orange
);
271 gfx::Transform replica_transform
;
272 replica_transform
.Rotate(180.0);
273 replica_transform
.Translate(50.0, 0.0);
275 scoped_refptr
<Layer
> replica
= Layer::Create(layer_settings());
276 replica
->SetTransformOrigin(gfx::Point3F(50.f
, 50.f
, 0.f
));
277 replica
->SetPosition(gfx::Point());
278 replica
->SetTransform(replica_transform
);
279 replica
->SetMaskLayer(mask
.get());
280 green
->SetReplicaLayer(replica
.get());
282 RunPixelResourceTest(background
,
283 base::FilePath(FILE_PATH_LITERAL(
284 "mask_of_replica_of_clipped_layer.png")));
287 class CheckerContentLayerClient
: public ContentLayerClient
{
289 CheckerContentLayerClient(const gfx::Size
& bounds
,
292 : bounds_(bounds
), color_(color
), vertical_(vertical
) {}
293 ~CheckerContentLayerClient() override
{}
294 bool FillsBoundsCompletely() const override
{ return false; }
295 void PaintContents(SkCanvas
* canvas
,
296 const gfx::Rect
& rect
,
297 PaintingControlSetting picture_control
) override
{
299 paint
.setStyle(SkPaint::kStroke_Style
);
300 paint
.setStrokeWidth(SkIntToScalar(4));
301 paint
.setColor(color_
);
302 canvas
->clear(SK_ColorTRANSPARENT
);
304 for (int i
= 4; i
< bounds_
.width(); i
+= 16) {
305 canvas
->drawLine(i
, 0, i
, bounds_
.height(), paint
);
308 for (int i
= 4; i
< bounds_
.height(); i
+= 16) {
309 canvas
->drawLine(0, i
, bounds_
.width(), i
, paint
);
313 void PaintContentsToDisplayList(
314 DisplayItemList
* display_list
,
315 const gfx::Rect
& clip
,
316 PaintingControlSetting picture_control
) override
{
326 class CircleContentLayerClient
: public ContentLayerClient
{
328 explicit CircleContentLayerClient(const gfx::Size
& bounds
)
330 ~CircleContentLayerClient() override
{}
331 bool FillsBoundsCompletely() const override
{ return false; }
332 void PaintContents(SkCanvas
* canvas
,
333 const gfx::Rect
& rect
,
334 PaintingControlSetting picture_control
) override
{
336 paint
.setStyle(SkPaint::kFill_Style
);
337 paint
.setColor(SK_ColorWHITE
);
338 canvas
->clear(SK_ColorTRANSPARENT
);
339 canvas
->drawCircle(bounds_
.width() / 2,
340 bounds_
.height() / 2,
344 void PaintContentsToDisplayList(
345 DisplayItemList
* display_list
,
346 const gfx::Rect
& clip
,
347 PaintingControlSetting picture_control
) override
{
355 using LayerTreeHostMasksForBackgroundFiltersPixelTest
=
356 ParameterizedPixelResourceTest
;
358 INSTANTIATE_TEST_CASE_P(
360 LayerTreeHostMasksForBackgroundFiltersPixelTest
,
362 // SOFTWARE, Background filters aren't implemented in software
363 GL_GPU_RASTER_2D_DRAW
,
364 GL_ONE_COPY_2D_STAGING_2D_DRAW
,
365 GL_ONE_COPY_RECT_STAGING_2D_DRAW
,
366 GL_ONE_COPY_EXTERNAL_STAGING_2D_DRAW
,
367 GL_ZERO_COPY_2D_DRAW
,
368 GL_ZERO_COPY_RECT_DRAW
,
369 GL_ZERO_COPY_EXTERNAL_DRAW
,
370 GL_ASYNC_UPLOAD_2D_DRAW
));
372 TEST_P(LayerTreeHostMasksForBackgroundFiltersPixelTest
,
373 MaskOfLayerWithBackgroundFilter
) {
374 scoped_refptr
<SolidColorLayer
> background
= CreateSolidColorLayer(
375 gfx::Rect(100, 100), SK_ColorWHITE
);
377 gfx::Size
picture_bounds(100, 100);
378 CheckerContentLayerClient
picture_client(picture_bounds
, SK_ColorGREEN
, true);
379 scoped_refptr
<PictureLayer
> picture
=
380 PictureLayer::Create(layer_settings(), &picture_client
);
381 picture
->SetBounds(picture_bounds
);
382 picture
->SetIsDrawable(true);
384 scoped_refptr
<SolidColorLayer
> blur
= CreateSolidColorLayer(
385 gfx::Rect(100, 100), SK_ColorTRANSPARENT
);
386 background
->AddChild(picture
);
387 background
->AddChild(blur
);
389 FilterOperations filters
;
390 filters
.Append(FilterOperation::CreateBlurFilter(1.5f
));
391 blur
->SetBackgroundFilters(filters
);
393 gfx::Size
mask_bounds(100, 100);
394 CircleContentLayerClient
mask_client(mask_bounds
);
395 scoped_refptr
<PictureLayer
> mask
=
396 PictureLayer::Create(layer_settings(), &mask_client
);
397 mask
->SetBounds(mask_bounds
);
398 mask
->SetIsDrawable(true);
399 mask
->SetIsMask(true);
400 blur
->SetMaskLayer(mask
.get());
402 float percentage_pixels_large_error
= 2.5f
; // 2.5%, ~250px / (100*100)
403 float percentage_pixels_small_error
= 0.0f
;
404 float average_error_allowed_in_bad_pixels
= 100.0f
;
405 int large_error_allowed
= 256;
406 int small_error_allowed
= 0;
407 pixel_comparator_
.reset(new FuzzyPixelComparator(
408 true, // discard_alpha
409 percentage_pixels_large_error
,
410 percentage_pixels_small_error
,
411 average_error_allowed_in_bad_pixels
,
413 small_error_allowed
));
415 RunPixelResourceTest(background
,
417 FILE_PATH_LITERAL("mask_of_background_filter.png")));
420 TEST_P(LayerTreeHostMasksForBackgroundFiltersPixelTest
,
421 MaskOfLayerWithBlend
) {
422 scoped_refptr
<SolidColorLayer
> background
= CreateSolidColorLayer(
423 gfx::Rect(128, 128), SK_ColorWHITE
);
425 gfx::Size
picture_bounds(128, 128);
426 CheckerContentLayerClient
picture_client_vertical(
427 picture_bounds
, SK_ColorGREEN
, true);
428 scoped_refptr
<PictureLayer
> picture_vertical
=
429 PictureLayer::Create(layer_settings(), &picture_client_vertical
);
430 picture_vertical
->SetBounds(picture_bounds
);
431 picture_vertical
->SetIsDrawable(true);
433 CheckerContentLayerClient
picture_client_horizontal(
434 picture_bounds
, SK_ColorMAGENTA
, false);
435 scoped_refptr
<PictureLayer
> picture_horizontal
=
436 PictureLayer::Create(layer_settings(), &picture_client_horizontal
);
437 picture_horizontal
->SetBounds(picture_bounds
);
438 picture_horizontal
->SetIsDrawable(true);
439 picture_horizontal
->SetContentsOpaque(false);
440 picture_horizontal
->SetBlendMode(SkXfermode::kMultiply_Mode
);
442 background
->AddChild(picture_vertical
);
443 background
->AddChild(picture_horizontal
);
445 gfx::Size
mask_bounds(128, 128);
446 CircleContentLayerClient
mask_client(mask_bounds
);
447 scoped_refptr
<PictureLayer
> mask
=
448 PictureLayer::Create(layer_settings(), &mask_client
);
449 mask
->SetBounds(mask_bounds
);
450 mask
->SetIsDrawable(true);
451 mask
->SetIsMask(true);
452 picture_horizontal
->SetMaskLayer(mask
.get());
454 float percentage_pixels_large_error
= 0.04f
; // 0.04%, ~6px / (128*128)
455 float percentage_pixels_small_error
= 0.0f
;
456 float average_error_allowed_in_bad_pixels
= 256.0f
;
457 int large_error_allowed
= 256;
458 int small_error_allowed
= 0;
459 pixel_comparator_
.reset(new FuzzyPixelComparator(
460 true, // discard_alpha
461 percentage_pixels_large_error
,
462 percentage_pixels_small_error
,
463 average_error_allowed_in_bad_pixels
,
465 small_error_allowed
));
467 RunPixelResourceTest(background
,
469 FILE_PATH_LITERAL("mask_of_layer_with_blend.png")));
475 #endif // !defined(OS_ANDROID)