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 |