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/picture_image_layer.h"
6 #include "cc/layers/solid_color_layer.h"
7 #include "cc/test/layer_tree_pixel_resource_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 LayerTreeHostPixelResourceTest
{
59 LayerTreeHostBlendingPixelTest()
60 : force_antialiasing_(false), force_blending_with_shaders_(false) {
61 pixel_comparator_
.reset(new FuzzyPixelOffByOneComparator(true));
64 void InitializeSettings(LayerTreeSettings
* settings
) override
{
65 settings
->renderer_settings
.force_antialiasing
= force_antialiasing_
;
66 settings
->renderer_settings
.force_blending_with_shaders
=
67 force_blending_with_shaders_
;
71 void RunBlendingWithRootPixelTestType(PixelResourceTestCase type
) {
72 const int kLaneWidth
= 2;
73 const int kLaneHeight
= kLaneWidth
;
74 const int kRootWidth
= (kBlendModesCount
+ 2) * kLaneWidth
;
75 const int kRootHeight
= 2 * kLaneWidth
+ kLaneHeight
;
76 InitializeFromTestCase(type
);
78 scoped_refptr
<SolidColorLayer
> background
=
79 CreateSolidColorLayer(gfx::Rect(kRootWidth
, kRootHeight
), kCSSOrange
);
81 // Orange child layers will blend with the green background
82 for (int i
= 0; i
< kBlendModesCount
; ++i
) {
84 (i
+ 1) * kLaneWidth
, kLaneWidth
, kLaneWidth
, kLaneHeight
);
85 scoped_refptr
<SolidColorLayer
> green_lane
=
86 CreateSolidColorLayer(child_rect
, kCSSGreen
);
87 background
->AddChild(green_lane
);
88 green_lane
->SetBlendMode(kBlendModes
[i
]);
93 base::FilePath(FILE_PATH_LITERAL("blending_with_root.png")));
96 void RunBlendingWithTransparentPixelTestType(PixelResourceTestCase type
) {
97 const int kLaneWidth
= 2;
98 const int kLaneHeight
= 3 * kLaneWidth
;
99 const int kRootWidth
= (kBlendModesCount
+ 2) * kLaneWidth
;
100 const int kRootHeight
= 2 * kLaneWidth
+ kLaneHeight
;
101 InitializeFromTestCase(type
);
103 scoped_refptr
<SolidColorLayer
> root
=
104 CreateSolidColorLayer(gfx::Rect(kRootWidth
, kRootHeight
), kCSSBrown
);
106 scoped_refptr
<SolidColorLayer
> background
= CreateSolidColorLayer(
107 gfx::Rect(0, kLaneWidth
* 2, kRootWidth
, kLaneWidth
), kCSSOrange
);
109 root
->AddChild(background
);
110 background
->SetIsRootForIsolatedGroup(true);
112 // Orange child layers will blend with the green background
113 for (int i
= 0; i
< kBlendModesCount
; ++i
) {
114 gfx::Rect
child_rect(
115 (i
+ 1) * kLaneWidth
, -kLaneWidth
, kLaneWidth
, kLaneHeight
);
116 scoped_refptr
<SolidColorLayer
> green_lane
=
117 CreateSolidColorLayer(child_rect
, kCSSGreen
);
118 background
->AddChild(green_lane
);
119 green_lane
->SetBlendMode(kBlendModes
[i
]);
122 RunPixelResourceTest(
123 root
, base::FilePath(FILE_PATH_LITERAL("blending_transparent.png")));
126 scoped_refptr
<Layer
> CreateColorfulBackdropLayer(int width
, int height
) {
127 // Draw the backdrop with horizontal lanes.
128 const int kLaneWidth
= width
;
129 const int kLaneHeight
= height
/ kCSSTestColorsCount
;
130 SkBitmap backing_store
;
131 backing_store
.allocN32Pixels(width
, height
);
132 SkCanvas
canvas(backing_store
);
133 canvas
.clear(SK_ColorTRANSPARENT
);
134 for (int i
= 0; i
< kCSSTestColorsCount
; ++i
) {
136 paint
.setColor(kCSSTestColors
[i
]);
138 SkRect::MakeXYWH(0, i
* kLaneHeight
, kLaneWidth
, kLaneHeight
), paint
);
140 scoped_refptr
<PictureImageLayer
> layer
= PictureImageLayer::Create();
141 layer
->SetIsDrawable(true);
142 layer
->SetBounds(gfx::Size(width
, height
));
143 layer
->SetBitmap(backing_store
);
147 void SetupMaskLayer(scoped_refptr
<Layer
> layer
) {
148 const int kMaskOffset
= 2;
149 gfx::Size bounds
= layer
->bounds();
150 scoped_refptr
<PictureImageLayer
> mask
= PictureImageLayer::Create();
151 mask
->SetIsDrawable(true);
152 mask
->SetIsMask(true);
153 mask
->SetBounds(bounds
);
156 bitmap
.allocN32Pixels(bounds
.width(), bounds
.height());
157 SkCanvas
canvas(bitmap
);
159 paint
.setColor(SK_ColorWHITE
);
160 canvas
.clear(SK_ColorTRANSPARENT
);
161 canvas
.drawRect(SkRect::MakeXYWH(kMaskOffset
,
163 bounds
.width() - kMaskOffset
* 2,
164 bounds
.height() - kMaskOffset
* 2),
166 mask
->SetBitmap(bitmap
);
167 layer
->SetMaskLayer(mask
.get());
170 void SetupColorMatrix(scoped_refptr
<Layer
> layer
) {
171 FilterOperations filter_operations
;
172 filter_operations
.Append(FilterOperation::CreateSepiaFilter(.001f
));
173 layer
->SetFilters(filter_operations
);
176 void CreateBlendingColorLayers(int lane_width
,
178 scoped_refptr
<Layer
> background
,
179 RenderPassOptions flags
) {
180 const int kLanesCount
= kBlendModesCount
+ 4;
181 const SkColor kMiscOpaqueColor
= 0xffc86464;
182 const SkColor kMiscTransparentColor
= 0x80c86464;
183 const SkXfermode::Mode kCoeffBlendMode
= SkXfermode::kScreen_Mode
;
184 const SkXfermode::Mode kShaderBlendMode
= SkXfermode::kColorBurn_Mode
;
185 // add vertical lanes with each of the blend modes
186 for (int i
= 0; i
< kLanesCount
; ++i
) {
187 gfx::Rect
child_rect(i
* lane_width
, 0, lane_width
, lane_height
);
188 SkXfermode::Mode blend_mode
= SkXfermode::kSrcOver_Mode
;
190 SkColor color
= kMiscOpaqueColor
;
192 if (i
< kBlendModesCount
) {
193 blend_mode
= kBlendModes
[i
];
194 } else if (i
== kBlendModesCount
) {
195 blend_mode
= kCoeffBlendMode
;
197 } else if (i
== kBlendModesCount
+ 1) {
198 blend_mode
= kCoeffBlendMode
;
199 color
= kMiscTransparentColor
;
200 } else if (i
== kBlendModesCount
+ 2) {
201 blend_mode
= kShaderBlendMode
;
203 } else if (i
== kBlendModesCount
+ 3) {
204 blend_mode
= kShaderBlendMode
;
205 color
= kMiscTransparentColor
;
208 scoped_refptr
<SolidColorLayer
> lane
=
209 CreateSolidColorLayer(child_rect
, color
);
210 lane
->SetBlendMode(blend_mode
);
211 lane
->SetOpacity(opacity
);
212 lane
->SetForceRenderSurface(true);
213 if (flags
& kUseMasks
)
214 SetupMaskLayer(lane
);
215 if (flags
& kUseColorMatrix
) {
216 SetupColorMatrix(lane
);
218 background
->AddChild(lane
);
222 void RunBlendingWithRenderPass(PixelResourceTestCase type
,
223 const base::FilePath::CharType
* expected_path
,
224 RenderPassOptions flags
) {
225 const int kLaneWidth
= 8;
226 const int kLaneHeight
= kLaneWidth
* kCSSTestColorsCount
;
227 const int kRootSize
= kLaneHeight
;
228 InitializeFromTestCase(type
);
230 scoped_refptr
<SolidColorLayer
> root
=
231 CreateSolidColorLayer(gfx::Rect(kRootSize
, kRootSize
), SK_ColorWHITE
);
232 scoped_refptr
<Layer
> background
=
233 CreateColorfulBackdropLayer(kRootSize
, kRootSize
);
235 background
->SetIsRootForIsolatedGroup(true);
236 root
->AddChild(background
);
238 CreateBlendingColorLayers(kLaneWidth
, kLaneHeight
, background
.get(), flags
);
240 this->force_antialiasing_
= (flags
& kUseAntialiasing
);
241 this->force_blending_with_shaders_
= (flags
& kForceShaders
);
243 if ((flags
& kUseAntialiasing
) && (test_type_
== PIXEL_TEST_GL
)) {
244 // Anti aliasing causes differences up to 8 pixels at the edges.
245 int large_error_allowed
= 8;
246 // Blending results might differ with one pixel.
247 int small_error_allowed
= 1;
248 // Most of the errors are one pixel errors.
249 float percentage_pixels_small_error
= 13.1f
;
250 // Because of anti-aliasing, around 10% of pixels (at the edges) have
251 // bigger errors (from small_error_allowed + 1 to large_error_allowed).
252 float percentage_pixels_error
= 22.5f
;
253 // The average error is still close to 1.
254 float average_error_allowed_in_bad_pixels
= 1.4f
;
256 pixel_comparator_
.reset(
257 new FuzzyPixelComparator(false, // discard_alpha
258 percentage_pixels_error
,
259 percentage_pixels_small_error
,
260 average_error_allowed_in_bad_pixels
,
262 small_error_allowed
));
265 RunPixelResourceTest(root
, base::FilePath(expected_path
));
268 bool force_antialiasing_
;
269 bool force_blending_with_shaders_
;
272 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRoot_GL
) {
273 RunBlendingWithRootPixelTestType(GL_ASYNC_UPLOAD_2D_DRAW
);
276 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRoot_Software
) {
277 RunBlendingWithRootPixelTestType(SOFTWARE
);
280 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithBackgroundFilter
) {
281 const int kLaneWidth
= 2;
282 const int kLaneHeight
= kLaneWidth
;
283 const int kRootWidth
= (kBlendModesCount
+ 2) * kLaneWidth
;
284 const int kRootHeight
= 2 * kLaneWidth
+ kLaneHeight
;
285 InitializeFromTestCase(GL_ASYNC_UPLOAD_2D_DRAW
);
287 scoped_refptr
<SolidColorLayer
> background
=
288 CreateSolidColorLayer(gfx::Rect(kRootWidth
, kRootHeight
), kCSSOrange
);
290 // Orange child layers have a background filter set and they will blend with
291 // the green background
292 for (int i
= 0; i
< kBlendModesCount
; ++i
) {
293 gfx::Rect
child_rect(
294 (i
+ 1) * kLaneWidth
, kLaneWidth
, kLaneWidth
, kLaneHeight
);
295 scoped_refptr
<SolidColorLayer
> green_lane
=
296 CreateSolidColorLayer(child_rect
, kCSSGreen
);
297 background
->AddChild(green_lane
);
299 FilterOperations filters
;
300 filters
.Append(FilterOperation::CreateGrayscaleFilter(.75));
301 green_lane
->SetBackgroundFilters(filters
);
302 green_lane
->SetBlendMode(kBlendModes
[i
]);
305 RunPixelResourceTest(
306 background
, base::FilePath(FILE_PATH_LITERAL("blending_and_filter.png")));
309 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithTransparent_GL
) {
310 RunBlendingWithTransparentPixelTestType(GL_ASYNC_UPLOAD_2D_DRAW
);
313 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithTransparent_Software
) {
314 RunBlendingWithTransparentPixelTestType(SOFTWARE
);
317 // Tests for render passes
318 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPass_GL
) {
319 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
320 FILE_PATH_LITERAL("blending_render_pass.png"), 0);
323 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPass_Software
) {
324 RunBlendingWithRenderPass(SOFTWARE
,
325 FILE_PATH_LITERAL("blending_render_pass.png"), 0);
328 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassAA_GL
) {
329 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
330 FILE_PATH_LITERAL("blending_render_pass.png"),
334 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassAA_Software
) {
335 RunBlendingWithRenderPass(SOFTWARE
,
336 FILE_PATH_LITERAL("blending_render_pass.png"),
340 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassWithMask_GL
) {
341 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
342 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
346 TEST_F(LayerTreeHostBlendingPixelTest
,
347 BlendingWithRenderPassWithMask_Software
) {
348 RunBlendingWithRenderPass(
349 SOFTWARE
, FILE_PATH_LITERAL("blending_render_pass_mask.png"), kUseMasks
);
352 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassWithMaskAA_GL
) {
353 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
354 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
355 kUseMasks
| kUseAntialiasing
);
358 TEST_F(LayerTreeHostBlendingPixelTest
,
359 BlendingWithRenderPassWithMaskAA_Software
) {
360 RunBlendingWithRenderPass(SOFTWARE
,
361 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
362 kUseMasks
| kUseAntialiasing
);
365 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassColorMatrix_GL
) {
366 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
367 FILE_PATH_LITERAL("blending_render_pass.png"),
371 TEST_F(LayerTreeHostBlendingPixelTest
,
372 BlendingWithRenderPassColorMatrix_Software
) {
373 RunBlendingWithRenderPass(
374 SOFTWARE
, FILE_PATH_LITERAL("blending_render_pass.png"), kUseColorMatrix
);
377 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassColorMatrixAA_GL
) {
378 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
379 FILE_PATH_LITERAL("blending_render_pass.png"),
380 kUseAntialiasing
| kUseColorMatrix
);
383 TEST_F(LayerTreeHostBlendingPixelTest
,
384 BlendingWithRenderPassColorMatrixAA_Software
) {
385 RunBlendingWithRenderPass(SOFTWARE
,
386 FILE_PATH_LITERAL("blending_render_pass.png"),
387 kUseAntialiasing
| kUseColorMatrix
);
390 TEST_F(LayerTreeHostBlendingPixelTest
,
391 BlendingWithRenderPassWithMaskColorMatrix_GL
) {
392 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
393 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
394 kUseMasks
| kUseColorMatrix
);
397 TEST_F(LayerTreeHostBlendingPixelTest
,
398 BlendingWithRenderPassWithMaskColorMatrix_Software
) {
399 RunBlendingWithRenderPass(SOFTWARE
,
400 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
401 kUseMasks
| kUseColorMatrix
);
404 TEST_F(LayerTreeHostBlendingPixelTest
,
405 BlendingWithRenderPassWithMaskColorMatrixAA_GL
) {
406 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
407 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
408 kUseMasks
| kUseAntialiasing
| kUseColorMatrix
);
411 TEST_F(LayerTreeHostBlendingPixelTest
,
412 BlendingWithRenderPassWithMaskColorMatrixAA_Software
) {
413 RunBlendingWithRenderPass(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(GL_ASYNC_UPLOAD_2D_DRAW
,
421 FILE_PATH_LITERAL("blending_render_pass.png"),
425 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassShadersAA_GL
) {
426 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
427 FILE_PATH_LITERAL("blending_render_pass.png"),
428 kUseAntialiasing
| kForceShaders
);
431 TEST_F(LayerTreeHostBlendingPixelTest
,
432 BlendingWithRenderPassShadersWithMask_GL
) {
433 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
434 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
435 kUseMasks
| kForceShaders
);
438 TEST_F(LayerTreeHostBlendingPixelTest
,
439 BlendingWithRenderPassShadersWithMask_GL_TextureRect
) {
440 RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW
,
441 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
442 kUseMasks
| kForceShaders
);
445 TEST_F(LayerTreeHostBlendingPixelTest
,
446 BlendingWithRenderPassShadersWithMaskAA_GL
) {
447 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
448 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
449 kUseMasks
| kUseAntialiasing
| kForceShaders
);
452 TEST_F(LayerTreeHostBlendingPixelTest
,
453 BlendingWithRenderPassShadersWithMaskAA_GL_TextureRect
) {
454 RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW
,
455 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
456 kUseMasks
| kUseAntialiasing
| kForceShaders
);
459 TEST_F(LayerTreeHostBlendingPixelTest
,
460 BlendingWithRenderPassShadersColorMatrix_GL
) {
461 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
462 FILE_PATH_LITERAL("blending_render_pass.png"),
463 kUseColorMatrix
| kForceShaders
);
466 TEST_F(LayerTreeHostBlendingPixelTest
,
467 BlendingWithRenderPassShadersColorMatrixAA_GL
) {
468 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
469 FILE_PATH_LITERAL("blending_render_pass.png"),
470 kUseAntialiasing
| kUseColorMatrix
| kForceShaders
);
473 TEST_F(LayerTreeHostBlendingPixelTest
,
474 BlendingWithRenderPassShadersWithMaskColorMatrix_GL
) {
475 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
476 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
477 kUseMasks
| kUseColorMatrix
| kForceShaders
);
480 TEST_F(LayerTreeHostBlendingPixelTest
,
481 BlendingWithRenderPassShadersWithMaskColorMatrix_GL_TextureRect
) {
482 RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW
,
483 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
484 kUseMasks
| kUseColorMatrix
| kForceShaders
);
487 TEST_F(LayerTreeHostBlendingPixelTest
,
488 BlendingWithRenderPassShadersWithMaskColorMatrixAA_GL
) {
489 RunBlendingWithRenderPass(
490 GL_ASYNC_UPLOAD_2D_DRAW
,
491 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
492 kUseMasks
| kUseAntialiasing
| kUseColorMatrix
| kForceShaders
);