158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger/*
258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * Copyright 2013 Google Inc.
358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger *
458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * found in the LICENSE file.
658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger */
758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "SkMipMap.h"
958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "SkBitmap.h"
1058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#include "SkColorPriv.h"
1158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
1258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic void downsampleby2_proc32(SkBitmap* dst, int x, int y,
1358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                                 const SkBitmap& src) {
1458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    x <<= 1;
1558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    y <<= 1;
1658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    const SkPMColor* p = src.getAddr32(x, y);
1758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    const SkPMColor* baseP = p;
1858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkPMColor c, ag, rb;
1958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
2058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    c = *p; ag = (c >> 8) & 0xFF00FF; rb = c & 0xFF00FF;
2158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (x < src.width() - 1) {
2258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        p += 1;
2358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
2458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
2558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
2658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    p = baseP;
2758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (y < src.height() - 1) {
2858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        p += src.rowBytes() >> 2;
2958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
3058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
3158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (x < src.width() - 1) {
3258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        p += 1;
3358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
3458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF;
3558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
3658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    *dst->getAddr32(x >> 1, y >> 1) =
3758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    ((rb >> 2) & 0xFF00FF) | ((ag << 6) & 0xFF00FF00);
3858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
3958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
4058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic inline uint32_t expand16(U16CPU c) {
4158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return (c & ~SK_G16_MASK_IN_PLACE) | ((c & SK_G16_MASK_IN_PLACE) << 16);
4258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
4358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
4458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger// returns dirt in the top 16bits, but we don't care, since we only
4558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger// store the low 16bits.
4658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic inline U16CPU pack16(uint32_t c) {
4758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return (c & ~SK_G16_MASK_IN_PLACE) | ((c >> 16) & SK_G16_MASK_IN_PLACE);
4858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
4958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
5058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic void downsampleby2_proc16(SkBitmap* dst, int x, int y,
5158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                                 const SkBitmap& src) {
5258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    x <<= 1;
5358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    y <<= 1;
5458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    const uint16_t* p = src.getAddr16(x, y);
5558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    const uint16_t* baseP = p;
5658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkPMColor       c;
5758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
5858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    c = expand16(*p);
5958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (x < src.width() - 1) {
6058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        p += 1;
6158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
6258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    c += expand16(*p);
6358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
6458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    p = baseP;
6558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (y < src.height() - 1) {
6658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        p += src.rowBytes() >> 1;
6758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
6858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    c += expand16(*p);
6958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (x < src.width() - 1) {
7058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        p += 1;
7158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
7258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    c += expand16(*p);
7358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
7458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)pack16(c >> 2);
7558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
7658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
7758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic uint32_t expand4444(U16CPU c) {
7858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return (c & 0xF0F) | ((c & ~0xF0F) << 12);
7958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
8058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
8158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic U16CPU collaps4444(uint32_t c) {
8258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return (c & 0xF0F) | ((c >> 12) & ~0xF0F);
8358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
8458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
8558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic void downsampleby2_proc4444(SkBitmap* dst, int x, int y,
8658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                                   const SkBitmap& src) {
8758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    x <<= 1;
8858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    y <<= 1;
8958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    const uint16_t* p = src.getAddr16(x, y);
9058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    const uint16_t* baseP = p;
9158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    uint32_t        c;
9258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
9358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    c = expand4444(*p);
9458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (x < src.width() - 1) {
9558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        p += 1;
9658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
9758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    c += expand4444(*p);
9858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
9958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    p = baseP;
10058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (y < src.height() - 1) {
10158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        p += src.rowBytes() >> 1;
10258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
10358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    c += expand4444(*p);
10458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (x < src.width() - 1) {
10558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        p += 1;
10658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
10758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    c += expand4444(*p);
10858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
10958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)collaps4444(c >> 2);
11058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
11158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
11258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic bool isPos32Bits(const Sk64& value) {
11358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return !value.isNeg() && value.is32();
11458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
11558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
11658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek SollenbergerSkMipMap::Level* SkMipMap::AllocLevels(int levelCount, size_t pixelSize) {
11758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (levelCount < 0) {
11858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return NULL;
11958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
12058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    Sk64 size;
12158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    size.setMul(levelCount + 1, sizeof(Level));
12258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    size.add(SkToS32(pixelSize));
12358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (!isPos32Bits(size)) {
12458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return NULL;
12558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
12658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return (Level*)sk_malloc_throw(size.get32());
12758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
12858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
12958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek SollenbergerSkMipMap* SkMipMap::Build(const SkBitmap& src) {
13058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    void (*proc)(SkBitmap* dst, int x, int y, const SkBitmap& src);
13158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
1320a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    const SkBitmap::Config config = src.config();
13358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    switch (config) {
13458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        case SkBitmap::kARGB_8888_Config:
13558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            proc = downsampleby2_proc32;
13658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            break;
13758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        case SkBitmap::kRGB_565_Config:
13858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            proc = downsampleby2_proc16;
13958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            break;
14058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        case SkBitmap::kARGB_4444_Config:
14158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            proc = downsampleby2_proc4444;
14258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            break;
14358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        case SkBitmap::kIndex8_Config:
14458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        case SkBitmap::kA8_Config:
14558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        default:
14658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            return NULL; // don't build mipmaps for these configs
14758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
14858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
14958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkAutoLockPixels alp(src);
15058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (!src.readyToDraw()) {
15158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return NULL;
15258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
15358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
15458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    // whip through our loop to compute the exact size needed
15558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    size_t  size = 0;
15658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    int     countLevels = 0;
15758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    {
15858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        int width = src.width();
15958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        int height = src.height();
16058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        for (;;) {
16158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            width >>= 1;
16258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            height >>= 1;
16358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            if (0 == width || 0 == height) {
16458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                break;
16558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            }
16658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            size += SkBitmap::ComputeRowBytes(config, width) * height;
16758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            countLevels += 1;
16858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
16958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
17058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (0 == countLevels) {
17158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return NULL;
17258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
17358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
17458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    Level* levels = SkMipMap::AllocLevels(countLevels, size);
17558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (NULL == levels) {
17658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return NULL;
17758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
17858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
17958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    uint8_t*    baseAddr = (uint8_t*)&levels[countLevels];
18058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    uint8_t*    addr = baseAddr;
18158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    int         width = src.width();
18258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    int         height = src.height();
18358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    uint32_t    rowBytes;
18458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkBitmap    srcBM(src);
18558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
18658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    for (int i = 0; i < countLevels; ++i) {
18758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        width >>= 1;
18858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        height >>= 1;
18958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        rowBytes = SkToU32(SkBitmap::ComputeRowBytes(config, width));
19058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
19158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        levels[i].fPixels   = addr;
19258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        levels[i].fWidth    = width;
19358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        levels[i].fHeight   = height;
19458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        levels[i].fRowBytes = rowBytes;
19558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        levels[i].fScale    = (float)width / src.width();
19658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
19758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        SkBitmap dstBM;
19858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        dstBM.setConfig(config, width, height, rowBytes);
19958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        dstBM.setPixels(addr);
20058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
20158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        srcBM.lockPixels();
20258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        for (int y = 0; y < height; y++) {
20358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            for (int x = 0; x < width; x++) {
20458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                proc(&dstBM, x, y, srcBM);
20558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            }
20658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        }
20758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        srcBM.unlockPixels();
20858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
20958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        srcBM = dstBM;
21058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        addr += height * rowBytes;
21158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
21258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkASSERT(addr == baseAddr + size);
21358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
21458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return SkNEW_ARGS(SkMipMap, (levels, countLevels, size));
21558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
21658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
21758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
21858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
21958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger//static int gCounter;
22058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
22158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek SollenbergerSkMipMap::SkMipMap(Level* levels, int count, size_t size)
22258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    : fSize(size), fLevels(levels), fCount(count) {
22358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkASSERT(levels);
22458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkASSERT(count > 0);
22558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger//    SkDebugf("mips %d\n", ++gCounter);
22658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
22758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
22858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek SollenbergerSkMipMap::~SkMipMap() {
22958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    sk_free(fLevels);
23058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger//    SkDebugf("mips %d\n", --gCounter);
23158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
23258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
23358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic SkFixed compute_level(SkScalar scale) {
23458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkFixed s = SkAbs32(SkScalarToFixed(SkScalarInvert(scale)));
23558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
23658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (s < SK_Fixed1) {
23758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return 0;
23858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
23958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    int clz = SkCLZ(s);
24058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkASSERT(clz >= 1 && clz <= 15);
24158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return SkIntToFixed(15 - clz) + ((unsigned)(s << (clz + 1)) >> 16);
24258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
24358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
24458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerbool SkMipMap::extractLevel(SkScalar scale, Level* levelPtr) const {
24558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (scale >= SK_Scalar1) {
24658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return false;
24758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
24858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
24958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    int level = compute_level(scale) >> 16;
25058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    SkASSERT(level >= 0);
25158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (level <= 0) {
25258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        return false;
25358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
25458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
25558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (level > fCount) {
25658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        level = fCount;
25758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
25858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    if (levelPtr) {
25958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger        *levelPtr = fLevels[level - 1];
26058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    }
26158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return true;
26258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}
263