| OLD | NEW | 
|    1 #include "SkConfig8888.h" |    1 #include "SkConfig8888.h" | 
|    2 #include "SkColorPriv.h" |  | 
|    3 #include "SkMathPriv.h" |    2 #include "SkMathPriv.h" | 
|    4 #include "SkUnPreMultiply.h" |    3 #include "SkUnPreMultiply.h" | 
|    5  |    4  | 
|    6 enum AlphaVerb { |    5 namespace { | 
|    7     kNothing_AlphaVerb, |    6  | 
|    8     kPremul_AlphaVerb, |    7 template <int A_IDX, int R_IDX, int G_IDX, int B_IDX> | 
|    9     kUnpremul_AlphaVerb, |    8 inline uint32_t pack_config8888(uint32_t a, uint32_t r, | 
|   10 }; |    9                                 uint32_t g, uint32_t b) { | 
|   11  |   10 #ifdef SK_CPU_LENDIAN | 
|   12 template <bool doSwapRB, AlphaVerb doAlpha> uint32_t convert32(uint32_t c) { |   11     return (a << (A_IDX * 8)) | (r << (R_IDX * 8)) | | 
|   13     if (doSwapRB) { |   12            (g << (G_IDX * 8)) | (b << (B_IDX * 8)); | 
|   14         c = SkSwizzle_RB(c); |   13 #else | 
|   15     } |   14     return (a << ((3-A_IDX) * 8)) | (r << ((3-R_IDX) * 8)) | | 
|   16  |   15            (g << ((3-G_IDX) * 8)) | (b << ((3-B_IDX) * 8)); | 
|   17     // Lucky for us, in both RGBA and BGRA, the alpha component is always in the
      same place, so |   16 #endif | 
|   18     // we can perform premul or unpremul the same way without knowing the swizzl
     es for RGB. |   17 } | 
|   19     switch (doAlpha) { |   18  | 
|   20         case kNothing_AlphaVerb: |   19 template <int A_IDX, int R_IDX, int G_IDX, int B_IDX> | 
|   21             // no change |   20 inline void unpack_config8888(uint32_t color, | 
|   22             break; |   21                               uint32_t* a, uint32_t* r, | 
|   23         case kPremul_AlphaVerb: |   22                               uint32_t* g, uint32_t* b) { | 
|   24             c = SkPreMultiplyARGB(SkGetPackedA32(c), SkGetPackedR32(c), |   23 #ifdef SK_CPU_LENDIAN | 
|   25                                   SkGetPackedG32(c), SkGetPackedB32(c)); |   24     *a = (color >> (A_IDX * 8)) & 0xff; | 
|   26             break; |   25     *r = (color >> (R_IDX * 8)) & 0xff; | 
|   27         case kUnpremul_AlphaVerb: |   26     *g = (color >> (G_IDX * 8)) & 0xff; | 
|   28             c = SkUnPreMultiply::UnPreMultiplyPreservingByteOrder(c); |   27     *b = (color >> (B_IDX * 8)) & 0xff; | 
|   29             break; |   28 #else | 
|   30     } |   29     *a = (color >> ((3 - A_IDX) * 8)) & 0xff; | 
|   31     return c; |   30     *r = (color >> ((3 - R_IDX) * 8)) & 0xff; | 
|   32 } |   31     *g = (color >> ((3 - G_IDX) * 8)) & 0xff; | 
|   33  |   32     *b = (color >> ((3 - B_IDX) * 8)) & 0xff; | 
|   34 template <bool doSwapRB, AlphaVerb doAlpha> |   33 #endif | 
|   35 void convert32_row(uint32_t* dst, const uint32_t* src, int count) { |   34 } | 
|   36     // This has to be correct if src == dst (but not partial overlap) |   35  | 
|   37     for (int i = 0; i < count; ++i) { |   36 #ifdef SK_CPU_LENDIAN | 
|   38         dst[i] = convert32<doSwapRB, doAlpha>(src[i]); |   37     static const int SK_NATIVE_A_IDX = SK_A32_SHIFT / 8; | 
|   39     } |   38     static const int SK_NATIVE_R_IDX = SK_R32_SHIFT / 8; | 
|   40 } |   39     static const int SK_NATIVE_G_IDX = SK_G32_SHIFT / 8; | 
|   41  |   40     static const int SK_NATIVE_B_IDX = SK_B32_SHIFT / 8; | 
|   42 static bool is_32bit_colortype(SkColorType ct) { |   41 #else | 
|   43     return kRGBA_8888_SkColorType == ct || kBGRA_8888_SkColorType == ct; |   42     static const int SK_NATIVE_A_IDX = 3 - (SK_A32_SHIFT / 8); | 
|   44 } |   43     static const int SK_NATIVE_R_IDX = 3 - (SK_R32_SHIFT / 8); | 
|   45  |   44     static const int SK_NATIVE_G_IDX = 3 - (SK_G32_SHIFT / 8); | 
|   46 static AlphaVerb compute_AlphaVerb(SkAlphaType src, SkAlphaType dst) { |   45     static const int SK_NATIVE_B_IDX = 3 - (SK_B32_SHIFT / 8); | 
|   47     SkASSERT(kIgnore_SkAlphaType != src); |   46 #endif | 
|   48     SkASSERT(kIgnore_SkAlphaType != dst); |   47  | 
|   49  |   48 /** | 
|   50     if (kOpaque_SkAlphaType == src || kOpaque_SkAlphaType == dst || src == dst) 
     { |   49  * convert_pixel<OUT_CFG, IN_CFG converts a pixel value from one Config8888 to | 
|   51         return kNothing_AlphaVerb; |   50  * another. It is implemented by first expanding OUT_CFG to r, g, b, a indices | 
|   52     } |   51  * and an is_premul bool as params to another template function. Then IN_CFG is | 
|   53     if (kPremul_SkAlphaType == dst) { |   52  * expanded via another function call. | 
|   54         SkASSERT(kUnpremul_SkAlphaType == src); |   53  */ | 
|   55         return kPremul_AlphaVerb; |   54  | 
|   56     } else { |   55 template <bool OUT_PM, int OUT_A_IDX, int OUT_R_IDX, int OUT_G_IDX, int OUT_B_ID
     X, | 
|   57         SkASSERT(kPremul_SkAlphaType == src); |   56           bool IN_PM,  int IN_A_IDX,  int IN_R_IDX,  int IN_G_IDX,  int IN_B_IDX
     > | 
|   58         SkASSERT(kUnpremul_SkAlphaType == dst); |   57 inline uint32_t convert_pixel(uint32_t pixel) { | 
|   59         return kUnpremul_AlphaVerb; |   58     uint32_t a, r, g, b; | 
|   60     } |   59     unpack_config8888<IN_A_IDX, IN_R_IDX, IN_G_IDX, IN_B_IDX>(pixel, &a, &r, &g,
      &b); | 
|   61 } |   60     if (IN_PM && !OUT_PM) { | 
|   62  |   61         // Using SkUnPreMultiply::ApplyScale is faster than (value * 0xff) / a. | 
|   63 static void memcpy32_row(uint32_t* dst, const uint32_t* src, int count) { |   62         if (a) { | 
|   64     memcpy(dst, src, count * 4); |   63             SkUnPreMultiply::Scale scale = SkUnPreMultiply::GetScale(a); | 
|   65 } |   64             r = SkUnPreMultiply::ApplyScale(scale, r); | 
|   66  |   65             g = SkUnPreMultiply::ApplyScale(scale, g); | 
|   67 bool SkSrcPixelInfo::convertPixelsTo(SkDstPixelInfo* dst, int width, int height)
      const { |   66             b = SkUnPreMultiply::ApplyScale(scale, b); | 
|   68     if (width <= 0 || height <= 0) { |   67         } else { | 
|   69         return false; |   68             return 0; | 
|   70     } |   69         } | 
|   71  |   70     } else if (!IN_PM && OUT_PM) { | 
|   72     if (!is_32bit_colortype(fColorType) || !is_32bit_colortype(dst->fColorType))
      { |   71         // This matches SkUnPreMultiply conversion which we are replacing. | 
|   73         return false; |   72         r = SkMulDiv255Round(r, a); | 
|   74     } |   73         g = SkMulDiv255Round(g, a); | 
|   75  |   74         b = SkMulDiv255Round(b, a); | 
|   76     void (*proc)(uint32_t* dst, const uint32_t* src, int count); |   75     } | 
|   77     AlphaVerb doAlpha = compute_AlphaVerb(fAlphaType, dst->fAlphaType); |   76     return pack_config8888<OUT_A_IDX, OUT_R_IDX, OUT_G_IDX, OUT_B_IDX>(a, r, g, 
     b); | 
|   78     bool doSwapRB = fColorType != dst->fColorType; |   77 } | 
|   79  |   78  | 
|   80     switch (doAlpha) { |   79 template <bool OUT_PM, int OUT_A_IDX, int OUT_R_IDX, int OUT_G_IDX, int OUT_B_ID
     X, SkCanvas::Config8888 IN_CFG> | 
|   81         case kNothing_AlphaVerb: |   80 inline uint32_t convert_pixel(uint32_t pixel) { | 
|   82             if (doSwapRB) { |   81     switch(IN_CFG) { | 
|   83                 proc = convert32_row<true, kNothing_AlphaVerb>; |   82         case SkCanvas::kNative_Premul_Config8888: | 
|   84             } else { |   83             return convert_pixel<OUT_PM, OUT_A_IDX,       OUT_R_IDX,       OUT_G
     _IDX,       OUT_B_IDX, | 
|   85                 if (fPixels == dst->fPixels) { |   84                                  true,  SK_NATIVE_A_IDX,  SK_NATIVE_R_IDX, SK_NA
     TIVE_G_IDX, SK_NATIVE_B_IDX>(pixel); | 
|   86                     return true; |   85             break; | 
|   87                 } |   86         case SkCanvas::kNative_Unpremul_Config8888: | 
|   88                 proc = memcpy32_row; |   87             return convert_pixel<OUT_PM, OUT_A_IDX,       OUT_R_IDX,       OUT_G
     _IDX,       OUT_B_IDX, | 
 |   88                                  false,  SK_NATIVE_A_IDX, SK_NATIVE_R_IDX, SK_NA
     TIVE_G_IDX, SK_NATIVE_B_IDX>(pixel); | 
 |   89             break; | 
 |   90         case SkCanvas::kBGRA_Premul_Config8888: | 
 |   91             return convert_pixel<OUT_PM, OUT_A_IDX, OUT_R_IDX, OUT_G_IDX, OUT_B_
     IDX, | 
 |   92                                  true,  3,         2,         1,         0>(pixe
     l); | 
 |   93             break; | 
 |   94         case SkCanvas::kBGRA_Unpremul_Config8888: | 
 |   95             return convert_pixel<OUT_PM, OUT_A_IDX, OUT_R_IDX, OUT_G_IDX, OUT_B_
     IDX, | 
 |   96                                  false,  3,         2,         1,         0>(pix
     el); | 
 |   97             break; | 
 |   98         case SkCanvas::kRGBA_Premul_Config8888: | 
 |   99             return convert_pixel<OUT_PM, OUT_A_IDX, OUT_R_IDX, OUT_G_IDX, OUT_B_
     IDX, | 
 |  100                                  true,  3,         0,         1,         2>(pixe
     l); | 
 |  101             break; | 
 |  102         case SkCanvas::kRGBA_Unpremul_Config8888: | 
 |  103             return convert_pixel<OUT_PM, OUT_A_IDX, OUT_R_IDX, OUT_G_IDX, OUT_B_
     IDX, | 
 |  104                                  false,  3,         0,         1,         2>(pix
     el); | 
 |  105             break; | 
 |  106         default: | 
 |  107             SkDEBUGFAIL("Unexpected config8888"); | 
 |  108             return 0; | 
 |  109             break; | 
 |  110     } | 
 |  111 } | 
 |  112  | 
 |  113 template <SkCanvas::Config8888 OUT_CFG, SkCanvas::Config8888 IN_CFG> | 
 |  114 inline uint32_t convert_pixel(uint32_t pixel) { | 
 |  115     switch(OUT_CFG) { | 
 |  116         case SkCanvas::kNative_Premul_Config8888: | 
 |  117             return convert_pixel<true,  SK_NATIVE_A_IDX,  SK_NATIVE_R_IDX, SK_NA
     TIVE_G_IDX, SK_NATIVE_B_IDX, IN_CFG>(pixel); | 
 |  118             break; | 
 |  119         case SkCanvas::kNative_Unpremul_Config8888: | 
 |  120             return convert_pixel<false,  SK_NATIVE_A_IDX,  SK_NATIVE_R_IDX, SK_N
     ATIVE_G_IDX, SK_NATIVE_B_IDX, IN_CFG>(pixel); | 
 |  121             break; | 
 |  122         case SkCanvas::kBGRA_Premul_Config8888: | 
 |  123             return convert_pixel<true, 3, 2, 1, 0, IN_CFG>(pixel); | 
 |  124             break; | 
 |  125         case SkCanvas::kBGRA_Unpremul_Config8888: | 
 |  126             return convert_pixel<false, 3, 2, 1, 0, IN_CFG>(pixel); | 
 |  127             break; | 
 |  128         case SkCanvas::kRGBA_Premul_Config8888: | 
 |  129             return convert_pixel<true, 3, 0, 1, 2, IN_CFG>(pixel); | 
 |  130             break; | 
 |  131         case SkCanvas::kRGBA_Unpremul_Config8888: | 
 |  132             return convert_pixel<false, 3, 0, 1, 2, IN_CFG>(pixel); | 
 |  133             break; | 
 |  134         default: | 
 |  135             SkDEBUGFAIL("Unexpected config8888"); | 
 |  136             return 0; | 
 |  137             break; | 
 |  138     } | 
 |  139 } | 
 |  140  | 
 |  141 /** | 
 |  142  * SkConvertConfig8888Pixels has 6 * 6 possible combinations of src and dst | 
 |  143  * configs. Each is implemented as an instantiation templated function. Two | 
 |  144  * levels of switch statements are used to select the correct instantiation, one | 
 |  145  * for the src config and one for the dst config. | 
 |  146  */ | 
 |  147  | 
 |  148 template <SkCanvas::Config8888 DST_CFG, SkCanvas::Config8888 SRC_CFG> | 
 |  149 inline void convert_config8888(uint32_t* dstPixels, | 
 |  150                                size_t dstRowBytes, | 
 |  151                                const uint32_t* srcPixels, | 
 |  152                                size_t srcRowBytes, | 
 |  153                                int width, | 
 |  154                                int height) { | 
 |  155     intptr_t dstPix = reinterpret_cast<intptr_t>(dstPixels); | 
 |  156     intptr_t srcPix = reinterpret_cast<intptr_t>(srcPixels); | 
 |  157  | 
 |  158     for (int y = 0; y < height; ++y) { | 
 |  159         srcPixels = reinterpret_cast<const uint32_t*>(srcPix); | 
 |  160         dstPixels = reinterpret_cast<uint32_t*>(dstPix); | 
 |  161         for (int x = 0; x < width; ++x) { | 
 |  162             dstPixels[x] = convert_pixel<DST_CFG, SRC_CFG>(srcPixels[x]); | 
 |  163         } | 
 |  164         dstPix += dstRowBytes; | 
 |  165         srcPix += srcRowBytes; | 
 |  166     } | 
 |  167 } | 
 |  168  | 
 |  169 template <SkCanvas::Config8888 SRC_CFG> | 
 |  170 inline void convert_config8888(uint32_t* dstPixels, | 
 |  171                                size_t dstRowBytes, | 
 |  172                                SkCanvas::Config8888 dstConfig, | 
 |  173                                const uint32_t* srcPixels, | 
 |  174                                size_t srcRowBytes, | 
 |  175                                int width, | 
 |  176                                int height) { | 
 |  177     switch(dstConfig) { | 
 |  178         case SkCanvas::kNative_Premul_Config8888: | 
 |  179             convert_config8888<SkCanvas::kNative_Premul_Config8888, SRC_CFG>(dst
     Pixels, dstRowBytes, srcPixels, srcRowBytes, width, height); | 
 |  180             break; | 
 |  181         case SkCanvas::kNative_Unpremul_Config8888: | 
 |  182             convert_config8888<SkCanvas::kNative_Unpremul_Config8888, SRC_CFG>(d
     stPixels, dstRowBytes, srcPixels, srcRowBytes, width, height); | 
 |  183             break; | 
 |  184         case SkCanvas::kBGRA_Premul_Config8888: | 
 |  185             convert_config8888<SkCanvas::kBGRA_Premul_Config8888, SRC_CFG>(dstPi
     xels, dstRowBytes, srcPixels, srcRowBytes, width, height); | 
 |  186             break; | 
 |  187         case SkCanvas::kBGRA_Unpremul_Config8888: | 
 |  188             convert_config8888<SkCanvas::kBGRA_Unpremul_Config8888, SRC_CFG>(dst
     Pixels, dstRowBytes, srcPixels, srcRowBytes, width, height); | 
 |  189             break; | 
 |  190         case SkCanvas::kRGBA_Premul_Config8888: | 
 |  191             convert_config8888<SkCanvas::kRGBA_Premul_Config8888, SRC_CFG>(dstPi
     xels, dstRowBytes, srcPixels, srcRowBytes, width, height); | 
 |  192             break; | 
 |  193         case SkCanvas::kRGBA_Unpremul_Config8888: | 
 |  194             convert_config8888<SkCanvas::kRGBA_Unpremul_Config8888, SRC_CFG>(dst
     Pixels, dstRowBytes, srcPixels, srcRowBytes, width, height); | 
 |  195             break; | 
 |  196         default: | 
 |  197             SkDEBUGFAIL("Unexpected config8888"); | 
 |  198             break; | 
 |  199     } | 
 |  200 } | 
 |  201  | 
 |  202 } | 
 |  203  | 
 |  204 void SkConvertConfig8888Pixels(uint32_t* dstPixels, | 
 |  205                                size_t dstRowBytes, | 
 |  206                                SkCanvas::Config8888 dstConfig, | 
 |  207                                const uint32_t* srcPixels, | 
 |  208                                size_t srcRowBytes, | 
 |  209                                SkCanvas::Config8888 srcConfig, | 
 |  210                                int width, | 
 |  211                                int height) { | 
 |  212     if (srcConfig == dstConfig) { | 
 |  213         if (srcPixels == dstPixels) { | 
 |  214             return; | 
 |  215         } | 
 |  216         if (dstRowBytes == srcRowBytes && | 
 |  217             4U * width == srcRowBytes) { | 
 |  218             memcpy(dstPixels, srcPixels, srcRowBytes * height); | 
 |  219             return; | 
 |  220         } else { | 
 |  221             intptr_t srcPix = reinterpret_cast<intptr_t>(srcPixels); | 
 |  222             intptr_t dstPix = reinterpret_cast<intptr_t>(dstPixels); | 
 |  223             for (int y = 0; y < height; ++y) { | 
 |  224                 srcPixels = reinterpret_cast<const uint32_t*>(srcPix); | 
 |  225                 dstPixels = reinterpret_cast<uint32_t*>(dstPix); | 
 |  226                 memcpy(dstPixels, srcPixels, 4 * width); | 
 |  227                 srcPix += srcRowBytes; | 
 |  228                 dstPix += dstRowBytes; | 
|   89             } |  229             } | 
|   90             break; |  230             return; | 
|   91         case kPremul_AlphaVerb: |  231         } | 
|   92             if (doSwapRB) { |  232     } | 
|   93                 proc = convert32_row<true, kPremul_AlphaVerb>; |  233     switch(srcConfig) { | 
|   94             } else { |  234         case SkCanvas::kNative_Premul_Config8888: | 
|   95                 proc = convert32_row<false, kPremul_AlphaVerb>; |  235             convert_config8888<SkCanvas::kNative_Premul_Config8888>(dstPixels, d
     stRowBytes, dstConfig, srcPixels, srcRowBytes, width, height); | 
|   96             } |  236             break; | 
|   97             break; |  237         case SkCanvas::kNative_Unpremul_Config8888: | 
|   98         case kUnpremul_AlphaVerb: |  238             convert_config8888<SkCanvas::kNative_Unpremul_Config8888>(dstPixels,
      dstRowBytes, dstConfig, srcPixels, srcRowBytes, width, height); | 
|   99             if (doSwapRB) { |  239             break; | 
|  100                 proc = convert32_row<true, kUnpremul_AlphaVerb>; |  240         case SkCanvas::kBGRA_Premul_Config8888: | 
|  101             } else { |  241             convert_config8888<SkCanvas::kBGRA_Premul_Config8888>(dstPixels, dst
     RowBytes, dstConfig, srcPixels, srcRowBytes, width, height); | 
|  102                 proc = convert32_row<false, kUnpremul_AlphaVerb>; |  242             break; | 
|  103             } |  243         case SkCanvas::kBGRA_Unpremul_Config8888: | 
|  104             break; |  244             convert_config8888<SkCanvas::kBGRA_Unpremul_Config8888>(dstPixels, d
     stRowBytes, dstConfig, srcPixels, srcRowBytes, width, height); | 
|  105     } |  245             break; | 
|  106  |  246         case SkCanvas::kRGBA_Premul_Config8888: | 
|  107     uint32_t* dstP = static_cast<uint32_t*>(dst->fPixels); |  247             convert_config8888<SkCanvas::kRGBA_Premul_Config8888>(dstPixels, dst
     RowBytes, dstConfig, srcPixels, srcRowBytes, width, height); | 
|  108     const uint32_t* srcP = static_cast<const uint32_t*>(fPixels); |  248             break; | 
|  109     size_t srcInc = fRowBytes >> 2; |  249         case SkCanvas::kRGBA_Unpremul_Config8888: | 
|  110     size_t dstInc = dst->fRowBytes >> 2; |  250             convert_config8888<SkCanvas::kRGBA_Unpremul_Config8888>(dstPixels, d
     stRowBytes, dstConfig, srcPixels, srcRowBytes, width, height); | 
|  111     for (int y = 0; y < height; ++y) { |  251             break; | 
|  112         proc(dstP, srcP, width); |  252         default: | 
|  113         dstP += dstInc; |  253             SkDEBUGFAIL("Unexpected config8888"); | 
|  114         srcP += srcInc; |  254             break; | 
|  115     } |  255     } | 
|  116     return true; |  256 } | 
|  117 } |  257  | 
 |  258 uint32_t SkPackConfig8888(SkCanvas::Config8888 config, | 
 |  259                           uint32_t a, | 
 |  260                           uint32_t r, | 
 |  261                           uint32_t g, | 
 |  262                           uint32_t b) { | 
 |  263     switch (config) { | 
 |  264         case SkCanvas::kNative_Premul_Config8888: | 
 |  265         case SkCanvas::kNative_Unpremul_Config8888: | 
 |  266             return pack_config8888<SK_NATIVE_A_IDX, | 
 |  267                                    SK_NATIVE_R_IDX, | 
 |  268                                    SK_NATIVE_G_IDX, | 
 |  269                                    SK_NATIVE_B_IDX>(a, r, g, b); | 
 |  270         case SkCanvas::kBGRA_Premul_Config8888: | 
 |  271         case SkCanvas::kBGRA_Unpremul_Config8888: | 
 |  272             return pack_config8888<3, 2, 1, 0>(a, r, g, b); | 
 |  273         case SkCanvas::kRGBA_Premul_Config8888: | 
 |  274         case SkCanvas::kRGBA_Unpremul_Config8888: | 
 |  275             return pack_config8888<3, 0, 1, 2>(a, r, g, b); | 
 |  276         default: | 
 |  277             SkDEBUGFAIL("Unexpected config8888"); | 
 |  278             return 0; | 
 |  279     } | 
 |  280 } | 
| OLD | NEW |