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