OLD | NEW |
| (Empty) |
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. | |
4 | |
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" | |
12 | |
13 #if !defined(OS_ANDROID) | |
14 | |
15 namespace cc { | |
16 namespace { | |
17 | |
18 typedef ParameterizedPixelResourceTest LayerTreeHostMasksPixelTest; | |
19 | |
20 INSTANTIATE_PIXEL_RESOURCE_TEST_CASE_P(LayerTreeHostMasksPixelTest); | |
21 | |
22 class MaskContentLayerClient : public ContentLayerClient { | |
23 public: | |
24 explicit MaskContentLayerClient(const gfx::Size& bounds) : bounds_(bounds) {} | |
25 ~MaskContentLayerClient() override {} | |
26 | |
27 bool FillsBoundsCompletely() const override { return false; } | |
28 | |
29 void PaintContents(SkCanvas* canvas, | |
30 const gfx::Rect& rect, | |
31 PaintingControlSetting picture_control) override { | |
32 SkPaint paint; | |
33 paint.setStyle(SkPaint::kStroke_Style); | |
34 paint.setStrokeWidth(SkIntToScalar(2)); | |
35 paint.setColor(SK_ColorWHITE); | |
36 | |
37 canvas->clear(SK_ColorTRANSPARENT); | |
38 gfx::Rect inset_rect(bounds_); | |
39 while (!inset_rect.IsEmpty()) { | |
40 inset_rect.Inset(3, 3, 2, 2); | |
41 canvas->drawRect( | |
42 SkRect::MakeXYWH(inset_rect.x(), inset_rect.y(), | |
43 inset_rect.width(), inset_rect.height()), | |
44 paint); | |
45 inset_rect.Inset(3, 3, 2, 2); | |
46 } | |
47 } | |
48 | |
49 scoped_refptr<DisplayItemList> PaintContentsToDisplayList( | |
50 const gfx::Rect& clip, | |
51 PaintingControlSetting picture_control) override { | |
52 NOTIMPLEMENTED(); | |
53 return DisplayItemList::Create(); | |
54 } | |
55 | |
56 private: | |
57 gfx::Size bounds_; | |
58 }; | |
59 | |
60 TEST_P(LayerTreeHostMasksPixelTest, MaskOfLayer) { | |
61 scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer( | |
62 gfx::Rect(100, 100), SK_ColorWHITE); | |
63 | |
64 scoped_refptr<SolidColorLayer> green = CreateSolidColorLayerWithBorder( | |
65 gfx::Rect(25, 25, 50, 50), kCSSGreen, 1, SK_ColorBLACK); | |
66 background->AddChild(green); | |
67 | |
68 gfx::Size mask_bounds(50, 50); | |
69 MaskContentLayerClient client(mask_bounds); | |
70 scoped_refptr<PictureLayer> mask = PictureLayer::Create(&client); | |
71 mask->SetBounds(mask_bounds); | |
72 mask->SetIsDrawable(true); | |
73 mask->SetIsMask(true); | |
74 green->SetMaskLayer(mask.get()); | |
75 | |
76 RunPixelResourceTest(background, | |
77 base::FilePath(FILE_PATH_LITERAL("mask_of_layer.png"))); | |
78 } | |
79 | |
80 TEST_P(LayerTreeHostMasksPixelTest, ImageMaskOfLayer) { | |
81 scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer( | |
82 gfx::Rect(100, 100), SK_ColorWHITE); | |
83 | |
84 gfx::Size mask_bounds(50, 50); | |
85 | |
86 scoped_refptr<PictureImageLayer> mask = PictureImageLayer::Create(); | |
87 mask->SetIsDrawable(true); | |
88 mask->SetIsMask(true); | |
89 mask->SetBounds(mask_bounds); | |
90 | |
91 SkBitmap bitmap; | |
92 bitmap.allocN32Pixels(200, 200); | |
93 SkCanvas canvas(bitmap); | |
94 canvas.scale(SkIntToScalar(4), SkIntToScalar(4)); | |
95 MaskContentLayerClient client(mask_bounds); | |
96 client.PaintContents(&canvas, gfx::Rect(mask_bounds), | |
97 ContentLayerClient::PAINTING_BEHAVIOR_NORMAL); | |
98 mask->SetBitmap(bitmap); | |
99 | |
100 scoped_refptr<SolidColorLayer> green = CreateSolidColorLayerWithBorder( | |
101 gfx::Rect(25, 25, 50, 50), kCSSGreen, 1, SK_ColorBLACK); | |
102 green->SetMaskLayer(mask.get()); | |
103 background->AddChild(green); | |
104 | |
105 RunPixelResourceTest( | |
106 background, base::FilePath(FILE_PATH_LITERAL("image_mask_of_layer.png"))); | |
107 } | |
108 | |
109 TEST_P(LayerTreeHostMasksPixelTest, MaskOfClippedLayer) { | |
110 scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer( | |
111 gfx::Rect(100, 100), SK_ColorWHITE); | |
112 | |
113 // Clip to the top half of the green layer. | |
114 scoped_refptr<Layer> clip = Layer::Create(); | |
115 clip->SetPosition(gfx::Point(0, 0)); | |
116 clip->SetBounds(gfx::Size(100, 50)); | |
117 clip->SetMasksToBounds(true); | |
118 background->AddChild(clip); | |
119 | |
120 scoped_refptr<SolidColorLayer> green = CreateSolidColorLayerWithBorder( | |
121 gfx::Rect(25, 25, 50, 50), kCSSGreen, 1, SK_ColorBLACK); | |
122 clip->AddChild(green); | |
123 | |
124 gfx::Size mask_bounds(50, 50); | |
125 MaskContentLayerClient client(mask_bounds); | |
126 scoped_refptr<PictureLayer> mask = PictureLayer::Create(&client); | |
127 mask->SetBounds(mask_bounds); | |
128 mask->SetIsDrawable(true); | |
129 mask->SetIsMask(true); | |
130 green->SetMaskLayer(mask.get()); | |
131 | |
132 RunPixelResourceTest( | |
133 background, | |
134 base::FilePath(FILE_PATH_LITERAL("mask_of_clipped_layer.png"))); | |
135 } | |
136 | |
137 TEST_P(LayerTreeHostMasksPixelTest, MaskWithReplica) { | |
138 scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer( | |
139 gfx::Rect(100, 100), SK_ColorWHITE); | |
140 | |
141 gfx::Size mask_bounds(50, 50); | |
142 MaskContentLayerClient client(mask_bounds); | |
143 scoped_refptr<PictureLayer> mask = PictureLayer::Create(&client); | |
144 mask->SetBounds(mask_bounds); | |
145 mask->SetIsDrawable(true); | |
146 mask->SetIsMask(true); | |
147 | |
148 scoped_refptr<SolidColorLayer> green = CreateSolidColorLayerWithBorder( | |
149 gfx::Rect(0, 0, 50, 50), kCSSGreen, 1, SK_ColorBLACK); | |
150 background->AddChild(green); | |
151 green->SetMaskLayer(mask.get()); | |
152 | |
153 gfx::Transform replica_transform; | |
154 replica_transform.Rotate(-90.0); | |
155 | |
156 scoped_refptr<Layer> replica = Layer::Create(); | |
157 replica->SetTransformOrigin(gfx::Point3F(25.f, 25.f, 0.f)); | |
158 replica->SetPosition(gfx::Point(50, 50)); | |
159 replica->SetTransform(replica_transform); | |
160 green->SetReplicaLayer(replica.get()); | |
161 | |
162 RunPixelResourceTest( | |
163 background, base::FilePath(FILE_PATH_LITERAL("mask_with_replica.png"))); | |
164 } | |
165 | |
166 TEST_P(LayerTreeHostMasksPixelTest, MaskWithReplicaOfClippedLayer) { | |
167 scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer( | |
168 gfx::Rect(100, 100), SK_ColorWHITE); | |
169 | |
170 gfx::Size mask_bounds(50, 50); | |
171 MaskContentLayerClient client(mask_bounds); | |
172 scoped_refptr<PictureLayer> mask = PictureLayer::Create(&client); | |
173 mask->SetBounds(mask_bounds); | |
174 mask->SetIsDrawable(true); | |
175 mask->SetIsMask(true); | |
176 | |
177 // Clip to the bottom half of the green layer, and the left half of the | |
178 // replica. | |
179 scoped_refptr<Layer> clip = Layer::Create(); | |
180 clip->SetPosition(gfx::Point(0, 25)); | |
181 clip->SetBounds(gfx::Size(75, 75)); | |
182 clip->SetMasksToBounds(true); | |
183 background->AddChild(clip); | |
184 | |
185 scoped_refptr<SolidColorLayer> green = CreateSolidColorLayerWithBorder( | |
186 gfx::Rect(0, -25, 50, 50), kCSSGreen, 1, SK_ColorBLACK); | |
187 clip->AddChild(green); | |
188 green->SetMaskLayer(mask.get()); | |
189 | |
190 gfx::Transform replica_transform; | |
191 replica_transform.Rotate(-90.0); | |
192 | |
193 scoped_refptr<Layer> replica = Layer::Create(); | |
194 replica->SetTransformOrigin(gfx::Point3F(25.f, 25.f, 0.f)); | |
195 replica->SetPosition(gfx::Point(50, 50)); | |
196 replica->SetTransform(replica_transform); | |
197 green->SetReplicaLayer(replica.get()); | |
198 | |
199 RunPixelResourceTest(background, | |
200 base::FilePath(FILE_PATH_LITERAL( | |
201 "mask_with_replica_of_clipped_layer.png"))); | |
202 } | |
203 | |
204 TEST_P(LayerTreeHostMasksPixelTest, MaskOfReplica) { | |
205 scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer( | |
206 gfx::Rect(100, 100), SK_ColorWHITE); | |
207 | |
208 gfx::Size mask_bounds(50, 50); | |
209 MaskContentLayerClient client(mask_bounds); | |
210 scoped_refptr<PictureLayer> mask = PictureLayer::Create(&client); | |
211 mask->SetBounds(mask_bounds); | |
212 mask->SetIsDrawable(true); | |
213 mask->SetIsMask(true); | |
214 | |
215 scoped_refptr<SolidColorLayer> green = CreateSolidColorLayerWithBorder( | |
216 gfx::Rect(25, 0, 50, 50), kCSSGreen, 1, SK_ColorBLACK); | |
217 background->AddChild(green); | |
218 | |
219 scoped_refptr<SolidColorLayer> orange = CreateSolidColorLayer( | |
220 gfx::Rect(-25, 25, 25, 25), kCSSOrange); | |
221 green->AddChild(orange); | |
222 | |
223 gfx::Transform replica_transform; | |
224 replica_transform.Rotate(180.0); | |
225 replica_transform.Translate(50.0, 0.0); | |
226 | |
227 scoped_refptr<Layer> replica = Layer::Create(); | |
228 replica->SetTransformOrigin(gfx::Point3F(50.f, 50.f, 0.f)); | |
229 replica->SetPosition(gfx::Point()); | |
230 replica->SetTransform(replica_transform); | |
231 replica->SetMaskLayer(mask.get()); | |
232 green->SetReplicaLayer(replica.get()); | |
233 | |
234 RunPixelResourceTest( | |
235 background, base::FilePath(FILE_PATH_LITERAL("mask_of_replica.png"))); | |
236 } | |
237 | |
238 TEST_P(LayerTreeHostMasksPixelTest, MaskOfReplicaOfClippedLayer) { | |
239 scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer( | |
240 gfx::Rect(100, 100), SK_ColorWHITE); | |
241 | |
242 gfx::Size mask_bounds(50, 50); | |
243 MaskContentLayerClient client(mask_bounds); | |
244 scoped_refptr<PictureLayer> mask = PictureLayer::Create(&client); | |
245 mask->SetBounds(mask_bounds); | |
246 mask->SetIsDrawable(true); | |
247 mask->SetIsMask(true); | |
248 | |
249 // Clip to the bottom 3/4 of the green layer, and the top 3/4 of the replica. | |
250 scoped_refptr<Layer> clip = Layer::Create(); | |
251 clip->SetPosition(gfx::Point(0, 12)); | |
252 clip->SetBounds(gfx::Size(100, 75)); | |
253 clip->SetMasksToBounds(true); | |
254 background->AddChild(clip); | |
255 | |
256 scoped_refptr<SolidColorLayer> green = CreateSolidColorLayerWithBorder( | |
257 gfx::Rect(25, -12, 50, 50), kCSSGreen, 1, SK_ColorBLACK); | |
258 clip->AddChild(green); | |
259 | |
260 scoped_refptr<SolidColorLayer> orange = CreateSolidColorLayer( | |
261 gfx::Rect(-25, 25, 25, 25), kCSSOrange); | |
262 green->AddChild(orange); | |
263 | |
264 gfx::Transform replica_transform; | |
265 replica_transform.Rotate(180.0); | |
266 replica_transform.Translate(50.0, 0.0); | |
267 | |
268 scoped_refptr<Layer> replica = Layer::Create(); | |
269 replica->SetTransformOrigin(gfx::Point3F(50.f, 50.f, 0.f)); | |
270 replica->SetPosition(gfx::Point()); | |
271 replica->SetTransform(replica_transform); | |
272 replica->SetMaskLayer(mask.get()); | |
273 green->SetReplicaLayer(replica.get()); | |
274 | |
275 RunPixelResourceTest(background, | |
276 base::FilePath(FILE_PATH_LITERAL( | |
277 "mask_of_replica_of_clipped_layer.png"))); | |
278 } | |
279 | |
280 class CheckerContentLayerClient : public ContentLayerClient { | |
281 public: | |
282 CheckerContentLayerClient(const gfx::Size& bounds, | |
283 SkColor color, | |
284 bool vertical) | |
285 : bounds_(bounds), color_(color), vertical_(vertical) {} | |
286 ~CheckerContentLayerClient() override {} | |
287 bool FillsBoundsCompletely() const override { return false; } | |
288 void PaintContents(SkCanvas* canvas, | |
289 const gfx::Rect& rect, | |
290 PaintingControlSetting picture_control) override { | |
291 SkPaint paint; | |
292 paint.setStyle(SkPaint::kStroke_Style); | |
293 paint.setStrokeWidth(SkIntToScalar(4)); | |
294 paint.setColor(color_); | |
295 canvas->clear(SK_ColorTRANSPARENT); | |
296 if (vertical_) { | |
297 for (int i = 4; i < bounds_.width(); i += 16) { | |
298 canvas->drawLine(i, 0, i, bounds_.height(), paint); | |
299 } | |
300 } else { | |
301 for (int i = 4; i < bounds_.height(); i += 16) { | |
302 canvas->drawLine(0, i, bounds_.width(), i, paint); | |
303 } | |
304 } | |
305 } | |
306 scoped_refptr<DisplayItemList> PaintContentsToDisplayList( | |
307 const gfx::Rect& clip, | |
308 PaintingControlSetting picture_control) override { | |
309 NOTIMPLEMENTED(); | |
310 return DisplayItemList::Create(); | |
311 } | |
312 | |
313 private: | |
314 gfx::Size bounds_; | |
315 SkColor color_; | |
316 bool vertical_; | |
317 }; | |
318 | |
319 class CircleContentLayerClient : public ContentLayerClient { | |
320 public: | |
321 explicit CircleContentLayerClient(const gfx::Size& bounds) | |
322 : bounds_(bounds) {} | |
323 ~CircleContentLayerClient() override {} | |
324 bool FillsBoundsCompletely() const override { return false; } | |
325 void PaintContents(SkCanvas* canvas, | |
326 const gfx::Rect& rect, | |
327 PaintingControlSetting picture_control) override { | |
328 SkPaint paint; | |
329 paint.setStyle(SkPaint::kFill_Style); | |
330 paint.setColor(SK_ColorWHITE); | |
331 canvas->clear(SK_ColorTRANSPARENT); | |
332 canvas->drawCircle(bounds_.width() / 2, | |
333 bounds_.height() / 2, | |
334 bounds_.width() / 4, | |
335 paint); | |
336 } | |
337 scoped_refptr<DisplayItemList> PaintContentsToDisplayList( | |
338 const gfx::Rect& clip, | |
339 PaintingControlSetting picture_control) override { | |
340 NOTIMPLEMENTED(); | |
341 return DisplayItemList::Create(); | |
342 } | |
343 | |
344 private: | |
345 gfx::Size bounds_; | |
346 }; | |
347 | |
348 using LayerTreeHostMasksForBackgroundFiltersPixelTest = | |
349 ParameterizedPixelResourceTest; | |
350 | |
351 INSTANTIATE_TEST_CASE_P( | |
352 PixelResourceTest, | |
353 LayerTreeHostMasksForBackgroundFiltersPixelTest, | |
354 ::testing::Values( | |
355 // SOFTWARE, Background filters aren't implemented in software | |
356 GL_GPU_RASTER_2D_DRAW, | |
357 GL_ONE_COPY_2D_STAGING_2D_DRAW, | |
358 GL_ONE_COPY_RECT_STAGING_2D_DRAW, | |
359 GL_ONE_COPY_EXTERNAL_STAGING_2D_DRAW, | |
360 GL_ZERO_COPY_2D_DRAW, | |
361 GL_ZERO_COPY_RECT_DRAW, | |
362 GL_ZERO_COPY_EXTERNAL_DRAW, | |
363 GL_ASYNC_UPLOAD_2D_DRAW)); | |
364 | |
365 TEST_P(LayerTreeHostMasksForBackgroundFiltersPixelTest, | |
366 MaskOfLayerWithBackgroundFilter) { | |
367 scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer( | |
368 gfx::Rect(100, 100), SK_ColorWHITE); | |
369 | |
370 gfx::Size picture_bounds(100, 100); | |
371 CheckerContentLayerClient picture_client(picture_bounds, SK_ColorGREEN, true); | |
372 scoped_refptr<PictureLayer> picture = PictureLayer::Create(&picture_client); | |
373 picture->SetBounds(picture_bounds); | |
374 picture->SetIsDrawable(true); | |
375 | |
376 scoped_refptr<SolidColorLayer> blur = CreateSolidColorLayer( | |
377 gfx::Rect(100, 100), SK_ColorTRANSPARENT); | |
378 background->AddChild(picture); | |
379 background->AddChild(blur); | |
380 | |
381 FilterOperations filters; | |
382 filters.Append(FilterOperation::CreateBlurFilter(1.5f)); | |
383 blur->SetBackgroundFilters(filters); | |
384 | |
385 gfx::Size mask_bounds(100, 100); | |
386 CircleContentLayerClient mask_client(mask_bounds); | |
387 scoped_refptr<PictureLayer> mask = PictureLayer::Create(&mask_client); | |
388 mask->SetBounds(mask_bounds); | |
389 mask->SetIsDrawable(true); | |
390 mask->SetIsMask(true); | |
391 blur->SetMaskLayer(mask.get()); | |
392 | |
393 float percentage_pixels_large_error = 2.5f; // 2.5%, ~250px / (100*100) | |
394 float percentage_pixels_small_error = 0.0f; | |
395 float average_error_allowed_in_bad_pixels = 100.0f; | |
396 int large_error_allowed = 256; | |
397 int small_error_allowed = 0; | |
398 pixel_comparator_.reset(new FuzzyPixelComparator( | |
399 true, // discard_alpha | |
400 percentage_pixels_large_error, | |
401 percentage_pixels_small_error, | |
402 average_error_allowed_in_bad_pixels, | |
403 large_error_allowed, | |
404 small_error_allowed)); | |
405 | |
406 RunPixelResourceTest(background, | |
407 base::FilePath( | |
408 FILE_PATH_LITERAL("mask_of_background_filter.png"))); | |
409 } | |
410 | |
411 TEST_P(LayerTreeHostMasksForBackgroundFiltersPixelTest, | |
412 MaskOfLayerWithBlend) { | |
413 scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer( | |
414 gfx::Rect(128, 128), SK_ColorWHITE); | |
415 | |
416 gfx::Size picture_bounds(128, 128); | |
417 CheckerContentLayerClient picture_client_vertical( | |
418 picture_bounds, SK_ColorGREEN, true); | |
419 scoped_refptr<PictureLayer> picture_vertical = | |
420 PictureLayer::Create(&picture_client_vertical); | |
421 picture_vertical->SetBounds(picture_bounds); | |
422 picture_vertical->SetIsDrawable(true); | |
423 | |
424 CheckerContentLayerClient picture_client_horizontal( | |
425 picture_bounds, SK_ColorMAGENTA, false); | |
426 scoped_refptr<PictureLayer> picture_horizontal = | |
427 PictureLayer::Create(&picture_client_horizontal); | |
428 picture_horizontal->SetBounds(picture_bounds); | |
429 picture_horizontal->SetIsDrawable(true); | |
430 picture_horizontal->SetContentsOpaque(false); | |
431 picture_horizontal->SetBlendMode(SkXfermode::kMultiply_Mode); | |
432 | |
433 background->AddChild(picture_vertical); | |
434 background->AddChild(picture_horizontal); | |
435 | |
436 gfx::Size mask_bounds(128, 128); | |
437 CircleContentLayerClient mask_client(mask_bounds); | |
438 scoped_refptr<PictureLayer> mask = PictureLayer::Create(&mask_client); | |
439 mask->SetBounds(mask_bounds); | |
440 mask->SetIsDrawable(true); | |
441 mask->SetIsMask(true); | |
442 picture_horizontal->SetMaskLayer(mask.get()); | |
443 | |
444 float percentage_pixels_large_error = 0.04f; // 0.04%, ~6px / (128*128) | |
445 float percentage_pixels_small_error = 0.0f; | |
446 float average_error_allowed_in_bad_pixels = 256.0f; | |
447 int large_error_allowed = 256; | |
448 int small_error_allowed = 0; | |
449 pixel_comparator_.reset(new FuzzyPixelComparator( | |
450 true, // discard_alpha | |
451 percentage_pixels_large_error, | |
452 percentage_pixels_small_error, | |
453 average_error_allowed_in_bad_pixels, | |
454 large_error_allowed, | |
455 small_error_allowed)); | |
456 | |
457 RunPixelResourceTest(background, | |
458 base::FilePath( | |
459 FILE_PATH_LITERAL("mask_of_layer_with_blend.png"))); | |
460 } | |
461 | |
462 } // namespace | |
463 } // namespace cc | |
464 | |
465 #endif // !defined(OS_ANDROID) | |
OLD | NEW |