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
=
141 PictureImageLayer::Create(layer_settings());
142 layer
->SetIsDrawable(true);
143 layer
->SetBounds(gfx::Size(width
, height
));
144 layer
->SetBitmap(backing_store
);
148 void SetupMaskLayer(scoped_refptr
<Layer
> layer
) {
149 const int kMaskOffset
= 2;
150 gfx::Size bounds
= layer
->bounds();
151 scoped_refptr
<PictureImageLayer
> mask
=
152 PictureImageLayer::Create(layer_settings());
153 mask
->SetIsDrawable(true);
154 mask
->SetIsMask(true);
155 mask
->SetBounds(bounds
);
158 bitmap
.allocN32Pixels(bounds
.width(), bounds
.height());
159 SkCanvas
canvas(bitmap
);
161 paint
.setColor(SK_ColorWHITE
);
162 canvas
.clear(SK_ColorTRANSPARENT
);
163 canvas
.drawRect(SkRect::MakeXYWH(kMaskOffset
,
165 bounds
.width() - kMaskOffset
* 2,
166 bounds
.height() - kMaskOffset
* 2),
168 mask
->SetBitmap(bitmap
);
169 layer
->SetMaskLayer(mask
.get());
172 void SetupColorMatrix(scoped_refptr
<Layer
> layer
) {
173 FilterOperations filter_operations
;
174 filter_operations
.Append(FilterOperation::CreateSepiaFilter(.001f
));
175 layer
->SetFilters(filter_operations
);
178 void CreateBlendingColorLayers(int lane_width
,
180 scoped_refptr
<Layer
> background
,
181 RenderPassOptions flags
) {
182 const int kLanesCount
= kBlendModesCount
+ 4;
183 const SkColor kMiscOpaqueColor
= 0xffc86464;
184 const SkColor kMiscTransparentColor
= 0x80c86464;
185 const SkXfermode::Mode kCoeffBlendMode
= SkXfermode::kScreen_Mode
;
186 const SkXfermode::Mode kShaderBlendMode
= SkXfermode::kColorBurn_Mode
;
187 // add vertical lanes with each of the blend modes
188 for (int i
= 0; i
< kLanesCount
; ++i
) {
189 gfx::Rect
child_rect(i
* lane_width
, 0, lane_width
, lane_height
);
190 SkXfermode::Mode blend_mode
= SkXfermode::kSrcOver_Mode
;
192 SkColor color
= kMiscOpaqueColor
;
194 if (i
< kBlendModesCount
) {
195 blend_mode
= kBlendModes
[i
];
196 } else if (i
== kBlendModesCount
) {
197 blend_mode
= kCoeffBlendMode
;
199 } else if (i
== kBlendModesCount
+ 1) {
200 blend_mode
= kCoeffBlendMode
;
201 color
= kMiscTransparentColor
;
202 } else if (i
== kBlendModesCount
+ 2) {
203 blend_mode
= kShaderBlendMode
;
205 } else if (i
== kBlendModesCount
+ 3) {
206 blend_mode
= kShaderBlendMode
;
207 color
= kMiscTransparentColor
;
210 scoped_refptr
<SolidColorLayer
> lane
=
211 CreateSolidColorLayer(child_rect
, color
);
212 lane
->SetBlendMode(blend_mode
);
213 lane
->SetOpacity(opacity
);
214 lane
->SetForceRenderSurface(true);
215 if (flags
& kUseMasks
)
216 SetupMaskLayer(lane
);
217 if (flags
& kUseColorMatrix
) {
218 SetupColorMatrix(lane
);
220 background
->AddChild(lane
);
224 void RunBlendingWithRenderPass(PixelResourceTestCase type
,
225 const base::FilePath::CharType
* expected_path
,
226 RenderPassOptions flags
) {
227 const int kLaneWidth
= 8;
228 const int kLaneHeight
= kLaneWidth
* kCSSTestColorsCount
;
229 const int kRootSize
= kLaneHeight
;
230 InitializeFromTestCase(type
);
232 scoped_refptr
<SolidColorLayer
> root
=
233 CreateSolidColorLayer(gfx::Rect(kRootSize
, kRootSize
), SK_ColorWHITE
);
234 scoped_refptr
<Layer
> background
=
235 CreateColorfulBackdropLayer(kRootSize
, kRootSize
);
237 background
->SetIsRootForIsolatedGroup(true);
238 root
->AddChild(background
);
240 CreateBlendingColorLayers(kLaneWidth
, kLaneHeight
, background
.get(), flags
);
242 this->force_antialiasing_
= (flags
& kUseAntialiasing
);
243 this->force_blending_with_shaders_
= (flags
& kForceShaders
);
245 if ((flags
& kUseAntialiasing
) && (test_type_
== PIXEL_TEST_GL
)) {
246 // Anti aliasing causes differences up to 8 pixels at the edges.
247 int large_error_allowed
= 8;
248 // Blending results might differ with one pixel.
249 int small_error_allowed
= 1;
250 // Most of the errors are one pixel errors.
251 float percentage_pixels_small_error
= 13.1f
;
252 // Because of anti-aliasing, around 10% of pixels (at the edges) have
253 // bigger errors (from small_error_allowed + 1 to large_error_allowed).
254 float percentage_pixels_error
= 22.5f
;
255 // The average error is still close to 1.
256 float average_error_allowed_in_bad_pixels
= 1.4f
;
258 pixel_comparator_
.reset(
259 new FuzzyPixelComparator(false, // discard_alpha
260 percentage_pixels_error
,
261 percentage_pixels_small_error
,
262 average_error_allowed_in_bad_pixels
,
264 small_error_allowed
));
267 RunPixelResourceTest(root
, base::FilePath(expected_path
));
270 bool force_antialiasing_
;
271 bool force_blending_with_shaders_
;
274 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRoot_GL
) {
275 RunBlendingWithRootPixelTestType(GL_ASYNC_UPLOAD_2D_DRAW
);
278 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRoot_Software
) {
279 RunBlendingWithRootPixelTestType(SOFTWARE
);
282 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithBackgroundFilter
) {
283 const int kLaneWidth
= 2;
284 const int kLaneHeight
= kLaneWidth
;
285 const int kRootWidth
= (kBlendModesCount
+ 2) * kLaneWidth
;
286 const int kRootHeight
= 2 * kLaneWidth
+ kLaneHeight
;
287 InitializeFromTestCase(GL_ASYNC_UPLOAD_2D_DRAW
);
289 scoped_refptr
<SolidColorLayer
> background
=
290 CreateSolidColorLayer(gfx::Rect(kRootWidth
, kRootHeight
), kCSSOrange
);
292 // Orange child layers have a background filter set and they will blend with
293 // the green background
294 for (int i
= 0; i
< kBlendModesCount
; ++i
) {
295 gfx::Rect
child_rect(
296 (i
+ 1) * kLaneWidth
, kLaneWidth
, kLaneWidth
, kLaneHeight
);
297 scoped_refptr
<SolidColorLayer
> green_lane
=
298 CreateSolidColorLayer(child_rect
, kCSSGreen
);
299 background
->AddChild(green_lane
);
301 FilterOperations filters
;
302 filters
.Append(FilterOperation::CreateGrayscaleFilter(.75));
303 green_lane
->SetBackgroundFilters(filters
);
304 green_lane
->SetBlendMode(kBlendModes
[i
]);
307 RunPixelResourceTest(
308 background
, base::FilePath(FILE_PATH_LITERAL("blending_and_filter.png")));
311 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithTransparent_GL
) {
312 RunBlendingWithTransparentPixelTestType(GL_ASYNC_UPLOAD_2D_DRAW
);
315 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithTransparent_Software
) {
316 RunBlendingWithTransparentPixelTestType(SOFTWARE
);
319 // Tests for render passes
320 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPass_GL
) {
321 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
322 FILE_PATH_LITERAL("blending_render_pass.png"), 0);
325 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPass_Software
) {
326 RunBlendingWithRenderPass(SOFTWARE
,
327 FILE_PATH_LITERAL("blending_render_pass.png"), 0);
330 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassAA_GL
) {
331 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
332 FILE_PATH_LITERAL("blending_render_pass.png"),
336 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassAA_Software
) {
337 RunBlendingWithRenderPass(SOFTWARE
,
338 FILE_PATH_LITERAL("blending_render_pass.png"),
342 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassWithMask_GL
) {
343 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
344 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
348 TEST_F(LayerTreeHostBlendingPixelTest
,
349 BlendingWithRenderPassWithMask_Software
) {
350 RunBlendingWithRenderPass(
351 SOFTWARE
, FILE_PATH_LITERAL("blending_render_pass_mask.png"), kUseMasks
);
354 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassWithMaskAA_GL
) {
355 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
356 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
357 kUseMasks
| kUseAntialiasing
);
360 TEST_F(LayerTreeHostBlendingPixelTest
,
361 BlendingWithRenderPassWithMaskAA_Software
) {
362 RunBlendingWithRenderPass(SOFTWARE
,
363 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
364 kUseMasks
| kUseAntialiasing
);
367 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassColorMatrix_GL
) {
368 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
369 FILE_PATH_LITERAL("blending_render_pass.png"),
373 TEST_F(LayerTreeHostBlendingPixelTest
,
374 BlendingWithRenderPassColorMatrix_Software
) {
375 RunBlendingWithRenderPass(
376 SOFTWARE
, FILE_PATH_LITERAL("blending_render_pass.png"), kUseColorMatrix
);
379 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassColorMatrixAA_GL
) {
380 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
381 FILE_PATH_LITERAL("blending_render_pass.png"),
382 kUseAntialiasing
| kUseColorMatrix
);
385 TEST_F(LayerTreeHostBlendingPixelTest
,
386 BlendingWithRenderPassColorMatrixAA_Software
) {
387 RunBlendingWithRenderPass(SOFTWARE
,
388 FILE_PATH_LITERAL("blending_render_pass.png"),
389 kUseAntialiasing
| kUseColorMatrix
);
392 TEST_F(LayerTreeHostBlendingPixelTest
,
393 BlendingWithRenderPassWithMaskColorMatrix_GL
) {
394 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
395 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
396 kUseMasks
| kUseColorMatrix
);
399 TEST_F(LayerTreeHostBlendingPixelTest
,
400 BlendingWithRenderPassWithMaskColorMatrix_Software
) {
401 RunBlendingWithRenderPass(SOFTWARE
,
402 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
403 kUseMasks
| kUseColorMatrix
);
406 TEST_F(LayerTreeHostBlendingPixelTest
,
407 BlendingWithRenderPassWithMaskColorMatrixAA_GL
) {
408 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
409 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
410 kUseMasks
| kUseAntialiasing
| kUseColorMatrix
);
413 TEST_F(LayerTreeHostBlendingPixelTest
,
414 BlendingWithRenderPassWithMaskColorMatrixAA_Software
) {
415 RunBlendingWithRenderPass(SOFTWARE
,
416 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
417 kUseMasks
| kUseAntialiasing
| kUseColorMatrix
);
420 // Tests for render passes forcing shaders for all the blend modes.
421 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassShaders_GL
) {
422 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
423 FILE_PATH_LITERAL("blending_render_pass.png"),
427 TEST_F(LayerTreeHostBlendingPixelTest
, BlendingWithRenderPassShadersAA_GL
) {
428 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
429 FILE_PATH_LITERAL("blending_render_pass.png"),
430 kUseAntialiasing
| kForceShaders
);
433 TEST_F(LayerTreeHostBlendingPixelTest
,
434 BlendingWithRenderPassShadersWithMask_GL
) {
435 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
436 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
437 kUseMasks
| kForceShaders
);
440 TEST_F(LayerTreeHostBlendingPixelTest
,
441 BlendingWithRenderPassShadersWithMask_GL_TextureRect
) {
442 RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW
,
443 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
444 kUseMasks
| kForceShaders
);
447 TEST_F(LayerTreeHostBlendingPixelTest
,
448 BlendingWithRenderPassShadersWithMaskAA_GL
) {
449 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
450 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
451 kUseMasks
| kUseAntialiasing
| kForceShaders
);
454 TEST_F(LayerTreeHostBlendingPixelTest
,
455 BlendingWithRenderPassShadersWithMaskAA_GL_TextureRect
) {
456 RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW
,
457 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
458 kUseMasks
| kUseAntialiasing
| kForceShaders
);
461 TEST_F(LayerTreeHostBlendingPixelTest
,
462 BlendingWithRenderPassShadersColorMatrix_GL
) {
463 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
464 FILE_PATH_LITERAL("blending_render_pass.png"),
465 kUseColorMatrix
| kForceShaders
);
468 TEST_F(LayerTreeHostBlendingPixelTest
,
469 BlendingWithRenderPassShadersColorMatrixAA_GL
) {
470 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
471 FILE_PATH_LITERAL("blending_render_pass.png"),
472 kUseAntialiasing
| kUseColorMatrix
| kForceShaders
);
475 TEST_F(LayerTreeHostBlendingPixelTest
,
476 BlendingWithRenderPassShadersWithMaskColorMatrix_GL
) {
477 RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW
,
478 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
479 kUseMasks
| kUseColorMatrix
| kForceShaders
);
482 TEST_F(LayerTreeHostBlendingPixelTest
,
483 BlendingWithRenderPassShadersWithMaskColorMatrix_GL_TextureRect
) {
484 RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW
,
485 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
486 kUseMasks
| kUseColorMatrix
| kForceShaders
);
489 TEST_F(LayerTreeHostBlendingPixelTest
,
490 BlendingWithRenderPassShadersWithMaskColorMatrixAA_GL
) {
491 RunBlendingWithRenderPass(
492 GL_ASYNC_UPLOAD_2D_DRAW
,
493 FILE_PATH_LITERAL("blending_render_pass_mask.png"),
494 kUseMasks
| kUseAntialiasing
| kUseColorMatrix
| kForceShaders
);