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;
55 const uint32 kForceShaders
= 1 << 3;
57 class LayerTreeHostBlendingPixelTest
: public LayerTreePixelTest
{
59 LayerTreeHostBlendingPixelTest()
60 : force_antialiasing_(false), force_blending_with_shaders_(false) {
61 pixel_comparator_
.reset(new FuzzyPixelOffByOneComparator(true));
64 virtual void InitializeSettings(LayerTreeSettings
* settings
) override
{
65 settings
->force_antialiasing
= force_antialiasing_
;
66 settings
->force_blending_with_shaders
= force_blending_with_shaders_
;
70 void RunBlendingWithRootPixelTestType(PixelTestType type
) {
71 const int kLaneWidth
= 2;
72 const int kLaneHeight
= kLaneWidth
;
73 const int kRootWidth
= (kBlendModesCount
+ 2) * kLaneWidth
;
74 const int kRootHeight
= 2 * kLaneWidth
+ kLaneHeight
;
76 scoped_refptr
<SolidColorLayer
> background
=
77 CreateSolidColorLayer(gfx::Rect(kRootWidth
, kRootHeight
), kCSSOrange
);
79 // Orange child layers will blend with the green background
80 for (int i
= 0; i
< kBlendModesCount
; ++i
) {
82 (i
+ 1) * kLaneWidth
, kLaneWidth
, kLaneWidth
, kLaneHeight
);
83 scoped_refptr
<SolidColorLayer
> green_lane
=
84 CreateSolidColorLayer(child_rect
, kCSSGreen
);
85 background
->AddChild(green_lane
);
86 green_lane
->SetBlendMode(kBlendModes
[i
]);
91 base::FilePath(FILE_PATH_LITERAL("blending_with_root.png")));
94 void RunBlendingWithTransparentPixelTestType(PixelTestType type
) {
95 const int kLaneWidth
= 2;
96 const int kLaneHeight
= 3 * kLaneWidth
;
97 const int kRootWidth
= (kBlendModesCount
+ 2) * kLaneWidth
;
98 const int kRootHeight
= 2 * kLaneWidth
+ kLaneHeight
;
100 scoped_refptr
<SolidColorLayer
> root
=
101 CreateSolidColorLayer(gfx::Rect(kRootWidth
, kRootHeight
), kCSSBrown
);
103 scoped_refptr
<SolidColorLayer
> background
= CreateSolidColorLayer(
104 gfx::Rect(0, kLaneWidth
* 2, kRootWidth
, kLaneWidth
), kCSSOrange
);
106 root
->AddChild(background
);
107 background
->SetIsRootForIsolatedGroup(true);
109 // Orange child layers will blend with the green background
110 for (int i
= 0; i
< kBlendModesCount
; ++i
) {
111 gfx::Rect
child_rect(
112 (i
+ 1) * kLaneWidth
, -kLaneWidth
, kLaneWidth
, kLaneHeight
);
113 scoped_refptr
<SolidColorLayer
> green_lane
=
114 CreateSolidColorLayer(child_rect
, kCSSGreen
);
115 background
->AddChild(green_lane
);
116 green_lane
->SetBlendMode(kBlendModes
[i
]);
121 base::FilePath(FILE_PATH_LITERAL("blending_transparent.png")));
124 scoped_refptr
<Layer
> CreateColorfulBackdropLayer(int width
, int height
) {
125 // Draw the backdrop with horizontal lanes.
126 const int kLaneWidth
= width
;
127 const int kLaneHeight
= height
/ kCSSTestColorsCount
;
128 SkBitmap backing_store
;
129 backing_store
.allocN32Pixels(width
, height
);
130 SkCanvas
canvas(backing_store
);
131 canvas
.clear(SK_ColorTRANSPARENT
);
132 for (int i
= 0; i
< kCSSTestColorsCount
; ++i
) {
134 paint
.setColor(kCSSTestColors
[i
]);
136 SkRect::MakeXYWH(0, i
* kLaneHeight
, kLaneWidth
, kLaneHeight
), paint
);
138 scoped_refptr
<ImageLayer
> layer
= ImageLayer::Create();
139 layer
->SetIsDrawable(true);
140 layer
->SetBounds(gfx::Size(width
, height
));
141 layer
->SetBitmap(backing_store
);
145 void SetupMaskLayer(scoped_refptr
<Layer
> layer
) {
146 const int kMaskOffset
= 2;
147 gfx::Size bounds
= layer
->bounds();
148 scoped_refptr
<ImageLayer
> mask
= ImageLayer::Create();
149 mask
->SetIsDrawable(true);
150 mask
->SetIsMask(true);
151 mask
->SetBounds(bounds
);
154 bitmap
.allocN32Pixels(bounds
.width(), bounds
.height());
155 SkCanvas
canvas(bitmap
);
157 paint
.setColor(SK_ColorWHITE
);
158 canvas
.clear(SK_ColorTRANSPARENT
);
159 canvas
.drawRect(SkRect::MakeXYWH(kMaskOffset
,
161 bounds
.width() - kMaskOffset
* 2,
162 bounds
.height() - kMaskOffset
* 2),
164 mask
->SetBitmap(bitmap
);
165 layer
->SetMaskLayer(mask
.get());
168 void SetupColorMatrix(scoped_refptr
<Layer
> layer
) {
169 FilterOperations filter_operations
;
170 filter_operations
.Append(FilterOperation::CreateSepiaFilter(.001f
));
171 layer
->SetFilters(filter_operations
);
174 void CreateBlendingColorLayers(int lane_width
,
176 scoped_refptr
<Layer
> background
,
177 RenderPassOptions flags
) {
178 const int kLanesCount
= kBlendModesCount
+ 4;
179 const SkColor kMiscOpaqueColor
= 0xffc86464;
180 const SkColor kMiscTransparentColor
= 0x80c86464;
181 const SkXfermode::Mode kCoeffBlendMode
= SkXfermode::kScreen_Mode
;
182 const SkXfermode::Mode kShaderBlendMode
= SkXfermode::kColorBurn_Mode
;
183 // add vertical lanes with each of the blend modes
184 for (int i
= 0; i
< kLanesCount
; ++i
) {
185 gfx::Rect
child_rect(i
* lane_width
, 0, lane_width
, lane_height
);
186 SkXfermode::Mode blend_mode
= SkXfermode::kSrcOver_Mode
;
188 SkColor color
= kMiscOpaqueColor
;
190 if (i
< kBlendModesCount
) {
191 blend_mode
= kBlendModes
[i
];
192 } else if (i
== kBlendModesCount
) {
193 blend_mode
= kCoeffBlendMode
;
195 } else if (i
== kBlendModesCount
+ 1) {
196 blend_mode
= kCoeffBlendMode
;
197 color
= kMiscTransparentColor
;
198 } else if (i
== kBlendModesCount
+ 2) {
199 blend_mode
= kShaderBlendMode
;
201 } else if (i
== kBlendModesCount
+ 3) {
202 blend_mode
= kShaderBlendMode
;
203 color
= kMiscTransparentColor
;
206 scoped_refptr
<SolidColorLayer
> lane
=
207 CreateSolidColorLayer(child_rect
, color
);
208 lane
->SetBlendMode(blend_mode
);
209 lane
->SetOpacity(opacity
);
210 lane
->SetForceRenderSurface(true);
211 if (flags
& kUseMasks
)
212 SetupMaskLayer(lane
);
213 if (flags
& kUseColorMatrix
) {
214 SetupColorMatrix(lane
);
216 background
->AddChild(lane
);
220 void RunBlendingWithRenderPass(PixelTestType type
,
221 const base::FilePath::CharType
* expected_path
,
222 RenderPassOptions flags
) {
223 const int kLaneWidth
= 8;
224 const int kLaneHeight
= kLaneWidth
* kCSSTestColorsCount
;
225 const int kRootSize
= kLaneHeight
;
227 scoped_refptr
<SolidColorLayer
> root
=
228 CreateSolidColorLayer(gfx::Rect(kRootSize
, kRootSize
), SK_ColorWHITE
);
229 scoped_refptr
<Layer
> background
=
230 CreateColorfulBackdropLayer(kRootSize
, kRootSize
);
232 background
->SetIsRootForIsolatedGroup(true);
233 root
->AddChild(background
);
235 CreateBlendingColorLayers(kLaneWidth
, kLaneHeight
, background
.get(), flags
);
237 this->impl_side_painting_
= false;
238 this->force_antialiasing_
= (flags
& kUseAntialiasing
);
239 this->force_blending_with_shaders_
= (flags
& kForceShaders
);
241 if ((flags
& kUseAntialiasing
) && (type
== PIXEL_TEST_GL
)) {
242 // Anti aliasing causes differences up to 8 pixels at the edges.
243 int large_error_allowed
= 8;
244 // Blending results might differ with one pixel.
245 int small_error_allowed
= 1;
246 // Most of the errors are one pixel errors.
247 float percentage_pixels_small_error
= 13.1f
;
248 // Because of anti-aliasing, around 10% of pixels (at the edges) have
249 // bigger errors (from small_error_allowed + 1 to large_error_allowed).
250 float percentage_pixels_error
= 22.5f
;
251 // The average error is still close to 1.
252 float average_error_allowed_in_bad_pixels
= 1.4f
;
254 pixel_comparator_
.reset(
255 new FuzzyPixelComparator(false, // discard_alpha
256 percentage_pixels_error
,
257 percentage_pixels_small_error
,
258 average_error_allowed_in_bad_pixels
,
260 small_error_allowed
));
263 RunPixelTest(type
, root
, base::FilePath(expected_path
));
266 bool force_antialiasing_
;
267 bool force_blending_with_shaders_
;
270 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRoot_GL
) {
271 RunBlendingWithRootPixelTestType(PIXEL_TEST_GL
);
274 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRoot_Software
) {
275 RunBlendingWithRootPixelTestType(PIXEL_TEST_SOFTWARE
);
278 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithBackgroundFilter
) {
279 const int kLaneWidth
= 2;
280 const int kLaneHeight
= kLaneWidth
;
281 const int kRootWidth
= (kBlendModesCount
+ 2) * kLaneWidth
;
282 const int kRootHeight
= 2 * kLaneWidth
+ kLaneHeight
;
284 scoped_refptr
<SolidColorLayer
> background
=
285 CreateSolidColorLayer(gfx::Rect(kRootWidth
, kRootHeight
), kCSSOrange
);
287 // Orange child layers have a background filter set and they will blend with
288 // the green background
289 for (int i
= 0; i
< kBlendModesCount
; ++i
) {
290 gfx::Rect
child_rect(
291 (i
+ 1) * kLaneWidth
, kLaneWidth
, kLaneWidth
, kLaneHeight
);
292 scoped_refptr
<SolidColorLayer
> green_lane
=
293 CreateSolidColorLayer(child_rect
, kCSSGreen
);
294 background
->AddChild(green_lane
);
296 FilterOperations filters
;
297 filters
.Append(FilterOperation::CreateGrayscaleFilter(.75));
298 green_lane
->SetBackgroundFilters(filters
);
299 green_lane
->SetBlendMode(kBlendModes
[i
]);
302 RunPixelTest(PIXEL_TEST_GL
,
304 base::FilePath(FILE_PATH_LITERAL("blending_and_filter.png")));
307 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithTransparent_GL
) {
308 RunBlendingWithTransparentPixelTestType(PIXEL_TEST_GL
);
311 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithTransparent_Software
) {
312 RunBlendingWithTransparentPixelTestType(PIXEL_TEST_SOFTWARE
);
315 // Tests for render passes
316 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPass_GL
) {
317 RunBlendingWithRenderPass(
318 PIXEL_TEST_GL
, FILE_PATH_LITERAL("blending_render_pass.png"), 0);
321 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPass_Software
) {
322 RunBlendingWithRenderPass(
323 PIXEL_TEST_SOFTWARE
, FILE_PATH_LITERAL("blending_render_pass.png"), 0);
326 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassAA_GL
) {
327 RunBlendingWithRenderPass(PIXEL_TEST_GL
,
328 FILE_PATH_LITERAL("blending_render_pass.png"),
332 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassAA_Software
) {
333 RunBlendingWithRenderPass(PIXEL_TEST_SOFTWARE
,
334 FILE_PATH_LITERAL("blending_render_pass.png"),
338 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassWithMask_GL
) {
339 RunBlendingWithRenderPass(PIXEL_TEST_GL
,
340 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
344 TEST_F(LayerTreeHostBlendingPixelTest
,
345 BlendingWithRenderPassWithMask_Software
) {
346 RunBlendingWithRenderPass(PIXEL_TEST_SOFTWARE
,
347 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
351 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassWithMaskAA_GL
) {
352 RunBlendingWithRenderPass(PIXEL_TEST_GL
,
353 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
354 kUseMasks
| kUseAntialiasing
);
357 TEST_F(LayerTreeHostBlendingPixelTest
,
358 BlendingWithRenderPassWithMaskAA_Software
) {
359 RunBlendingWithRenderPass(PIXEL_TEST_SOFTWARE
,
360 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
361 kUseMasks
| kUseAntialiasing
);
364 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassColorMatrix_GL
) {
365 RunBlendingWithRenderPass(PIXEL_TEST_GL
,
366 FILE_PATH_LITERAL("blending_render_pass.png"),
370 TEST_F(LayerTreeHostBlendingPixelTest
,
371 BlendingWithRenderPassColorMatrix_Software
) {
372 RunBlendingWithRenderPass(PIXEL_TEST_SOFTWARE
,
373 FILE_PATH_LITERAL("blending_render_pass.png"),
377 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassColorMatrixAA_GL
) {
378 RunBlendingWithRenderPass(PIXEL_TEST_GL
,
379 FILE_PATH_LITERAL("blending_render_pass.png"),
380 kUseAntialiasing
| kUseColorMatrix
);
383 TEST_F(LayerTreeHostBlendingPixelTest
,
384 BlendingWithRenderPassColorMatrixAA_Software
) {
385 RunBlendingWithRenderPass(PIXEL_TEST_SOFTWARE
,
386 FILE_PATH_LITERAL("blending_render_pass.png"),
387 kUseAntialiasing
| kUseColorMatrix
);
390 TEST_F(LayerTreeHostBlendingPixelTest
,
391 BlendingWithRenderPassWithMaskColorMatrix_GL
) {
392 RunBlendingWithRenderPass(PIXEL_TEST_GL
,
393 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
394 kUseMasks
| kUseColorMatrix
);
397 TEST_F(LayerTreeHostBlendingPixelTest
,
398 BlendingWithRenderPassWithMaskColorMatrix_Software
) {
399 RunBlendingWithRenderPass(PIXEL_TEST_SOFTWARE
,
400 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
401 kUseMasks
| kUseColorMatrix
);
404 TEST_F(LayerTreeHostBlendingPixelTest
,
405 BlendingWithRenderPassWithMaskColorMatrixAA_GL
) {
406 RunBlendingWithRenderPass(PIXEL_TEST_GL
,
407 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
408 kUseMasks
| kUseAntialiasing
| kUseColorMatrix
);
411 TEST_F(LayerTreeHostBlendingPixelTest
,
412 BlendingWithRenderPassWithMaskColorMatrixAA_Software
) {
413 RunBlendingWithRenderPass(PIXEL_TEST_SOFTWARE
,
414 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
415 kUseMasks
| kUseAntialiasing
| kUseColorMatrix
);
418 // Tests for render passes forcing shaders for all the blend modes.
419 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassShaders_GL
) {
420 RunBlendingWithRenderPass(PIXEL_TEST_GL
,
421 FILE_PATH_LITERAL("blending_render_pass.png"),
425 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassShadersAA_GL
) {
426 RunBlendingWithRenderPass(PIXEL_TEST_GL
,
427 FILE_PATH_LITERAL("blending_render_pass.png"),
428 kUseAntialiasing
| kForceShaders
);
431 TEST_F(LayerTreeHostBlendingPixelTest
,
432 BlendingWithRenderPassShadersWithMask_GL
) {
433 RunBlendingWithRenderPass(PIXEL_TEST_GL
,
434 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
435 kUseMasks
| kForceShaders
);
438 TEST_F(LayerTreeHostBlendingPixelTest
,
439 BlendingWithRenderPassShadersWithMaskAA_GL
) {
440 RunBlendingWithRenderPass(PIXEL_TEST_GL
,
441 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
442 kUseMasks
| kUseAntialiasing
| kForceShaders
);
445 TEST_F(LayerTreeHostBlendingPixelTest
,
446 BlendingWithRenderPassShadersColorMatrix_GL
) {
447 RunBlendingWithRenderPass(PIXEL_TEST_GL
,
448 FILE_PATH_LITERAL("blending_render_pass.png"),
449 kUseColorMatrix
| kForceShaders
);
452 TEST_F(LayerTreeHostBlendingPixelTest
,
453 BlendingWithRenderPassShadersColorMatrixAA_GL
) {
454 RunBlendingWithRenderPass(PIXEL_TEST_GL
,
455 FILE_PATH_LITERAL("blending_render_pass.png"),
456 kUseAntialiasing
| kUseColorMatrix
| kForceShaders
);
459 TEST_F(LayerTreeHostBlendingPixelTest
,
460 BlendingWithRenderPassShadersWithMaskColorMatrix_GL
) {
461 RunBlendingWithRenderPass(PIXEL_TEST_GL
,
462 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
463 kUseMasks
| kUseColorMatrix
| kForceShaders
);
466 TEST_F(LayerTreeHostBlendingPixelTest
,
467 BlendingWithRenderPassShadersWithMaskColorMatrixAA_GL
) {
468 RunBlendingWithRenderPass(
469 PIXEL_TEST_GL
, FILE_PATH_LITERAL("blending_render_pass_mask.png"),
470 kUseMasks
| kUseAntialiasing
| kUseColorMatrix
| kForceShaders
);