--- src/core/SkPixmap.cpp.orig +++ src/core/SkPixmap.cpp @@ -188,6 +188,17 @@ this->rowBytes()); } +// Sk4f_toL32() stores the four lanes in ascending memory order, but SkColor is always the +// number 0xAARRGGBB. On little endian that means the lanes must be ; on big endian +// they must be . p4 is always . +static inline uint32_t rgba4f_to_SkColor(const skvx::float4& p4) { +#ifdef SK_CPU_BENDIAN + return Sk4f_toL32(skvx::shuffle<3, 0, 1, 2>(p4)); +#else + return Sk4f_toL32(swizzle_rb(p4)); +#endif +} + SkColor SkPixmap::getColor(int x, int y) const { SkASSERT(this->addr()); SkASSERT((unsigned)x < (unsigned)this->width()); @@ -195,8 +206,13 @@ const bool needsUnpremul = (kPremul_SkAlphaType == fInfo.alphaType()); auto toColor = [needsUnpremul](uint32_t maybePremulColor) { + // SkColor is always the number 0xAARRGGBB; SkPMColor's layout is endian dependent, + // so unpack it through the SK_*32_SHIFT accessors rather than swizzling bytes. return needsUnpremul ? SkUnPreMultiply::PMColorToColor(maybePremulColor) - : SkSwizzle_BGRA_to_PMColor(maybePremulColor); + : SkColorSetARGB(SkGetPackedA32(maybePremulColor), + SkGetPackedR32(maybePremulColor), + SkGetPackedG32(maybePremulColor), + SkGetPackedB32(maybePremulColor)); }; switch (this->colorType()) { @@ -227,8 +243,8 @@ return toColor(c); } case kR8G8_unorm_SkColorType: { - uint16_t value = *this->addr16(x, y); - return SkColorSetRGB((uint8_t)(value & 0xffff), (uint8_t)((value >> 8) & 0xffff), 0); + const uint8_t* rg = (const uint8_t*)this->addr16(x, y); + return SkColorSetRGB(rg[0], rg[1], 0); } case kR16_unorm_SkColorType: { uint16_t value = *this->addr16(x, y); @@ -236,19 +252,30 @@ } case kR16G16_unorm_SkColorType: { uint32_t value = *this->addr32(x, y); + // R is the first 16-bit channel in memory, i.e. the high half on big endian. +#if defined(SK_CPU_BENDIAN) + uint8_t r = ((value >> 16) & 0xffff) * (255.0f / 65535.0f), + g = ((value >> 0) & 0xffff) * (255.0f / 65535.0f); +#else uint8_t r = ((value >> 0) & 0xffff) * (255.0f / 65535.0f), g = ((value >> 16) & 0xffff) * (255.0f / 65535.0f); +#endif return SkColorSetRGB(r, g, 0); } case kR16G16_float_SkColorType: { uint32_t value = *this->addr32(x, y); - float r = SkHalfToFloat((uint16_t)(value >> 0) & 0xffff), - g = SkHalfToFloat((uint16_t)(value >> 16) & 0xffff); +#if defined(SK_CPU_BENDIAN) + float r = SkHalfToFloat((uint16_t)((value >> 16) & 0xffff)), + g = SkHalfToFloat((uint16_t)((value >> 0) & 0xffff)); +#else + float r = SkHalfToFloat((uint16_t)((value >> 0) & 0xffff)), + g = SkHalfToFloat((uint16_t)((value >> 16) & 0xffff)); +#endif return SkColorSetRGB((uint8_t)(255 * r), (uint8_t)(255 * g), 0); } case kRGB_888x_SkColorType: { - uint32_t value = *this->addr32(x, y); - return SkSwizzle_RB(value | 0xff000000); + const uint8_t* rgb = (const uint8_t*)this->addr32(x, y); + return SkColorSetRGB(rgb[0], rgb[1], rgb[2]); } case kBGRA_8888_SkColorType: { uint32_t value = *this->addr32(x, y); @@ -259,11 +286,11 @@ return toColor(SkSwizzle_RGBA_to_PMColor(value)); } case kSRGBA_8888_SkColorType: { - uint32_t value = *this->addr32(x, y); - float r = ((value >> 0) & 0xff) * (1/255.0f), - g = ((value >> 8) & 0xff) * (1/255.0f), - b = ((value >> 16) & 0xff) * (1/255.0f), - a = ((value >> 24) & 0xff) * (1/255.0f); + const uint8_t* rgba = (const uint8_t*)this->addr32(x, y); + float r = rgba[0] * (1/255.0f), + g = rgba[1] * (1/255.0f), + b = rgba[2] * (1/255.0f), + a = rgba[3] * (1/255.0f); auto srgb_to_linear = [](float x) { return (x <= 0.04045f) ? x * (1 / 12.92f) @@ -352,8 +379,7 @@ (const uint64_t*)fPixels + y * (fRowBytes >> 3) + x; skvx::float4 p4 = from_half(skvx::half4::Load(addr)); p4[3] = 1.0f; - // p4 is RGBA, but we want BGRA, so we need to swap next - return Sk4f_toL32(swizzle_rb(p4)); + return rgba4f_to_SkColor(p4); } case kRGBA_F16Norm_SkColorType: case kRGBA_F16_SkColorType: { @@ -364,8 +390,7 @@ float inva = 1 / p4[3]; p4 = p4 * skvx::float4(inva, inva, inva, 1); } - // p4 is RGBA, but we want BGRA, so we need to swap next - return Sk4f_toL32(swizzle_rb(p4)); + return rgba4f_to_SkColor(p4); } case kRGBA_F32_SkColorType: { const float* rgba = @@ -376,8 +401,7 @@ float inva = 1 / p4[3]; p4 = p4 * skvx::float4(inva, inva, inva, 1); } - // p4 is RGBA, but we want BGRA, so we need to swap next - return Sk4f_toL32(swizzle_rb(p4)); + return rgba4f_to_SkColor(p4); } case kUnknown_SkColorType: break; @@ -395,8 +419,13 @@ const bool needsUnpremul = (kPremul_SkAlphaType == fInfo.alphaType()); auto toColor = [needsUnpremul](uint32_t maybePremulColor) { + // SkColor is always the number 0xAARRGGBB; SkPMColor's layout is endian dependent, + // so unpack it through the SK_*32_SHIFT accessors rather than swizzling bytes. return needsUnpremul ? SkUnPreMultiply::PMColorToColor(maybePremulColor) - : SkSwizzle_BGRA_to_PMColor(maybePremulColor); + : SkColorSetARGB(SkGetPackedA32(maybePremulColor), + SkGetPackedR32(maybePremulColor), + SkGetPackedG32(maybePremulColor), + SkGetPackedB32(maybePremulColor)); }; switch (this->colorType()) { @@ -430,24 +459,34 @@ return SkColor4f::FromColor(toColor(c)); } case kR8G8_unorm_SkColorType: { - uint16_t value = *this->addr16(x, y); - return SkColor4f::FromColor(SkColorSetRGB((uint8_t)(value), (uint8_t)(value >> 8), 0)); + const uint8_t* rg = (const uint8_t*)this->addr16(x, y); + return SkColor4f::FromColor(SkColorSetRGB(rg[0], rg[1], 0)); } case kR16G16_unorm_SkColorType: { uint32_t value = *this->addr32(x, y); +#if defined(SK_CPU_BENDIAN) + float r = ((value >> 16) & 0xffff) * (1.0f / 65535.0f), + g = ((value >> 0) & 0xffff) * (1.0f / 65535.0f); +#else float r = ((value >> 0) & 0xffff) * (1.0f / 65535.0f), g = ((value >> 16) & 0xffff) * (1.0f / 65535.0f); +#endif return SkColor4f{r, g, 0.0, 1.0}; } case kR16G16_float_SkColorType: { uint32_t value = *this->addr32(x, y); +#if defined(SK_CPU_BENDIAN) + float r = SkHalfToFloat((value >> 16) & 0xffff); + float g = SkHalfToFloat((value >> 0 ) & 0xffff); +#else float r = SkHalfToFloat((value >> 0 ) & 0xffff); float g = SkHalfToFloat((value >> 16) & 0xffff); +#endif return SkColor4f{r, g, 0.0, 1.0}; } case kRGB_888x_SkColorType: { - SkColor c = SkSwizzle_RB(*this->addr32(x, y) | 0xff000000); - return SkColor4f::FromColor(c); + const uint8_t* rgb = (const uint8_t*)this->addr32(x, y); + return SkColor4f::FromColor(SkColorSetRGB(rgb[0], rgb[1], rgb[2])); } case kBGRA_8888_SkColorType: { SkPMColor c = SkSwizzle_BGRA_to_PMColor(*this->addr32(x, y)); @@ -463,11 +502,11 @@ : std::pow(x * (1 / 1.055f) + (0.055f / 1.055f), 2.4f); }; - uint32_t value = *this->addr32(x, y); - float r = ((value >> 0) & 0xff) * (1 / 255.0f), - g = ((value >> 8) & 0xff) * (1 / 255.0f), - b = ((value >> 16) & 0xff) * (1 / 255.0f), - a = ((value >> 24) & 0xff) * (1 / 255.0f); + const uint8_t* rgba = (const uint8_t*)this->addr32(x, y); + float r = rgba[0] * (1 / 255.0f), + g = rgba[1] * (1 / 255.0f), + b = rgba[2] * (1 / 255.0f), + a = rgba[3] * (1 / 255.0f); r = srgb_to_linear(r); g = srgb_to_linear(g); b = srgb_to_linear(b);