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