| Index: src/core/SkMipMap.cpp
|
| diff --git a/src/core/SkMipMap.cpp b/src/core/SkMipMap.cpp
|
| index 355c1edebbd755c55305e5f15b53ce510328f9ab..69c8466f69c30073fe0ace194254ef2215575959 100644
|
| --- a/src/core/SkMipMap.cpp
|
| +++ b/src/core/SkMipMap.cpp
|
| @@ -11,6 +11,7 @@
|
| #include "SkHalf.h"
|
| #include "SkMathPriv.h"
|
| #include "SkNx.h"
|
| +#include "SkPM4fPriv.h"
|
| #include "SkTypes.h"
|
|
|
| //
|
| @@ -41,6 +42,16 @@ struct ColorTypeFilter_8888 {
|
| #endif
|
| };
|
|
|
| +struct ColorTypeFilter_S32 {
|
| + typedef uint32_t Type;
|
| + static Sk4f Expand(uint32_t x) {
|
| + return Sk4f_fromS32(x);
|
| + }
|
| + static uint32_t Compact(const Sk4f& x) {
|
| + return Sk4f_toS32(x);
|
| + }
|
| +};
|
| +
|
| struct ColorTypeFilter_565 {
|
| typedef uint16_t Type;
|
| static uint32_t Expand(uint16_t x) {
|
| @@ -293,7 +304,16 @@ size_t SkMipMap::AllocLevelsSize(int levelCount, size_t pixelSize) {
|
| return sk_64_asS32(size);
|
| }
|
|
|
| -SkMipMap* SkMipMap::Build(const SkPixmap& src, SkDiscardableFactoryProc fact) {
|
| +static bool treat_like_srgb(const SkImageInfo& info) {
|
| + if (info.colorSpace()) {
|
| + return SkColorSpace::k2Dot2Curve_GammaNamed == info.colorSpace()->gammaNamed();
|
| + } else {
|
| + return kSRGB_SkColorProfileType == info.profileType();
|
| + }
|
| +}
|
| +
|
| +SkMipMap* SkMipMap::Build(const SkPixmap& src, SkSourceGammaTreatment treatment,
|
| + SkDiscardableFactoryProc fact) {
|
| typedef void FilterProc(void*, const void* srcPtr, size_t srcRB, int count);
|
|
|
| FilterProc* proc_1_2 = nullptr;
|
| @@ -307,17 +327,31 @@ SkMipMap* SkMipMap::Build(const SkPixmap& src, SkDiscardableFactoryProc fact) {
|
|
|
| const SkColorType ct = src.colorType();
|
| const SkAlphaType at = src.alphaType();
|
| + const bool srgbGamma = (SkSourceGammaTreatment::kRespect == treatment)
|
| + && treat_like_srgb(src.info());
|
| +
|
| switch (ct) {
|
| case kRGBA_8888_SkColorType:
|
| case kBGRA_8888_SkColorType:
|
| - proc_1_2 = downsample_1_2<ColorTypeFilter_8888>;
|
| - proc_1_3 = downsample_1_3<ColorTypeFilter_8888>;
|
| - proc_2_1 = downsample_2_1<ColorTypeFilter_8888>;
|
| - proc_2_2 = downsample_2_2<ColorTypeFilter_8888>;
|
| - proc_2_3 = downsample_2_3<ColorTypeFilter_8888>;
|
| - proc_3_1 = downsample_3_1<ColorTypeFilter_8888>;
|
| - proc_3_2 = downsample_3_2<ColorTypeFilter_8888>;
|
| - proc_3_3 = downsample_3_3<ColorTypeFilter_8888>;
|
| + if (srgbGamma) {
|
| + proc_1_2 = downsample_1_2<ColorTypeFilter_S32>;
|
| + proc_1_3 = downsample_1_3<ColorTypeFilter_S32>;
|
| + proc_2_1 = downsample_2_1<ColorTypeFilter_S32>;
|
| + proc_2_2 = downsample_2_2<ColorTypeFilter_S32>;
|
| + proc_2_3 = downsample_2_3<ColorTypeFilter_S32>;
|
| + proc_3_1 = downsample_3_1<ColorTypeFilter_S32>;
|
| + proc_3_2 = downsample_3_2<ColorTypeFilter_S32>;
|
| + proc_3_3 = downsample_3_3<ColorTypeFilter_S32>;
|
| + } else {
|
| + proc_1_2 = downsample_1_2<ColorTypeFilter_8888>;
|
| + proc_1_3 = downsample_1_3<ColorTypeFilter_8888>;
|
| + proc_2_1 = downsample_2_1<ColorTypeFilter_8888>;
|
| + proc_2_2 = downsample_2_2<ColorTypeFilter_8888>;
|
| + proc_2_3 = downsample_2_3<ColorTypeFilter_8888>;
|
| + proc_3_1 = downsample_3_1<ColorTypeFilter_8888>;
|
| + proc_3_2 = downsample_3_2<ColorTypeFilter_8888>;
|
| + proc_3_3 = downsample_3_3<ColorTypeFilter_8888>;
|
| + }
|
| break;
|
| case kRGB_565_SkColorType:
|
| proc_1_2 = downsample_1_2<ColorTypeFilter_565>;
|
| @@ -394,8 +428,10 @@ SkMipMap* SkMipMap::Build(const SkPixmap& src, SkDiscardableFactoryProc fact) {
|
| }
|
|
|
| // init
|
| + mipmap->fCS = sk_ref_sp(src.info().colorSpace());
|
| mipmap->fCount = countLevels;
|
| mipmap->fLevels = (Level*)mipmap->writable_data();
|
| + SkASSERT(mipmap->fLevels);
|
|
|
| Level* levels = mipmap->fLevels;
|
| uint8_t* baseAddr = (uint8_t*)&levels[countLevels];
|
| @@ -440,6 +476,9 @@ SkMipMap* SkMipMap::Build(const SkPixmap& src, SkDiscardableFactoryProc fact) {
|
| height = SkTMax(1, height >> 1);
|
| rowBytes = SkToU32(SkColorTypeMinRowBytes(ct, width));
|
|
|
| + // We make the Info w/o any colorspace, since that storage is not under our control, and
|
| + // will not be deleted in a controlled fashion. When the caller is given the pixmap for
|
| + // a given level, we augment this pixmap with fCS (which we do manage).
|
| new (&levels[i].fPixmap) SkPixmap(SkImageInfo::Make(width, height, ct, at), addr, rowBytes);
|
| levels[i].fScale = SkSize::Make(SkIntToScalar(width) / src.width(),
|
| SkIntToScalar(height) / src.height());
|
| @@ -459,6 +498,7 @@ SkMipMap* SkMipMap::Build(const SkPixmap& src, SkDiscardableFactoryProc fact) {
|
| }
|
| SkASSERT(addr == baseAddr + size);
|
|
|
| + SkASSERT(mipmap->fLevels);
|
| return mipmap;
|
| }
|
|
|
| @@ -547,9 +587,7 @@ bool SkMipMap::extractLevel(const SkSize& scaleSize, Level* levelPtr) const {
|
| return false;
|
| }
|
| SkASSERT(L >= 0);
|
| -// int rndLevel = SkScalarRoundToInt(L);
|
| int level = SkScalarFloorToInt(L);
|
| -// SkDebugf("mipmap scale=%g L=%g level=%d rndLevel=%d\n", scale, L, level, rndLevel);
|
|
|
| SkASSERT(level >= 0);
|
| if (level <= 0) {
|
| @@ -561,13 +599,16 @@ bool SkMipMap::extractLevel(const SkSize& scaleSize, Level* levelPtr) const {
|
| }
|
| if (levelPtr) {
|
| *levelPtr = fLevels[level - 1];
|
| + // need to augment with our colorspace
|
| + levelPtr->fPixmap.setColorSpace(fCS);
|
| }
|
| return true;
|
| }
|
|
|
| // Helper which extracts a pixmap from the src bitmap
|
| //
|
| -SkMipMap* SkMipMap::Build(const SkBitmap& src, SkDiscardableFactoryProc fact) {
|
| +SkMipMap* SkMipMap::Build(const SkBitmap& src, SkSourceGammaTreatment treatment,
|
| + SkDiscardableFactoryProc fact) {
|
| SkAutoPixmapUnlock srcUnlocker;
|
| if (!src.requestLock(&srcUnlocker)) {
|
| return nullptr;
|
| @@ -577,7 +618,7 @@ SkMipMap* SkMipMap::Build(const SkBitmap& src, SkDiscardableFactoryProc fact) {
|
| if (nullptr == srcPixmap.addr()) {
|
| sk_throw();
|
| }
|
| - return Build(srcPixmap, fact);
|
| + return Build(srcPixmap, treatment, fact);
|
| }
|
|
|
| int SkMipMap::countLevels() const {
|
|
|