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/solid_color_layer.h"
7 #include "cc/test/layer_tree_pixel_test.h"
8 #include "cc/test/pixel_comparator.h"
9 #include "third_party/skia/include/effects/SkColorFilterImageFilter.h"
10 #include "third_party/skia/include/effects/SkColorMatrixFilter.h"
12 #if !defined(OS_ANDROID)
17 class LayerTreeHostFiltersPixelTest
: public LayerTreePixelTest
{};
19 TEST_F(LayerTreeHostFiltersPixelTest
, BackgroundFilterBlur
) {
20 scoped_refptr
<SolidColorLayer
> background
= CreateSolidColorLayer(
21 gfx::Rect(200, 200), SK_ColorWHITE
);
23 // The green box is entirely behind a layer with background blur, so it
24 // should appear blurred on its edges.
25 scoped_refptr
<SolidColorLayer
> green
= CreateSolidColorLayer(
26 gfx::Rect(50, 50, 100, 100), kCSSGreen
);
27 scoped_refptr
<SolidColorLayer
> blur
= CreateSolidColorLayer(
28 gfx::Rect(30, 30, 140, 140), SK_ColorTRANSPARENT
);
29 background
->AddChild(green
);
30 background
->AddChild(blur
);
32 FilterOperations filters
;
33 filters
.Append(FilterOperation::CreateBlurFilter(2.f
));
34 blur
->SetBackgroundFilters(filters
);
37 // Windows has 436 pixels off by 1: crbug.com/259915
38 float percentage_pixels_large_error
= 1.09f
; // 436px / (200*200)
39 float percentage_pixels_small_error
= 0.0f
;
40 float average_error_allowed_in_bad_pixels
= 1.f
;
41 int large_error_allowed
= 1;
42 int small_error_allowed
= 0;
43 pixel_comparator_
.reset(new FuzzyPixelComparator(
44 true, // discard_alpha
45 percentage_pixels_large_error
,
46 percentage_pixels_small_error
,
47 average_error_allowed_in_bad_pixels
,
49 small_error_allowed
));
52 RunPixelTest(PIXEL_TEST_GL
,
54 base::FilePath(FILE_PATH_LITERAL("background_filter_blur.png")));
57 TEST_F(LayerTreeHostFiltersPixelTest
, BackgroundFilterBlurOutsets
) {
58 scoped_refptr
<SolidColorLayer
> background
= CreateSolidColorLayer(
59 gfx::Rect(200, 200), SK_ColorWHITE
);
61 // The green border is outside the layer with background blur, but the
62 // background blur should use pixels from outside its layer borders, up to the
63 // radius of the blur effect. So the border should be blurred underneath the
64 // top layer causing the green to bleed under the transparent layer, but not
65 // in the 1px region between the transparent layer and the green border.
66 scoped_refptr
<SolidColorLayer
> green_border
= CreateSolidColorLayerWithBorder(
67 gfx::Rect(1, 1, 198, 198), SK_ColorWHITE
, 10, kCSSGreen
);
68 scoped_refptr
<SolidColorLayer
> blur
= CreateSolidColorLayer(
69 gfx::Rect(12, 12, 176, 176), SK_ColorTRANSPARENT
);
70 background
->AddChild(green_border
);
71 background
->AddChild(blur
);
73 FilterOperations filters
;
74 filters
.Append(FilterOperation::CreateBlurFilter(5.f
));
75 blur
->SetBackgroundFilters(filters
);
78 // Windows has 2596 pixels off by at most 2: crbug.com/259922
79 float percentage_pixels_large_error
= 6.5f
; // 2596px / (200*200), rounded up
80 float percentage_pixels_small_error
= 0.0f
;
81 float average_error_allowed_in_bad_pixels
= 1.f
;
82 int large_error_allowed
= 2;
83 int small_error_allowed
= 0;
84 pixel_comparator_
.reset(new FuzzyPixelComparator(
85 true, // discard_alpha
86 percentage_pixels_large_error
,
87 percentage_pixels_small_error
,
88 average_error_allowed_in_bad_pixels
,
90 small_error_allowed
));
96 base::FilePath(FILE_PATH_LITERAL("background_filter_blur_outsets.png")));
99 TEST_F(LayerTreeHostFiltersPixelTest
, BackgroundFilterBlurOffAxis
) {
100 scoped_refptr
<SolidColorLayer
> background
=
101 CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorTRANSPARENT
);
103 // This verifies that the perspective of the clear layer (with black border)
104 // does not influence the blending of the green box behind it. Also verifies
105 // that the blur is correctly clipped inside the transformed clear layer.
106 scoped_refptr
<SolidColorLayer
> green
= CreateSolidColorLayer(
107 gfx::Rect(50, 50, 100, 100), kCSSGreen
);
108 scoped_refptr
<SolidColorLayer
> blur
= CreateSolidColorLayerWithBorder(
109 gfx::Rect(30, 30, 120, 120), SK_ColorTRANSPARENT
, 1, SK_ColorBLACK
);
110 background
->AddChild(green
);
111 background
->AddChild(blur
);
113 background
->SetShouldFlattenTransform(false);
114 background
->Set3dSortingContextId(1);
115 green
->SetShouldFlattenTransform(false);
116 green
->Set3dSortingContextId(1);
117 gfx::Transform background_transform
;
118 background_transform
.ApplyPerspectiveDepth(200.0);
119 background
->SetTransform(background_transform
);
121 blur
->SetShouldFlattenTransform(false);
122 blur
->Set3dSortingContextId(1);
123 for (size_t i
= 0; i
< blur
->children().size(); ++i
)
124 blur
->children()[i
]->Set3dSortingContextId(1);
126 gfx::Transform blur_transform
;
127 blur_transform
.Translate(55.0, 65.0);
128 blur_transform
.RotateAboutXAxis(85.0);
129 blur_transform
.RotateAboutYAxis(180.0);
130 blur_transform
.RotateAboutZAxis(20.0);
131 blur_transform
.Translate(-60.0, -60.0);
132 blur
->SetTransform(blur_transform
);
134 FilterOperations filters
;
135 filters
.Append(FilterOperation::CreateBlurFilter(2.f
));
136 blur
->SetBackgroundFilters(filters
);
139 // Windows has 116 pixels off by at most 2: crbug.com/225027
140 float percentage_pixels_large_error
= 0.3f
; // 116px / (200*200), rounded up
141 float percentage_pixels_small_error
= 0.0f
;
142 float average_error_allowed_in_bad_pixels
= 1.f
;
143 int large_error_allowed
= 2;
144 int small_error_allowed
= 0;
145 pixel_comparator_
.reset(new FuzzyPixelComparator(
146 true, // discard_alpha
147 percentage_pixels_large_error
,
148 percentage_pixels_small_error
,
149 average_error_allowed_in_bad_pixels
,
151 small_error_allowed
));
157 base::FilePath(FILE_PATH_LITERAL("background_filter_blur_off_axis.png")));
160 class LayerTreeHostFiltersScaledPixelTest
161 : public LayerTreeHostFiltersPixelTest
{
162 void InitializeSettings(LayerTreeSettings
* settings
) override
{
163 // Required so that device scale is inherited by content scale.
164 settings
->layer_transforms_should_scale_layer_contents
= true;
167 void SetupTree() override
{
168 layer_tree_host()->SetDeviceScaleFactor(device_scale_factor_
);
169 LayerTreePixelTest::SetupTree();
173 void RunPixelTestType(int content_size
,
174 float device_scale_factor
,
175 PixelTestType test_type
) {
176 int half_content
= content_size
/ 2;
178 scoped_refptr
<SolidColorLayer
> root
= CreateSolidColorLayer(
179 gfx::Rect(0, 0, content_size
, content_size
), SK_ColorWHITE
);
181 scoped_refptr
<SolidColorLayer
> background
= CreateSolidColorLayer(
182 gfx::Rect(0, 0, content_size
, content_size
), SK_ColorGREEN
);
183 root
->AddChild(background
);
185 // Add a blue layer that completely covers the green layer.
186 scoped_refptr
<SolidColorLayer
> foreground
= CreateSolidColorLayer(
187 gfx::Rect(0, 0, content_size
, content_size
), SK_ColorBLUE
);
188 background
->AddChild(foreground
);
190 // Add an alpha threshold filter to the blue layer which will filter out
191 // everything except the lower right corner.
192 FilterOperations filters
;
193 SkRegion alpha_region
;
194 alpha_region
.setRect(
195 half_content
, half_content
, content_size
, content_size
);
197 FilterOperation::CreateAlphaThresholdFilter(alpha_region
, 1.f
, 0.f
));
198 foreground
->SetFilters(filters
);
200 device_scale_factor_
= device_scale_factor
;
204 base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
207 float device_scale_factor_
;
210 TEST_F(LayerTreeHostFiltersScaledPixelTest
, StandardDpi_GL
) {
211 RunPixelTestType(100, 1.f
, PIXEL_TEST_GL
);
214 TEST_F(LayerTreeHostFiltersScaledPixelTest
, StandardDpi_Software
) {
215 RunPixelTestType(100, 1.f
, PIXEL_TEST_SOFTWARE
);
218 TEST_F(LayerTreeHostFiltersScaledPixelTest
, HiDpi_GL
) {
219 RunPixelTestType(50, 2.f
, PIXEL_TEST_GL
);
222 TEST_F(LayerTreeHostFiltersScaledPixelTest
, HiDpi_Software
) {
223 RunPixelTestType(50, 2.f
, PIXEL_TEST_SOFTWARE
);
226 class ImageFilterClippedPixelTest
: public LayerTreeHostFiltersPixelTest
{
228 void RunPixelTestType(PixelTestType test_type
) {
229 scoped_refptr
<SolidColorLayer
> root
=
230 CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorBLACK
);
232 scoped_refptr
<SolidColorLayer
> background
=
233 CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorYELLOW
);
234 root
->AddChild(background
);
236 scoped_refptr
<SolidColorLayer
> foreground
=
237 CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorRED
);
238 background
->AddChild(foreground
);
241 memset(matrix
, 0, 20 * sizeof(matrix
[0]));
242 // This filter does a red-blue swap, so the foreground becomes blue.
243 matrix
[2] = matrix
[6] = matrix
[10] = matrix
[18] = SK_Scalar1
;
244 skia::RefPtr
<SkColorFilter
> colorFilter(
245 skia::AdoptRef(SkColorMatrixFilter::Create(matrix
)));
246 // We filter only the bottom 200x100 pixels of the foreground.
247 SkImageFilter::CropRect
crop_rect(SkRect::MakeXYWH(0, 100, 200, 100));
248 skia::RefPtr
<SkImageFilter
> filter
= skia::AdoptRef(
249 SkColorFilterImageFilter::Create(colorFilter
.get(), NULL
, &crop_rect
));
250 FilterOperations filters
;
251 filters
.Append(FilterOperation::CreateReferenceFilter(filter
));
253 // Make the foreground layer's render surface be clipped by the background
255 background
->SetMasksToBounds(true);
256 foreground
->SetFilters(filters
);
258 // Then we translate the foreground up by 100 pixels in Y, so the cropped
259 // region is moved to to the top. This ensures that the crop rect is being
260 // correctly transformed in skia by the amount of clipping that the
261 // compositor performs.
262 gfx::Transform transform
;
263 transform
.Translate(0.0, -100.0);
264 foreground
->SetTransform(transform
);
266 RunPixelTest(test_type
,
268 base::FilePath(FILE_PATH_LITERAL("blue_yellow.png")));
272 TEST_F(ImageFilterClippedPixelTest
, ImageFilterClipped_GL
) {
273 RunPixelTestType(PIXEL_TEST_GL
);
276 TEST_F(ImageFilterClippedPixelTest
, ImageFilterClipped_Software
) {
277 RunPixelTestType(PIXEL_TEST_SOFTWARE
);
280 TEST_F(LayerTreeHostFiltersPixelTest
, ImageFilterScaled_GL
) {
281 scoped_refptr
<SolidColorLayer
> background
=
282 CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE
);
284 gfx::Rect
rect(50, 50, 100, 100);
286 const int kInset
= 3;
287 for (int i
= 0; !rect
.IsEmpty(); ++i
) {
288 scoped_refptr
<SolidColorLayer
> layer
=
289 CreateSolidColorLayer(rect
, (i
& 1) ? SK_ColorWHITE
: SK_ColorRED
);
291 gfx::Transform transform
;
292 transform
.Translate(rect
.width() / 2.0, rect
.height() / 2.0);
293 transform
.RotateAboutZAxis(30.0);
294 transform
.Translate(-rect
.width() / 2.0, -rect
.height() / 2.0);
295 layer
->SetTransform(transform
);
297 background
->AddChild(layer
);
299 rect
.Inset(kInset
, kInset
);
302 scoped_refptr
<SolidColorLayer
> filter
=
303 CreateSolidColorLayer(gfx::Rect(100, 0, 100, 200), SK_ColorTRANSPARENT
);
305 background
->AddChild(filter
);
307 // Apply a scale to |background| so that we can see any scaling artifacts that
309 gfx::Transform background_transform
;
310 static float scale
= 1.1f
;
311 background_transform
.Scale(scale
, scale
);
312 background
->SetTransform(background_transform
);
314 FilterOperations filters
;
315 filters
.Append(FilterOperation::CreateGrayscaleFilter(1.0f
));
316 filter
->SetBackgroundFilters(filters
);
319 // Windows has 153 pixels off by at most 2: crbug.com/225027
320 float percentage_pixels_large_error
= 0.3825f
; // 153px / (200*200)
321 float percentage_pixels_small_error
= 0.0f
;
322 float average_error_allowed_in_bad_pixels
= 1.f
;
323 int large_error_allowed
= 2;
324 int small_error_allowed
= 0;
325 pixel_comparator_
.reset(new FuzzyPixelComparator(
326 true, // discard_alpha
327 percentage_pixels_large_error
, percentage_pixels_small_error
,
328 average_error_allowed_in_bad_pixels
, large_error_allowed
,
329 small_error_allowed
));
332 // TODO(hendrikw): Enable test in software as well: crbug.com/432157
333 RunPixelTest(PIXEL_TEST_GL
, background
,
334 base::FilePath(FILE_PATH_LITERAL("filter_on_scaled_layer.png")));
337 class ImageScaledRenderSurface
: public LayerTreeHostFiltersPixelTest
{
339 void RunPixelTestType(PixelTestType test_type
, base::FilePath image_name
) {
340 // A filter will cause a render surface to be used. Here we force the
341 // render surface on, and scale the result to make sure that we rasterize at
342 // the correct resolution.
343 scoped_refptr
<SolidColorLayer
> background
=
344 CreateSolidColorLayer(gfx::Rect(300, 300), SK_ColorBLUE
);
346 scoped_refptr
<SolidColorLayer
> render_surface_layer
=
347 CreateSolidColorLayer(gfx::Rect(0, 0, 200, 200), SK_ColorWHITE
);
349 gfx::Rect
rect(50, 50, 100, 100);
351 scoped_refptr
<SolidColorLayer
> child
=
352 CreateSolidColorLayer(rect
, SK_ColorRED
);
354 gfx::Transform transform
;
355 transform
.Translate(rect
.width() / 2.0, rect
.height() / 2.0);
356 transform
.RotateAboutZAxis(30.0);
357 transform
.Translate(-rect
.width() / 2.0, -rect
.height() / 2.0);
358 child
->SetTransform(transform
);
360 render_surface_layer
->AddChild(child
);
362 gfx::Transform render_surface_transform
;
363 render_surface_transform
.Scale(1.5f
, 1.5f
);
364 render_surface_layer
->SetTransform(render_surface_transform
);
365 render_surface_layer
->SetForceRenderSurface(true);
367 background
->AddChild(render_surface_layer
);
369 // Software has some huge differences in the AA'd pixels on the different
370 // trybots. See crbug.com/452198.
371 float percentage_pixels_large_error
= 0.686f
;
372 float percentage_pixels_small_error
= 0.0f
;
373 float average_error_allowed_in_bad_pixels
= 16.f
;
374 int large_error_allowed
= 17;
375 int small_error_allowed
= 0;
376 pixel_comparator_
.reset(new FuzzyPixelComparator(
377 true, // discard_alpha
378 percentage_pixels_large_error
, percentage_pixels_small_error
,
379 average_error_allowed_in_bad_pixels
, large_error_allowed
,
380 small_error_allowed
));
382 RunPixelTest(test_type
, background
, image_name
);
386 TEST_F(ImageScaledRenderSurface
, ImageRenderSurfaceScaled_GL
) {
389 base::FilePath(FILE_PATH_LITERAL("scaled_render_surface_layer_gl.png")));
392 TEST_F(ImageScaledRenderSurface
, ImageRenderSurfaceScaled_Software
) {
395 base::FilePath(FILE_PATH_LITERAL("scaled_render_surface_layer_sw.png")));
398 class EnlargedTextureWithAlphaThresholdFilter
399 : public LayerTreeHostFiltersPixelTest
{
401 void RunPixelTestType(PixelTestType test_type
, base::FilePath image_name
) {
402 // Rectangles choosen so that if flipped, the test will fail.
403 gfx::Rect
rect1(10, 10, 10, 15);
404 gfx::Rect
rect2(20, 25, 70, 65);
406 scoped_refptr
<SolidColorLayer
> child1
=
407 CreateSolidColorLayer(rect1
, SK_ColorRED
);
408 scoped_refptr
<SolidColorLayer
> child2
=
409 CreateSolidColorLayer(rect2
, SK_ColorGREEN
);
410 scoped_refptr
<SolidColorLayer
> background
=
411 CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorBLUE
);
412 scoped_refptr
<SolidColorLayer
> filter_layer
=
413 CreateSolidColorLayer(gfx::Rect(100, 100), SK_ColorWHITE
);
415 // Make sure a transformation does not cause misregistration of the filter
416 // and source texture.
417 gfx::Transform filter_transform
;
418 filter_transform
.Scale(2.f
, 2.f
);
419 filter_layer
->SetTransform(filter_transform
);
420 filter_layer
->AddChild(child1
);
421 filter_layer
->AddChild(child2
);
425 SkRegion alpha_region
;
426 SkIRect rects
[2] = {gfx::RectToSkIRect(rect1
), gfx::RectToSkIRect(rect2
)};
427 alpha_region
.setRects(rects
, 2);
428 FilterOperations filters
;
430 FilterOperation::CreateAlphaThresholdFilter(alpha_region
, 0.f
, 0.f
));
431 filter_layer
->SetFilters(filters
);
433 background
->AddChild(filter_layer
);
435 // Force the allocation a larger textures.
436 set_enlarge_texture_amount(gfx::Vector2d(50, 50));
438 RunPixelTest(test_type
, background
, image_name
);
442 TEST_F(EnlargedTextureWithAlphaThresholdFilter
, GL
) {
445 base::FilePath(FILE_PATH_LITERAL("enlarged_texture_on_threshold.png")));
448 TEST_F(EnlargedTextureWithAlphaThresholdFilter
, Software
) {
451 base::FilePath(FILE_PATH_LITERAL("enlarged_texture_on_threshold.png")));