Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2013 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkBitmap.h"
      9 #include "SkMipMap.h"
     10 #include "SkRandom.h"
     11 #include "Test.h"
     12 
     13 static void make_bitmap(SkBitmap* bm, int width, int height) {
     14     bm->allocN32Pixels(width, height);
     15     bm->eraseColor(SK_ColorWHITE);
     16 }
     17 
     18 DEF_TEST(MipMap, reporter) {
     19     SkBitmap bm;
     20     SkRandom rand;
     21 
     22     for (int i = 0; i < 500; ++i) {
     23         int width = 1 + rand.nextU() % 1000;
     24         int height = 1 + rand.nextU() % 1000;
     25         make_bitmap(&bm, width, height);
     26         sk_sp<SkMipMap> mm(SkMipMap::Build(bm, SkDestinationSurfaceColorMode::kLegacy, nullptr));
     27 
     28         REPORTER_ASSERT(reporter, mm->countLevels() == SkMipMap::ComputeLevelCount(width, height));
     29         REPORTER_ASSERT(reporter, !mm->extractLevel(SkSize::Make(SK_Scalar1, SK_Scalar1),
     30                                                     nullptr));
     31         REPORTER_ASSERT(reporter, !mm->extractLevel(SkSize::Make(SK_Scalar1 * 2, SK_Scalar1 * 2),
     32                                                     nullptr));
     33 
     34         SkMipMap::Level prevLevel;
     35         sk_bzero(&prevLevel, sizeof(prevLevel));
     36 
     37         SkScalar scale = SK_Scalar1;
     38         for (int j = 0; j < 30; ++j) {
     39             scale = scale * 2 / 3;
     40 
     41             SkMipMap::Level level;
     42             if (mm->extractLevel(SkSize::Make(scale, scale), &level)) {
     43                 REPORTER_ASSERT(reporter, level.fPixmap.addr());
     44                 REPORTER_ASSERT(reporter, level.fPixmap.width() > 0);
     45                 REPORTER_ASSERT(reporter, level.fPixmap.height() > 0);
     46                 REPORTER_ASSERT(reporter, (int)level.fPixmap.rowBytes() >= level.fPixmap.width() * 4);
     47 
     48                 if (prevLevel.fPixmap.addr()) {
     49                     REPORTER_ASSERT(reporter, level.fPixmap.width() <= prevLevel.fPixmap.width());
     50                     REPORTER_ASSERT(reporter, level.fPixmap.height() <= prevLevel.fPixmap.height());
     51                 }
     52                 prevLevel = level;
     53             }
     54         }
     55     }
     56 }
     57 
     58 static void test_mipmap_generation(int width, int height, int expectedMipLevelCount,
     59                                    skiatest::Reporter* reporter) {
     60     SkBitmap bm;
     61     bm.allocN32Pixels(width, height);
     62     bm.eraseColor(SK_ColorWHITE);
     63     sk_sp<SkMipMap> mm(SkMipMap::Build(bm, SkDestinationSurfaceColorMode::kLegacy, nullptr));
     64 
     65     const int mipLevelCount = mm->countLevels();
     66     REPORTER_ASSERT(reporter, mipLevelCount == expectedMipLevelCount);
     67     REPORTER_ASSERT(reporter, mipLevelCount == SkMipMap::ComputeLevelCount(width, height));
     68     for (int i = 0; i < mipLevelCount; ++i) {
     69         SkMipMap::Level level;
     70         REPORTER_ASSERT(reporter, mm->getLevel(i, &level));
     71         // Make sure the mipmaps contain valid data and that the sizes are correct
     72         REPORTER_ASSERT(reporter, level.fPixmap.addr());
     73         SkISize size = SkMipMap::ComputeLevelSize(width, height, i);
     74         REPORTER_ASSERT(reporter, level.fPixmap.width() == size.width());
     75         REPORTER_ASSERT(reporter, level.fPixmap.height() == size.height());
     76 
     77         // + 1 because SkMipMap does not include the base mipmap level.
     78         int twoToTheMipLevel = 1 << (i + 1);
     79         int currentWidth = width / twoToTheMipLevel;
     80         int currentHeight = height / twoToTheMipLevel;
     81         REPORTER_ASSERT(reporter, level.fPixmap.width() == currentWidth);
     82         REPORTER_ASSERT(reporter, level.fPixmap.height() == currentHeight);
     83     }
     84 }
     85 
     86 DEF_TEST(MipMap_DirectLevelAccess, reporter) {
     87     // create mipmap with invalid size
     88     {
     89         // SkMipMap current requires the dimensions be greater than 2x2
     90         SkBitmap bm;
     91         bm.allocN32Pixels(1, 1);
     92         bm.eraseColor(SK_ColorWHITE);
     93         sk_sp<SkMipMap> mm(SkMipMap::Build(bm, SkDestinationSurfaceColorMode::kLegacy, nullptr));
     94 
     95         REPORTER_ASSERT(reporter, mm == nullptr);
     96     }
     97 
     98     // check small mipmap's count and levels
     99     // There should be 5 mipmap levels generated:
    100     // 16x16, 8x8, 4x4, 2x2, 1x1
    101     test_mipmap_generation(32, 32, 5, reporter);
    102 
    103     // check large mipmap's count and levels
    104     // There should be 9 mipmap levels generated:
    105     // 500x500, 250x250, 125x125, 62x62, 31x31, 15x15, 7x7, 3x3, 1x1
    106     test_mipmap_generation(1000, 1000, 9, reporter);
    107 }
    108 
    109 struct LevelCountScenario {
    110     int fWidth;
    111     int fHeight;
    112     int fExpectedLevelCount;
    113 };
    114 
    115 DEF_TEST(MipMap_ComputeLevelCount, reporter) {
    116     const LevelCountScenario tests[] = {
    117         // Test mipmaps with negative sizes
    118         {-100, 100, 0},
    119         {100, -100, 0},
    120         {-100, -100, 0},
    121 
    122         // Test mipmaps with 0, 1, 2 as dimensions
    123         // (SkMipMap::Build requires a min size of 1)
    124         //
    125         // 0
    126         {0, 100, 0},
    127         {100, 0, 0},
    128         {0, 0, 0},
    129         // 1
    130         {1, 100, 6},
    131         {100, 1, 6},
    132         {1, 1, 0},
    133         // 2
    134         {2, 100, 6},
    135         {100, 2, 6},
    136         {2, 2, 1},
    137 
    138         // Test a handful of boundaries such as 63x63 and 64x64
    139         {63, 63, 5},
    140         {64, 64, 6},
    141         {127, 127, 6},
    142         {128, 128, 7},
    143         {255, 255, 7},
    144         {256, 256, 8},
    145 
    146         // Test different dimensions, such as 256x64
    147         {64, 129, 7},
    148         {255, 32, 7},
    149         {500, 1000, 9}
    150     };
    151 
    152     for (auto& currentTest : tests) {
    153         int levelCount = SkMipMap::ComputeLevelCount(currentTest.fWidth, currentTest.fHeight);
    154         REPORTER_ASSERT(reporter, currentTest.fExpectedLevelCount == levelCount);
    155     }
    156 }
    157 
    158 struct LevelSizeScenario {
    159     int fBaseWidth;
    160     int fBaseHeight;
    161     int fLevel;
    162     SkISize fExpectedMipMapLevelSize;
    163 };
    164 
    165 DEF_TEST(MipMap_ComputeLevelSize, reporter) {
    166     const LevelSizeScenario tests[] = {
    167         // Test mipmaps with negative sizes
    168         {-100, 100, 0, SkISize::Make(0, 0)},
    169         {100, -100, 0, SkISize::Make(0, 0)},
    170         {-100, -100, 0, SkISize::Make(0, 0)},
    171 
    172         // Test mipmaps with 0, 1, 2 as dimensions
    173         // (SkMipMap::Build requires a min size of 1)
    174         //
    175         // 0
    176         {0, 100, 0, SkISize::Make(0, 0)},
    177         {100, 0, 0, SkISize::Make(0, 0)},
    178         {0, 0, 0, SkISize::Make(0, 0)},
    179         // 1
    180 
    181         {1, 100, 0, SkISize::Make(1, 50)},
    182         {100, 1, 0, SkISize::Make(50, 1)},
    183         {1, 1, 0, SkISize::Make(0, 0)},
    184         // 2
    185         {2, 100, 0, SkISize::Make(1, 50)},
    186         {100, 2, 1, SkISize::Make(25, 1)},
    187         {2, 2, 0, SkISize::Make(1, 1)},
    188 
    189         // Test a handful of cases
    190         {63, 63, 2, SkISize::Make(7, 7)},
    191         {64, 64, 2, SkISize::Make(8, 8)},
    192         {127, 127, 2, SkISize::Make(15, 15)},
    193         {64, 129, 3, SkISize::Make(4, 8)},
    194         {255, 32, 6, SkISize::Make(1, 1)},
    195         {500, 1000, 1, SkISize::Make(125, 250)},
    196     };
    197 
    198     for (auto& currentTest : tests) {
    199         SkISize levelSize = SkMipMap::ComputeLevelSize(currentTest.fBaseWidth,
    200                                                        currentTest.fBaseHeight,
    201                                                        currentTest.fLevel);
    202         REPORTER_ASSERT(reporter, currentTest.fExpectedMipMapLevelSize == levelSize);
    203     }
    204 }
    205