| 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 #include "SkHalf.h" | 11 #include "SkHalf.h" | 
| 12 #include "SkMathPriv.h" | 12 #include "SkMathPriv.h" | 
| 13 #include "SkNx.h" | 13 #include "SkNx.h" | 
|  | 14 #include "SkPM4fPriv.h" | 
| 14 #include "SkTypes.h" | 15 #include "SkTypes.h" | 
| 15 | 16 | 
| 16 // | 17 // | 
| 17 // ColorTypeFilter is the "Type" we pass to some downsample template functions. | 18 // 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 // 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 t
     he intermediates | 20 // so we can then perform our simple filter (either box or triangle) and store t
     he intermediates | 
| 20 // in the expanded type. | 21 // in the expanded type. | 
| 21 // | 22 // | 
| 22 | 23 | 
| 23 struct ColorTypeFilter_8888 { | 24 struct ColorTypeFilter_8888 { | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
| 34 #else | 35 #else | 
| 35     static uint64_t Expand(uint32_t x) { | 36     static uint64_t Expand(uint32_t x) { | 
| 36         return (x & 0xFF00FF) | ((uint64_t)(x & 0xFF00FF00) << 24); | 37         return (x & 0xFF00FF) | ((uint64_t)(x & 0xFF00FF00) << 24); | 
| 37     } | 38     } | 
| 38     static uint32_t Compact(uint64_t x) { | 39     static uint32_t Compact(uint64_t x) { | 
| 39         return (uint32_t)((x & 0xFF00FF) | ((x >> 24) & 0xFF00FF00)); | 40         return (uint32_t)((x & 0xFF00FF) | ((x >> 24) & 0xFF00FF00)); | 
| 40     } | 41     } | 
| 41 #endif | 42 #endif | 
| 42 }; | 43 }; | 
| 43 | 44 | 
|  | 45 struct ColorTypeFilter_S32 { | 
|  | 46     typedef uint32_t Type; | 
|  | 47     static Sk4f Expand(uint32_t x) { | 
|  | 48         return Sk4f_fromS32(x); | 
|  | 49     } | 
|  | 50     static uint32_t Compact(const Sk4f& x) { | 
|  | 51         return Sk4f_toS32(x); | 
|  | 52     } | 
|  | 53 }; | 
|  | 54 | 
| 44 struct ColorTypeFilter_565 { | 55 struct ColorTypeFilter_565 { | 
| 45     typedef uint16_t Type; | 56     typedef uint16_t Type; | 
| 46     static uint32_t Expand(uint16_t x) { | 57     static uint32_t Expand(uint16_t x) { | 
| 47         return (x & ~SK_G16_MASK_IN_PLACE) | ((x & SK_G16_MASK_IN_PLACE) << 16); | 58         return (x & ~SK_G16_MASK_IN_PLACE) | ((x & SK_G16_MASK_IN_PLACE) << 16); | 
| 48     } | 59     } | 
| 49     static uint16_t Compact(uint32_t x) { | 60     static uint16_t Compact(uint32_t x) { | 
| 50         return (x & ~SK_G16_MASK_IN_PLACE) | ((x >> 16) & SK_G16_MASK_IN_PLACE); | 61         return (x & ~SK_G16_MASK_IN_PLACE) | ((x >> 16) & SK_G16_MASK_IN_PLACE); | 
| 51     } | 62     } | 
| 52 }; | 63 }; | 
| 53 | 64 | 
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 286     if (levelCount < 0) { | 297     if (levelCount < 0) { | 
| 287         return 0; | 298         return 0; | 
| 288     } | 299     } | 
| 289     int64_t size = sk_64_mul(levelCount + 1, sizeof(Level)) + pixelSize; | 300     int64_t size = sk_64_mul(levelCount + 1, sizeof(Level)) + pixelSize; | 
| 290     if (!sk_64_isS32(size)) { | 301     if (!sk_64_isS32(size)) { | 
| 291         return 0; | 302         return 0; | 
| 292     } | 303     } | 
| 293     return sk_64_asS32(size); | 304     return sk_64_asS32(size); | 
| 294 } | 305 } | 
| 295 | 306 | 
| 296 SkMipMap* SkMipMap::Build(const SkPixmap& src, SkDiscardableFactoryProc fact) { | 307 static bool treat_like_srgb(const SkImageInfo& info) { | 
|  | 308     if (info.colorSpace()) { | 
|  | 309         return SkColorSpace::k2Dot2Curve_GammaNamed == info.colorSpace()->gammaN
     amed(); | 
|  | 310     } else { | 
|  | 311         return kSRGB_SkColorProfileType == info.profileType(); | 
|  | 312     } | 
|  | 313 } | 
|  | 314 | 
|  | 315 SkMipMap* SkMipMap::Build(const SkPixmap& src, SkSourceGammaTreatment treatment, | 
|  | 316                           SkDiscardableFactoryProc fact) { | 
| 297     typedef void FilterProc(void*, const void* srcPtr, size_t srcRB, int count); | 317     typedef void FilterProc(void*, const void* srcPtr, size_t srcRB, int count); | 
| 298 | 318 | 
| 299     FilterProc* proc_1_2 = nullptr; | 319     FilterProc* proc_1_2 = nullptr; | 
| 300     FilterProc* proc_1_3 = nullptr; | 320     FilterProc* proc_1_3 = nullptr; | 
| 301     FilterProc* proc_2_1 = nullptr; | 321     FilterProc* proc_2_1 = nullptr; | 
| 302     FilterProc* proc_2_2 = nullptr; | 322     FilterProc* proc_2_2 = nullptr; | 
| 303     FilterProc* proc_2_3 = nullptr; | 323     FilterProc* proc_2_3 = nullptr; | 
| 304     FilterProc* proc_3_1 = nullptr; | 324     FilterProc* proc_3_1 = nullptr; | 
| 305     FilterProc* proc_3_2 = nullptr; | 325     FilterProc* proc_3_2 = nullptr; | 
| 306     FilterProc* proc_3_3 = nullptr; | 326     FilterProc* proc_3_3 = nullptr; | 
| 307 | 327 | 
| 308     const SkColorType ct = src.colorType(); | 328     const SkColorType ct = src.colorType(); | 
| 309     const SkAlphaType at = src.alphaType(); | 329     const SkAlphaType at = src.alphaType(); | 
|  | 330     const bool srgbGamma = (SkSourceGammaTreatment::kRespect == treatment) | 
|  | 331                             && treat_like_srgb(src.info()); | 
|  | 332 | 
| 310     switch (ct) { | 333     switch (ct) { | 
| 311         case kRGBA_8888_SkColorType: | 334         case kRGBA_8888_SkColorType: | 
| 312         case kBGRA_8888_SkColorType: | 335         case kBGRA_8888_SkColorType: | 
| 313             proc_1_2 = downsample_1_2<ColorTypeFilter_8888>; | 336             if (srgbGamma) { | 
| 314             proc_1_3 = downsample_1_3<ColorTypeFilter_8888>; | 337                 proc_1_2 = downsample_1_2<ColorTypeFilter_S32>; | 
| 315             proc_2_1 = downsample_2_1<ColorTypeFilter_8888>; | 338                 proc_1_3 = downsample_1_3<ColorTypeFilter_S32>; | 
| 316             proc_2_2 = downsample_2_2<ColorTypeFilter_8888>; | 339                 proc_2_1 = downsample_2_1<ColorTypeFilter_S32>; | 
| 317             proc_2_3 = downsample_2_3<ColorTypeFilter_8888>; | 340                 proc_2_2 = downsample_2_2<ColorTypeFilter_S32>; | 
| 318             proc_3_1 = downsample_3_1<ColorTypeFilter_8888>; | 341                 proc_2_3 = downsample_2_3<ColorTypeFilter_S32>; | 
| 319             proc_3_2 = downsample_3_2<ColorTypeFilter_8888>; | 342                 proc_3_1 = downsample_3_1<ColorTypeFilter_S32>; | 
| 320             proc_3_3 = downsample_3_3<ColorTypeFilter_8888>; | 343                 proc_3_2 = downsample_3_2<ColorTypeFilter_S32>; | 
|  | 344                 proc_3_3 = downsample_3_3<ColorTypeFilter_S32>; | 
|  | 345             } else { | 
|  | 346                 proc_1_2 = downsample_1_2<ColorTypeFilter_8888>; | 
|  | 347                 proc_1_3 = downsample_1_3<ColorTypeFilter_8888>; | 
|  | 348                 proc_2_1 = downsample_2_1<ColorTypeFilter_8888>; | 
|  | 349                 proc_2_2 = downsample_2_2<ColorTypeFilter_8888>; | 
|  | 350                 proc_2_3 = downsample_2_3<ColorTypeFilter_8888>; | 
|  | 351                 proc_3_1 = downsample_3_1<ColorTypeFilter_8888>; | 
|  | 352                 proc_3_2 = downsample_3_2<ColorTypeFilter_8888>; | 
|  | 353                 proc_3_3 = downsample_3_3<ColorTypeFilter_8888>; | 
|  | 354             } | 
| 321             break; | 355             break; | 
| 322         case kRGB_565_SkColorType: | 356         case kRGB_565_SkColorType: | 
| 323             proc_1_2 = downsample_1_2<ColorTypeFilter_565>; | 357             proc_1_2 = downsample_1_2<ColorTypeFilter_565>; | 
| 324             proc_1_3 = downsample_1_3<ColorTypeFilter_565>; | 358             proc_1_3 = downsample_1_3<ColorTypeFilter_565>; | 
| 325             proc_2_1 = downsample_2_1<ColorTypeFilter_565>; | 359             proc_2_1 = downsample_2_1<ColorTypeFilter_565>; | 
| 326             proc_2_2 = downsample_2_2<ColorTypeFilter_565>; | 360             proc_2_2 = downsample_2_2<ColorTypeFilter_565>; | 
| 327             proc_2_3 = downsample_2_3<ColorTypeFilter_565>; | 361             proc_2_3 = downsample_2_3<ColorTypeFilter_565>; | 
| 328             proc_3_1 = downsample_3_1<ColorTypeFilter_565>; | 362             proc_3_1 = downsample_3_1<ColorTypeFilter_565>; | 
| 329             proc_3_2 = downsample_3_2<ColorTypeFilter_565>; | 363             proc_3_2 = downsample_3_2<ColorTypeFilter_565>; | 
| 330             proc_3_3 = downsample_3_3<ColorTypeFilter_565>; | 364             proc_3_3 = downsample_3_3<ColorTypeFilter_565>; | 
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 387         SkDiscardableMemory* dm = fact(storageSize); | 421         SkDiscardableMemory* dm = fact(storageSize); | 
| 388         if (nullptr == dm) { | 422         if (nullptr == dm) { | 
| 389             return nullptr; | 423             return nullptr; | 
| 390         } | 424         } | 
| 391         mipmap = new SkMipMap(storageSize, dm); | 425         mipmap = new SkMipMap(storageSize, dm); | 
| 392     } else { | 426     } else { | 
| 393         mipmap = new SkMipMap(sk_malloc_throw(storageSize), storageSize); | 427         mipmap = new SkMipMap(sk_malloc_throw(storageSize), storageSize); | 
| 394     } | 428     } | 
| 395 | 429 | 
| 396     // init | 430     // init | 
|  | 431     mipmap->fCS = sk_ref_sp(src.info().colorSpace()); | 
| 397     mipmap->fCount = countLevels; | 432     mipmap->fCount = countLevels; | 
| 398     mipmap->fLevels = (Level*)mipmap->writable_data(); | 433     mipmap->fLevels = (Level*)mipmap->writable_data(); | 
|  | 434     SkASSERT(mipmap->fLevels); | 
| 399 | 435 | 
| 400     Level* levels = mipmap->fLevels; | 436     Level* levels = mipmap->fLevels; | 
| 401     uint8_t*    baseAddr = (uint8_t*)&levels[countLevels]; | 437     uint8_t*    baseAddr = (uint8_t*)&levels[countLevels]; | 
| 402     uint8_t*    addr = baseAddr; | 438     uint8_t*    addr = baseAddr; | 
| 403     int         width = src.width(); | 439     int         width = src.width(); | 
| 404     int         height = src.height(); | 440     int         height = src.height(); | 
| 405     uint32_t    rowBytes; | 441     uint32_t    rowBytes; | 
| 406     SkPixmap    srcPM(src); | 442     SkPixmap    srcPM(src); | 
| 407 | 443 | 
| 408     for (int i = 0; i < countLevels; ++i) { | 444     for (int i = 0; i < countLevels; ++i) { | 
| (...skipping 24 matching lines...) Expand all  Loading... | 
| 433                     proc = proc_3_2; | 469                     proc = proc_3_2; | 
| 434                 } | 470                 } | 
| 435             } else {                  // src-width is 2 | 471             } else {                  // src-width is 2 | 
| 436                 proc = proc_2_2; | 472                 proc = proc_2_2; | 
| 437             } | 473             } | 
| 438         } | 474         } | 
| 439         width = SkTMax(1, width >> 1); | 475         width = SkTMax(1, width >> 1); | 
| 440         height = SkTMax(1, height >> 1); | 476         height = SkTMax(1, height >> 1); | 
| 441         rowBytes = SkToU32(SkColorTypeMinRowBytes(ct, width)); | 477         rowBytes = SkToU32(SkColorTypeMinRowBytes(ct, width)); | 
| 442 | 478 | 
|  | 479         // We make the Info w/o any colorspace, since that storage is not under 
     our control, and | 
|  | 480         // will not be deleted in a controlled fashion. When the caller is given
      the pixmap for | 
|  | 481         // a given level, we augment this pixmap with fCS (which we do manage). | 
| 443         new (&levels[i].fPixmap) SkPixmap(SkImageInfo::Make(width, height, ct, a
     t), addr, rowBytes); | 482         new (&levels[i].fPixmap) SkPixmap(SkImageInfo::Make(width, height, ct, a
     t), addr, rowBytes); | 
| 444         levels[i].fScale  = SkSize::Make(SkIntToScalar(width)  / src.width(), | 483         levels[i].fScale  = SkSize::Make(SkIntToScalar(width)  / src.width(), | 
| 445                                          SkIntToScalar(height) / src.height()); | 484                                          SkIntToScalar(height) / src.height()); | 
| 446 | 485 | 
| 447         const SkPixmap& dstPM = levels[i].fPixmap; | 486         const SkPixmap& dstPM = levels[i].fPixmap; | 
| 448         const void* srcBasePtr = srcPM.addr(); | 487         const void* srcBasePtr = srcPM.addr(); | 
| 449         void* dstBasePtr = dstPM.writable_addr(); | 488         void* dstBasePtr = dstPM.writable_addr(); | 
| 450 | 489 | 
| 451         const size_t srcRB = srcPM.rowBytes(); | 490         const size_t srcRB = srcPM.rowBytes(); | 
| 452         for (int y = 0; y < height; y++) { | 491         for (int y = 0; y < height; y++) { | 
| 453             proc(dstBasePtr, srcBasePtr, srcRB, width); | 492             proc(dstBasePtr, srcBasePtr, srcRB, width); | 
| 454             srcBasePtr = (char*)srcBasePtr + srcRB * 2; // jump two rows | 493             srcBasePtr = (char*)srcBasePtr + srcRB * 2; // jump two rows | 
| 455             dstBasePtr = (char*)dstBasePtr + dstPM.rowBytes(); | 494             dstBasePtr = (char*)dstBasePtr + dstPM.rowBytes(); | 
| 456         } | 495         } | 
| 457         srcPM = dstPM; | 496         srcPM = dstPM; | 
| 458         addr += height * rowBytes; | 497         addr += height * rowBytes; | 
| 459     } | 498     } | 
| 460     SkASSERT(addr == baseAddr + size); | 499     SkASSERT(addr == baseAddr + size); | 
| 461 | 500 | 
|  | 501     SkASSERT(mipmap->fLevels); | 
| 462     return mipmap; | 502     return mipmap; | 
| 463 } | 503 } | 
| 464 | 504 | 
| 465 int SkMipMap::ComputeLevelCount(int baseWidth, int baseHeight) { | 505 int SkMipMap::ComputeLevelCount(int baseWidth, int baseHeight) { | 
| 466     if (baseWidth < 1 || baseHeight < 1) { | 506     if (baseWidth < 1 || baseHeight < 1) { | 
| 467         return 0; | 507         return 0; | 
| 468     } | 508     } | 
| 469 | 509 | 
| 470     // OpenGL's spec requires that each mipmap level have height/width equal to | 510     // OpenGL's spec requires that each mipmap level have height/width equal to | 
| 471     // max(1, floor(original_height / 2^i) | 511     // max(1, floor(original_height / 2^i) | 
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 540 | 580 | 
| 541     if (scale >= SK_Scalar1 || scale <= 0 || !SkScalarIsFinite(scale)) { | 581     if (scale >= SK_Scalar1 || scale <= 0 || !SkScalarIsFinite(scale)) { | 
| 542         return false; | 582         return false; | 
| 543     } | 583     } | 
| 544 | 584 | 
| 545     SkScalar L = -SkScalarLog2(scale); | 585     SkScalar L = -SkScalarLog2(scale); | 
| 546     if (!SkScalarIsFinite(L)) { | 586     if (!SkScalarIsFinite(L)) { | 
| 547         return false; | 587         return false; | 
| 548     } | 588     } | 
| 549     SkASSERT(L >= 0); | 589     SkASSERT(L >= 0); | 
| 550 //    int rndLevel = SkScalarRoundToInt(L); |  | 
| 551     int level = SkScalarFloorToInt(L); | 590     int level = SkScalarFloorToInt(L); | 
| 552 //    SkDebugf("mipmap scale=%g L=%g level=%d rndLevel=%d\n", scale, L, level, r
     ndLevel); |  | 
| 553 | 591 | 
| 554     SkASSERT(level >= 0); | 592     SkASSERT(level >= 0); | 
| 555     if (level <= 0) { | 593     if (level <= 0) { | 
| 556         return false; | 594         return false; | 
| 557     } | 595     } | 
| 558 | 596 | 
| 559     if (level > fCount) { | 597     if (level > fCount) { | 
| 560         level = fCount; | 598         level = fCount; | 
| 561     } | 599     } | 
| 562     if (levelPtr) { | 600     if (levelPtr) { | 
| 563         *levelPtr = fLevels[level - 1]; | 601         *levelPtr = fLevels[level - 1]; | 
|  | 602         // need to augment with our colorspace | 
|  | 603         levelPtr->fPixmap.setColorSpace(fCS); | 
| 564     } | 604     } | 
| 565     return true; | 605     return true; | 
| 566 } | 606 } | 
| 567 | 607 | 
| 568 // Helper which extracts a pixmap from the src bitmap | 608 // Helper which extracts a pixmap from the src bitmap | 
| 569 // | 609 // | 
| 570 SkMipMap* SkMipMap::Build(const SkBitmap& src, SkDiscardableFactoryProc fact) { | 610 SkMipMap* SkMipMap::Build(const SkBitmap& src, SkSourceGammaTreatment treatment, | 
|  | 611                           SkDiscardableFactoryProc fact) { | 
| 571     SkAutoPixmapUnlock srcUnlocker; | 612     SkAutoPixmapUnlock srcUnlocker; | 
| 572     if (!src.requestLock(&srcUnlocker)) { | 613     if (!src.requestLock(&srcUnlocker)) { | 
| 573         return nullptr; | 614         return nullptr; | 
| 574     } | 615     } | 
| 575     const SkPixmap& srcPixmap = srcUnlocker.pixmap(); | 616     const SkPixmap& srcPixmap = srcUnlocker.pixmap(); | 
| 576     // Try to catch where we might have returned nullptr for src crbug.com/49281
     8 | 617     // Try to catch where we might have returned nullptr for src crbug.com/49281
     8 | 
| 577     if (nullptr == srcPixmap.addr()) { | 618     if (nullptr == srcPixmap.addr()) { | 
| 578         sk_throw(); | 619         sk_throw(); | 
| 579     } | 620     } | 
| 580     return Build(srcPixmap, fact); | 621     return Build(srcPixmap, treatment, fact); | 
| 581 } | 622 } | 
| 582 | 623 | 
| 583 int SkMipMap::countLevels() const { | 624 int SkMipMap::countLevels() const { | 
| 584     return fCount; | 625     return fCount; | 
| 585 } | 626 } | 
| 586 | 627 | 
| 587 bool SkMipMap::getLevel(int index, Level* levelPtr) const { | 628 bool SkMipMap::getLevel(int index, Level* levelPtr) const { | 
| 588     if (NULL == fLevels) { | 629     if (NULL == fLevels) { | 
| 589         return false; | 630         return false; | 
| 590     } | 631     } | 
| 591     if (index < 0) { | 632     if (index < 0) { | 
| 592         return false; | 633         return false; | 
| 593     } | 634     } | 
| 594     if (index > fCount - 1) { | 635     if (index > fCount - 1) { | 
| 595         return false; | 636         return false; | 
| 596     } | 637     } | 
| 597     if (levelPtr) { | 638     if (levelPtr) { | 
| 598         *levelPtr = fLevels[index]; | 639         *levelPtr = fLevels[index]; | 
| 599     } | 640     } | 
| 600     return true; | 641     return true; | 
| 601 } | 642 } | 
| OLD | NEW | 
|---|