Home | History | Annotate | Download | only in core
      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 "SkMipMap.h"
      9 #include "SkBitmap.h"
     10 #include "SkColorPriv.h"
     11 
     12 static void downsampleby2_proc32(SkBitmap* dst, int x, int y,
     13                                  const SkBitmap& src) {
     14     x <<= 1;
     15     y <<= 1;
     16     const SkPMColor* p = src.getAddr32(x, y);
     17     const SkPMColor* baseP = p;
     18     SkPMColor c, ag, rb;
     19 
     20     c = *p; ag = (c >> 8) & 0xFF00FF; rb = c & 0xFF00FF;
     21     if (x < src.width() - 1) {
     22         p += 1;
     23     }
     24     c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
     25 
     26     p = baseP;
     27     if (y < src.height() - 1) {
     28         p += src.rowBytes() >> 2;
     29     }
     30     c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
     31     if (x < src.width() - 1) {
     32         p += 1;
     33     }
     34     c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
     35 
     36     *dst->getAddr32(x >> 1, y >> 1) =
     37     ((rb >> 2) & 0xFF00FF) | ((ag << 6) & 0xFF00FF00);
     38 }
     39 
     40 static inline uint32_t expand16(U16CPU c) {
     41     return (c & ~SK_G16_MASK_IN_PLACE) | ((c & SK_G16_MASK_IN_PLACE) << 16);
     42 }
     43 
     44 // returns dirt in the top 16bits, but we don't care, since we only
     45 // store the low 16bits.
     46 static inline U16CPU pack16(uint32_t c) {
     47     return (c & ~SK_G16_MASK_IN_PLACE) | ((c >> 16) & SK_G16_MASK_IN_PLACE);
     48 }
     49 
     50 static void downsampleby2_proc16(SkBitmap* dst, int x, int y,
     51                                  const SkBitmap& src) {
     52     x <<= 1;
     53     y <<= 1;
     54     const uint16_t* p = src.getAddr16(x, y);
     55     const uint16_t* baseP = p;
     56     SkPMColor       c;
     57 
     58     c = expand16(*p);
     59     if (x < src.width() - 1) {
     60         p += 1;
     61     }
     62     c += expand16(*p);
     63 
     64     p = baseP;
     65     if (y < src.height() - 1) {
     66         p += src.rowBytes() >> 1;
     67     }
     68     c += expand16(*p);
     69     if (x < src.width() - 1) {
     70         p += 1;
     71     }
     72     c += expand16(*p);
     73 
     74     *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)pack16(c >> 2);
     75 }
     76 
     77 static uint32_t expand4444(U16CPU c) {
     78     return (c & 0xF0F) | ((c & ~0xF0F) << 12);
     79 }
     80 
     81 static U16CPU collaps4444(uint32_t c) {
     82     return (c & 0xF0F) | ((c >> 12) & ~0xF0F);
     83 }
     84 
     85 static void downsampleby2_proc4444(SkBitmap* dst, int x, int y,
     86                                    const SkBitmap& src) {
     87     x <<= 1;
     88     y <<= 1;
     89     const uint16_t* p = src.getAddr16(x, y);
     90     const uint16_t* baseP = p;
     91     uint32_t        c;
     92 
     93     c = expand4444(*p);
     94     if (x < src.width() - 1) {
     95         p += 1;
     96     }
     97     c += expand4444(*p);
     98 
     99     p = baseP;
    100     if (y < src.height() - 1) {
    101         p += src.rowBytes() >> 1;
    102     }
    103     c += expand4444(*p);
    104     if (x < src.width() - 1) {
    105         p += 1;
    106     }
    107     c += expand4444(*p);
    108 
    109     *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)collaps4444(c >> 2);
    110 }
    111 
    112 SkMipMap::Level* SkMipMap::AllocLevels(int levelCount, size_t pixelSize) {
    113     if (levelCount < 0) {
    114         return NULL;
    115     }
    116     int64_t size = sk_64_mul(levelCount + 1, sizeof(Level)) + pixelSize;
    117     if (!sk_64_isS32(size)) {
    118         return NULL;
    119     }
    120     return (Level*)sk_malloc_throw(sk_64_asS32(size));
    121 }
    122 
    123 SkMipMap* SkMipMap::Build(const SkBitmap& src) {
    124     void (*proc)(SkBitmap* dst, int x, int y, const SkBitmap& src);
    125 
    126     const SkColorType ct = src.colorType();
    127     const SkAlphaType at = src.alphaType();
    128     switch (ct) {
    129         case kRGBA_8888_SkColorType:
    130         case kBGRA_8888_SkColorType:
    131             proc = downsampleby2_proc32;
    132             break;
    133         case kRGB_565_SkColorType:
    134             proc = downsampleby2_proc16;
    135             break;
    136         case kARGB_4444_SkColorType:
    137             proc = downsampleby2_proc4444;
    138             break;
    139         default:
    140             return NULL; // don't build mipmaps for any other colortypes (yet)
    141     }
    142 
    143     SkAutoLockPixels alp(src);
    144     if (!src.readyToDraw()) {
    145         return NULL;
    146     }
    147 
    148     // whip through our loop to compute the exact size needed
    149     size_t  size = 0;
    150     int     countLevels = 0;
    151     {
    152         int width = src.width();
    153         int height = src.height();
    154         for (;;) {
    155             width >>= 1;
    156             height >>= 1;
    157             if (0 == width || 0 == height) {
    158                 break;
    159             }
    160             size += SkColorTypeMinRowBytes(ct, width) * height;
    161             countLevels += 1;
    162         }
    163     }
    164     if (0 == countLevels) {
    165         return NULL;
    166     }
    167 
    168     Level* levels = SkMipMap::AllocLevels(countLevels, size);
    169     if (NULL == levels) {
    170         return NULL;
    171     }
    172 
    173     uint8_t*    baseAddr = (uint8_t*)&levels[countLevels];
    174     uint8_t*    addr = baseAddr;
    175     int         width = src.width();
    176     int         height = src.height();
    177     uint32_t    rowBytes;
    178     SkBitmap    srcBM(src);
    179 
    180     for (int i = 0; i < countLevels; ++i) {
    181         width >>= 1;
    182         height >>= 1;
    183         rowBytes = SkToU32(SkColorTypeMinRowBytes(ct, width));
    184 
    185         levels[i].fPixels   = addr;
    186         levels[i].fWidth    = width;
    187         levels[i].fHeight   = height;
    188         levels[i].fRowBytes = rowBytes;
    189         levels[i].fScale    = (float)width / src.width();
    190 
    191         SkBitmap dstBM;
    192         dstBM.installPixels(SkImageInfo::Make(width, height, ct, at), addr, rowBytes);
    193 
    194         srcBM.lockPixels();
    195         for (int y = 0; y < height; y++) {
    196             for (int x = 0; x < width; x++) {
    197                 proc(&dstBM, x, y, srcBM);
    198             }
    199         }
    200         srcBM.unlockPixels();
    201 
    202         srcBM = dstBM;
    203         addr += height * rowBytes;
    204     }
    205     SkASSERT(addr == baseAddr + size);
    206 
    207     return SkNEW_ARGS(SkMipMap, (levels, countLevels, size));
    208 }
    209 
    210 ///////////////////////////////////////////////////////////////////////////////
    211 
    212 //static int gCounter;
    213 
    214 SkMipMap::SkMipMap(Level* levels, int count, size_t size)
    215     : fSize(size), fLevels(levels), fCount(count) {
    216     SkASSERT(levels);
    217     SkASSERT(count > 0);
    218 //    SkDebugf("mips %d\n", ++gCounter);
    219 }
    220 
    221 SkMipMap::~SkMipMap() {
    222     sk_free(fLevels);
    223 //    SkDebugf("mips %d\n", --gCounter);
    224 }
    225 
    226 static SkFixed compute_level(SkScalar scale) {
    227     SkFixed s = SkAbs32(SkScalarToFixed(SkScalarInvert(scale)));
    228 
    229     if (s < SK_Fixed1) {
    230         return 0;
    231     }
    232     int clz = SkCLZ(s);
    233     SkASSERT(clz >= 1 && clz <= 15);
    234     return SkIntToFixed(15 - clz) + ((unsigned)(s << (clz + 1)) >> 16);
    235 }
    236 
    237 bool SkMipMap::extractLevel(SkScalar scale, Level* levelPtr) const {
    238     if (scale >= SK_Scalar1) {
    239         return false;
    240     }
    241 
    242     int level = compute_level(scale) >> 16;
    243     SkASSERT(level >= 0);
    244     if (level <= 0) {
    245         return false;
    246     }
    247 
    248     if (level > fCount) {
    249         level = fCount;
    250     }
    251     if (levelPtr) {
    252         *levelPtr = fLevels[level - 1];
    253     }
    254     return true;
    255 }
    256