1 /* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkMipMap.h" 9 #include "SkBitmap.h" 10 #include "SkColorData.h" 11 #include "SkHalf.h" 12 #include "SkImageInfoPriv.h" 13 #include "SkMathPriv.h" 14 #include "SkNx.h" 15 #include "SkPM4fPriv.h" 16 #include "SkSRGB.h" 17 #include "SkTypes.h" 18 19 // 20 // ColorTypeFilter is the "Type" we pass to some downsample template functions. 21 // It controls how we expand a pixel into a large type, with space between each component, 22 // so we can then perform our simple filter (either box or triangle) and store the intermediates 23 // in the expanded type. 24 // 25 26 struct ColorTypeFilter_8888 { 27 typedef uint32_t Type; 28 static Sk4h Expand(uint32_t x) { 29 return SkNx_cast<uint16_t>(Sk4b::Load(&x)); 30 } 31 static uint32_t Compact(const Sk4h& x) { 32 uint32_t r; 33 SkNx_cast<uint8_t>(x).store(&r); 34 return r; 35 } 36 }; 37 38 struct ColorTypeFilter_S32 { 39 typedef uint32_t Type; 40 static Sk4h Expand(uint32_t x) { 41 return Sk4h(sk_linear12_from_srgb[(x ) & 0xFF], 42 sk_linear12_from_srgb[(x >> 8) & 0xFF], 43 sk_linear12_from_srgb[(x >> 16) & 0xFF], 44 (x >> 24) << 4); 45 } 46 static uint32_t Compact(const Sk4h& x) { 47 return sk_linear12_to_srgb[x[0]] | 48 sk_linear12_to_srgb[x[1]] << 8 | 49 sk_linear12_to_srgb[x[2]] << 16 | 50 (x[3] >> 4) << 24; 51 } 52 }; 53 54 struct ColorTypeFilter_565 { 55 typedef uint16_t Type; 56 static uint32_t Expand(uint16_t x) { 57 return (x & ~SK_G16_MASK_IN_PLACE) | ((x & SK_G16_MASK_IN_PLACE) << 16); 58 } 59 static uint16_t Compact(uint32_t x) { 60 return (x & ~SK_G16_MASK_IN_PLACE) | ((x >> 16) & SK_G16_MASK_IN_PLACE); 61 } 62 }; 63 64 struct ColorTypeFilter_4444 { 65 typedef uint16_t Type; 66 static uint32_t Expand(uint16_t x) { 67 return (x & 0xF0F) | ((x & ~0xF0F) << 12); 68 } 69 static uint16_t Compact(uint32_t x) { 70 return (x & 0xF0F) | ((x >> 12) & ~0xF0F); 71 } 72 }; 73 74 struct ColorTypeFilter_8 { 75 typedef uint8_t Type; 76 static unsigned Expand(unsigned x) { 77 return x; 78 } 79 static uint8_t Compact(unsigned x) { 80 return (uint8_t)x; 81 } 82 }; 83 84 struct ColorTypeFilter_F16 { 85 typedef uint64_t Type; // SkHalf x4 86 static Sk4f Expand(uint64_t x) { 87 return SkHalfToFloat_finite_ftz(x); 88 } 89 static uint64_t Compact(const Sk4f& x) { 90 uint64_t r; 91 SkFloatToHalf_finite_ftz(x).store(&r); 92 return r; 93 } 94 }; 95 96 template <typename T> T add_121(const T& a, const T& b, const T& c) { 97 return a + b + b + c; 98 } 99 100 template <typename T> T shift_right(const T& x, int bits) { 101 return x >> bits; 102 } 103 104 Sk4f shift_right(const Sk4f& x, int bits) { 105 return x * (1.0f / (1 << bits)); 106 } 107 108 template <typename T> T shift_left(const T& x, int bits) { 109 return x << bits; 110 } 111 112 Sk4f shift_left(const Sk4f& x, int bits) { 113 return x * (1 << bits); 114 } 115 116 // 117 // To produce each mip level, we need to filter down by 1/2 (e.g. 100x100 -> 50,50) 118 // If the starting dimension is odd, we floor the size of the lower level (e.g. 101 -> 50) 119 // In those (odd) cases, we use a triangle filter, with 1-pixel overlap between samplings, 120 // else for even cases, we just use a 2x box filter. 121 // 122 // This produces 4 possible isotropic filters: 2x2 2x3 3x2 3x3 where WxH indicates the number of 123 // src pixels we need to sample in each dimension to produce 1 dst pixel. 124 // 125 // OpenGL expects a full mipmap stack to contain anisotropic space as well. 126 // This means a 100x1 image would continue down to a 50x1 image, 25x1 image... 127 // Because of this, we need 4 more anisotropic filters: 1x2, 1x3, 2x1, 3x1. 128 129 template <typename F> void downsample_1_2(void* dst, const void* src, size_t srcRB, int count) { 130 SkASSERT(count > 0); 131 auto p0 = static_cast<const typename F::Type*>(src); 132 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 133 auto d = static_cast<typename F::Type*>(dst); 134 135 for (int i = 0; i < count; ++i) { 136 auto c00 = F::Expand(p0[0]); 137 auto c10 = F::Expand(p1[0]); 138 139 auto c = c00 + c10; 140 d[i] = F::Compact(shift_right(c, 1)); 141 p0 += 2; 142 p1 += 2; 143 } 144 } 145 146 template <typename F> void downsample_1_3(void* dst, const void* src, size_t srcRB, int count) { 147 SkASSERT(count > 0); 148 auto p0 = static_cast<const typename F::Type*>(src); 149 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 150 auto p2 = (const typename F::Type*)((const char*)p1 + srcRB); 151 auto d = static_cast<typename F::Type*>(dst); 152 153 for (int i = 0; i < count; ++i) { 154 auto c00 = F::Expand(p0[0]); 155 auto c10 = F::Expand(p1[0]); 156 auto c20 = F::Expand(p2[0]); 157 158 auto c = add_121(c00, c10, c20); 159 d[i] = F::Compact(shift_right(c, 2)); 160 p0 += 2; 161 p1 += 2; 162 p2 += 2; 163 } 164 } 165 166 template <typename F> void downsample_2_1(void* dst, const void* src, size_t srcRB, int count) { 167 SkASSERT(count > 0); 168 auto p0 = static_cast<const typename F::Type*>(src); 169 auto d = static_cast<typename F::Type*>(dst); 170 171 for (int i = 0; i < count; ++i) { 172 auto c00 = F::Expand(p0[0]); 173 auto c01 = F::Expand(p0[1]); 174 175 auto c = c00 + c01; 176 d[i] = F::Compact(shift_right(c, 1)); 177 p0 += 2; 178 } 179 } 180 181 template <typename F> void downsample_2_2(void* dst, const void* src, size_t srcRB, int count) { 182 SkASSERT(count > 0); 183 auto p0 = static_cast<const typename F::Type*>(src); 184 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 185 auto d = static_cast<typename F::Type*>(dst); 186 187 for (int i = 0; i < count; ++i) { 188 auto c00 = F::Expand(p0[0]); 189 auto c01 = F::Expand(p0[1]); 190 auto c10 = F::Expand(p1[0]); 191 auto c11 = F::Expand(p1[1]); 192 193 auto c = c00 + c10 + c01 + c11; 194 d[i] = F::Compact(shift_right(c, 2)); 195 p0 += 2; 196 p1 += 2; 197 } 198 } 199 200 template <typename F> void downsample_2_3(void* dst, const void* src, size_t srcRB, int count) { 201 SkASSERT(count > 0); 202 auto p0 = static_cast<const typename F::Type*>(src); 203 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 204 auto p2 = (const typename F::Type*)((const char*)p1 + srcRB); 205 auto d = static_cast<typename F::Type*>(dst); 206 207 for (int i = 0; i < count; ++i) { 208 auto c00 = F::Expand(p0[0]); 209 auto c01 = F::Expand(p0[1]); 210 auto c10 = F::Expand(p1[0]); 211 auto c11 = F::Expand(p1[1]); 212 auto c20 = F::Expand(p2[0]); 213 auto c21 = F::Expand(p2[1]); 214 215 auto c = add_121(c00, c10, c20) + add_121(c01, c11, c21); 216 d[i] = F::Compact(shift_right(c, 3)); 217 p0 += 2; 218 p1 += 2; 219 p2 += 2; 220 } 221 } 222 223 template <typename F> void downsample_3_1(void* dst, const void* src, size_t srcRB, int count) { 224 SkASSERT(count > 0); 225 auto p0 = static_cast<const typename F::Type*>(src); 226 auto d = static_cast<typename F::Type*>(dst); 227 228 auto c02 = F::Expand(p0[0]); 229 for (int i = 0; i < count; ++i) { 230 auto c00 = c02; 231 auto c01 = F::Expand(p0[1]); 232 c02 = F::Expand(p0[2]); 233 234 auto c = add_121(c00, c01, c02); 235 d[i] = F::Compact(shift_right(c, 2)); 236 p0 += 2; 237 } 238 } 239 240 template <typename F> void downsample_3_2(void* dst, const void* src, size_t srcRB, int count) { 241 SkASSERT(count > 0); 242 auto p0 = static_cast<const typename F::Type*>(src); 243 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 244 auto d = static_cast<typename F::Type*>(dst); 245 246 // Given pixels: 247 // a0 b0 c0 d0 e0 ... 248 // a1 b1 c1 d1 e1 ... 249 // We want: 250 // (a0 + 2*b0 + c0 + a1 + 2*b1 + c1) / 8 251 // (c0 + 2*d0 + e0 + c1 + 2*d1 + e1) / 8 252 // ... 253 254 auto c0 = F::Expand(p0[0]); 255 auto c1 = F::Expand(p1[0]); 256 auto c = c0 + c1; 257 for (int i = 0; i < count; ++i) { 258 auto a = c; 259 260 auto b0 = F::Expand(p0[1]); 261 auto b1 = F::Expand(p1[1]); 262 auto b = b0 + b0 + b1 + b1; 263 264 c0 = F::Expand(p0[2]); 265 c1 = F::Expand(p1[2]); 266 c = c0 + c1; 267 268 auto sum = a + b + c; 269 d[i] = F::Compact(shift_right(sum, 3)); 270 p0 += 2; 271 p1 += 2; 272 } 273 } 274 275 template <typename F> void downsample_3_3(void* dst, const void* src, size_t srcRB, int count) { 276 SkASSERT(count > 0); 277 auto p0 = static_cast<const typename F::Type*>(src); 278 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 279 auto p2 = (const typename F::Type*)((const char*)p1 + srcRB); 280 auto d = static_cast<typename F::Type*>(dst); 281 282 // Given pixels: 283 // a0 b0 c0 d0 e0 ... 284 // a1 b1 c1 d1 e1 ... 285 // a2 b2 c2 d2 e2 ... 286 // We want: 287 // (a0 + 2*b0 + c0 + 2*a1 + 4*b1 + 2*c1 + a2 + 2*b2 + c2) / 16 288 // (c0 + 2*d0 + e0 + 2*c1 + 4*d1 + 2*e1 + c2 + 2*d2 + e2) / 16 289 // ... 290 291 auto c0 = F::Expand(p0[0]); 292 auto c1 = F::Expand(p1[0]); 293 auto c2 = F::Expand(p2[0]); 294 auto c = add_121(c0, c1, c2); 295 for (int i = 0; i < count; ++i) { 296 auto a = c; 297 298 auto b0 = F::Expand(p0[1]); 299 auto b1 = F::Expand(p1[1]); 300 auto b2 = F::Expand(p2[1]); 301 auto b = shift_left(add_121(b0, b1, b2), 1); 302 303 c0 = F::Expand(p0[2]); 304 c1 = F::Expand(p1[2]); 305 c2 = F::Expand(p2[2]); 306 c = add_121(c0, c1, c2); 307 308 auto sum = a + b + c; 309 d[i] = F::Compact(shift_right(sum, 4)); 310 p0 += 2; 311 p1 += 2; 312 p2 += 2; 313 } 314 } 315 316 /////////////////////////////////////////////////////////////////////////////////////////////////// 317 318 // Some sRGB specific performance optimizations. 319 320 void downsample_2_2_srgb(void* dst, const void* src, size_t srcRB, int count) { 321 const uint8_t* p0 = ((const uint8_t*) src); 322 const uint8_t* p1 = ((const uint8_t*) src) + srcRB; 323 uint8_t* d = (uint8_t*) dst; 324 325 // Given pixels: 326 // a0 b0 c0 d0 ... 327 // a1 b1 c1 d1 ... 328 // We want: 329 // (a0 + b0 + a1 + b1) / 4 330 // (c0 + d0 + c1 + d1) / 4 331 // ... 332 while (count >= 2) { 333 Sk8h a0c0 = Sk8h(sk_linear12_from_srgb[p0[ 0]], 334 sk_linear12_from_srgb[p0[ 1]], 335 sk_linear12_from_srgb[p0[ 2]], 336 p0[ 3] << 4 , 337 sk_linear12_from_srgb[p0[ 8]], 338 sk_linear12_from_srgb[p0[ 9]], 339 sk_linear12_from_srgb[p0[10]], 340 p0[11] << 4 ); 341 Sk8h b0d0 = Sk8h(sk_linear12_from_srgb[p0[ 4]], 342 sk_linear12_from_srgb[p0[ 5]], 343 sk_linear12_from_srgb[p0[ 6]], 344 p0[ 7] << 4 , 345 sk_linear12_from_srgb[p0[12]], 346 sk_linear12_from_srgb[p0[13]], 347 sk_linear12_from_srgb[p0[14]], 348 p0[15] << 4 ); 349 Sk8h a1c1 = Sk8h(sk_linear12_from_srgb[p1[ 0]], 350 sk_linear12_from_srgb[p1[ 1]], 351 sk_linear12_from_srgb[p1[ 2]], 352 p1[ 3] << 4 , 353 sk_linear12_from_srgb[p1[ 8]], 354 sk_linear12_from_srgb[p1[ 9]], 355 sk_linear12_from_srgb[p1[10]], 356 p1[11] << 4 ); 357 Sk8h b1d1 = Sk8h(sk_linear12_from_srgb[p1[ 4]], 358 sk_linear12_from_srgb[p1[ 5]], 359 sk_linear12_from_srgb[p1[ 6]], 360 p1[ 7] << 4 , 361 sk_linear12_from_srgb[p1[12]], 362 sk_linear12_from_srgb[p1[13]], 363 sk_linear12_from_srgb[p1[14]], 364 p1[15] << 4 ); 365 366 Sk8h avg = (a0c0 + b0d0 + a1c1 + b1d1) >> 2; 367 d[0] = sk_linear12_to_srgb[avg[0]]; 368 d[1] = sk_linear12_to_srgb[avg[1]]; 369 d[2] = sk_linear12_to_srgb[avg[2]]; 370 d[3] = avg[3] >> 4; 371 d[4] = sk_linear12_to_srgb[avg[4]]; 372 d[5] = sk_linear12_to_srgb[avg[5]]; 373 d[6] = sk_linear12_to_srgb[avg[6]]; 374 d[7] = avg[7] >> 4; 375 376 p0 += 16; 377 p1 += 16; 378 d += 8; 379 count -= 2; 380 } 381 382 if (count) { 383 downsample_2_2<ColorTypeFilter_S32>(d, p0, srcRB, count); 384 } 385 } 386 387 void downsample_2_3_srgb(void* dst, const void* src, size_t srcRB, int count) { 388 const uint8_t* p0 = ((const uint8_t*) src); 389 const uint8_t* p1 = p0 + srcRB; 390 const uint8_t* p2 = p1 + srcRB; 391 uint8_t* d = (uint8_t*) dst; 392 393 // Given pixels: 394 // a0 b0 c0 d0 ... 395 // a1 b1 c1 d1 ... 396 // a2 b2 c2 d2 ... 397 // We want: 398 // (a0 + b0 + 2*a1 + 2*b1 + a2 + b2) / 8 399 // (c0 + d0 + 2*c1 + 2*d1 + c2 + d2) / 8 400 // ... 401 while (count >= 2) { 402 Sk8h a0c0 = Sk8h(sk_linear12_from_srgb[p0[ 0]], 403 sk_linear12_from_srgb[p0[ 1]], 404 sk_linear12_from_srgb[p0[ 2]], 405 p0[ 3] << 4 , 406 sk_linear12_from_srgb[p0[ 8]], 407 sk_linear12_from_srgb[p0[ 9]], 408 sk_linear12_from_srgb[p0[10]], 409 p0[11] << 4 ); 410 Sk8h b0d0 = Sk8h(sk_linear12_from_srgb[p0[ 4]], 411 sk_linear12_from_srgb[p0[ 5]], 412 sk_linear12_from_srgb[p0[ 6]], 413 p0[ 7] << 4 , 414 sk_linear12_from_srgb[p0[12]], 415 sk_linear12_from_srgb[p0[13]], 416 sk_linear12_from_srgb[p0[14]], 417 p0[15] << 4 ); 418 Sk8h a1c1 = Sk8h(sk_linear12_from_srgb[p1[ 0]], 419 sk_linear12_from_srgb[p1[ 1]], 420 sk_linear12_from_srgb[p1[ 2]], 421 p1[ 3] << 4 , 422 sk_linear12_from_srgb[p1[ 8]], 423 sk_linear12_from_srgb[p1[ 9]], 424 sk_linear12_from_srgb[p1[10]], 425 p1[11] << 4 ); 426 Sk8h b1d1 = Sk8h(sk_linear12_from_srgb[p1[ 4]], 427 sk_linear12_from_srgb[p1[ 5]], 428 sk_linear12_from_srgb[p1[ 6]], 429 p1[ 7] << 4 , 430 sk_linear12_from_srgb[p1[12]], 431 sk_linear12_from_srgb[p1[13]], 432 sk_linear12_from_srgb[p1[14]], 433 p1[15] << 4 ); 434 Sk8h a2c2 = Sk8h(sk_linear12_from_srgb[p2[ 0]], 435 sk_linear12_from_srgb[p2[ 1]], 436 sk_linear12_from_srgb[p2[ 2]], 437 p2[ 3] << 4 , 438 sk_linear12_from_srgb[p2[ 8]], 439 sk_linear12_from_srgb[p2[ 9]], 440 sk_linear12_from_srgb[p2[10]], 441 p2[11] << 4 ); 442 Sk8h b2d2 = Sk8h(sk_linear12_from_srgb[p2[ 4]], 443 sk_linear12_from_srgb[p2[ 5]], 444 sk_linear12_from_srgb[p2[ 6]], 445 p2[ 7] << 4 , 446 sk_linear12_from_srgb[p2[12]], 447 sk_linear12_from_srgb[p2[13]], 448 sk_linear12_from_srgb[p2[14]], 449 p2[15] << 4 ); 450 451 Sk8h avg = (a0c0 + b0d0 + a1c1 + a1c1 + b1d1 + b1d1 + a2c2 + b2d2) >> 3; 452 d[0] = sk_linear12_to_srgb[avg[0]]; 453 d[1] = sk_linear12_to_srgb[avg[1]]; 454 d[2] = sk_linear12_to_srgb[avg[2]]; 455 d[3] = avg[3] >> 4; 456 d[4] = sk_linear12_to_srgb[avg[4]]; 457 d[5] = sk_linear12_to_srgb[avg[5]]; 458 d[6] = sk_linear12_to_srgb[avg[6]]; 459 d[7] = avg[7] >> 4; 460 461 p0 += 16; 462 p1 += 16; 463 p2 += 16; 464 d += 8; 465 count -= 2; 466 } 467 468 if (count) { 469 downsample_2_3<ColorTypeFilter_S32>(d, p0, srcRB, count); 470 } 471 } 472 473 /////////////////////////////////////////////////////////////////////////////////////////////////// 474 475 size_t SkMipMap::AllocLevelsSize(int levelCount, size_t pixelSize) { 476 if (levelCount < 0) { 477 return 0; 478 } 479 int64_t size = sk_64_mul(levelCount + 1, sizeof(Level)) + pixelSize; 480 if (!sk_64_isS32(size)) { 481 return 0; 482 } 483 return sk_64_asS32(size); 484 } 485 486 SkMipMap* SkMipMap::Build(const SkPixmap& src, SkDestinationSurfaceColorMode colorMode, 487 SkDiscardableFactoryProc fact) { 488 typedef void FilterProc(void*, const void* srcPtr, size_t srcRB, int count); 489 490 FilterProc* proc_1_2 = nullptr; 491 FilterProc* proc_1_3 = nullptr; 492 FilterProc* proc_2_1 = nullptr; 493 FilterProc* proc_2_2 = nullptr; 494 FilterProc* proc_2_3 = nullptr; 495 FilterProc* proc_3_1 = nullptr; 496 FilterProc* proc_3_2 = nullptr; 497 FilterProc* proc_3_3 = nullptr; 498 499 const SkColorType ct = src.colorType(); 500 const SkAlphaType at = src.alphaType(); 501 const bool srgbGamma = (SkDestinationSurfaceColorMode::kGammaAndColorSpaceAware == colorMode) 502 && src.info().gammaCloseToSRGB(); 503 504 switch (ct) { 505 case kRGBA_8888_SkColorType: 506 case kBGRA_8888_SkColorType: 507 if (srgbGamma) { 508 proc_1_2 = downsample_1_2<ColorTypeFilter_S32>; 509 proc_1_3 = downsample_1_3<ColorTypeFilter_S32>; 510 proc_2_1 = downsample_2_1<ColorTypeFilter_S32>; 511 proc_2_2 = downsample_2_2_srgb; 512 proc_2_3 = downsample_2_3_srgb; 513 proc_3_1 = downsample_3_1<ColorTypeFilter_S32>; 514 proc_3_2 = downsample_3_2<ColorTypeFilter_S32>; 515 proc_3_3 = downsample_3_3<ColorTypeFilter_S32>; 516 } else { 517 proc_1_2 = downsample_1_2<ColorTypeFilter_8888>; 518 proc_1_3 = downsample_1_3<ColorTypeFilter_8888>; 519 proc_2_1 = downsample_2_1<ColorTypeFilter_8888>; 520 proc_2_2 = downsample_2_2<ColorTypeFilter_8888>; 521 proc_2_3 = downsample_2_3<ColorTypeFilter_8888>; 522 proc_3_1 = downsample_3_1<ColorTypeFilter_8888>; 523 proc_3_2 = downsample_3_2<ColorTypeFilter_8888>; 524 proc_3_3 = downsample_3_3<ColorTypeFilter_8888>; 525 } 526 break; 527 case kRGB_565_SkColorType: 528 proc_1_2 = downsample_1_2<ColorTypeFilter_565>; 529 proc_1_3 = downsample_1_3<ColorTypeFilter_565>; 530 proc_2_1 = downsample_2_1<ColorTypeFilter_565>; 531 proc_2_2 = downsample_2_2<ColorTypeFilter_565>; 532 proc_2_3 = downsample_2_3<ColorTypeFilter_565>; 533 proc_3_1 = downsample_3_1<ColorTypeFilter_565>; 534 proc_3_2 = downsample_3_2<ColorTypeFilter_565>; 535 proc_3_3 = downsample_3_3<ColorTypeFilter_565>; 536 break; 537 case kARGB_4444_SkColorType: 538 proc_1_2 = downsample_1_2<ColorTypeFilter_4444>; 539 proc_1_3 = downsample_1_3<ColorTypeFilter_4444>; 540 proc_2_1 = downsample_2_1<ColorTypeFilter_4444>; 541 proc_2_2 = downsample_2_2<ColorTypeFilter_4444>; 542 proc_2_3 = downsample_2_3<ColorTypeFilter_4444>; 543 proc_3_1 = downsample_3_1<ColorTypeFilter_4444>; 544 proc_3_2 = downsample_3_2<ColorTypeFilter_4444>; 545 proc_3_3 = downsample_3_3<ColorTypeFilter_4444>; 546 break; 547 case kAlpha_8_SkColorType: 548 case kGray_8_SkColorType: 549 proc_1_2 = downsample_1_2<ColorTypeFilter_8>; 550 proc_1_3 = downsample_1_3<ColorTypeFilter_8>; 551 proc_2_1 = downsample_2_1<ColorTypeFilter_8>; 552 proc_2_2 = downsample_2_2<ColorTypeFilter_8>; 553 proc_2_3 = downsample_2_3<ColorTypeFilter_8>; 554 proc_3_1 = downsample_3_1<ColorTypeFilter_8>; 555 proc_3_2 = downsample_3_2<ColorTypeFilter_8>; 556 proc_3_3 = downsample_3_3<ColorTypeFilter_8>; 557 break; 558 case kRGBA_F16_SkColorType: 559 proc_1_2 = downsample_1_2<ColorTypeFilter_F16>; 560 proc_1_3 = downsample_1_3<ColorTypeFilter_F16>; 561 proc_2_1 = downsample_2_1<ColorTypeFilter_F16>; 562 proc_2_2 = downsample_2_2<ColorTypeFilter_F16>; 563 proc_2_3 = downsample_2_3<ColorTypeFilter_F16>; 564 proc_3_1 = downsample_3_1<ColorTypeFilter_F16>; 565 proc_3_2 = downsample_3_2<ColorTypeFilter_F16>; 566 proc_3_3 = downsample_3_3<ColorTypeFilter_F16>; 567 break; 568 default: 569 // TODO: We could build miplevels for kIndex8 if the levels were in 8888. 570 // Means using more ram, but the quality would be fine. 571 return nullptr; 572 } 573 574 if (src.width() <= 1 && src.height() <= 1) { 575 return nullptr; 576 } 577 // whip through our loop to compute the exact size needed 578 size_t size = 0; 579 int countLevels = ComputeLevelCount(src.width(), src.height()); 580 for (int currentMipLevel = countLevels; currentMipLevel >= 0; currentMipLevel--) { 581 SkISize mipSize = ComputeLevelSize(src.width(), src.height(), currentMipLevel); 582 size += SkColorTypeMinRowBytes(ct, mipSize.fWidth) * mipSize.fHeight; 583 } 584 585 size_t storageSize = SkMipMap::AllocLevelsSize(countLevels, size); 586 if (0 == storageSize) { 587 return nullptr; 588 } 589 590 SkMipMap* mipmap; 591 if (fact) { 592 SkDiscardableMemory* dm = fact(storageSize); 593 if (nullptr == dm) { 594 return nullptr; 595 } 596 mipmap = new SkMipMap(storageSize, dm); 597 } else { 598 mipmap = new SkMipMap(sk_malloc_throw(storageSize), storageSize); 599 } 600 601 // init 602 mipmap->fCS = sk_ref_sp(src.info().colorSpace()); 603 mipmap->fCount = countLevels; 604 mipmap->fLevels = (Level*)mipmap->writable_data(); 605 SkASSERT(mipmap->fLevels); 606 607 Level* levels = mipmap->fLevels; 608 uint8_t* baseAddr = (uint8_t*)&levels[countLevels]; 609 uint8_t* addr = baseAddr; 610 int width = src.width(); 611 int height = src.height(); 612 uint32_t rowBytes; 613 SkPixmap srcPM(src); 614 615 for (int i = 0; i < countLevels; ++i) { 616 FilterProc* proc; 617 if (height & 1) { 618 if (height == 1) { // src-height is 1 619 if (width & 1) { // src-width is 3 620 proc = proc_3_1; 621 } else { // src-width is 2 622 proc = proc_2_1; 623 } 624 } else { // src-height is 3 625 if (width & 1) { 626 if (width == 1) { // src-width is 1 627 proc = proc_1_3; 628 } else { // src-width is 3 629 proc = proc_3_3; 630 } 631 } else { // src-width is 2 632 proc = proc_2_3; 633 } 634 } 635 } else { // src-height is 2 636 if (width & 1) { 637 if (width == 1) { // src-width is 1 638 proc = proc_1_2; 639 } else { // src-width is 3 640 proc = proc_3_2; 641 } 642 } else { // src-width is 2 643 proc = proc_2_2; 644 } 645 } 646 width = SkTMax(1, width >> 1); 647 height = SkTMax(1, height >> 1); 648 rowBytes = SkToU32(SkColorTypeMinRowBytes(ct, width)); 649 650 // We make the Info w/o any colorspace, since that storage is not under our control, and 651 // will not be deleted in a controlled fashion. When the caller is given the pixmap for 652 // a given level, we augment this pixmap with fCS (which we do manage). 653 new (&levels[i].fPixmap) SkPixmap(SkImageInfo::Make(width, height, ct, at), addr, rowBytes); 654 levels[i].fScale = SkSize::Make(SkIntToScalar(width) / src.width(), 655 SkIntToScalar(height) / src.height()); 656 657 const SkPixmap& dstPM = levels[i].fPixmap; 658 const void* srcBasePtr = srcPM.addr(); 659 void* dstBasePtr = dstPM.writable_addr(); 660 661 const size_t srcRB = srcPM.rowBytes(); 662 for (int y = 0; y < height; y++) { 663 proc(dstBasePtr, srcBasePtr, srcRB, width); 664 srcBasePtr = (char*)srcBasePtr + srcRB * 2; // jump two rows 665 dstBasePtr = (char*)dstBasePtr + dstPM.rowBytes(); 666 } 667 srcPM = dstPM; 668 addr += height * rowBytes; 669 } 670 SkASSERT(addr == baseAddr + size); 671 672 SkASSERT(mipmap->fLevels); 673 return mipmap; 674 } 675 676 int SkMipMap::ComputeLevelCount(int baseWidth, int baseHeight) { 677 if (baseWidth < 1 || baseHeight < 1) { 678 return 0; 679 } 680 681 // OpenGL's spec requires that each mipmap level have height/width equal to 682 // max(1, floor(original_height / 2^i) 683 // (or original_width) where i is the mipmap level. 684 // Continue scaling down until both axes are size 1. 685 686 const int largestAxis = SkTMax(baseWidth, baseHeight); 687 if (largestAxis < 2) { 688 // SkMipMap::Build requires a minimum size of 2. 689 return 0; 690 } 691 const int leadingZeros = SkCLZ(static_cast<uint32_t>(largestAxis)); 692 // If the value 00011010 has 3 leading 0s then it has 5 significant bits 693 // (the bits which are not leading zeros) 694 const int significantBits = (sizeof(uint32_t) * 8) - leadingZeros; 695 // This is making the assumption that the size of a byte is 8 bits 696 // and that sizeof(uint32_t)'s implementation-defined behavior is 4. 697 int mipLevelCount = significantBits; 698 699 // SkMipMap does not include the base mip level. 700 // For example, it contains levels 1-x instead of 0-x. 701 // This is because the image used to create SkMipMap is the base level. 702 // So subtract 1 from the mip level count. 703 if (mipLevelCount > 0) { 704 --mipLevelCount; 705 } 706 707 return mipLevelCount; 708 } 709 710 SkISize SkMipMap::ComputeLevelSize(int baseWidth, int baseHeight, int level) { 711 if (baseWidth < 1 || baseHeight < 1) { 712 return SkISize::Make(0, 0); 713 } 714 715 int maxLevelCount = ComputeLevelCount(baseWidth, baseHeight); 716 if (level >= maxLevelCount || level < 0) { 717 return SkISize::Make(0, 0); 718 } 719 // OpenGL's spec requires that each mipmap level have height/width equal to 720 // max(1, floor(original_height / 2^i) 721 // (or original_width) where i is the mipmap level. 722 723 // SkMipMap does not include the base mip level. 724 // For example, it contains levels 1-x instead of 0-x. 725 // This is because the image used to create SkMipMap is the base level. 726 // So subtract 1 from the mip level to get the index stored by SkMipMap. 727 int width = SkTMax(1, baseWidth >> (level + 1)); 728 int height = SkTMax(1, baseHeight >> (level + 1)); 729 730 return SkISize::Make(width, height); 731 } 732 733 /////////////////////////////////////////////////////////////////////////////// 734 735 bool SkMipMap::extractLevel(const SkSize& scaleSize, Level* levelPtr) const { 736 if (nullptr == fLevels) { 737 return false; 738 } 739 740 SkASSERT(scaleSize.width() >= 0 && scaleSize.height() >= 0); 741 742 #ifndef SK_SUPPORT_LEGACY_ANISOTROPIC_MIPMAP_SCALE 743 // Use the smallest scale to match the GPU impl. 744 const SkScalar scale = SkTMin(scaleSize.width(), scaleSize.height()); 745 #else 746 // Ideally we'd pick the smaller scale, to match Ganesh. But ignoring one of the 747 // scales can produce some atrocious results, so for now we use the geometric mean. 748 // (https://bugs.chromium.org/p/skia/issues/detail?id=4863) 749 const SkScalar scale = SkScalarSqrt(scaleSize.width() * scaleSize.height()); 750 #endif 751 752 if (scale >= SK_Scalar1 || scale <= 0 || !SkScalarIsFinite(scale)) { 753 return false; 754 } 755 756 SkScalar L = -SkScalarLog2(scale); 757 if (!SkScalarIsFinite(L)) { 758 return false; 759 } 760 SkASSERT(L >= 0); 761 int level = SkScalarFloorToInt(L); 762 763 SkASSERT(level >= 0); 764 if (level <= 0) { 765 return false; 766 } 767 768 if (level > fCount) { 769 level = fCount; 770 } 771 if (levelPtr) { 772 *levelPtr = fLevels[level - 1]; 773 // need to augment with our colorspace 774 levelPtr->fPixmap.setColorSpace(fCS); 775 } 776 return true; 777 } 778 779 // Helper which extracts a pixmap from the src bitmap 780 // 781 SkMipMap* SkMipMap::Build(const SkBitmap& src, SkDestinationSurfaceColorMode colorMode, 782 SkDiscardableFactoryProc fact) { 783 SkPixmap srcPixmap; 784 if (!src.peekPixels(&srcPixmap)) { 785 return nullptr; 786 } 787 return Build(srcPixmap, colorMode, fact); 788 } 789 790 int SkMipMap::countLevels() const { 791 return fCount; 792 } 793 794 bool SkMipMap::getLevel(int index, Level* levelPtr) const { 795 if (nullptr == fLevels) { 796 return false; 797 } 798 if (index < 0) { 799 return false; 800 } 801 if (index > fCount - 1) { 802 return false; 803 } 804 if (levelPtr) { 805 *levelPtr = fLevels[index]; 806 } 807 return true; 808 } 809