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 
    208 static const SkBlitRow::Proc gDefault_565_Procs[] = {
    209     // no dither
    210     S32_D565_Opaque,
    211     S32_D565_Blend,
    212 
    213     S32A_D565_Opaque,
    214     S32A_D565_Blend,
    215 
    216     // dither
    217     S32_D565_Opaque_Dither,
    218     S32_D565_Blend_Dither,
    219 
    220     S32A_D565_Opaque_Dither,
    221     S32A_D565_Blend_Dither
    222 };
    223 
    224 SkBlitRow::Proc SkBlitRow::Factory(unsigned flags, SkColorType ct) {
    225     SkASSERT(flags < SK_ARRAY_COUNT(gDefault_565_Procs));
    226     // just so we don't crash
    227     flags &= kFlags16_Mask;
    228 
    229     SkBlitRow::Proc proc = NULL;
    230 
    231     switch (ct) {
    232         case kRGB_565_SkColorType:
    233             proc = PlatformProcs565(flags);
    234             if (NULL == proc) {
    235                 proc = gDefault_565_Procs[flags];
    236             }
    237             break;
    238         default:
    239             break;
    240     }
    241     return proc;
    242 }
    243