This sets up API to release OutputSurface from LTHClient.
[chromium-blink-merge.git] / cc / trees / layer_tree_host_pixeltest_masks.cc
blobce9dde54c4da4132719381d13d0d80a3d52c9bd2
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/playback/display_item_list_settings.h"
11 #include "cc/playback/drawing_display_item.h"
12 #include "cc/test/layer_tree_pixel_resource_test.h"
13 #include "cc/test/pixel_comparator.h"
14 #include "third_party/skia/include/core/SkImage.h"
15 #include "third_party/skia/include/core/SkPictureRecorder.h"
16 #include "third_party/skia/include/core/SkSurface.h"
18 #if !defined(OS_ANDROID)
20 namespace cc {
21 namespace {
23 typedef ParameterizedPixelResourceTest LayerTreeHostMasksPixelTest;
25 INSTANTIATE_PIXEL_RESOURCE_TEST_CASE_P(LayerTreeHostMasksPixelTest);
27 class MaskContentLayerClient : public ContentLayerClient {
28 public:
29 explicit MaskContentLayerClient(const gfx::Size& bounds) : bounds_(bounds) {}
30 ~MaskContentLayerClient() override {}
32 bool FillsBoundsCompletely() const override { return false; }
33 size_t GetApproximateUnsharedMemoryUsage() const override { return 0; }
35 // TODO(pdr): Remove PaintContents as all calls should go through
36 // PaintContentsToDisplayList.
37 void PaintContents(SkCanvas* canvas,
38 const gfx::Rect& rect,
39 PaintingControlSetting picture_control) override {
40 scoped_refptr<DisplayItemList> contents =
41 PaintContentsToDisplayList(rect, picture_control);
42 contents->Raster(canvas, nullptr, rect, 1.0f);
45 scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
46 const gfx::Rect& clip,
47 PaintingControlSetting picture_control) override {
48 SkPictureRecorder recorder;
49 skia::RefPtr<SkCanvas> canvas = skia::SharePtr(
50 recorder.beginRecording(gfx::RectToSkRect(gfx::Rect(bounds_))));
52 SkPaint paint;
53 paint.setStyle(SkPaint::kStroke_Style);
54 paint.setStrokeWidth(SkIntToScalar(2));
55 paint.setColor(SK_ColorWHITE);
57 canvas->clear(SK_ColorTRANSPARENT);
58 gfx::Rect inset_rect(bounds_);
59 while (!inset_rect.IsEmpty()) {
60 inset_rect.Inset(3, 3, 2, 2);
61 canvas->drawRect(
62 SkRect::MakeXYWH(inset_rect.x(), inset_rect.y(),
63 inset_rect.width(), inset_rect.height()),
64 paint);
65 inset_rect.Inset(3, 3, 2, 2);
68 scoped_refptr<DisplayItemList> display_list =
69 DisplayItemList::Create(clip, DisplayItemListSettings());
70 auto* item = display_list->CreateAndAppendItem<DrawingDisplayItem>();
72 skia::RefPtr<SkPicture> picture =
73 skia::AdoptRef(recorder.endRecordingAsPicture());
74 item->SetNew(picture.Pass());
76 display_list->Finalize();
77 return display_list;
80 private:
81 gfx::Size bounds_;
84 TEST_P(LayerTreeHostMasksPixelTest, MaskOfLayer) {
85 scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
86 gfx::Rect(100, 100), SK_ColorWHITE);
88 scoped_refptr<SolidColorLayer> green = CreateSolidColorLayerWithBorder(
89 gfx::Rect(25, 25, 50, 50), kCSSGreen, 1, SK_ColorBLACK);
90 background->AddChild(green);
92 gfx::Size mask_bounds(50, 50);
93 MaskContentLayerClient client(mask_bounds);
94 scoped_refptr<PictureLayer> mask =
95 PictureLayer::Create(layer_settings(), &client);
96 mask->SetBounds(mask_bounds);
97 mask->SetIsDrawable(true);
98 mask->SetIsMask(true);
99 green->SetMaskLayer(mask.get());
101 RunPixelResourceTest(background,
102 base::FilePath(FILE_PATH_LITERAL("mask_of_layer.png")));
105 TEST_P(LayerTreeHostMasksPixelTest, ImageMaskOfLayer) {
106 scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
107 gfx::Rect(100, 100), SK_ColorWHITE);
109 gfx::Size mask_bounds(50, 50);
111 scoped_refptr<PictureImageLayer> mask =
112 PictureImageLayer::Create(layer_settings());
113 mask->SetIsDrawable(true);
114 mask->SetIsMask(true);
115 mask->SetBounds(mask_bounds);
117 skia::RefPtr<SkSurface> surface =
118 skia::AdoptRef(SkSurface::NewRasterN32Premul(200, 200));
119 SkCanvas* canvas = surface->getCanvas();
120 canvas->scale(SkIntToScalar(4), SkIntToScalar(4));
121 MaskContentLayerClient client(mask_bounds);
122 client.PaintContents(canvas, gfx::Rect(mask_bounds),
123 ContentLayerClient::PAINTING_BEHAVIOR_NORMAL);
124 skia::RefPtr<const SkImage> image =
125 skia::AdoptRef(surface->newImageSnapshot());
126 mask->SetImage(image.Pass());
128 scoped_refptr<SolidColorLayer> green = CreateSolidColorLayerWithBorder(
129 gfx::Rect(25, 25, 50, 50), kCSSGreen, 1, SK_ColorBLACK);
130 green->SetMaskLayer(mask.get());
131 background->AddChild(green);
133 RunPixelResourceTest(
134 background, base::FilePath(FILE_PATH_LITERAL("image_mask_of_layer.png")));
137 TEST_P(LayerTreeHostMasksPixelTest, MaskOfClippedLayer) {
138 scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
139 gfx::Rect(100, 100), SK_ColorWHITE);
141 // Clip to the top half of the green layer.
142 scoped_refptr<Layer> clip = Layer::Create(layer_settings());
143 clip->SetPosition(gfx::Point(0, 0));
144 clip->SetBounds(gfx::Size(100, 50));
145 clip->SetMasksToBounds(true);
146 background->AddChild(clip);
148 scoped_refptr<SolidColorLayer> green = CreateSolidColorLayerWithBorder(
149 gfx::Rect(25, 25, 50, 50), kCSSGreen, 1, SK_ColorBLACK);
150 clip->AddChild(green);
152 gfx::Size mask_bounds(50, 50);
153 MaskContentLayerClient client(mask_bounds);
154 scoped_refptr<PictureLayer> mask =
155 PictureLayer::Create(layer_settings(), &client);
156 mask->SetBounds(mask_bounds);
157 mask->SetIsDrawable(true);
158 mask->SetIsMask(true);
159 green->SetMaskLayer(mask.get());
161 RunPixelResourceTest(
162 background,
163 base::FilePath(FILE_PATH_LITERAL("mask_of_clipped_layer.png")));
166 TEST_P(LayerTreeHostMasksPixelTest, MaskWithReplica) {
167 scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
168 gfx::Rect(100, 100), SK_ColorWHITE);
170 gfx::Size mask_bounds(50, 50);
171 MaskContentLayerClient client(mask_bounds);
172 scoped_refptr<PictureLayer> mask =
173 PictureLayer::Create(layer_settings(), &client);
174 mask->SetBounds(mask_bounds);
175 mask->SetIsDrawable(true);
176 mask->SetIsMask(true);
178 scoped_refptr<SolidColorLayer> green = CreateSolidColorLayerWithBorder(
179 gfx::Rect(0, 0, 50, 50), kCSSGreen, 1, SK_ColorBLACK);
180 background->AddChild(green);
181 green->SetMaskLayer(mask.get());
183 gfx::Transform replica_transform;
184 replica_transform.Rotate(-90.0);
186 scoped_refptr<Layer> replica = Layer::Create(layer_settings());
187 replica->SetTransformOrigin(gfx::Point3F(25.f, 25.f, 0.f));
188 replica->SetPosition(gfx::Point(50, 50));
189 replica->SetTransform(replica_transform);
190 green->SetReplicaLayer(replica.get());
192 RunPixelResourceTest(
193 background, base::FilePath(FILE_PATH_LITERAL("mask_with_replica.png")));
196 TEST_P(LayerTreeHostMasksPixelTest, MaskWithReplicaOfClippedLayer) {
197 scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
198 gfx::Rect(100, 100), SK_ColorWHITE);
200 gfx::Size mask_bounds(50, 50);
201 MaskContentLayerClient client(mask_bounds);
202 scoped_refptr<PictureLayer> mask =
203 PictureLayer::Create(layer_settings(), &client);
204 mask->SetBounds(mask_bounds);
205 mask->SetIsDrawable(true);
206 mask->SetIsMask(true);
208 // Clip to the bottom half of the green layer, and the left half of the
209 // replica.
210 scoped_refptr<Layer> clip = Layer::Create(layer_settings());
211 clip->SetPosition(gfx::Point(0, 25));
212 clip->SetBounds(gfx::Size(75, 75));
213 clip->SetMasksToBounds(true);
214 background->AddChild(clip);
216 scoped_refptr<SolidColorLayer> green = CreateSolidColorLayerWithBorder(
217 gfx::Rect(0, -25, 50, 50), kCSSGreen, 1, SK_ColorBLACK);
218 clip->AddChild(green);
219 green->SetMaskLayer(mask.get());
221 gfx::Transform replica_transform;
222 replica_transform.Rotate(-90.0);
224 scoped_refptr<Layer> replica = Layer::Create(layer_settings());
225 replica->SetTransformOrigin(gfx::Point3F(25.f, 25.f, 0.f));
226 replica->SetPosition(gfx::Point(50, 50));
227 replica->SetTransform(replica_transform);
228 green->SetReplicaLayer(replica.get());
230 RunPixelResourceTest(background,
231 base::FilePath(FILE_PATH_LITERAL(
232 "mask_with_replica_of_clipped_layer.png")));
235 TEST_P(LayerTreeHostMasksPixelTest, MaskOfReplica) {
236 scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
237 gfx::Rect(100, 100), SK_ColorWHITE);
239 gfx::Size mask_bounds(50, 50);
240 MaskContentLayerClient client(mask_bounds);
241 scoped_refptr<PictureLayer> mask =
242 PictureLayer::Create(layer_settings(), &client);
243 mask->SetBounds(mask_bounds);
244 mask->SetIsDrawable(true);
245 mask->SetIsMask(true);
247 scoped_refptr<SolidColorLayer> green = CreateSolidColorLayerWithBorder(
248 gfx::Rect(25, 0, 50, 50), kCSSGreen, 1, SK_ColorBLACK);
249 background->AddChild(green);
251 scoped_refptr<SolidColorLayer> orange = CreateSolidColorLayer(
252 gfx::Rect(-25, 25, 25, 25), kCSSOrange);
253 green->AddChild(orange);
255 gfx::Transform replica_transform;
256 replica_transform.Rotate(180.0);
257 replica_transform.Translate(50.0, 0.0);
259 scoped_refptr<Layer> replica = Layer::Create(layer_settings());
260 replica->SetTransformOrigin(gfx::Point3F(50.f, 50.f, 0.f));
261 replica->SetPosition(gfx::Point());
262 replica->SetTransform(replica_transform);
263 replica->SetMaskLayer(mask.get());
264 green->SetReplicaLayer(replica.get());
266 RunPixelResourceTest(
267 background, base::FilePath(FILE_PATH_LITERAL("mask_of_replica.png")));
270 TEST_P(LayerTreeHostMasksPixelTest, MaskOfReplicaOfClippedLayer) {
271 scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
272 gfx::Rect(100, 100), SK_ColorWHITE);
274 gfx::Size mask_bounds(50, 50);
275 MaskContentLayerClient client(mask_bounds);
276 scoped_refptr<PictureLayer> mask =
277 PictureLayer::Create(layer_settings(), &client);
278 mask->SetBounds(mask_bounds);
279 mask->SetIsDrawable(true);
280 mask->SetIsMask(true);
282 // Clip to the bottom 3/4 of the green layer, and the top 3/4 of the replica.
283 scoped_refptr<Layer> clip = Layer::Create(layer_settings());
284 clip->SetPosition(gfx::Point(0, 12));
285 clip->SetBounds(gfx::Size(100, 75));
286 clip->SetMasksToBounds(true);
287 background->AddChild(clip);
289 scoped_refptr<SolidColorLayer> green = CreateSolidColorLayerWithBorder(
290 gfx::Rect(25, -12, 50, 50), kCSSGreen, 1, SK_ColorBLACK);
291 clip->AddChild(green);
293 scoped_refptr<SolidColorLayer> orange = CreateSolidColorLayer(
294 gfx::Rect(-25, 25, 25, 25), kCSSOrange);
295 green->AddChild(orange);
297 gfx::Transform replica_transform;
298 replica_transform.Rotate(180.0);
299 replica_transform.Translate(50.0, 0.0);
301 scoped_refptr<Layer> replica = Layer::Create(layer_settings());
302 replica->SetTransformOrigin(gfx::Point3F(50.f, 50.f, 0.f));
303 replica->SetPosition(gfx::Point());
304 replica->SetTransform(replica_transform);
305 replica->SetMaskLayer(mask.get());
306 green->SetReplicaLayer(replica.get());
308 RunPixelResourceTest(background,
309 base::FilePath(FILE_PATH_LITERAL(
310 "mask_of_replica_of_clipped_layer.png")));
313 class CheckerContentLayerClient : public ContentLayerClient {
314 public:
315 CheckerContentLayerClient(const gfx::Size& bounds,
316 SkColor color,
317 bool vertical)
318 : bounds_(bounds), color_(color), vertical_(vertical) {}
319 ~CheckerContentLayerClient() override {}
320 bool FillsBoundsCompletely() const override { return false; }
321 size_t GetApproximateUnsharedMemoryUsage() const override { return 0; }
322 // TODO(pdr): Remove PaintContents as all calls should go through
323 // PaintContentsToDisplayList.
324 void PaintContents(SkCanvas* canvas,
325 const gfx::Rect& rect,
326 PaintingControlSetting picture_control) override {
327 scoped_refptr<DisplayItemList> contents =
328 PaintContentsToDisplayList(rect, picture_control);
329 contents->Raster(canvas, nullptr, rect, 1.0f);
331 scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
332 const gfx::Rect& clip,
333 PaintingControlSetting picture_control) override {
334 SkPictureRecorder recorder;
335 skia::RefPtr<SkCanvas> canvas = skia::SharePtr(
336 recorder.beginRecording(gfx::RectToSkRect(gfx::Rect(bounds_))));
338 SkPaint paint;
339 paint.setStyle(SkPaint::kStroke_Style);
340 paint.setStrokeWidth(SkIntToScalar(4));
341 paint.setColor(color_);
342 canvas->clear(SK_ColorTRANSPARENT);
343 if (vertical_) {
344 for (int i = 4; i < bounds_.width(); i += 16) {
345 canvas->drawLine(i, 0, i, bounds_.height(), paint);
347 } else {
348 for (int i = 4; i < bounds_.height(); i += 16) {
349 canvas->drawLine(0, i, bounds_.width(), i, paint);
353 scoped_refptr<DisplayItemList> display_list =
354 DisplayItemList::Create(clip, DisplayItemListSettings());
355 auto* item = display_list->CreateAndAppendItem<DrawingDisplayItem>();
357 skia::RefPtr<SkPicture> picture =
358 skia::AdoptRef(recorder.endRecordingAsPicture());
359 item->SetNew(picture.Pass());
361 display_list->Finalize();
362 return display_list;
365 private:
366 gfx::Size bounds_;
367 SkColor color_;
368 bool vertical_;
371 class CircleContentLayerClient : public ContentLayerClient {
372 public:
373 explicit CircleContentLayerClient(const gfx::Size& bounds)
374 : bounds_(bounds) {}
375 ~CircleContentLayerClient() override {}
376 bool FillsBoundsCompletely() const override { return false; }
377 size_t GetApproximateUnsharedMemoryUsage() const override { return 0; }
378 // TODO(pdr): Remove PaintContents as all calls should go through
379 // PaintContentsToDisplayList.
380 void PaintContents(SkCanvas* canvas,
381 const gfx::Rect& rect,
382 PaintingControlSetting picture_control) override {
383 scoped_refptr<DisplayItemList> contents =
384 PaintContentsToDisplayList(rect, picture_control);
385 contents->Raster(canvas, nullptr, rect, 1.0f);
387 scoped_refptr<DisplayItemList> PaintContentsToDisplayList(
388 const gfx::Rect& clip,
389 PaintingControlSetting picture_control) override {
390 SkPictureRecorder recorder;
391 skia::RefPtr<SkCanvas> canvas = skia::SharePtr(
392 recorder.beginRecording(gfx::RectToSkRect(gfx::Rect(bounds_))));
394 SkPaint paint;
395 paint.setStyle(SkPaint::kFill_Style);
396 paint.setColor(SK_ColorWHITE);
397 canvas->clear(SK_ColorTRANSPARENT);
398 canvas->drawCircle(bounds_.width() / 2,
399 bounds_.height() / 2,
400 bounds_.width() / 4,
401 paint);
403 scoped_refptr<DisplayItemList> display_list =
404 DisplayItemList::Create(clip, DisplayItemListSettings());
405 auto* item = display_list->CreateAndAppendItem<DrawingDisplayItem>();
406 skia::RefPtr<SkPicture> picture =
407 skia::AdoptRef(recorder.endRecordingAsPicture());
408 item->SetNew(picture.Pass());
410 display_list->Finalize();
411 return display_list;
414 private:
415 gfx::Size bounds_;
418 using LayerTreeHostMasksForBackgroundFiltersPixelTest =
419 ParameterizedPixelResourceTest;
421 INSTANTIATE_TEST_CASE_P(PixelResourceTest,
422 LayerTreeHostMasksForBackgroundFiltersPixelTest,
423 ::testing::Values(SOFTWARE,
424 GL_GPU_RASTER_2D_DRAW,
425 GL_ONE_COPY_2D_STAGING_2D_DRAW,
426 GL_ONE_COPY_RECT_STAGING_2D_DRAW,
427 GL_ONE_COPY_EXTERNAL_STAGING_2D_DRAW,
428 GL_ZERO_COPY_2D_DRAW,
429 GL_ZERO_COPY_RECT_DRAW,
430 GL_ZERO_COPY_EXTERNAL_DRAW));
432 TEST_P(LayerTreeHostMasksForBackgroundFiltersPixelTest,
433 MaskOfLayerWithBackgroundFilter) {
434 scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
435 gfx::Rect(100, 100), SK_ColorWHITE);
437 gfx::Size picture_bounds(100, 100);
438 CheckerContentLayerClient picture_client(picture_bounds, SK_ColorGREEN, true);
439 scoped_refptr<PictureLayer> picture =
440 PictureLayer::Create(layer_settings(), &picture_client);
441 picture->SetBounds(picture_bounds);
442 picture->SetIsDrawable(true);
444 scoped_refptr<SolidColorLayer> blur = CreateSolidColorLayer(
445 gfx::Rect(100, 100), SK_ColorTRANSPARENT);
446 background->AddChild(picture);
447 background->AddChild(blur);
449 FilterOperations filters;
450 filters.Append(FilterOperation::CreateGrayscaleFilter(1.0));
451 blur->SetBackgroundFilters(filters);
453 gfx::Size mask_bounds(100, 100);
454 CircleContentLayerClient mask_client(mask_bounds);
455 scoped_refptr<PictureLayer> mask =
456 PictureLayer::Create(layer_settings(), &mask_client);
457 mask->SetBounds(mask_bounds);
458 mask->SetIsDrawable(true);
459 mask->SetIsMask(true);
460 blur->SetMaskLayer(mask.get());
462 float percentage_pixels_large_error = 2.5f; // 2.5%, ~250px / (100*100)
463 float percentage_pixels_small_error = 0.0f;
464 float average_error_allowed_in_bad_pixels = 100.0f;
465 int large_error_allowed = 256;
466 int small_error_allowed = 0;
467 pixel_comparator_.reset(new FuzzyPixelComparator(
468 true, // discard_alpha
469 percentage_pixels_large_error,
470 percentage_pixels_small_error,
471 average_error_allowed_in_bad_pixels,
472 large_error_allowed,
473 small_error_allowed));
475 RunPixelResourceTest(background,
476 base::FilePath(
477 FILE_PATH_LITERAL("mask_of_background_filter.png")));
480 TEST_P(LayerTreeHostMasksForBackgroundFiltersPixelTest,
481 MaskOfLayerWithBlend) {
482 scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
483 gfx::Rect(128, 128), SK_ColorWHITE);
485 gfx::Size picture_bounds(128, 128);
486 CheckerContentLayerClient picture_client_vertical(
487 picture_bounds, SK_ColorGREEN, true);
488 scoped_refptr<PictureLayer> picture_vertical =
489 PictureLayer::Create(layer_settings(), &picture_client_vertical);
490 picture_vertical->SetBounds(picture_bounds);
491 picture_vertical->SetIsDrawable(true);
493 CheckerContentLayerClient picture_client_horizontal(
494 picture_bounds, SK_ColorMAGENTA, false);
495 scoped_refptr<PictureLayer> picture_horizontal =
496 PictureLayer::Create(layer_settings(), &picture_client_horizontal);
497 picture_horizontal->SetBounds(picture_bounds);
498 picture_horizontal->SetIsDrawable(true);
499 picture_horizontal->SetContentsOpaque(false);
500 picture_horizontal->SetBlendMode(SkXfermode::kMultiply_Mode);
502 background->AddChild(picture_vertical);
503 background->AddChild(picture_horizontal);
505 gfx::Size mask_bounds(128, 128);
506 CircleContentLayerClient mask_client(mask_bounds);
507 scoped_refptr<PictureLayer> mask =
508 PictureLayer::Create(layer_settings(), &mask_client);
509 mask->SetBounds(mask_bounds);
510 mask->SetIsDrawable(true);
511 mask->SetIsMask(true);
512 picture_horizontal->SetMaskLayer(mask.get());
514 float percentage_pixels_large_error = 0.04f; // 0.04%, ~6px / (128*128)
515 float percentage_pixels_small_error = 0.0f;
516 float average_error_allowed_in_bad_pixels = 256.0f;
517 int large_error_allowed = 256;
518 int small_error_allowed = 0;
519 pixel_comparator_.reset(new FuzzyPixelComparator(
520 true, // discard_alpha
521 percentage_pixels_large_error,
522 percentage_pixels_small_error,
523 average_error_allowed_in_bad_pixels,
524 large_error_allowed,
525 small_error_allowed));
527 RunPixelResourceTest(background,
528 base::FilePath(
529 FILE_PATH_LITERAL("mask_of_layer_with_blend.png")));
532 } // namespace
533 } // namespace cc
535 #endif // !defined(OS_ANDROID)