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