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. 4 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" 11 12 #if !defined(OS_ANDROID) 13 14 namespace cc { 15 namespace { 16 17 class LayerTreeHostFiltersPixelTest : public LayerTreePixelTest {}; 18 19 TEST_F(LayerTreeHostFiltersPixelTest, BackgroundFilterBlur) { 20 scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer( 21 gfx::Rect(200, 200), SK_ColorWHITE); 22 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); 31 32 FilterOperations filters; 33 filters.Append(FilterOperation::CreateBlurFilter(2.f)); 34 blur->SetBackgroundFilters(filters); 35 36 #if defined(OS_WIN) 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, 48 large_error_allowed, 49 small_error_allowed)); 50 #endif 51 52 RunPixelTest(GL_WITH_BITMAP, 53 background, 54 base::FilePath(FILE_PATH_LITERAL("background_filter_blur.png"))); 55 } 56 57 TEST_F(LayerTreeHostFiltersPixelTest, BackgroundFilterBlurOutsets) { 58 scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer( 59 gfx::Rect(200, 200), SK_ColorWHITE); 60 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); 72 73 FilterOperations filters; 74 filters.Append(FilterOperation::CreateBlurFilter(5.f)); 75 blur->SetBackgroundFilters(filters); 76 77 #if defined(OS_WIN) 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, 89 large_error_allowed, 90 small_error_allowed)); 91 #endif 92 93 RunPixelTest(GL_WITH_BITMAP, 94 background, 95 base::FilePath(FILE_PATH_LITERAL( 96 "background_filter_blur_outsets.png"))); 97 } 98 99 TEST_F(LayerTreeHostFiltersPixelTest, BackgroundFilterBlurOffAxis) { 100 scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer( 101 gfx::Rect(200, 200), SK_ColorWHITE); 102 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); 112 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); 120 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); 125 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); 133 134 FilterOperations filters; 135 filters.Append(FilterOperation::CreateBlurFilter(2.f)); 136 blur->SetBackgroundFilters(filters); 137 138 #if defined(OS_WIN) 139 // Windows has 153 pixels off by at most 2: crbug.com/225027 140 float percentage_pixels_large_error = 0.3825f; // 153px / (200*200) 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, 150 large_error_allowed, 151 small_error_allowed)); 152 #endif 153 154 RunPixelTest(GL_WITH_BITMAP, 155 background, 156 base::FilePath(FILE_PATH_LITERAL( 157 "background_filter_blur_off_axis.png"))); 158 } 159 160 class LayerTreeHostFiltersScaledPixelTest 161 : public LayerTreeHostFiltersPixelTest { 162 virtual 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; 165 } 166 167 virtual void SetupTree() OVERRIDE { 168 layer_tree_host()->SetDeviceScaleFactor(device_scale_factor_); 169 LayerTreePixelTest::SetupTree(); 170 } 171 172 protected: 173 void RunPixelTestType(int content_size, 174 float device_scale_factor, 175 PixelTestType test_type) { 176 int half_content = content_size / 2; 177 178 scoped_refptr<SolidColorLayer> root = CreateSolidColorLayer( 179 gfx::Rect(0, 0, content_size, content_size), SK_ColorWHITE); 180 181 scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer( 182 gfx::Rect(0, 0, content_size, content_size), SK_ColorGREEN); 183 root->AddChild(background); 184 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); 189 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); 196 filters.Append( 197 FilterOperation::CreateAlphaThresholdFilter(alpha_region, 1.f, 0.f)); 198 foreground->SetFilters(filters); 199 200 device_scale_factor_ = device_scale_factor; 201 RunPixelTest( 202 test_type, 203 background, 204 base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png"))); 205 } 206 207 float device_scale_factor_; 208 }; 209 210 TEST_F(LayerTreeHostFiltersScaledPixelTest, StandardDpi_GLBitmap) { 211 RunPixelTestType(100, 1.f, GL_WITH_BITMAP); 212 } 213 214 TEST_F(LayerTreeHostFiltersScaledPixelTest, StandardDpi_GLDefault) { 215 RunPixelTestType(100, 1.f, GL_WITH_DEFAULT); 216 } 217 218 TEST_F(LayerTreeHostFiltersScaledPixelTest, StandardDpi_Software) { 219 RunPixelTestType(100, 1.f, SOFTWARE_WITH_BITMAP); 220 } 221 222 TEST_F(LayerTreeHostFiltersScaledPixelTest, HiDpi_GLBitmap) { 223 RunPixelTestType(50, 2.f, GL_WITH_BITMAP); 224 } 225 226 TEST_F(LayerTreeHostFiltersScaledPixelTest, HiDpi_GLDefault) { 227 RunPixelTestType(50, 2.f, GL_WITH_DEFAULT); 228 } 229 230 TEST_F(LayerTreeHostFiltersScaledPixelTest, HiDpi_Software) { 231 RunPixelTestType(50, 2.f, SOFTWARE_WITH_BITMAP); 232 } 233 234 class ImageFilterClippedPixelTest : public LayerTreeHostFiltersPixelTest { 235 protected: 236 void RunPixelTestType(PixelTestType test_type) { 237 scoped_refptr<SolidColorLayer> root = 238 CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorBLACK); 239 240 scoped_refptr<SolidColorLayer> background = 241 CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorYELLOW); 242 root->AddChild(background); 243 244 scoped_refptr<SolidColorLayer> foreground = 245 CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorRED); 246 background->AddChild(foreground); 247 248 SkScalar matrix[20]; 249 memset(matrix, 0, 20 * sizeof(matrix[0])); 250 // This filter does a red-blue swap, so the foreground becomes blue. 251 matrix[2] = matrix[6] = matrix[10] = matrix[18] = SK_Scalar1; 252 skia::RefPtr<SkColorFilter> colorFilter( 253 skia::AdoptRef(SkColorMatrixFilter::Create(matrix))); 254 // We filter only the bottom 200x100 pixels of the foreground. 255 SkImageFilter::CropRect crop_rect(SkRect::MakeXYWH(0, 100, 200, 100)); 256 skia::RefPtr<SkImageFilter> filter = skia::AdoptRef( 257 SkColorFilterImageFilter::Create(colorFilter.get(), NULL, &crop_rect)); 258 FilterOperations filters; 259 filters.Append(FilterOperation::CreateReferenceFilter(filter)); 260 261 // Make the foreground layer's render surface be clipped by the background 262 // layer. 263 background->SetMasksToBounds(true); 264 foreground->SetFilters(filters); 265 266 // Then we translate the foreground up by 100 pixels in Y, so the cropped 267 // region is moved to to the top. This ensures that the crop rect is being 268 // correctly transformed in skia by the amount of clipping that the 269 // compositor performs. 270 gfx::Transform transform; 271 transform.Translate(0.0, -100.0); 272 foreground->SetTransform(transform); 273 274 RunPixelTest(test_type, 275 background, 276 base::FilePath(FILE_PATH_LITERAL("blue_yellow.png"))); 277 } 278 }; 279 280 TEST_F(ImageFilterClippedPixelTest, ImageFilterClipped_GL) { 281 RunPixelTestType(GL_WITH_BITMAP); 282 } 283 284 TEST_F(ImageFilterClippedPixelTest, ImageFilterClipped_Software) { 285 RunPixelTestType(SOFTWARE_WITH_BITMAP); 286 } 287 288 } // namespace 289 } // namespace cc 290 291 #endif // OS_ANDROID 292