| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkMipMap.h" | 8 #include "SkMipMap.h" |
| 9 #include "SkBitmap.h" | 9 #include "SkBitmap.h" |
| 10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
| 11 | 11 |
| 12 static void downsampleby2_proc32(SkBitmap* dst, int x, int y, | 12 static void downsample32_nocheck(void* dst, int, int, const void* srcPtr, const
SkBitmap& srcBM) { |
| 13 const SkBitmap& src) { | 13 const uint32_t* p = static_cast<const uint32_t*>(srcPtr); |
| 14 const uint32_t* baseP = p; |
| 15 uint32_t c, ag, rb; |
| 16 |
| 17 c = *p; ag = (c >> 8) & 0xFF00FF; rb = c & 0xFF00FF; |
| 18 p += 1; |
| 19 |
| 20 c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF; |
| 21 |
| 22 p = baseP; |
| 23 p += srcBM.rowBytes() >> 2; |
| 24 |
| 25 c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF; |
| 26 p += 1; |
| 27 |
| 28 c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF; |
| 29 |
| 30 *(uint32_t*)dst = ((rb >> 2) & 0xFF00FF) | ((ag << 6) & 0xFF00FF00); |
| 31 } |
| 32 |
| 33 static void downsample32_check(void* dst, int x, int y, const void* srcPtr, cons
t SkBitmap& srcBM) { |
| 34 const uint32_t* p = static_cast<const uint32_t*>(srcPtr); |
| 35 const uint32_t* baseP = p; |
| 36 |
| 14 x <<= 1; | 37 x <<= 1; |
| 15 y <<= 1; | 38 y <<= 1; |
| 16 const SkPMColor* p = src.getAddr32(x, y); | 39 SkASSERT(srcBM.getAddr32(x, y) == p); |
| 17 const SkPMColor* baseP = p; | 40 |
| 18 SkPMColor c, ag, rb; | 41 SkPMColor c, ag, rb; |
| 19 | 42 |
| 20 c = *p; ag = (c >> 8) & 0xFF00FF; rb = c & 0xFF00FF; | 43 c = *p; ag = (c >> 8) & 0xFF00FF; rb = c & 0xFF00FF; |
| 21 if (x < src.width() - 1) { | 44 if (x < srcBM.width() - 1) { |
| 22 p += 1; | 45 p += 1; |
| 23 } | 46 } |
| 24 c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF; | 47 c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF; |
| 25 | 48 |
| 26 p = baseP; | 49 p = baseP; |
| 27 if (y < src.height() - 1) { | 50 if (y < srcBM.height() - 1) { |
| 28 p += src.rowBytes() >> 2; | 51 p += srcBM.rowBytes() >> 2; |
| 29 } | 52 } |
| 30 c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF; | 53 c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF; |
| 31 if (x < src.width() - 1) { | 54 if (x < srcBM.width() - 1) { |
| 32 p += 1; | 55 p += 1; |
| 33 } | 56 } |
| 34 c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF; | 57 c = *p; ag += (c >> 8) & 0xFF00FF; rb += c & 0xFF00FF; |
| 35 | 58 |
| 36 *dst->getAddr32(x >> 1, y >> 1) = | 59 *((uint32_t*)dst) = ((rb >> 2) & 0xFF00FF) | ((ag << 6) & 0xFF00FF00); |
| 37 ((rb >> 2) & 0xFF00FF) | ((ag << 6) & 0xFF00FF00); | |
| 38 } | 60 } |
| 39 | 61 |
| 40 static inline uint32_t expand16(U16CPU c) { | 62 static inline uint32_t expand16(U16CPU c) { |
| 41 return (c & ~SK_G16_MASK_IN_PLACE) | ((c & SK_G16_MASK_IN_PLACE) << 16); | 63 return (c & ~SK_G16_MASK_IN_PLACE) | ((c & SK_G16_MASK_IN_PLACE) << 16); |
| 42 } | 64 } |
| 43 | 65 |
| 44 // returns dirt in the top 16bits, but we don't care, since we only | 66 // returns dirt in the top 16bits, but we don't care, since we only |
| 45 // store the low 16bits. | 67 // store the low 16bits. |
| 46 static inline U16CPU pack16(uint32_t c) { | 68 static inline U16CPU pack16(uint32_t c) { |
| 47 return (c & ~SK_G16_MASK_IN_PLACE) | ((c >> 16) & SK_G16_MASK_IN_PLACE); | 69 return (c & ~SK_G16_MASK_IN_PLACE) | ((c >> 16) & SK_G16_MASK_IN_PLACE); |
| 48 } | 70 } |
| 49 | 71 |
| 50 static void downsampleby2_proc16(SkBitmap* dst, int x, int y, | 72 static void downsample16(void* dst, int x, int y, const void* srcPtr, const SkBi
tmap& srcBM) { |
| 51 const SkBitmap& src) { | 73 const uint16_t* p = static_cast<const uint16_t*>(srcPtr); |
| 74 const uint16_t* baseP = p; |
| 75 |
| 52 x <<= 1; | 76 x <<= 1; |
| 53 y <<= 1; | 77 y <<= 1; |
| 54 const uint16_t* p = src.getAddr16(x, y); | 78 SkASSERT(srcBM.getAddr16(x, y) == p); |
| 55 const uint16_t* baseP = p; | 79 |
| 56 SkPMColor c; | 80 SkPMColor c; |
| 57 | 81 |
| 58 c = expand16(*p); | 82 c = expand16(*p); |
| 59 if (x < src.width() - 1) { | 83 if (x < srcBM.width() - 1) { |
| 60 p += 1; | 84 p += 1; |
| 61 } | 85 } |
| 62 c += expand16(*p); | 86 c += expand16(*p); |
| 63 | 87 |
| 64 p = baseP; | 88 p = baseP; |
| 65 if (y < src.height() - 1) { | 89 if (y < srcBM.height() - 1) { |
| 66 p += src.rowBytes() >> 1; | 90 p += srcBM.rowBytes() >> 1; |
| 67 } | 91 } |
| 68 c += expand16(*p); | 92 c += expand16(*p); |
| 69 if (x < src.width() - 1) { | 93 if (x < srcBM.width() - 1) { |
| 70 p += 1; | 94 p += 1; |
| 71 } | 95 } |
| 72 c += expand16(*p); | 96 c += expand16(*p); |
| 73 | 97 |
| 74 *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)pack16(c >> 2); | 98 *((uint16_t*)dst) = (uint16_t)pack16(c >> 2); |
| 75 } | 99 } |
| 76 | 100 |
| 77 static uint32_t expand4444(U16CPU c) { | 101 static uint32_t expand4444(U16CPU c) { |
| 78 return (c & 0xF0F) | ((c & ~0xF0F) << 12); | 102 return (c & 0xF0F) | ((c & ~0xF0F) << 12); |
| 79 } | 103 } |
| 80 | 104 |
| 81 static U16CPU collaps4444(uint32_t c) { | 105 static U16CPU collaps4444(uint32_t c) { |
| 82 return (c & 0xF0F) | ((c >> 12) & ~0xF0F); | 106 return (c & 0xF0F) | ((c >> 12) & ~0xF0F); |
| 83 } | 107 } |
| 84 | 108 |
| 85 static void downsampleby2_proc4444(SkBitmap* dst, int x, int y, | 109 static void downsample4444(void* dst, int x, int y, const void* srcPtr, const Sk
Bitmap& srcBM) { |
| 86 const SkBitmap& src) { | 110 const uint16_t* p = static_cast<const uint16_t*>(srcPtr); |
| 111 const uint16_t* baseP = p; |
| 112 |
| 87 x <<= 1; | 113 x <<= 1; |
| 88 y <<= 1; | 114 y <<= 1; |
| 89 const uint16_t* p = src.getAddr16(x, y); | 115 SkASSERT(srcBM.getAddr16(x, y) == p); |
| 90 const uint16_t* baseP = p; | 116 |
| 91 uint32_t c; | 117 uint32_t c; |
| 92 | 118 |
| 93 c = expand4444(*p); | 119 c = expand4444(*p); |
| 94 if (x < src.width() - 1) { | 120 if (x < srcBM.width() - 1) { |
| 95 p += 1; | 121 p += 1; |
| 96 } | 122 } |
| 97 c += expand4444(*p); | 123 c += expand4444(*p); |
| 98 | 124 |
| 99 p = baseP; | 125 p = baseP; |
| 100 if (y < src.height() - 1) { | 126 if (y < srcBM.height() - 1) { |
| 101 p += src.rowBytes() >> 1; | 127 p += srcBM.rowBytes() >> 1; |
| 102 } | 128 } |
| 103 c += expand4444(*p); | 129 c += expand4444(*p); |
| 104 if (x < src.width() - 1) { | 130 if (x < srcBM.width() - 1) { |
| 105 p += 1; | 131 p += 1; |
| 106 } | 132 } |
| 107 c += expand4444(*p); | 133 c += expand4444(*p); |
| 108 | 134 |
| 109 *dst->getAddr16(x >> 1, y >> 1) = (uint16_t)collaps4444(c >> 2); | 135 *((uint16_t*)dst) = (uint16_t)collaps4444(c >> 2); |
| 110 } | 136 } |
| 111 | 137 |
| 112 size_t SkMipMap::AllocLevelsSize(int levelCount, size_t pixelSize) { | 138 size_t SkMipMap::AllocLevelsSize(int levelCount, size_t pixelSize) { |
| 113 if (levelCount < 0) { | 139 if (levelCount < 0) { |
| 114 return 0; | 140 return 0; |
| 115 } | 141 } |
| 116 int64_t size = sk_64_mul(levelCount + 1, sizeof(Level)) + pixelSize; | 142 int64_t size = sk_64_mul(levelCount + 1, sizeof(Level)) + pixelSize; |
| 117 if (!sk_64_isS32(size)) { | 143 if (!sk_64_isS32(size)) { |
| 118 return 0; | 144 return 0; |
| 119 } | 145 } |
| 120 return sk_64_asS32(size); | 146 return sk_64_asS32(size); |
| 121 } | 147 } |
| 122 | 148 |
| 149 typedef void SkDownSampleProc(void*, int x, int y, const void* srcPtr, const SkB
itmap& srcBM); |
| 150 |
| 123 SkMipMap* SkMipMap::Build(const SkBitmap& src, SkDiscardableFactoryProc fact) { | 151 SkMipMap* SkMipMap::Build(const SkBitmap& src, SkDiscardableFactoryProc fact) { |
| 124 void (*proc)(SkBitmap* dst, int x, int y, const SkBitmap& src); | 152 SkDownSampleProc* proc_nocheck, *proc_check; |
| 125 | 153 |
| 126 const SkColorType ct = src.colorType(); | 154 const SkColorType ct = src.colorType(); |
| 127 const SkAlphaType at = src.alphaType(); | 155 const SkAlphaType at = src.alphaType(); |
| 128 switch (ct) { | 156 switch (ct) { |
| 129 case kRGBA_8888_SkColorType: | 157 case kRGBA_8888_SkColorType: |
| 130 case kBGRA_8888_SkColorType: | 158 case kBGRA_8888_SkColorType: |
| 131 proc = downsampleby2_proc32; | 159 proc_check = downsample32_check; |
| 160 proc_nocheck = downsample32_nocheck; |
| 132 break; | 161 break; |
| 133 case kRGB_565_SkColorType: | 162 case kRGB_565_SkColorType: |
| 134 proc = downsampleby2_proc16; | 163 proc_check = downsample16; |
| 164 proc_nocheck = proc_check; |
| 135 break; | 165 break; |
| 136 case kARGB_4444_SkColorType: | 166 case kARGB_4444_SkColorType: |
| 137 proc = downsampleby2_proc4444; | 167 proc_check = downsample4444; |
| 168 proc_nocheck = proc_check; |
| 138 break; | 169 break; |
| 139 default: | 170 default: |
| 140 return NULL; // don't build mipmaps for any other colortypes (yet) | 171 return NULL; // don't build mipmaps for any other colortypes (yet) |
| 141 } | 172 } |
| 142 | 173 |
| 143 SkAutoLockPixels alp(src); | 174 SkAutoLockPixels alp(src); |
| 144 if (!src.readyToDraw()) { | 175 if (!src.readyToDraw()) { |
| 145 return NULL; | 176 return NULL; |
| 146 } | 177 } |
| 147 | 178 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 levels[i].fPixels = addr; | 232 levels[i].fPixels = addr; |
| 202 levels[i].fWidth = width; | 233 levels[i].fWidth = width; |
| 203 levels[i].fHeight = height; | 234 levels[i].fHeight = height; |
| 204 levels[i].fRowBytes = rowBytes; | 235 levels[i].fRowBytes = rowBytes; |
| 205 levels[i].fScale = (float)width / src.width(); | 236 levels[i].fScale = (float)width / src.width(); |
| 206 | 237 |
| 207 SkBitmap dstBM; | 238 SkBitmap dstBM; |
| 208 dstBM.installPixels(SkImageInfo::Make(width, height, ct, at), addr, rowB
ytes); | 239 dstBM.installPixels(SkImageInfo::Make(width, height, ct, at), addr, rowB
ytes); |
| 209 | 240 |
| 210 srcBM.lockPixels(); | 241 srcBM.lockPixels(); |
| 211 for (int y = 0; y < height; y++) { | 242 const int widthEven = width & ~1; |
| 243 const int heightEven = height & ~1; |
| 244 const size_t pixelSize = srcBM.info().bytesPerPixel(); |
| 245 |
| 246 const void* srcBasePtr = srcBM.getPixels(); |
| 247 void* dstBasePtr = dstBM.getPixels(); |
| 248 for (int y = 0; y < heightEven; y++) { |
| 249 const void* srcPtr = srcBasePtr; |
| 250 void* dstPtr = dstBasePtr; |
| 251 for (int x = 0; x < widthEven; x++) { |
| 252 proc_nocheck(dstPtr, x, y, srcPtr, srcBM); |
| 253 srcPtr = (char*)srcPtr + pixelSize * 2; |
| 254 dstPtr = (char*)dstPtr + pixelSize; |
| 255 } |
| 256 if (width & 1) { |
| 257 proc_check(dstPtr, widthEven, y, srcPtr, srcBM); |
| 258 } |
| 259 |
| 260 srcBasePtr = (char*)srcBasePtr + srcBM.rowBytes() * 2; |
| 261 dstBasePtr = (char*)dstBasePtr + dstBM.rowBytes(); |
| 262 } |
| 263 if (height & 1) { |
| 264 const void* srcPtr = srcBasePtr; |
| 265 void* dstPtr = dstBasePtr; |
| 212 for (int x = 0; x < width; x++) { | 266 for (int x = 0; x < width; x++) { |
| 213 proc(&dstBM, x, y, srcBM); | 267 proc_check(dstPtr, x, heightEven, srcPtr, srcBM); |
| 268 srcPtr = (char*)srcPtr + pixelSize * 2; |
| 269 dstPtr = (char*)dstPtr + pixelSize; |
| 214 } | 270 } |
| 215 } | 271 } |
| 272 |
| 216 srcBM.unlockPixels(); | 273 srcBM.unlockPixels(); |
| 217 | 274 |
| 218 srcBM = dstBM; | 275 srcBM = dstBM; |
| 219 addr += height * rowBytes; | 276 addr += height * rowBytes; |
| 220 } | 277 } |
| 221 SkASSERT(addr == baseAddr + size); | 278 SkASSERT(addr == baseAddr + size); |
| 222 | 279 |
| 223 return mipmap; | 280 return mipmap; |
| 224 } | 281 } |
| 225 | 282 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 248 } | 305 } |
| 249 | 306 |
| 250 if (level > fCount) { | 307 if (level > fCount) { |
| 251 level = fCount; | 308 level = fCount; |
| 252 } | 309 } |
| 253 if (levelPtr) { | 310 if (levelPtr) { |
| 254 *levelPtr = fLevels[level - 1]; | 311 *levelPtr = fLevels[level - 1]; |
| 255 } | 312 } |
| 256 return true; | 313 return true; |
| 257 } | 314 } |
| OLD | NEW |