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 "cc/layers/image_layer.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"
10 #if !defined(OS_ANDROID)
15 SkXfermode::Mode
const kBlendModes
[] = {
16 SkXfermode::kSrcOver_Mode
, SkXfermode::kScreen_Mode
,
17 SkXfermode::kOverlay_Mode
, SkXfermode::kDarken_Mode
,
18 SkXfermode::kLighten_Mode
, SkXfermode::kColorDodge_Mode
,
19 SkXfermode::kColorBurn_Mode
, SkXfermode::kHardLight_Mode
,
20 SkXfermode::kSoftLight_Mode
, SkXfermode::kDifference_Mode
,
21 SkXfermode::kExclusion_Mode
, SkXfermode::kMultiply_Mode
,
22 SkXfermode::kHue_Mode
, SkXfermode::kSaturation_Mode
,
23 SkXfermode::kColor_Mode
, SkXfermode::kLuminosity_Mode
};
25 SkColor kCSSTestColors
[] = {
30 0xffff00ff, // fuchsia
42 0x80000000, // black with transparency
44 0x80ffffff, // white with transparency
45 0x00000000 // transparent
48 const int kBlendModesCount
= arraysize(kBlendModes
);
49 const int kCSSTestColorsCount
= arraysize(kCSSTestColors
);
51 using RenderPassOptions
= uint32
;
52 const uint32 kUseMasks
= 1 << 0;
53 const uint32 kUseAntialiasing
= 1 << 1;
54 const uint32 kUseColorMatrix
= 1 << 2;
56 class LayerTreeHostBlendingPixelTest
: public LayerTreePixelTest
{
58 LayerTreeHostBlendingPixelTest() {
59 pixel_comparator_
.reset(new FuzzyPixelOffByOneComparator(true));
62 virtual void InitializeSettings(LayerTreeSettings
* settings
) override
{
63 settings
->force_antialiasing
= force_antialiasing_
;
67 void RunBlendingWithRootPixelTestType(PixelTestType type
) {
68 const int kLaneWidth
= 15;
69 const int kLaneHeight
= kBlendModesCount
* kLaneWidth
;
70 const int kRootSize
= (kBlendModesCount
+ 2) * kLaneWidth
;
72 scoped_refptr
<SolidColorLayer
> background
=
73 CreateSolidColorLayer(gfx::Rect(kRootSize
, kRootSize
), kCSSOrange
);
75 // Orange child layers will blend with the green background
76 for (int i
= 0; i
< kBlendModesCount
; ++i
) {
78 (i
+ 1) * kLaneWidth
, kLaneWidth
, kLaneWidth
, kLaneHeight
);
79 scoped_refptr
<SolidColorLayer
> green_lane
=
80 CreateSolidColorLayer(child_rect
, kCSSGreen
);
81 background
->AddChild(green_lane
);
82 green_lane
->SetBlendMode(kBlendModes
[i
]);
87 base::FilePath(FILE_PATH_LITERAL("blending_with_root.png")));
90 void RunBlendingWithTransparentPixelTestType(PixelTestType type
) {
91 const int kLaneWidth
= 15;
92 const int kLaneHeight
= kBlendModesCount
* kLaneWidth
;
93 const int kRootSize
= (kBlendModesCount
+ 2) * kLaneWidth
;
95 scoped_refptr
<SolidColorLayer
> root
=
96 CreateSolidColorLayer(gfx::Rect(kRootSize
, kRootSize
), kCSSBrown
);
98 scoped_refptr
<SolidColorLayer
> background
= CreateSolidColorLayer(
99 gfx::Rect(0, kLaneWidth
* 2, kRootSize
, kLaneWidth
), kCSSOrange
);
101 root
->AddChild(background
);
102 background
->SetIsRootForIsolatedGroup(true);
104 // Orange child layers will blend with the green background
105 for (int i
= 0; i
< kBlendModesCount
; ++i
) {
106 gfx::Rect
child_rect(
107 (i
+ 1) * kLaneWidth
, -kLaneWidth
, kLaneWidth
, kLaneHeight
);
108 scoped_refptr
<SolidColorLayer
> green_lane
=
109 CreateSolidColorLayer(child_rect
, kCSSGreen
);
110 background
->AddChild(green_lane
);
111 green_lane
->SetBlendMode(kBlendModes
[i
]);
116 base::FilePath(FILE_PATH_LITERAL("blending_transparent.png")));
119 scoped_refptr
<Layer
> CreateColorfulBackdropLayer(int width
, int height
) {
120 // Draw the backdrop with horizontal lanes.
121 const int kLaneWidth
= width
;
122 const int kLaneHeight
= height
/ kCSSTestColorsCount
;
123 SkBitmap backing_store
;
124 backing_store
.allocN32Pixels(width
, height
);
125 SkCanvas
canvas(backing_store
);
126 canvas
.clear(SK_ColorTRANSPARENT
);
127 for (int i
= 0; i
< kCSSTestColorsCount
; ++i
) {
129 paint
.setColor(kCSSTestColors
[i
]);
131 SkRect::MakeXYWH(0, i
* kLaneHeight
, kLaneWidth
, kLaneHeight
), paint
);
133 scoped_refptr
<ImageLayer
> layer
= ImageLayer::Create();
134 layer
->SetIsDrawable(true);
135 layer
->SetBounds(gfx::Size(width
, height
));
136 layer
->SetBitmap(backing_store
);
140 void SetupMaskLayer(scoped_refptr
<Layer
> layer
) {
141 const int kMaskOffset
= 5;
142 gfx::Size bounds
= layer
->bounds();
143 scoped_refptr
<ImageLayer
> mask
= ImageLayer::Create();
144 mask
->SetIsDrawable(true);
145 mask
->SetIsMask(true);
146 mask
->SetBounds(bounds
);
149 bitmap
.allocN32Pixels(bounds
.width(), bounds
.height());
150 SkCanvas
canvas(bitmap
);
152 paint
.setColor(SK_ColorWHITE
);
153 canvas
.clear(SK_ColorTRANSPARENT
);
154 canvas
.drawRect(SkRect::MakeXYWH(kMaskOffset
,
156 bounds
.width() - kMaskOffset
* 2,
157 bounds
.height() - kMaskOffset
* 2),
159 mask
->SetBitmap(bitmap
);
160 layer
->SetMaskLayer(mask
.get());
163 void SetupColorMatrix(scoped_refptr
<Layer
> layer
) {
164 FilterOperations filter_operations
;
165 filter_operations
.Append(FilterOperation::CreateSepiaFilter(1.f
));
166 layer
->SetFilters(filter_operations
);
169 void CreateBlendingColorLayers(int width
,
171 scoped_refptr
<Layer
> background
,
172 RenderPassOptions flags
) {
173 const int kLanesCount
= kBlendModesCount
+ 4;
174 int lane_width
= width
/ kLanesCount
;
175 const SkColor kMiscOpaqueColor
= 0xffc86464;
176 const SkColor kMiscTransparentColor
= 0x80c86464;
177 const SkXfermode::Mode kCoeffBlendMode
= SkXfermode::kScreen_Mode
;
178 const SkXfermode::Mode kShaderBlendMode
= SkXfermode::kColorBurn_Mode
;
179 // add vertical lanes with each of the blend modes
180 for (int i
= 0; i
< kLanesCount
; ++i
) {
181 gfx::Rect
child_rect(i
* lane_width
, 0, lane_width
, height
);
182 SkXfermode::Mode blend_mode
= SkXfermode::kSrcOver_Mode
;
184 SkColor color
= kMiscOpaqueColor
;
186 if (i
< kBlendModesCount
) {
187 blend_mode
= kBlendModes
[i
];
188 } else if (i
== kBlendModesCount
) {
189 blend_mode
= kCoeffBlendMode
;
191 } else if (i
== kBlendModesCount
+ 1) {
192 blend_mode
= kCoeffBlendMode
;
193 color
= kMiscTransparentColor
;
194 } else if (i
== kBlendModesCount
+ 2) {
195 blend_mode
= kShaderBlendMode
;
197 } else if (i
== kBlendModesCount
+ 3) {
198 blend_mode
= kShaderBlendMode
;
199 color
= kMiscTransparentColor
;
202 scoped_refptr
<SolidColorLayer
> lane
=
203 CreateSolidColorLayer(child_rect
, color
);
204 lane
->SetBlendMode(blend_mode
);
205 lane
->SetOpacity(opacity
);
206 lane
->SetForceRenderSurface(true);
207 if (flags
& kUseMasks
)
208 SetupMaskLayer(lane
);
209 if (flags
& kUseColorMatrix
) {
210 SetupColorMatrix(lane
);
212 background
->AddChild(lane
);
216 void RunBlendingWithRenderPass(PixelTestType type
,
217 const base::FilePath::CharType
* expected_path
,
218 RenderPassOptions flags
) {
219 const int kRootSize
= 400;
221 scoped_refptr
<SolidColorLayer
> root
=
222 CreateSolidColorLayer(gfx::Rect(kRootSize
, kRootSize
), SK_ColorWHITE
);
223 scoped_refptr
<Layer
> background
=
224 CreateColorfulBackdropLayer(kRootSize
, kRootSize
);
226 background
->SetIsRootForIsolatedGroup(true);
227 root
->AddChild(background
);
229 CreateBlendingColorLayers(kRootSize
, kRootSize
, background
.get(), flags
);
231 this->impl_side_painting_
= false;
232 this->force_antialiasing_
= (flags
& kUseAntialiasing
);
234 if ((flags
& kUseAntialiasing
) && (type
== PIXEL_TEST_GL
)) {
235 // Anti aliasing causes differences up to 7 pixels at the edges.
236 // Several pixels have 9 units difference on the alpha channel.
237 int large_error_allowed
= (flags
& kUseMasks
) ? 7 : 9;
238 // Blending results might differ with one pixel.
239 int small_error_allowed
= 1;
240 // Most of the errors are one pixel errors.
241 float percentage_pixels_small_error
= (flags
& kUseMasks
) ? 7.7f
: 12.1f
;
242 // Because of anti-aliasing, around 3% of pixels (at the edges) have
243 // bigger errors (from small_error_allowed + 1 to large_error_allowed).
244 float percentage_pixels_error
= (flags
& kUseMasks
) ? 12.4f
: 15.f
;
245 // The average error is still close to 1.
246 float average_error_allowed_in_bad_pixels
=
247 (flags
& kUseMasks
) ? 1.3f
: 1.f
;
249 // The sepia filter generates more small errors, but the number of large
250 // errors remains around 3%.
251 if (flags
& kUseColorMatrix
) {
252 percentage_pixels_small_error
= (flags
& kUseMasks
) ? 14.0f
: 26.f
;
253 percentage_pixels_error
= (flags
& kUseMasks
) ? 18.5f
: 29.f
;
254 average_error_allowed_in_bad_pixels
= (flags
& kUseMasks
) ? 0.9f
: 0.7f
;
257 pixel_comparator_
.reset(
258 new FuzzyPixelComparator(false, // discard_alpha
259 percentage_pixels_error
,
260 percentage_pixels_small_error
,
261 average_error_allowed_in_bad_pixels
,
263 small_error_allowed
));
264 } else if ((flags
& kUseColorMatrix
) && (type
== PIXEL_TEST_GL
)) {
265 float percentage_pixels_error
= 100.f
;
266 float percentage_pixels_small_error
= 0.f
;
267 float average_error_allowed_in_bad_pixels
= 1.f
;
268 int large_error_allowed
= 2;
269 int small_error_allowed
= 0;
270 pixel_comparator_
.reset(
271 new FuzzyPixelComparator(false, // discard_alpha
272 percentage_pixels_error
,
273 percentage_pixels_small_error
,
274 average_error_allowed_in_bad_pixels
,
276 small_error_allowed
));
279 RunPixelTest(type
, root
, base::FilePath(expected_path
));
282 bool force_antialiasing_
= false;
285 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRoot_GL
) {
286 RunBlendingWithRootPixelTestType(PIXEL_TEST_GL
);
289 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRoot_Software
) {
290 RunBlendingWithRootPixelTestType(PIXEL_TEST_SOFTWARE
);
293 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithBackgroundFilter
) {
294 const int kLaneWidth
= 15;
295 const int kLaneHeight
= kBlendModesCount
* kLaneWidth
;
296 const int kRootSize
= (kBlendModesCount
+ 2) * kLaneWidth
;
298 scoped_refptr
<SolidColorLayer
> background
=
299 CreateSolidColorLayer(gfx::Rect(kRootSize
, kRootSize
), kCSSOrange
);
301 // Orange child layers have a background filter set and they will blend with
302 // the green background
303 for (int i
= 0; i
< kBlendModesCount
; ++i
) {
304 gfx::Rect
child_rect(
305 (i
+ 1) * kLaneWidth
, kLaneWidth
, kLaneWidth
, kLaneHeight
);
306 scoped_refptr
<SolidColorLayer
> green_lane
=
307 CreateSolidColorLayer(child_rect
, kCSSGreen
);
308 background
->AddChild(green_lane
);
310 FilterOperations filters
;
311 filters
.Append(FilterOperation::CreateGrayscaleFilter(.75));
312 green_lane
->SetBackgroundFilters(filters
);
313 green_lane
->SetBlendMode(kBlendModes
[i
]);
316 RunPixelTest(PIXEL_TEST_GL
,
318 base::FilePath(FILE_PATH_LITERAL("blending_and_filter.png")));
321 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithTransparent_GL
) {
322 RunBlendingWithTransparentPixelTestType(PIXEL_TEST_GL
);
325 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithTransparent_Software
) {
326 RunBlendingWithTransparentPixelTestType(PIXEL_TEST_SOFTWARE
);
329 // Tests for render passes
330 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPass_GL
) {
331 RunBlendingWithRenderPass(
332 PIXEL_TEST_GL
, FILE_PATH_LITERAL("blending_render_pass.png"), 0);
335 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPass_Software
) {
336 RunBlendingWithRenderPass(
337 PIXEL_TEST_SOFTWARE
, FILE_PATH_LITERAL("blending_render_pass.png"), 0);
340 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassAA_GL
) {
341 RunBlendingWithRenderPass(PIXEL_TEST_GL
,
342 FILE_PATH_LITERAL("blending_render_pass.png"),
346 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassAA_Software
) {
347 RunBlendingWithRenderPass(PIXEL_TEST_SOFTWARE
,
348 FILE_PATH_LITERAL("blending_render_pass.png"),
352 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassWithMask_GL
) {
353 RunBlendingWithRenderPass(PIXEL_TEST_GL
,
354 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
358 TEST_F(LayerTreeHostBlendingPixelTest
,
359 BlendingWithRenderPassWithMask_Software
) {
360 RunBlendingWithRenderPass(PIXEL_TEST_SOFTWARE
,
361 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
365 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassWithMaskAA_GL
) {
366 RunBlendingWithRenderPass(PIXEL_TEST_GL
,
367 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
368 kUseMasks
| kUseAntialiasing
);
371 TEST_F(LayerTreeHostBlendingPixelTest
,
372 BlendingWithRenderPassWithMaskAA_Software
) {
373 RunBlendingWithRenderPass(PIXEL_TEST_SOFTWARE
,
374 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
375 kUseMasks
| kUseAntialiasing
);
378 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassColorMatrix_GL
) {
379 RunBlendingWithRenderPass(PIXEL_TEST_GL
,
380 FILE_PATH_LITERAL("blending_render_pass_cm.png"),
384 TEST_F(LayerTreeHostBlendingPixelTest
,
385 BlendingWithRenderPassColorMatrix_Software
) {
386 RunBlendingWithRenderPass(PIXEL_TEST_SOFTWARE
,
387 FILE_PATH_LITERAL("blending_render_pass_cm.png"),
391 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassColorMatrixAA_GL
) {
392 RunBlendingWithRenderPass(PIXEL_TEST_GL
,
393 FILE_PATH_LITERAL("blending_render_pass_cm.png"),
394 kUseAntialiasing
| kUseColorMatrix
);
397 TEST_F(LayerTreeHostBlendingPixelTest
,
398 BlendingWithRenderPassColorMatrixAA_Software
) {
399 RunBlendingWithRenderPass(PIXEL_TEST_SOFTWARE
,
400 FILE_PATH_LITERAL("blending_render_pass_cm.png"),
401 kUseAntialiasing
| kUseColorMatrix
);
404 TEST_F(LayerTreeHostBlendingPixelTest
,
405 BlendingWithRenderPassWithMaskColorMatrix_GL
) {
406 RunBlendingWithRenderPass(
408 FILE_PATH_LITERAL("blending_render_pass_mask_cm.png"),
409 kUseMasks
| kUseColorMatrix
);
412 TEST_F(LayerTreeHostBlendingPixelTest
,
413 BlendingWithRenderPassWithMaskColorMatrix_Software
) {
414 RunBlendingWithRenderPass(
416 FILE_PATH_LITERAL("blending_render_pass_mask_cm.png"),
417 kUseMasks
| kUseColorMatrix
);
420 TEST_F(LayerTreeHostBlendingPixelTest
,
421 BlendingWithRenderPassWithMaskColorMatrixAA_GL
) {
422 RunBlendingWithRenderPass(
424 FILE_PATH_LITERAL("blending_render_pass_mask_cm.png"),
425 kUseMasks
| kUseAntialiasing
| kUseColorMatrix
);
428 TEST_F(LayerTreeHostBlendingPixelTest
,
429 BlendingWithRenderPassWithMaskColorMatrixAA_Software
) {
430 RunBlendingWithRenderPass(
432 FILE_PATH_LITERAL("blending_render_pass_mask_cm.png"),
433 kUseMasks
| kUseAntialiasing
| kUseColorMatrix
);