Home | History | Annotate | Download | only in trees
      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