SkMipMap.cpp revision 1817d282cda17cb8c2db0ac6fdc937743c026016
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 "SkColorPriv.h" 11#include "SkHalf.h" 12#include "SkMath.h" 13#include "SkNx.h" 14#include "SkTypes.h" 15 16// 17// ColorTypeFilter is the "Type" we pass to some downsample template functions. 18// It controls how we expand a pixel into a large type, with space between each component, 19// so we can then perform our simple filter (either box or triangle) and store the intermediates 20// in the expanded type. 21// 22 23struct ColorTypeFilter_8888 { 24 typedef uint32_t Type; 25#if defined(SKNX_IS_FAST) 26 static Sk4h Expand(uint32_t x) { 27 return SkNx_cast<uint16_t>(Sk4b::Load(&x)); 28 } 29 static uint32_t Compact(const Sk4h& x) { 30 uint32_t r; 31 SkNx_cast<uint8_t>(x).store(&r); 32 return r; 33 } 34#else 35 static uint64_t Expand(uint32_t x) { 36 return (x & 0xFF00FF) | ((uint64_t)(x & 0xFF00FF00) << 24); 37 } 38 static uint32_t Compact(uint64_t x) { 39 return (uint32_t)((x & 0xFF00FF) | ((x >> 24) & 0xFF00FF00)); 40 } 41#endif 42}; 43 44struct ColorTypeFilter_565 { 45 typedef uint16_t Type; 46 static uint32_t Expand(uint16_t x) { 47 return (x & ~SK_G16_MASK_IN_PLACE) | ((x & SK_G16_MASK_IN_PLACE) << 16); 48 } 49 static uint16_t Compact(uint32_t x) { 50 return (x & ~SK_G16_MASK_IN_PLACE) | ((x >> 16) & SK_G16_MASK_IN_PLACE); 51 } 52}; 53 54struct ColorTypeFilter_4444 { 55 typedef uint16_t Type; 56 static uint32_t Expand(uint16_t x) { 57 return (x & 0xF0F) | ((x & ~0xF0F) << 12); 58 } 59 static uint16_t Compact(uint32_t x) { 60 return (x & 0xF0F) | ((x >> 12) & ~0xF0F); 61 } 62}; 63 64struct ColorTypeFilter_8 { 65 typedef uint8_t Type; 66 static unsigned Expand(unsigned x) { 67 return x; 68 } 69 static uint8_t Compact(unsigned x) { 70 return (uint8_t)x; 71 } 72}; 73 74struct ColorTypeFilter_F16 { 75 typedef uint64_t Type; // SkHalf x4 76 static Sk4f Expand(uint64_t x) { 77 return SkHalfToFloat_01(x); 78 } 79 static uint64_t Compact(const Sk4f& x) { 80 return SkFloatToHalf_01(x); 81 } 82}; 83 84template <typename T> T add_121(const T& a, const T& b, const T& c) { 85 return a + b + b + c; 86} 87 88template <typename T> T shift_right(const T& x, int bits) { 89 return x >> bits; 90} 91 92Sk4f shift_right(const Sk4f& x, int bits) { 93 return x * (1.0f / (1 << bits)); 94} 95 96template <typename T> T shift_left(const T& x, int bits) { 97 return x << bits; 98} 99 100Sk4f shift_left(const Sk4f& x, int bits) { 101 return x * (1 << bits); 102} 103 104// 105// To produce each mip level, we need to filter down by 1/2 (e.g. 100x100 -> 50,50) 106// If the starting dimension is odd, we floor the size of the lower level (e.g. 101 -> 50) 107// In those (odd) cases, we use a triangle filter, with 1-pixel overlap between samplings, 108// else for even cases, we just use a 2x box filter. 109// 110// This produces 4 possible isotropic filters: 2x2 2x3 3x2 3x3 where WxH indicates the number of 111// src pixels we need to sample in each dimension to produce 1 dst pixel. 112// 113// OpenGL expects a full mipmap stack to contain anisotropic space as well. 114// This means a 100x1 image would continue down to a 50x1 image, 25x1 image... 115// Because of this, we need 4 more anisotropic filters: 1x2, 1x3, 2x1, 3x1. 116 117template <typename F> void downsample_1_2(void* dst, const void* src, size_t srcRB, int count) { 118 SkASSERT(count > 0); 119 auto p0 = static_cast<const typename F::Type*>(src); 120 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 121 auto d = static_cast<typename F::Type*>(dst); 122 123 for (int i = 0; i < count; ++i) { 124 auto c00 = F::Expand(p0[0]); 125 auto c10 = F::Expand(p1[0]); 126 127 auto c = c00 + c10; 128 d[i] = F::Compact(shift_right(c, 1)); 129 p0 += 2; 130 p1 += 2; 131 } 132} 133 134template <typename F> void downsample_1_3(void* dst, const void* src, size_t srcRB, int count) { 135 SkASSERT(count > 0); 136 auto p0 = static_cast<const typename F::Type*>(src); 137 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 138 auto p2 = (const typename F::Type*)((const char*)p1 + srcRB); 139 auto d = static_cast<typename F::Type*>(dst); 140 141 for (int i = 0; i < count; ++i) { 142 auto c00 = F::Expand(p0[0]); 143 auto c10 = F::Expand(p1[0]); 144 auto c20 = F::Expand(p2[0]); 145 146 auto c = add_121(c00, c10, c20); 147 d[i] = F::Compact(shift_right(c, 2)); 148 p0 += 2; 149 p1 += 2; 150 p2 += 2; 151 } 152} 153 154template <typename F> void downsample_2_1(void* dst, const void* src, size_t srcRB, int count) { 155 SkASSERT(count > 0); 156 auto p0 = static_cast<const typename F::Type*>(src); 157 auto d = static_cast<typename F::Type*>(dst); 158 159 for (int i = 0; i < count; ++i) { 160 auto c00 = F::Expand(p0[0]); 161 auto c01 = F::Expand(p0[1]); 162 163 auto c = c00 + c01; 164 d[i] = F::Compact(shift_right(c, 1)); 165 p0 += 2; 166 } 167} 168 169template <typename F> void downsample_2_2(void* dst, const void* src, size_t srcRB, int count) { 170 SkASSERT(count > 0); 171 auto p0 = static_cast<const typename F::Type*>(src); 172 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 173 auto d = static_cast<typename F::Type*>(dst); 174 175 for (int i = 0; i < count; ++i) { 176 auto c00 = F::Expand(p0[0]); 177 auto c01 = F::Expand(p0[1]); 178 auto c10 = F::Expand(p1[0]); 179 auto c11 = F::Expand(p1[1]); 180 181 auto c = c00 + c10 + c01 + c11; 182 d[i] = F::Compact(shift_right(c, 2)); 183 p0 += 2; 184 p1 += 2; 185 } 186} 187 188template <typename F> void downsample_2_3(void* dst, const void* src, size_t srcRB, int count) { 189 SkASSERT(count > 0); 190 auto p0 = static_cast<const typename F::Type*>(src); 191 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 192 auto p2 = (const typename F::Type*)((const char*)p1 + srcRB); 193 auto d = static_cast<typename F::Type*>(dst); 194 195 for (int i = 0; i < count; ++i) { 196 auto c00 = F::Expand(p0[0]); 197 auto c01 = F::Expand(p0[1]); 198 auto c10 = F::Expand(p1[0]); 199 auto c11 = F::Expand(p1[1]); 200 auto c20 = F::Expand(p2[0]); 201 auto c21 = F::Expand(p2[1]); 202 203 auto c = add_121(c00, c10, c20) + add_121(c01, c11, c21); 204 d[i] = F::Compact(shift_right(c, 3)); 205 p0 += 2; 206 p1 += 2; 207 p2 += 2; 208 } 209} 210 211template <typename F> void downsample_3_1(void* dst, const void* src, size_t srcRB, int count) { 212 SkASSERT(count > 0); 213 auto p0 = static_cast<const typename F::Type*>(src); 214 auto d = static_cast<typename F::Type*>(dst); 215 216 auto c02 = F::Expand(p0[0]); 217 for (int i = 0; i < count; ++i) { 218 auto c00 = c02; 219 auto c01 = F::Expand(p0[1]); 220 c02 = F::Expand(p0[2]); 221 222 auto c = add_121(c00, c01, c02); 223 d[i] = F::Compact(shift_right(c, 2)); 224 p0 += 2; 225 } 226} 227 228template <typename F> void downsample_3_2(void* dst, const void* src, size_t srcRB, int count) { 229 SkASSERT(count > 0); 230 auto p0 = static_cast<const typename F::Type*>(src); 231 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 232 auto d = static_cast<typename F::Type*>(dst); 233 234 auto c02 = F::Expand(p0[0]); 235 auto c12 = F::Expand(p1[0]); 236 for (int i = 0; i < count; ++i) { 237 auto c00 = c02; 238 auto c01 = F::Expand(p0[1]); 239 c02 = F::Expand(p0[2]); 240 auto c10 = c12; 241 auto c11 = F::Expand(p1[1]); 242 c12 = F::Expand(p1[2]); 243 244 auto c = add_121(c00, c01, c02) + add_121(c10, c11, c12); 245 d[i] = F::Compact(shift_right(c, 3)); 246 p0 += 2; 247 p1 += 2; 248 } 249} 250 251template <typename F> void downsample_3_3(void* dst, const void* src, size_t srcRB, int count) { 252 SkASSERT(count > 0); 253 auto p0 = static_cast<const typename F::Type*>(src); 254 auto p1 = (const typename F::Type*)((const char*)p0 + srcRB); 255 auto p2 = (const typename F::Type*)((const char*)p1 + srcRB); 256 auto d = static_cast<typename F::Type*>(dst); 257 258 auto c02 = F::Expand(p0[0]); 259 auto c12 = F::Expand(p1[0]); 260 auto c22 = F::Expand(p2[0]); 261 for (int i = 0; i < count; ++i) { 262 auto c00 = c02; 263 auto c01 = F::Expand(p0[1]); 264 c02 = F::Expand(p0[2]); 265 auto c10 = c12; 266 auto c11 = F::Expand(p1[1]); 267 c12 = F::Expand(p1[2]); 268 auto c20 = c22; 269 auto c21 = F::Expand(p2[1]); 270 c22 = F::Expand(p2[2]); 271 272 auto c = 273 add_121(c00, c01, c02) + 274 shift_left(add_121(c10, c11, c12), 1) + 275 add_121(c20, c21, c22); 276 d[i] = F::Compact(shift_right(c, 4)); 277 p0 += 2; 278 p1 += 2; 279 p2 += 2; 280 } 281} 282 283/////////////////////////////////////////////////////////////////////////////////////////////////// 284 285size_t SkMipMap::AllocLevelsSize(int levelCount, size_t pixelSize) { 286 if (levelCount < 0) { 287 return 0; 288 } 289 int64_t size = sk_64_mul(levelCount + 1, sizeof(Level)) + pixelSize; 290 if (!sk_64_isS32(size)) { 291 return 0; 292 } 293 return sk_64_asS32(size); 294} 295 296SkMipMap* SkMipMap::Build(const SkPixmap& src, SkDiscardableFactoryProc fact) { 297 typedef void FilterProc(void*, const void* srcPtr, size_t srcRB, int count); 298 299 FilterProc* proc_1_2 = nullptr; 300 FilterProc* proc_1_3 = nullptr; 301 FilterProc* proc_2_1 = nullptr; 302 FilterProc* proc_2_2 = nullptr; 303 FilterProc* proc_2_3 = nullptr; 304 FilterProc* proc_3_1 = nullptr; 305 FilterProc* proc_3_2 = nullptr; 306 FilterProc* proc_3_3 = nullptr; 307 308 const SkColorType ct = src.colorType(); 309 const SkAlphaType at = src.alphaType(); 310 switch (ct) { 311 case kRGBA_8888_SkColorType: 312 case kBGRA_8888_SkColorType: 313 proc_1_2 = downsample_1_2<ColorTypeFilter_8888>; 314 proc_1_3 = downsample_1_3<ColorTypeFilter_8888>; 315 proc_2_1 = downsample_2_1<ColorTypeFilter_8888>; 316 proc_2_2 = downsample_2_2<ColorTypeFilter_8888>; 317 proc_2_3 = downsample_2_3<ColorTypeFilter_8888>; 318 proc_3_1 = downsample_3_1<ColorTypeFilter_8888>; 319 proc_3_2 = downsample_3_2<ColorTypeFilter_8888>; 320 proc_3_3 = downsample_3_3<ColorTypeFilter_8888>; 321 break; 322 case kRGB_565_SkColorType: 323 proc_1_2 = downsample_1_2<ColorTypeFilter_565>; 324 proc_1_3 = downsample_1_3<ColorTypeFilter_565>; 325 proc_2_1 = downsample_2_1<ColorTypeFilter_565>; 326 proc_2_2 = downsample_2_2<ColorTypeFilter_565>; 327 proc_2_3 = downsample_2_3<ColorTypeFilter_565>; 328 proc_3_1 = downsample_3_1<ColorTypeFilter_565>; 329 proc_3_2 = downsample_3_2<ColorTypeFilter_565>; 330 proc_3_3 = downsample_3_3<ColorTypeFilter_565>; 331 break; 332 case kARGB_4444_SkColorType: 333 proc_1_2 = downsample_1_2<ColorTypeFilter_4444>; 334 proc_1_3 = downsample_1_3<ColorTypeFilter_4444>; 335 proc_2_1 = downsample_2_1<ColorTypeFilter_4444>; 336 proc_2_2 = downsample_2_2<ColorTypeFilter_4444>; 337 proc_2_3 = downsample_2_3<ColorTypeFilter_4444>; 338 proc_3_1 = downsample_3_1<ColorTypeFilter_4444>; 339 proc_3_2 = downsample_3_2<ColorTypeFilter_4444>; 340 proc_3_3 = downsample_3_3<ColorTypeFilter_4444>; 341 break; 342 case kAlpha_8_SkColorType: 343 case kGray_8_SkColorType: 344 proc_1_2 = downsample_1_2<ColorTypeFilter_8>; 345 proc_1_3 = downsample_1_3<ColorTypeFilter_8>; 346 proc_2_1 = downsample_2_1<ColorTypeFilter_8>; 347 proc_2_2 = downsample_2_2<ColorTypeFilter_8>; 348 proc_2_3 = downsample_2_3<ColorTypeFilter_8>; 349 proc_3_1 = downsample_3_1<ColorTypeFilter_8>; 350 proc_3_2 = downsample_3_2<ColorTypeFilter_8>; 351 proc_3_3 = downsample_3_3<ColorTypeFilter_8>; 352 break; 353 case kRGBA_F16_SkColorType: 354 proc_1_2 = downsample_1_2<ColorTypeFilter_F16>; 355 proc_1_3 = downsample_1_3<ColorTypeFilter_F16>; 356 proc_2_1 = downsample_2_1<ColorTypeFilter_F16>; 357 proc_2_2 = downsample_2_2<ColorTypeFilter_F16>; 358 proc_2_3 = downsample_2_3<ColorTypeFilter_F16>; 359 proc_3_1 = downsample_3_1<ColorTypeFilter_F16>; 360 proc_3_2 = downsample_3_2<ColorTypeFilter_F16>; 361 proc_3_3 = downsample_3_3<ColorTypeFilter_F16>; 362 break; 363 default: 364 // TODO: We could build miplevels for kIndex8 if the levels were in 8888. 365 // Means using more ram, but the quality would be fine. 366 return nullptr; 367 } 368 369 if (src.width() <= 1 && src.height() <= 1) { 370 return nullptr; 371 } 372 // whip through our loop to compute the exact size needed 373 size_t size = 0; 374 int countLevels = 0; 375 { 376 int width = src.width(); 377 int height = src.height(); 378 for (;;) { 379 width = SkTMax(1, width >> 1); 380 height = SkTMax(1, height >> 1); 381 size += SkColorTypeMinRowBytes(ct, width) * height; 382 countLevels += 1; 383 if (1 == width && 1 == height) { 384 break; 385 } 386 } 387 } 388 389 SkASSERT(countLevels == SkMipMap::ComputeLevelCount(src.width(), src.height())); 390 391 size_t storageSize = SkMipMap::AllocLevelsSize(countLevels, size); 392 if (0 == storageSize) { 393 return nullptr; 394 } 395 396 SkMipMap* mipmap; 397 if (fact) { 398 SkDiscardableMemory* dm = fact(storageSize); 399 if (nullptr == dm) { 400 return nullptr; 401 } 402 mipmap = new SkMipMap(storageSize, dm); 403 } else { 404 mipmap = new SkMipMap(sk_malloc_throw(storageSize), storageSize); 405 } 406 407 // init 408 mipmap->fCount = countLevels; 409 mipmap->fLevels = (Level*)mipmap->writable_data(); 410 411 Level* levels = mipmap->fLevels; 412 uint8_t* baseAddr = (uint8_t*)&levels[countLevels]; 413 uint8_t* addr = baseAddr; 414 int width = src.width(); 415 int height = src.height(); 416 uint32_t rowBytes; 417 SkPixmap srcPM(src); 418 419 for (int i = 0; i < countLevels; ++i) { 420 FilterProc* proc; 421 if (height & 1) { 422 if (height == 1) { // src-height is 1 423 if (width & 1) { // src-width is 3 424 proc = proc_3_1; 425 } else { // src-width is 2 426 proc = proc_2_1; 427 } 428 } else { // src-height is 3 429 if (width & 1) { 430 if (width == 1) { // src-width is 1 431 proc = proc_1_3; 432 } else { // src-width is 3 433 proc = proc_3_3; 434 } 435 } else { // src-width is 2 436 proc = proc_2_3; 437 } 438 } 439 } else { // src-height is 2 440 if (width & 1) { 441 if (width == 1) { // src-width is 1 442 proc = proc_1_2; 443 } else { // src-width is 3 444 proc = proc_3_2; 445 } 446 } else { // src-width is 2 447 proc = proc_2_2; 448 } 449 } 450 width = SkTMax(1, width >> 1); 451 height = SkTMax(1, height >> 1); 452 rowBytes = SkToU32(SkColorTypeMinRowBytes(ct, width)); 453 454 levels[i].fPixmap = SkPixmap(SkImageInfo::Make(width, height, ct, at), addr, rowBytes); 455 levels[i].fScale = SkSize::Make(SkIntToScalar(width) / src.width(), 456 SkIntToScalar(height) / src.height()); 457 458 const SkPixmap& dstPM = levels[i].fPixmap; 459 const void* srcBasePtr = srcPM.addr(); 460 void* dstBasePtr = dstPM.writable_addr(); 461 462 const size_t srcRB = srcPM.rowBytes(); 463 for (int y = 0; y < height; y++) { 464 proc(dstBasePtr, srcBasePtr, srcRB, width); 465 srcBasePtr = (char*)srcBasePtr + srcRB * 2; // jump two rows 466 dstBasePtr = (char*)dstBasePtr + dstPM.rowBytes(); 467 } 468 srcPM = dstPM; 469 addr += height * rowBytes; 470 } 471 SkASSERT(addr == baseAddr + size); 472 473 return mipmap; 474} 475 476int SkMipMap::ComputeLevelCount(int baseWidth, int baseHeight) { 477 if (baseWidth < 1 || baseHeight < 1) { 478 return 0; 479 } 480 481 // OpenGL's spec requires that each mipmap level have height/width equal to 482 // max(1, floor(original_height / 2^i) 483 // (or original_width) where i is the mipmap level. 484 // Continue scaling down until both axes are size 1. 485 486 const int largestAxis = SkTMax(baseWidth, baseHeight); 487 if (largestAxis < 2) { 488 // SkMipMap::Build requires a minimum size of 2. 489 return 0; 490 } 491 const int leadingZeros = SkCLZ(static_cast<uint32_t>(largestAxis)); 492 // If the value 00011010 has 3 leading 0s then it has 5 significant bits 493 // (the bits which are not leading zeros) 494 const int significantBits = (sizeof(uint32_t) * 8) - leadingZeros; 495 // This is making the assumption that the size of a byte is 8 bits 496 // and that sizeof(uint32_t)'s implementation-defined behavior is 4. 497 int mipLevelCount = significantBits; 498 499 // SkMipMap does not include the base mip level. 500 // For example, it contains levels 1-x instead of 0-x. 501 // This is because the image used to create SkMipMap is the base level. 502 // So subtract 1 from the mip level count. 503 if (mipLevelCount > 0) { 504 --mipLevelCount; 505 } 506 507 return mipLevelCount; 508} 509 510/////////////////////////////////////////////////////////////////////////////// 511 512bool SkMipMap::extractLevel(const SkSize& scaleSize, Level* levelPtr) const { 513 if (nullptr == fLevels) { 514 return false; 515 } 516 517 SkASSERT(scaleSize.width() >= 0 && scaleSize.height() >= 0); 518 519#ifndef SK_SUPPORT_LEGACY_ANISOTROPIC_MIPMAP_SCALE 520 // Use the smallest scale to match the GPU impl. 521 const SkScalar scale = SkTMin(scaleSize.width(), scaleSize.height()); 522#else 523 // Ideally we'd pick the smaller scale, to match Ganesh. But ignoring one of the 524 // scales can produce some atrocious results, so for now we use the geometric mean. 525 // (https://bugs.chromium.org/p/skia/issues/detail?id=4863) 526 const SkScalar scale = SkScalarSqrt(scaleSize.width() * scaleSize.height()); 527#endif 528 529 if (scale >= SK_Scalar1 || scale <= 0 || !SkScalarIsFinite(scale)) { 530 return false; 531 } 532 533 SkScalar L = -SkScalarLog2(scale); 534 if (!SkScalarIsFinite(L)) { 535 return false; 536 } 537 SkASSERT(L >= 0); 538// int rndLevel = SkScalarRoundToInt(L); 539 int level = SkScalarFloorToInt(L); 540// SkDebugf("mipmap scale=%g L=%g level=%d rndLevel=%d\n", scale, L, level, rndLevel); 541 542 SkASSERT(level >= 0); 543 if (level <= 0) { 544 return false; 545 } 546 547 if (level > fCount) { 548 level = fCount; 549 } 550 if (levelPtr) { 551 *levelPtr = fLevels[level - 1]; 552 } 553 return true; 554} 555 556// Helper which extracts a pixmap from the src bitmap 557// 558SkMipMap* SkMipMap::Build(const SkBitmap& src, SkDiscardableFactoryProc fact) { 559 SkAutoPixmapUnlock srcUnlocker; 560 if (!src.requestLock(&srcUnlocker)) { 561 return nullptr; 562 } 563 const SkPixmap& srcPixmap = srcUnlocker.pixmap(); 564 // Try to catch where we might have returned nullptr for src crbug.com/492818 565 if (nullptr == srcPixmap.addr()) { 566 sk_throw(); 567 } 568 return Build(srcPixmap, fact); 569} 570 571int SkMipMap::countLevels() const { 572 return fCount; 573} 574 575bool SkMipMap::getLevel(int index, Level* levelPtr) const { 576 if (NULL == fLevels) { 577 return false; 578 } 579 if (index < 0) { 580 return false; 581 } 582 if (index > fCount - 1) { 583 return false; 584 } 585 if (levelPtr) { 586 *levelPtr = fLevels[index]; 587 } 588 return true; 589} 590