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                 unsigned dst_scale = 255 - SkMulDiv255Round(SkGetPackedA32(sc), alpha);
     78                 unsigned dr = SkMulS16(SkPacked32ToR16(sc), alpha) + SkMulS16(SkGetPackedR16(dc), dst_scale);
     79                 unsigned dg = SkMulS16(SkPacked32ToG16(sc), alpha) + SkMulS16(SkGetPackedG16(dc), dst_scale);
     80                 unsigned db = SkMulS16(SkPacked32ToB16(sc), alpha) + SkMulS16(SkGetPackedB16(dc), dst_scale);
     81                 *dst = SkPackRGB16(SkDiv255Round(dr), SkDiv255Round(dg), SkDiv255Round(db));
     82             }
     83             dst += 1;
     84         } while (--count != 0);
     85     }
     86 }
     87 
     88 /////////////////////////////////////////////////////////////////////////////
     89 
     90 static void S32_D565_Opaque_Dither(uint16_t* SK_RESTRICT dst,
     91                                      const SkPMColor* SK_RESTRICT src,
     92                                      int count, U8CPU alpha, int x, int y) {
     93     SkASSERT(255 == alpha);
     94 
     95     if (count > 0) {
     96         DITHER_565_SCAN(y);
     97         do {
     98             SkPMColor c = *src++;
     99             SkPMColorAssert(c);
    100 
    101             unsigned dither = DITHER_VALUE(x);
    102             *dst++ = SkDitherRGB32To565(c, dither);
    103             DITHER_INC_X(x);
    104         } while (--count != 0);
    105     }
    106 }
    107 
    108 static void S32_D565_Blend_Dither(uint16_t* SK_RESTRICT dst,
    109                                     const SkPMColor* SK_RESTRICT src,
    110                                     int count, U8CPU alpha, int x, int y) {
    111     SkASSERT(255 > alpha);
    112 
    113     if (count > 0) {
    114         int scale = SkAlpha255To256(alpha);
    115         DITHER_565_SCAN(y);
    116         do {
    117             SkPMColor c = *src++;
    118             SkPMColorAssert(c);
    119 
    120             int dither = DITHER_VALUE(x);
    121             int sr = SkGetPackedR32(c);
    122             int sg = SkGetPackedG32(c);
    123             int sb = SkGetPackedB32(c);
    124             sr = SkDITHER_R32To565(sr, dither);
    125             sg = SkDITHER_G32To565(sg, dither);
    126             sb = SkDITHER_B32To565(sb, dither);
    127 
    128             uint16_t d = *dst;
    129             *dst++ = SkPackRGB16(SkAlphaBlend(sr, SkGetPackedR16(d), scale),
    130                                  SkAlphaBlend(sg, SkGetPackedG16(d), scale),
    131                                  SkAlphaBlend(sb, SkGetPackedB16(d), scale));
    132             DITHER_INC_X(x);
    133         } while (--count != 0);
    134     }
    135 }
    136 
    137 static void S32A_D565_Opaque_Dither(uint16_t* SK_RESTRICT dst,
    138                                       const SkPMColor* SK_RESTRICT src,
    139                                       int count, U8CPU alpha, int x, int y) {
    140     SkASSERT(255 == alpha);
    141 
    142     if (count > 0) {
    143         DITHER_565_SCAN(y);
    144         do {
    145             SkPMColor c = *src++;
    146             SkPMColorAssert(c);
    147             if (c) {
    148                 unsigned a = SkGetPackedA32(c);
    149 
    150                 int d = SkAlphaMul(DITHER_VALUE(x), SkAlpha255To256(a));
    151 
    152                 unsigned sr = SkGetPackedR32(c);
    153                 unsigned sg = SkGetPackedG32(c);
    154                 unsigned sb = SkGetPackedB32(c);
    155                 sr = SkDITHER_R32_FOR_565(sr, d);
    156                 sg = SkDITHER_G32_FOR_565(sg, d);
    157                 sb = SkDITHER_B32_FOR_565(sb, d);
    158 
    159                 uint32_t src_expanded = (sg << 24) | (sr << 13) | (sb << 2);
    160                 uint32_t dst_expanded = SkExpand_rgb_16(*dst);
    161                 dst_expanded = dst_expanded * (SkAlpha255To256(255 - a) >> 3);
    162                 // now src and dst expanded are in g:11 r:10 x:1 b:10
    163                 *dst = SkCompact_rgb_16((src_expanded + dst_expanded) >> 5);
    164             }
    165             dst += 1;
    166             DITHER_INC_X(x);
    167         } while (--count != 0);
    168     }
    169 }
    170 
    171 static void S32A_D565_Blend_Dither(uint16_t* SK_RESTRICT dst,
    172                                      const SkPMColor* SK_RESTRICT src,
    173                                      int count, U8CPU alpha, int x, int y) {
    174     SkASSERT(255 > alpha);
    175 
    176     if (count > 0) {
    177         int src_scale = SkAlpha255To256(alpha);
    178         DITHER_565_SCAN(y);
    179         do {
    180             SkPMColor c = *src++;
    181             SkPMColorAssert(c);
    182             if (c)
    183             {
    184                 unsigned d = *dst;
    185                 int sa = SkGetPackedA32(c);
    186                 int dst_scale = SkAlpha255To256(255 - SkAlphaMul(sa, src_scale));
    187                 int dither = DITHER_VALUE(x);
    188 
    189                 int sr = SkGetPackedR32(c);
    190                 int sg = SkGetPackedG32(c);
    191                 int sb = SkGetPackedB32(c);
    192                 sr = SkDITHER_R32To565(sr, dither);
    193                 sg = SkDITHER_G32To565(sg, dither);
    194                 sb = SkDITHER_B32To565(sb, dither);
    195 
    196                 int dr = (sr * src_scale + SkGetPackedR16(d) * dst_scale) >> 8;
    197                 int dg = (sg * src_scale + SkGetPackedG16(d) * dst_scale) >> 8;
    198                 int db = (sb * src_scale + SkGetPackedB16(d) * dst_scale) >> 8;
    199 
    200                 *dst = SkPackRGB16(dr, dg, db);
    201             }
    202             dst += 1;
    203             DITHER_INC_X(x);
    204         } while (--count != 0);
    205     }
    206 }
    207 
    208 ///////////////////////////////////////////////////////////////////////////////
    209 ///////////////////////////////////////////////////////////////////////////////
    210 
    211 static const SkBlitRow::Proc gDefault_565_Procs[] = {
    212     // no dither
    213     S32_D565_Opaque,
    214     S32_D565_Blend,
    215 
    216     S32A_D565_Opaque,
    217     S32A_D565_Blend,
    218 
    219     // dither
    220     S32_D565_Opaque_Dither,
    221     S32_D565_Blend_Dither,
    222 
    223     S32A_D565_Opaque_Dither,
    224     S32A_D565_Blend_Dither
    225 };
    226 
    227 SkBlitRow::Proc SkBlitRow::Factory(unsigned flags, SkBitmap::Config config) {
    228     SkASSERT(flags < SK_ARRAY_COUNT(gDefault_565_Procs));
    229     // just so we don't crash
    230     flags &= kFlags16_Mask;
    231 
    232     SkBlitRow::Proc proc = NULL;
    233 
    234     switch (config) {
    235         case SkBitmap::kRGB_565_Config:
    236             proc = PlatformProcs565(flags);
    237             if (NULL == proc) {
    238                 proc = gDefault_565_Procs[flags];
    239             }
    240             break;
    241         default:
    242             break;
    243     }
    244     return proc;
    245 }
    246