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