Home | History | Annotate | Download | only in core
      1 #include "SkBlitRow.h"
      2 #include "SkColorPriv.h"
      3 #include "SkDither.h"
      4 
      5 ///////////////////////////////////////////////////////////////////////////////
      6 
      7 static void S32_D565_Opaque(uint16_t* SK_RESTRICT dst,
      8                             const SkPMColor* SK_RESTRICT src, int count,
      9                             U8CPU alpha, int /*x*/, int /*y*/) {
     10     SkASSERT(255 == alpha);
     11 
     12     if (count > 0) {
     13         do {
     14             SkPMColor c = *src++;
     15             SkPMColorAssert(c);
     16             SkASSERT(SkGetPackedA32(c) == 255);
     17             *dst++ = SkPixel32ToPixel16_ToU16(c);
     18         } while (--count != 0);
     19     }
     20 }
     21 
     22 static void S32_D565_Blend(uint16_t* SK_RESTRICT dst,
     23                              const SkPMColor* SK_RESTRICT src, int count,
     24                              U8CPU alpha, int /*x*/, int /*y*/) {
     25     SkASSERT(255 > alpha);
     26 
     27     if (count > 0) {
     28         int scale = SkAlpha255To256(alpha);
     29         do {
     30             SkPMColor c = *src++;
     31             SkPMColorAssert(c);
     32             SkASSERT(SkGetPackedA32(c) == 255);
     33             uint16_t d = *dst;
     34             *dst++ = SkPackRGB16(
     35                     SkAlphaBlend(SkPacked32ToR16(c), SkGetPackedR16(d), scale),
     36                     SkAlphaBlend(SkPacked32ToG16(c), SkGetPackedG16(d), scale),
     37                     SkAlphaBlend(SkPacked32ToB16(c), SkGetPackedB16(d), scale));
     38         } while (--count != 0);
     39     }
     40 }
     41 
     42 static void S32A_D565_Opaque(uint16_t* SK_RESTRICT dst,
     43                                const SkPMColor* SK_RESTRICT src, int count,
     44                                U8CPU alpha, int /*x*/, int /*y*/) {
     45     SkASSERT(255 == alpha);
     46 
     47     if (count > 0) {
     48         do {
     49             SkPMColor c = *src++;
     50             SkPMColorAssert(c);
     51 //            if (__builtin_expect(c!=0, 1))
     52             if (c) {
     53                 *dst = SkSrcOver32To16(c, *dst);
     54             }
     55             dst += 1;
     56         } while (--count != 0);
     57     }
     58 }
     59 
     60 static void S32A_D565_Blend(uint16_t* SK_RESTRICT dst,
     61                               const SkPMColor* SK_RESTRICT src, int count,
     62                                U8CPU alpha, int /*x*/, int /*y*/) {
     63     SkASSERT(255 > alpha);
     64 
     65     if (count > 0) {
     66         do {
     67             SkPMColor sc = *src++;
     68             SkPMColorAssert(sc);
     69             if (sc) {
     70                 uint16_t dc = *dst;
     71                 unsigned dst_scale = 255 - SkMulDiv255Round(SkGetPackedA32(sc), alpha);
     72                 unsigned dr = SkMulS16(SkPacked32ToR16(sc), alpha) + SkMulS16(SkGetPackedR16(dc), dst_scale);
     73                 unsigned dg = SkMulS16(SkPacked32ToG16(sc), alpha) + SkMulS16(SkGetPackedG16(dc), dst_scale);
     74                 unsigned db = SkMulS16(SkPacked32ToB16(sc), alpha) + SkMulS16(SkGetPackedB16(dc), dst_scale);
     75                 *dst = SkPackRGB16(SkDiv255Round(dr), SkDiv255Round(dg), SkDiv255Round(db));
     76             }
     77             dst += 1;
     78         } while (--count != 0);
     79     }
     80 }
     81 
     82 /////////////////////////////////////////////////////////////////////////////
     83 
     84 static void S32_D565_Opaque_Dither(uint16_t* SK_RESTRICT dst,
     85                                      const SkPMColor* SK_RESTRICT src,
     86                                      int count, U8CPU alpha, int x, int y) {
     87     SkASSERT(255 == alpha);
     88 
     89     if (count > 0) {
     90         DITHER_565_SCAN(y);
     91         do {
     92             SkPMColor c = *src++;
     93             SkPMColorAssert(c);
     94             SkASSERT(SkGetPackedA32(c) == 255);
     95 
     96             unsigned dither = DITHER_VALUE(x);
     97             *dst++ = SkDitherRGB32To565(c, dither);
     98             DITHER_INC_X(x);
     99         } while (--count != 0);
    100     }
    101 }
    102 
    103 static void S32_D565_Blend_Dither(uint16_t* SK_RESTRICT dst,
    104                                     const SkPMColor* SK_RESTRICT src,
    105                                     int count, U8CPU alpha, int x, int y) {
    106     SkASSERT(255 > alpha);
    107 
    108     if (count > 0) {
    109         int scale = SkAlpha255To256(alpha);
    110         DITHER_565_SCAN(y);
    111         do {
    112             SkPMColor c = *src++;
    113             SkPMColorAssert(c);
    114             SkASSERT(SkGetPackedA32(c) == 255);
    115 
    116             int dither = DITHER_VALUE(x);
    117             int sr = SkGetPackedR32(c);
    118             int sg = SkGetPackedG32(c);
    119             int sb = SkGetPackedB32(c);
    120             sr = SkDITHER_R32To565(sr, dither);
    121             sg = SkDITHER_G32To565(sg, dither);
    122             sb = SkDITHER_B32To565(sb, dither);
    123 
    124             uint16_t d = *dst;
    125             *dst++ = SkPackRGB16(SkAlphaBlend(sr, SkGetPackedR16(d), scale),
    126                                  SkAlphaBlend(sg, SkGetPackedG16(d), scale),
    127                                  SkAlphaBlend(sb, SkGetPackedB16(d), scale));
    128             DITHER_INC_X(x);
    129         } while (--count != 0);
    130     }
    131 }
    132 
    133 static void S32A_D565_Opaque_Dither(uint16_t* SK_RESTRICT dst,
    134                                       const SkPMColor* SK_RESTRICT src,
    135                                       int count, U8CPU alpha, int x, int y) {
    136     SkASSERT(255 == alpha);
    137 
    138     if (count > 0) {
    139         DITHER_565_SCAN(y);
    140         do {
    141             SkPMColor c = *src++;
    142             SkPMColorAssert(c);
    143             if (c) {
    144                 unsigned a = SkGetPackedA32(c);
    145 
    146                 int d = SkAlphaMul(DITHER_VALUE(x), SkAlpha255To256(a));
    147 
    148                 unsigned sr = SkGetPackedR32(c);
    149                 unsigned sg = SkGetPackedG32(c);
    150                 unsigned sb = SkGetPackedB32(c);
    151                 sr = SkDITHER_R32_FOR_565(sr, d);
    152                 sg = SkDITHER_G32_FOR_565(sg, d);
    153                 sb = SkDITHER_B32_FOR_565(sb, d);
    154 
    155                 uint32_t src_expanded = (sg << 24) | (sr << 13) | (sb << 2);
    156                 uint32_t dst_expanded = SkExpand_rgb_16(*dst);
    157                 dst_expanded = dst_expanded * (SkAlpha255To256(255 - a) >> 3);
    158                 // now src and dst expanded are in g:11 r:10 x:1 b:10
    159                 *dst = SkCompact_rgb_16((src_expanded + dst_expanded) >> 5);
    160             }
    161             dst += 1;
    162             DITHER_INC_X(x);
    163         } while (--count != 0);
    164     }
    165 }
    166 
    167 static void S32A_D565_Blend_Dither(uint16_t* SK_RESTRICT dst,
    168                                      const SkPMColor* SK_RESTRICT src,
    169                                      int count, U8CPU alpha, int x, int y) {
    170     SkASSERT(255 > alpha);
    171 
    172     if (count > 0) {
    173         int src_scale = SkAlpha255To256(alpha);
    174         DITHER_565_SCAN(y);
    175         do {
    176             SkPMColor c = *src++;
    177             SkPMColorAssert(c);
    178             if (c)
    179             {
    180                 unsigned d = *dst;
    181                 int sa = SkGetPackedA32(c);
    182                 int dst_scale = SkAlpha255To256(255 - SkAlphaMul(sa, src_scale));
    183                 int dither = DITHER_VALUE(x);
    184 
    185                 int sr = SkGetPackedR32(c);
    186                 int sg = SkGetPackedG32(c);
    187                 int sb = SkGetPackedB32(c);
    188                 sr = SkDITHER_R32To565(sr, dither);
    189                 sg = SkDITHER_G32To565(sg, dither);
    190                 sb = SkDITHER_B32To565(sb, dither);
    191 
    192                 int dr = (sr * src_scale + SkGetPackedR16(d) * dst_scale) >> 8;
    193                 int dg = (sg * src_scale + SkGetPackedG16(d) * dst_scale) >> 8;
    194                 int db = (sb * src_scale + SkGetPackedB16(d) * dst_scale) >> 8;
    195 
    196                 *dst = SkPackRGB16(dr, dg, db);
    197             }
    198             dst += 1;
    199             DITHER_INC_X(x);
    200         } while (--count != 0);
    201     }
    202 }
    203 
    204 ///////////////////////////////////////////////////////////////////////////////
    205 ///////////////////////////////////////////////////////////////////////////////
    206 
    207 static const SkBlitRow::Proc gDefault_565_Procs[] = {
    208     // no dither
    209     S32_D565_Opaque,
    210     S32_D565_Blend,
    211 
    212     S32A_D565_Opaque,
    213     S32A_D565_Blend,
    214 
    215     // dither
    216     S32_D565_Opaque_Dither,
    217     S32_D565_Blend_Dither,
    218 
    219     S32A_D565_Opaque_Dither,
    220     S32A_D565_Blend_Dither
    221 };
    222 
    223 extern SkBlitRow::Proc SkBlitRow_Factory_4444(unsigned flags);
    224 
    225 SkBlitRow::Proc SkBlitRow::Factory(unsigned flags, SkBitmap::Config config) {
    226     SkASSERT(flags < SK_ARRAY_COUNT(gDefault_565_Procs));
    227     // just so we don't crash
    228     flags &= kFlags16_Mask;
    229 
    230     SkBlitRow::Proc proc = NULL;
    231 
    232     switch (config) {
    233         case SkBitmap::kRGB_565_Config:
    234             proc = PlatformProcs565(flags);
    235             if (NULL == proc) {
    236                 proc = gDefault_565_Procs[flags];
    237             }
    238             break;
    239         case SkBitmap::kARGB_4444_Config:
    240             proc = PlatformProcs4444(flags);
    241             if (NULL == proc) {
    242                 proc = SkBlitRow_Factory_4444(flags);
    243             }
    244             break;
    245         default:
    246             break;
    247     }
    248     return proc;
    249 }
    250 
    251