1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/core/SkConfig8888.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,280 @@ 1.4 +#include "SkConfig8888.h" 1.5 +#include "SkMathPriv.h" 1.6 +#include "SkUnPreMultiply.h" 1.7 + 1.8 +namespace { 1.9 + 1.10 +template <int A_IDX, int R_IDX, int G_IDX, int B_IDX> 1.11 +inline uint32_t pack_config8888(uint32_t a, uint32_t r, 1.12 + uint32_t g, uint32_t b) { 1.13 +#ifdef SK_CPU_LENDIAN 1.14 + return (a << (A_IDX * 8)) | (r << (R_IDX * 8)) | 1.15 + (g << (G_IDX * 8)) | (b << (B_IDX * 8)); 1.16 +#else 1.17 + return (a << ((3-A_IDX) * 8)) | (r << ((3-R_IDX) * 8)) | 1.18 + (g << ((3-G_IDX) * 8)) | (b << ((3-B_IDX) * 8)); 1.19 +#endif 1.20 +} 1.21 + 1.22 +template <int A_IDX, int R_IDX, int G_IDX, int B_IDX> 1.23 +inline void unpack_config8888(uint32_t color, 1.24 + uint32_t* a, uint32_t* r, 1.25 + uint32_t* g, uint32_t* b) { 1.26 +#ifdef SK_CPU_LENDIAN 1.27 + *a = (color >> (A_IDX * 8)) & 0xff; 1.28 + *r = (color >> (R_IDX * 8)) & 0xff; 1.29 + *g = (color >> (G_IDX * 8)) & 0xff; 1.30 + *b = (color >> (B_IDX * 8)) & 0xff; 1.31 +#else 1.32 + *a = (color >> ((3 - A_IDX) * 8)) & 0xff; 1.33 + *r = (color >> ((3 - R_IDX) * 8)) & 0xff; 1.34 + *g = (color >> ((3 - G_IDX) * 8)) & 0xff; 1.35 + *b = (color >> ((3 - B_IDX) * 8)) & 0xff; 1.36 +#endif 1.37 +} 1.38 + 1.39 +#ifdef SK_CPU_LENDIAN 1.40 + static const int SK_NATIVE_A_IDX = SK_A32_SHIFT / 8; 1.41 + static const int SK_NATIVE_R_IDX = SK_R32_SHIFT / 8; 1.42 + static const int SK_NATIVE_G_IDX = SK_G32_SHIFT / 8; 1.43 + static const int SK_NATIVE_B_IDX = SK_B32_SHIFT / 8; 1.44 +#else 1.45 + static const int SK_NATIVE_A_IDX = 3 - (SK_A32_SHIFT / 8); 1.46 + static const int SK_NATIVE_R_IDX = 3 - (SK_R32_SHIFT / 8); 1.47 + static const int SK_NATIVE_G_IDX = 3 - (SK_G32_SHIFT / 8); 1.48 + static const int SK_NATIVE_B_IDX = 3 - (SK_B32_SHIFT / 8); 1.49 +#endif 1.50 + 1.51 +/** 1.52 + * convert_pixel<OUT_CFG, IN_CFG converts a pixel value from one Config8888 to 1.53 + * another. It is implemented by first expanding OUT_CFG to r, g, b, a indices 1.54 + * and an is_premul bool as params to another template function. Then IN_CFG is 1.55 + * expanded via another function call. 1.56 + */ 1.57 + 1.58 +template <bool OUT_PM, int OUT_A_IDX, int OUT_R_IDX, int OUT_G_IDX, int OUT_B_IDX, 1.59 + bool IN_PM, int IN_A_IDX, int IN_R_IDX, int IN_G_IDX, int IN_B_IDX> 1.60 +inline uint32_t convert_pixel(uint32_t pixel) { 1.61 + uint32_t a, r, g, b; 1.62 + unpack_config8888<IN_A_IDX, IN_R_IDX, IN_G_IDX, IN_B_IDX>(pixel, &a, &r, &g, &b); 1.63 + if (IN_PM && !OUT_PM) { 1.64 + // Using SkUnPreMultiply::ApplyScale is faster than (value * 0xff) / a. 1.65 + if (a) { 1.66 + SkUnPreMultiply::Scale scale = SkUnPreMultiply::GetScale(a); 1.67 + r = SkUnPreMultiply::ApplyScale(scale, r); 1.68 + g = SkUnPreMultiply::ApplyScale(scale, g); 1.69 + b = SkUnPreMultiply::ApplyScale(scale, b); 1.70 + } else { 1.71 + return 0; 1.72 + } 1.73 + } else if (!IN_PM && OUT_PM) { 1.74 + // This matches SkUnPreMultiply conversion which we are replacing. 1.75 + r = SkMulDiv255Round(r, a); 1.76 + g = SkMulDiv255Round(g, a); 1.77 + b = SkMulDiv255Round(b, a); 1.78 + } 1.79 + return pack_config8888<OUT_A_IDX, OUT_R_IDX, OUT_G_IDX, OUT_B_IDX>(a, r, g, b); 1.80 +} 1.81 + 1.82 +template <bool OUT_PM, int OUT_A_IDX, int OUT_R_IDX, int OUT_G_IDX, int OUT_B_IDX, SkCanvas::Config8888 IN_CFG> 1.83 +inline uint32_t convert_pixel(uint32_t pixel) { 1.84 + switch(IN_CFG) { 1.85 + case SkCanvas::kNative_Premul_Config8888: 1.86 + return convert_pixel<OUT_PM, OUT_A_IDX, OUT_R_IDX, OUT_G_IDX, OUT_B_IDX, 1.87 + true, SK_NATIVE_A_IDX, SK_NATIVE_R_IDX, SK_NATIVE_G_IDX, SK_NATIVE_B_IDX>(pixel); 1.88 + break; 1.89 + case SkCanvas::kNative_Unpremul_Config8888: 1.90 + return convert_pixel<OUT_PM, OUT_A_IDX, OUT_R_IDX, OUT_G_IDX, OUT_B_IDX, 1.91 + false, SK_NATIVE_A_IDX, SK_NATIVE_R_IDX, SK_NATIVE_G_IDX, SK_NATIVE_B_IDX>(pixel); 1.92 + break; 1.93 + case SkCanvas::kBGRA_Premul_Config8888: 1.94 + return convert_pixel<OUT_PM, OUT_A_IDX, OUT_R_IDX, OUT_G_IDX, OUT_B_IDX, 1.95 + true, 3, 2, 1, 0>(pixel); 1.96 + break; 1.97 + case SkCanvas::kBGRA_Unpremul_Config8888: 1.98 + return convert_pixel<OUT_PM, OUT_A_IDX, OUT_R_IDX, OUT_G_IDX, OUT_B_IDX, 1.99 + false, 3, 2, 1, 0>(pixel); 1.100 + break; 1.101 + case SkCanvas::kRGBA_Premul_Config8888: 1.102 + return convert_pixel<OUT_PM, OUT_A_IDX, OUT_R_IDX, OUT_G_IDX, OUT_B_IDX, 1.103 + true, 3, 0, 1, 2>(pixel); 1.104 + break; 1.105 + case SkCanvas::kRGBA_Unpremul_Config8888: 1.106 + return convert_pixel<OUT_PM, OUT_A_IDX, OUT_R_IDX, OUT_G_IDX, OUT_B_IDX, 1.107 + false, 3, 0, 1, 2>(pixel); 1.108 + break; 1.109 + default: 1.110 + SkDEBUGFAIL("Unexpected config8888"); 1.111 + return 0; 1.112 + break; 1.113 + } 1.114 +} 1.115 + 1.116 +template <SkCanvas::Config8888 OUT_CFG, SkCanvas::Config8888 IN_CFG> 1.117 +inline uint32_t convert_pixel(uint32_t pixel) { 1.118 + switch(OUT_CFG) { 1.119 + case SkCanvas::kNative_Premul_Config8888: 1.120 + return convert_pixel<true, SK_NATIVE_A_IDX, SK_NATIVE_R_IDX, SK_NATIVE_G_IDX, SK_NATIVE_B_IDX, IN_CFG>(pixel); 1.121 + break; 1.122 + case SkCanvas::kNative_Unpremul_Config8888: 1.123 + return convert_pixel<false, SK_NATIVE_A_IDX, SK_NATIVE_R_IDX, SK_NATIVE_G_IDX, SK_NATIVE_B_IDX, IN_CFG>(pixel); 1.124 + break; 1.125 + case SkCanvas::kBGRA_Premul_Config8888: 1.126 + return convert_pixel<true, 3, 2, 1, 0, IN_CFG>(pixel); 1.127 + break; 1.128 + case SkCanvas::kBGRA_Unpremul_Config8888: 1.129 + return convert_pixel<false, 3, 2, 1, 0, IN_CFG>(pixel); 1.130 + break; 1.131 + case SkCanvas::kRGBA_Premul_Config8888: 1.132 + return convert_pixel<true, 3, 0, 1, 2, IN_CFG>(pixel); 1.133 + break; 1.134 + case SkCanvas::kRGBA_Unpremul_Config8888: 1.135 + return convert_pixel<false, 3, 0, 1, 2, IN_CFG>(pixel); 1.136 + break; 1.137 + default: 1.138 + SkDEBUGFAIL("Unexpected config8888"); 1.139 + return 0; 1.140 + break; 1.141 + } 1.142 +} 1.143 + 1.144 +/** 1.145 + * SkConvertConfig8888Pixels has 6 * 6 possible combinations of src and dst 1.146 + * configs. Each is implemented as an instantiation templated function. Two 1.147 + * levels of switch statements are used to select the correct instantiation, one 1.148 + * for the src config and one for the dst config. 1.149 + */ 1.150 + 1.151 +template <SkCanvas::Config8888 DST_CFG, SkCanvas::Config8888 SRC_CFG> 1.152 +inline void convert_config8888(uint32_t* dstPixels, 1.153 + size_t dstRowBytes, 1.154 + const uint32_t* srcPixels, 1.155 + size_t srcRowBytes, 1.156 + int width, 1.157 + int height) { 1.158 + intptr_t dstPix = reinterpret_cast<intptr_t>(dstPixels); 1.159 + intptr_t srcPix = reinterpret_cast<intptr_t>(srcPixels); 1.160 + 1.161 + for (int y = 0; y < height; ++y) { 1.162 + srcPixels = reinterpret_cast<const uint32_t*>(srcPix); 1.163 + dstPixels = reinterpret_cast<uint32_t*>(dstPix); 1.164 + for (int x = 0; x < width; ++x) { 1.165 + dstPixels[x] = convert_pixel<DST_CFG, SRC_CFG>(srcPixels[x]); 1.166 + } 1.167 + dstPix += dstRowBytes; 1.168 + srcPix += srcRowBytes; 1.169 + } 1.170 +} 1.171 + 1.172 +template <SkCanvas::Config8888 SRC_CFG> 1.173 +inline void convert_config8888(uint32_t* dstPixels, 1.174 + size_t dstRowBytes, 1.175 + SkCanvas::Config8888 dstConfig, 1.176 + const uint32_t* srcPixels, 1.177 + size_t srcRowBytes, 1.178 + int width, 1.179 + int height) { 1.180 + switch(dstConfig) { 1.181 + case SkCanvas::kNative_Premul_Config8888: 1.182 + convert_config8888<SkCanvas::kNative_Premul_Config8888, SRC_CFG>(dstPixels, dstRowBytes, srcPixels, srcRowBytes, width, height); 1.183 + break; 1.184 + case SkCanvas::kNative_Unpremul_Config8888: 1.185 + convert_config8888<SkCanvas::kNative_Unpremul_Config8888, SRC_CFG>(dstPixels, dstRowBytes, srcPixels, srcRowBytes, width, height); 1.186 + break; 1.187 + case SkCanvas::kBGRA_Premul_Config8888: 1.188 + convert_config8888<SkCanvas::kBGRA_Premul_Config8888, SRC_CFG>(dstPixels, dstRowBytes, srcPixels, srcRowBytes, width, height); 1.189 + break; 1.190 + case SkCanvas::kBGRA_Unpremul_Config8888: 1.191 + convert_config8888<SkCanvas::kBGRA_Unpremul_Config8888, SRC_CFG>(dstPixels, dstRowBytes, srcPixels, srcRowBytes, width, height); 1.192 + break; 1.193 + case SkCanvas::kRGBA_Premul_Config8888: 1.194 + convert_config8888<SkCanvas::kRGBA_Premul_Config8888, SRC_CFG>(dstPixels, dstRowBytes, srcPixels, srcRowBytes, width, height); 1.195 + break; 1.196 + case SkCanvas::kRGBA_Unpremul_Config8888: 1.197 + convert_config8888<SkCanvas::kRGBA_Unpremul_Config8888, SRC_CFG>(dstPixels, dstRowBytes, srcPixels, srcRowBytes, width, height); 1.198 + break; 1.199 + default: 1.200 + SkDEBUGFAIL("Unexpected config8888"); 1.201 + break; 1.202 + } 1.203 +} 1.204 + 1.205 +} 1.206 + 1.207 +void SkConvertConfig8888Pixels(uint32_t* dstPixels, 1.208 + size_t dstRowBytes, 1.209 + SkCanvas::Config8888 dstConfig, 1.210 + const uint32_t* srcPixels, 1.211 + size_t srcRowBytes, 1.212 + SkCanvas::Config8888 srcConfig, 1.213 + int width, 1.214 + int height) { 1.215 + if (srcConfig == dstConfig) { 1.216 + if (srcPixels == dstPixels) { 1.217 + return; 1.218 + } 1.219 + if (dstRowBytes == srcRowBytes && 1.220 + 4U * width == srcRowBytes) { 1.221 + memcpy(dstPixels, srcPixels, srcRowBytes * height); 1.222 + return; 1.223 + } else { 1.224 + intptr_t srcPix = reinterpret_cast<intptr_t>(srcPixels); 1.225 + intptr_t dstPix = reinterpret_cast<intptr_t>(dstPixels); 1.226 + for (int y = 0; y < height; ++y) { 1.227 + srcPixels = reinterpret_cast<const uint32_t*>(srcPix); 1.228 + dstPixels = reinterpret_cast<uint32_t*>(dstPix); 1.229 + memcpy(dstPixels, srcPixels, 4 * width); 1.230 + srcPix += srcRowBytes; 1.231 + dstPix += dstRowBytes; 1.232 + } 1.233 + return; 1.234 + } 1.235 + } 1.236 + switch(srcConfig) { 1.237 + case SkCanvas::kNative_Premul_Config8888: 1.238 + convert_config8888<SkCanvas::kNative_Premul_Config8888>(dstPixels, dstRowBytes, dstConfig, srcPixels, srcRowBytes, width, height); 1.239 + break; 1.240 + case SkCanvas::kNative_Unpremul_Config8888: 1.241 + convert_config8888<SkCanvas::kNative_Unpremul_Config8888>(dstPixels, dstRowBytes, dstConfig, srcPixels, srcRowBytes, width, height); 1.242 + break; 1.243 + case SkCanvas::kBGRA_Premul_Config8888: 1.244 + convert_config8888<SkCanvas::kBGRA_Premul_Config8888>(dstPixels, dstRowBytes, dstConfig, srcPixels, srcRowBytes, width, height); 1.245 + break; 1.246 + case SkCanvas::kBGRA_Unpremul_Config8888: 1.247 + convert_config8888<SkCanvas::kBGRA_Unpremul_Config8888>(dstPixels, dstRowBytes, dstConfig, srcPixels, srcRowBytes, width, height); 1.248 + break; 1.249 + case SkCanvas::kRGBA_Premul_Config8888: 1.250 + convert_config8888<SkCanvas::kRGBA_Premul_Config8888>(dstPixels, dstRowBytes, dstConfig, srcPixels, srcRowBytes, width, height); 1.251 + break; 1.252 + case SkCanvas::kRGBA_Unpremul_Config8888: 1.253 + convert_config8888<SkCanvas::kRGBA_Unpremul_Config8888>(dstPixels, dstRowBytes, dstConfig, srcPixels, srcRowBytes, width, height); 1.254 + break; 1.255 + default: 1.256 + SkDEBUGFAIL("Unexpected config8888"); 1.257 + break; 1.258 + } 1.259 +} 1.260 + 1.261 +uint32_t SkPackConfig8888(SkCanvas::Config8888 config, 1.262 + uint32_t a, 1.263 + uint32_t r, 1.264 + uint32_t g, 1.265 + uint32_t b) { 1.266 + switch (config) { 1.267 + case SkCanvas::kNative_Premul_Config8888: 1.268 + case SkCanvas::kNative_Unpremul_Config8888: 1.269 + return pack_config8888<SK_NATIVE_A_IDX, 1.270 + SK_NATIVE_R_IDX, 1.271 + SK_NATIVE_G_IDX, 1.272 + SK_NATIVE_B_IDX>(a, r, g, b); 1.273 + case SkCanvas::kBGRA_Premul_Config8888: 1.274 + case SkCanvas::kBGRA_Unpremul_Config8888: 1.275 + return pack_config8888<3, 2, 1, 0>(a, r, g, b); 1.276 + case SkCanvas::kRGBA_Premul_Config8888: 1.277 + case SkCanvas::kRGBA_Unpremul_Config8888: 1.278 + return pack_config8888<3, 0, 1, 2>(a, r, g, b); 1.279 + default: 1.280 + SkDEBUGFAIL("Unexpected config8888"); 1.281 + return 0; 1.282 + } 1.283 +}