michael@0: #include "SkConfig8888.h" michael@0: #include "SkMathPriv.h" michael@0: #include "SkUnPreMultiply.h" michael@0: michael@0: namespace { michael@0: michael@0: template michael@0: inline uint32_t pack_config8888(uint32_t a, uint32_t r, michael@0: uint32_t g, uint32_t b) { michael@0: #ifdef SK_CPU_LENDIAN michael@0: return (a << (A_IDX * 8)) | (r << (R_IDX * 8)) | michael@0: (g << (G_IDX * 8)) | (b << (B_IDX * 8)); michael@0: #else michael@0: return (a << ((3-A_IDX) * 8)) | (r << ((3-R_IDX) * 8)) | michael@0: (g << ((3-G_IDX) * 8)) | (b << ((3-B_IDX) * 8)); michael@0: #endif michael@0: } michael@0: michael@0: template michael@0: inline void unpack_config8888(uint32_t color, michael@0: uint32_t* a, uint32_t* r, michael@0: uint32_t* g, uint32_t* b) { michael@0: #ifdef SK_CPU_LENDIAN michael@0: *a = (color >> (A_IDX * 8)) & 0xff; michael@0: *r = (color >> (R_IDX * 8)) & 0xff; michael@0: *g = (color >> (G_IDX * 8)) & 0xff; michael@0: *b = (color >> (B_IDX * 8)) & 0xff; michael@0: #else michael@0: *a = (color >> ((3 - A_IDX) * 8)) & 0xff; michael@0: *r = (color >> ((3 - R_IDX) * 8)) & 0xff; michael@0: *g = (color >> ((3 - G_IDX) * 8)) & 0xff; michael@0: *b = (color >> ((3 - B_IDX) * 8)) & 0xff; michael@0: #endif michael@0: } michael@0: michael@0: #ifdef SK_CPU_LENDIAN michael@0: static const int SK_NATIVE_A_IDX = SK_A32_SHIFT / 8; michael@0: static const int SK_NATIVE_R_IDX = SK_R32_SHIFT / 8; michael@0: static const int SK_NATIVE_G_IDX = SK_G32_SHIFT / 8; michael@0: static const int SK_NATIVE_B_IDX = SK_B32_SHIFT / 8; michael@0: #else michael@0: static const int SK_NATIVE_A_IDX = 3 - (SK_A32_SHIFT / 8); michael@0: static const int SK_NATIVE_R_IDX = 3 - (SK_R32_SHIFT / 8); michael@0: static const int SK_NATIVE_G_IDX = 3 - (SK_G32_SHIFT / 8); michael@0: static const int SK_NATIVE_B_IDX = 3 - (SK_B32_SHIFT / 8); michael@0: #endif michael@0: michael@0: /** michael@0: * convert_pixel michael@0: inline uint32_t convert_pixel(uint32_t pixel) { michael@0: uint32_t a, r, g, b; michael@0: unpack_config8888(pixel, &a, &r, &g, &b); michael@0: if (IN_PM && !OUT_PM) { michael@0: // Using SkUnPreMultiply::ApplyScale is faster than (value * 0xff) / a. michael@0: if (a) { michael@0: SkUnPreMultiply::Scale scale = SkUnPreMultiply::GetScale(a); michael@0: r = SkUnPreMultiply::ApplyScale(scale, r); michael@0: g = SkUnPreMultiply::ApplyScale(scale, g); michael@0: b = SkUnPreMultiply::ApplyScale(scale, b); michael@0: } else { michael@0: return 0; michael@0: } michael@0: } else if (!IN_PM && OUT_PM) { michael@0: // This matches SkUnPreMultiply conversion which we are replacing. michael@0: r = SkMulDiv255Round(r, a); michael@0: g = SkMulDiv255Round(g, a); michael@0: b = SkMulDiv255Round(b, a); michael@0: } michael@0: return pack_config8888(a, r, g, b); michael@0: } michael@0: michael@0: template michael@0: inline uint32_t convert_pixel(uint32_t pixel) { michael@0: switch(IN_CFG) { michael@0: case SkCanvas::kNative_Premul_Config8888: michael@0: return convert_pixel(pixel); michael@0: break; michael@0: case SkCanvas::kNative_Unpremul_Config8888: michael@0: return convert_pixel(pixel); michael@0: break; michael@0: case SkCanvas::kBGRA_Premul_Config8888: michael@0: return convert_pixel(pixel); michael@0: break; michael@0: case SkCanvas::kBGRA_Unpremul_Config8888: michael@0: return convert_pixel(pixel); michael@0: break; michael@0: case SkCanvas::kRGBA_Premul_Config8888: michael@0: return convert_pixel(pixel); michael@0: break; michael@0: case SkCanvas::kRGBA_Unpremul_Config8888: michael@0: return convert_pixel(pixel); michael@0: break; michael@0: default: michael@0: SkDEBUGFAIL("Unexpected config8888"); michael@0: return 0; michael@0: break; michael@0: } michael@0: } michael@0: michael@0: template michael@0: inline uint32_t convert_pixel(uint32_t pixel) { michael@0: switch(OUT_CFG) { michael@0: case SkCanvas::kNative_Premul_Config8888: michael@0: return convert_pixel(pixel); michael@0: break; michael@0: case SkCanvas::kNative_Unpremul_Config8888: michael@0: return convert_pixel(pixel); michael@0: break; michael@0: case SkCanvas::kBGRA_Premul_Config8888: michael@0: return convert_pixel(pixel); michael@0: break; michael@0: case SkCanvas::kBGRA_Unpremul_Config8888: michael@0: return convert_pixel(pixel); michael@0: break; michael@0: case SkCanvas::kRGBA_Premul_Config8888: michael@0: return convert_pixel(pixel); michael@0: break; michael@0: case SkCanvas::kRGBA_Unpremul_Config8888: michael@0: return convert_pixel(pixel); michael@0: break; michael@0: default: michael@0: SkDEBUGFAIL("Unexpected config8888"); michael@0: return 0; michael@0: break; michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * SkConvertConfig8888Pixels has 6 * 6 possible combinations of src and dst michael@0: * configs. Each is implemented as an instantiation templated function. Two michael@0: * levels of switch statements are used to select the correct instantiation, one michael@0: * for the src config and one for the dst config. michael@0: */ michael@0: michael@0: template michael@0: inline void convert_config8888(uint32_t* dstPixels, michael@0: size_t dstRowBytes, michael@0: const uint32_t* srcPixels, michael@0: size_t srcRowBytes, michael@0: int width, michael@0: int height) { michael@0: intptr_t dstPix = reinterpret_cast(dstPixels); michael@0: intptr_t srcPix = reinterpret_cast(srcPixels); michael@0: michael@0: for (int y = 0; y < height; ++y) { michael@0: srcPixels = reinterpret_cast(srcPix); michael@0: dstPixels = reinterpret_cast(dstPix); michael@0: for (int x = 0; x < width; ++x) { michael@0: dstPixels[x] = convert_pixel(srcPixels[x]); michael@0: } michael@0: dstPix += dstRowBytes; michael@0: srcPix += srcRowBytes; michael@0: } michael@0: } michael@0: michael@0: template michael@0: inline void convert_config8888(uint32_t* dstPixels, michael@0: size_t dstRowBytes, michael@0: SkCanvas::Config8888 dstConfig, michael@0: const uint32_t* srcPixels, michael@0: size_t srcRowBytes, michael@0: int width, michael@0: int height) { michael@0: switch(dstConfig) { michael@0: case SkCanvas::kNative_Premul_Config8888: michael@0: convert_config8888(dstPixels, dstRowBytes, srcPixels, srcRowBytes, width, height); michael@0: break; michael@0: case SkCanvas::kNative_Unpremul_Config8888: michael@0: convert_config8888(dstPixels, dstRowBytes, srcPixels, srcRowBytes, width, height); michael@0: break; michael@0: case SkCanvas::kBGRA_Premul_Config8888: michael@0: convert_config8888(dstPixels, dstRowBytes, srcPixels, srcRowBytes, width, height); michael@0: break; michael@0: case SkCanvas::kBGRA_Unpremul_Config8888: michael@0: convert_config8888(dstPixels, dstRowBytes, srcPixels, srcRowBytes, width, height); michael@0: break; michael@0: case SkCanvas::kRGBA_Premul_Config8888: michael@0: convert_config8888(dstPixels, dstRowBytes, srcPixels, srcRowBytes, width, height); michael@0: break; michael@0: case SkCanvas::kRGBA_Unpremul_Config8888: michael@0: convert_config8888(dstPixels, dstRowBytes, srcPixels, srcRowBytes, width, height); michael@0: break; michael@0: default: michael@0: SkDEBUGFAIL("Unexpected config8888"); michael@0: break; michael@0: } michael@0: } michael@0: michael@0: } michael@0: michael@0: void SkConvertConfig8888Pixels(uint32_t* dstPixels, michael@0: size_t dstRowBytes, michael@0: SkCanvas::Config8888 dstConfig, michael@0: const uint32_t* srcPixels, michael@0: size_t srcRowBytes, michael@0: SkCanvas::Config8888 srcConfig, michael@0: int width, michael@0: int height) { michael@0: if (srcConfig == dstConfig) { michael@0: if (srcPixels == dstPixels) { michael@0: return; michael@0: } michael@0: if (dstRowBytes == srcRowBytes && michael@0: 4U * width == srcRowBytes) { michael@0: memcpy(dstPixels, srcPixels, srcRowBytes * height); michael@0: return; michael@0: } else { michael@0: intptr_t srcPix = reinterpret_cast(srcPixels); michael@0: intptr_t dstPix = reinterpret_cast(dstPixels); michael@0: for (int y = 0; y < height; ++y) { michael@0: srcPixels = reinterpret_cast(srcPix); michael@0: dstPixels = reinterpret_cast(dstPix); michael@0: memcpy(dstPixels, srcPixels, 4 * width); michael@0: srcPix += srcRowBytes; michael@0: dstPix += dstRowBytes; michael@0: } michael@0: return; michael@0: } michael@0: } michael@0: switch(srcConfig) { michael@0: case SkCanvas::kNative_Premul_Config8888: michael@0: convert_config8888(dstPixels, dstRowBytes, dstConfig, srcPixels, srcRowBytes, width, height); michael@0: break; michael@0: case SkCanvas::kNative_Unpremul_Config8888: michael@0: convert_config8888(dstPixels, dstRowBytes, dstConfig, srcPixels, srcRowBytes, width, height); michael@0: break; michael@0: case SkCanvas::kBGRA_Premul_Config8888: michael@0: convert_config8888(dstPixels, dstRowBytes, dstConfig, srcPixels, srcRowBytes, width, height); michael@0: break; michael@0: case SkCanvas::kBGRA_Unpremul_Config8888: michael@0: convert_config8888(dstPixels, dstRowBytes, dstConfig, srcPixels, srcRowBytes, width, height); michael@0: break; michael@0: case SkCanvas::kRGBA_Premul_Config8888: michael@0: convert_config8888(dstPixels, dstRowBytes, dstConfig, srcPixels, srcRowBytes, width, height); michael@0: break; michael@0: case SkCanvas::kRGBA_Unpremul_Config8888: michael@0: convert_config8888(dstPixels, dstRowBytes, dstConfig, srcPixels, srcRowBytes, width, height); michael@0: break; michael@0: default: michael@0: SkDEBUGFAIL("Unexpected config8888"); michael@0: break; michael@0: } michael@0: } michael@0: michael@0: uint32_t SkPackConfig8888(SkCanvas::Config8888 config, michael@0: uint32_t a, michael@0: uint32_t r, michael@0: uint32_t g, michael@0: uint32_t b) { michael@0: switch (config) { michael@0: case SkCanvas::kNative_Premul_Config8888: michael@0: case SkCanvas::kNative_Unpremul_Config8888: michael@0: return pack_config8888(a, r, g, b); michael@0: case SkCanvas::kBGRA_Premul_Config8888: michael@0: case SkCanvas::kBGRA_Unpremul_Config8888: michael@0: return pack_config8888<3, 2, 1, 0>(a, r, g, b); michael@0: case SkCanvas::kRGBA_Premul_Config8888: michael@0: case SkCanvas::kRGBA_Unpremul_Config8888: michael@0: return pack_config8888<3, 0, 1, 2>(a, r, g, b); michael@0: default: michael@0: SkDEBUGFAIL("Unexpected config8888"); michael@0: return 0; michael@0: } michael@0: }