Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2011 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkBlitRow.h"
      9 #include "SkColorPriv.h"
     10 #include "SkDither.h"
     11 #include "SkMathPriv.h"
     12 
     13 ///////////////////////////////////////////////////////////////////////////////
     14 
     15 static void S32_D565_Opaque(uint16_t* SK_RESTRICT dst,
     16                             const SkPMColor* SK_RESTRICT src, int count,
     17                             U8CPU alpha, int /*x*/, int /*y*/) {
     18     SkASSERT(255 == alpha);
     19 
     20     if (count > 0) {
     21         do {
     22             SkPMColor c = *src++;
     23             SkPMColorAssert(c);
     24             *dst++ = SkPixel32ToPixel16_ToU16(c);
     25         } while (--count != 0);
     26     }
     27 }
     28 
     29 static void S32_D565_Blend(uint16_t* SK_RESTRICT dst,
     30                              const SkPMColor* SK_RESTRICT src, int count,
     31                              U8CPU alpha, int /*x*/, int /*y*/) {
     32     SkASSERT(255 > alpha);
     33 
     34     if (count > 0) {
     35         int scale = SkAlpha255To256(alpha);
     36         do {
     37             SkPMColor c = *src++;
     38             SkPMColorAssert(c);
     39             uint16_t d = *dst;
     40             *dst++ = SkPackRGB16(
     41                     SkAlphaBlend(SkPacked32ToR16(c), SkGetPackedR16(d), scale),
     42                     SkAlphaBlend(SkPacked32ToG16(c), SkGetPackedG16(d), scale),
     43                     SkAlphaBlend(SkPacked32ToB16(c), SkGetPackedB16(d), scale));
     44         } while (--count != 0);
     45     }
     46 }
     47 
     48 static void S32A_D565_Opaque(uint16_t* SK_RESTRICT dst,
     49                                const SkPMColor* SK_RESTRICT src, int count,
     50                                U8CPU alpha, int /*x*/, int /*y*/) {
     51     SkASSERT(255 == alpha);
     52 
     53     if (count > 0) {
     54         do {
     55             SkPMColor c = *src++;
     56             SkPMColorAssert(c);
     57 //            if (__builtin_expect(c!=0, 1))
     58             if (c) {
     59                 *dst = SkSrcOver32To16(c, *dst);
     60             }
     61             dst += 1;
     62         } while (--count != 0);
     63     }
     64 }
     65 
     66 static void S32A_D565_Blend(uint16_t* SK_RESTRICT dst,
     67                               const SkPMColor* SK_RESTRICT src, int count,
     68                                U8CPU alpha, int /*x*/, int /*y*/) {
     69     SkASSERT(255 > alpha);
     70 
     71     if (count > 0) {
     72         do {
     73             SkPMColor sc = *src++;
     74             SkPMColorAssert(sc);
     75             if (sc) {
     76                 uint16_t dc = *dst;
     77                 SkPMColor res = SkBlendARGB32(sc, SkPixel16ToPixel32(dc), alpha);
     78                 *dst = SkPixel32ToPixel16(res);
     79             }
     80             dst += 1;
     81         } while (--count != 0);
     82     }
     83 }
     84 
     85 /////////////////////////////////////////////////////////////////////////////
     86 
     87 static void S32_D565_Opaque_Dither(uint16_t* SK_RESTRICT dst,
     88                                      const SkPMColor* SK_RESTRICT src,
     89                                      int count, U8CPU alpha, int x, int y) {
     90     SkASSERT(255 == alpha);
     91 
     92     if (count > 0) {
     93         DITHER_565_SCAN(y);
     94         do {
     95             SkPMColor c = *src++;
     96             SkPMColorAssert(c);
     97 
     98             unsigned dither = DITHER_VALUE(x);
     99             *dst++ = SkDitherRGB32To565(c, dither);
    100             DITHER_INC_X(x);
    101         } while (--count != 0);
    102     }
    103 }
    104 
    105 static void S32_D565_Blend_Dither(uint16_t* SK_RESTRICT dst,
    106                                     const SkPMColor* SK_RESTRICT src,
    107                                     int count, U8CPU alpha, int x, int y) {
    108     SkASSERT(255 > alpha);
    109 
    110     if (count > 0) {
    111         int scale = SkAlpha255To256(alpha);
    112         DITHER_565_SCAN(y);
    113         do {
    114             SkPMColor c = *src++;
    115             SkPMColorAssert(c);
    116 
    117             int dither = DITHER_VALUE(x);
    118             int sr = SkGetPackedR32(c);
    119             int sg = SkGetPackedG32(c);
    120             int sb = SkGetPackedB32(c);
    121             sr = SkDITHER_R32To565(sr, dither);
    122             sg = SkDITHER_G32To565(sg, dither);
    123             sb = SkDITHER_B32To565(sb, dither);
    124 
    125             uint16_t d = *dst;
    126             *dst++ = SkPackRGB16(SkAlphaBlend(sr, SkGetPackedR16(d), scale),
    127                                  SkAlphaBlend(sg, SkGetPackedG16(d), scale),
    128                                  SkAlphaBlend(sb, SkGetPackedB16(d), scale));
    129             DITHER_INC_X(x);
    130         } while (--count != 0);
    131     }
    132 }
    133 
    134 static void S32A_D565_Opaque_Dither(uint16_t* SK_RESTRICT dst,
    135                                       const SkPMColor* SK_RESTRICT src,
    136                                       int count, U8CPU alpha, int x, int y) {
    137     SkASSERT(255 == alpha);
    138 
    139     if (count > 0) {
    140         DITHER_565_SCAN(y);
    141         do {
    142             SkPMColor c = *src++;
    143             SkPMColorAssert(c);
    144             if (c) {
    145                 unsigned a = SkGetPackedA32(c);
    146 
    147                 int d = SkAlphaMul(DITHER_VALUE(x), SkAlpha255To256(a));
    148 
    149                 unsigned sr = SkGetPackedR32(c);
    150                 unsigned sg = SkGetPackedG32(c);
    151                 unsigned sb = SkGetPackedB32(c);
    152                 sr = SkDITHER_R32_FOR_565(sr, d);
    153                 sg = SkDITHER_G32_FOR_565(sg, d);
    154                 sb = SkDITHER_B32_FOR_565(sb, d);
    155 
    156                 uint32_t src_expanded = (sg << 24) | (sr << 13) | (sb << 2);
    157                 uint32_t dst_expanded = SkExpand_rgb_16(*dst);
    158                 dst_expanded = dst_expanded * (SkAlpha255To256(255 - a) >> 3);
    159                 // now src and dst expanded are in g:11 r:10 x:1 b:10
    160                 *dst = SkCompact_rgb_16((src_expanded + dst_expanded) >> 5);
    161             }
    162             dst += 1;
    163             DITHER_INC_X(x);
    164         } while (--count != 0);
    165     }
    166 }
    167 
    168 static void S32A_D565_Blend_Dither(uint16_t* SK_RESTRICT dst,
    169                                      const SkPMColor* SK_RESTRICT src,
    170                                      int count, U8CPU alpha, int x, int y) {
    171     SkASSERT(255 > alpha);
    172 
    173     if (count > 0) {
    174         int src_scale = SkAlpha255To256(alpha);
    175         DITHER_565_SCAN(y);
    176         do {
    177             SkPMColor c = *src++;
    178             SkPMColorAssert(c);
    179             if (c)
    180             {
    181                 unsigned d = *dst;
    182                 int sa = SkGetPackedA32(c);
    183                 int dst_scale = SkAlpha255To256(255 - SkAlphaMul(sa, src_scale));
    184                 int dither = DITHER_VALUE(x);
    185 
    186                 int sr = SkGetPackedR32(c);
    187                 int sg = SkGetPackedG32(c);
    188                 int sb = SkGetPackedB32(c);
    189                 sr = SkDITHER_R32To565(sr, dither);
    190                 sg = SkDITHER_G32To565(sg, dither);
    191                 sb = SkDITHER_B32To565(sb, dither);
    192 
    193                 int dr = (sr * src_scale + SkGetPackedR16(d) * dst_scale) >> 8;
    194                 int dg = (sg * src_scale + SkGetPackedG16(d) * dst_scale) >> 8;
    195                 int db = (sb * src_scale + SkGetPackedB16(d) * dst_scale) >> 8;
    196 
    197                 *dst = SkPackRGB16(dr, dg, db);
    198             }
    199             dst += 1;
    200             DITHER_INC_X(x);
    201         } while (--count != 0);
    202     }
    203 }
    204 
    205 ///////////////////////////////////////////////////////////////////////////////
    206 
    207 static uint32_t pmcolor_to_expand16(SkPMColor c) {
    208     unsigned r = SkGetPackedR32(c);
    209     unsigned g = SkGetPackedG32(c);
    210     unsigned b = SkGetPackedB32(c);
    211     return (g << 24) | (r << 13) | (b << 2);
    212 }
    213 
    214 static void Color32A_D565(uint16_t dst[], SkPMColor src, int count, int x, int y) {
    215     SkASSERT(count > 0);
    216     uint32_t src_expand = pmcolor_to_expand16(src);
    217     unsigned scale = SkAlpha255To256(0xFF - SkGetPackedA32(src)) >> 3;
    218     do {
    219         *dst = SkBlend32_RGB16(src_expand, *dst, scale);
    220         dst += 1;
    221     } while (--count != 0);
    222 }
    223 
    224 ///////////////////////////////////////////////////////////////////////////////
    225 ///////////////////////////////////////////////////////////////////////////////
    226 
    227 static const SkBlitRow::Proc16 gDefault_565_Procs[] = {
    228     // no dither
    229     S32_D565_Opaque,
    230     S32_D565_Blend,
    231 
    232     S32A_D565_Opaque,
    233     S32A_D565_Blend,
    234 
    235     // dither
    236     S32_D565_Opaque_Dither,
    237     S32_D565_Blend_Dither,
    238 
    239     S32A_D565_Opaque_Dither,
    240     S32A_D565_Blend_Dither
    241 };
    242 
    243 SkBlitRow::Proc16 SkBlitRow::Factory16(unsigned flags) {
    244     SkASSERT(flags < SK_ARRAY_COUNT(gDefault_565_Procs));
    245     // just so we don't crash
    246     flags &= kFlags16_Mask;
    247 
    248     SkBlitRow::Proc16 proc = PlatformFactory565(flags);
    249     if (NULL == proc) {
    250         proc = gDefault_565_Procs[flags];
    251     }
    252     return proc;
    253 }
    254 
    255 static const SkBlitRow::ColorProc16 gDefault_565_ColorProcs[] = {
    256 #if 0
    257     Color32A_D565,
    258     Color32A_D565_Dither
    259 #else
    260     // TODO: stop cheating and fill dither from the above specializations!
    261     Color32A_D565,
    262     Color32A_D565,
    263 #endif
    264 };
    265 
    266 SkBlitRow::ColorProc16 SkBlitRow::ColorFactory16(unsigned flags) {
    267     SkASSERT((flags & ~kFlags16_Mask) == 0);
    268     // just so we don't crash
    269     flags &= kFlags16_Mask;
    270     // we ignore both kGlobalAlpha_Flag and kSrcPixelAlpha_Flag, so shift down
    271     // no need for the additional code specializing on opaque alpha at this time
    272     flags >>= 2;
    273 
    274     SkASSERT(flags < SK_ARRAY_COUNT(gDefault_565_ColorProcs));
    275 
    276     SkBlitRow::ColorProc16 proc = PlatformColorFactory565(flags);
    277     if (NULL == proc) {
    278         proc = gDefault_565_ColorProcs[flags];
    279     }
    280     return proc;
    281 }
    282