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 "SkBlitMask.h"
     10 #include "SkColorPriv.h"
     11 #include "SkUtils.h"
     12 
     13 #define UNROLL
     14 
     15 SkBlitRow::ColorRectProc PlatformColorRectProcFactory();
     16 
     17 static void S32_Opaque_BlitRow32(SkPMColor* SK_RESTRICT dst,
     18                                  const SkPMColor* SK_RESTRICT src,
     19                                  int count, U8CPU alpha) {
     20     SkASSERT(255 == alpha);
     21     sk_memcpy32(dst, src, count);
     22 }
     23 
     24 static void S32_Blend_BlitRow32(SkPMColor* SK_RESTRICT dst,
     25                                 const SkPMColor* SK_RESTRICT src,
     26                                 int count, U8CPU alpha) {
     27     SkASSERT(alpha <= 255);
     28     if (count > 0) {
     29         unsigned src_scale = SkAlpha255To256(alpha);
     30         unsigned dst_scale = 256 - src_scale;
     31 
     32 #ifdef UNROLL
     33         if (count & 1) {
     34             *dst = SkAlphaMulQ(*(src++), src_scale) + SkAlphaMulQ(*dst, dst_scale);
     35             dst += 1;
     36             count -= 1;
     37         }
     38 
     39         const SkPMColor* SK_RESTRICT srcEnd = src + count;
     40         while (src != srcEnd) {
     41             *dst = SkAlphaMulQ(*(src++), src_scale) + SkAlphaMulQ(*dst, dst_scale);
     42             dst += 1;
     43             *dst = SkAlphaMulQ(*(src++), src_scale) + SkAlphaMulQ(*dst, dst_scale);
     44             dst += 1;
     45         }
     46 #else
     47         do {
     48             *dst = SkAlphaMulQ(*src, src_scale) + SkAlphaMulQ(*dst, dst_scale);
     49             src += 1;
     50             dst += 1;
     51         } while (--count > 0);
     52 #endif
     53     }
     54 }
     55 
     56 static void S32A_Opaque_BlitRow32(SkPMColor* SK_RESTRICT dst,
     57                                   const SkPMColor* SK_RESTRICT src,
     58                                   int count, U8CPU alpha) {
     59     SkASSERT(255 == alpha);
     60     if (count > 0) {
     61 #ifdef UNROLL
     62         if (count & 1) {
     63             *dst = SkPMSrcOver(*(src++), *dst);
     64             dst += 1;
     65             count -= 1;
     66         }
     67 
     68         const SkPMColor* SK_RESTRICT srcEnd = src + count;
     69         while (src != srcEnd) {
     70             *dst = SkPMSrcOver(*(src++), *dst);
     71             dst += 1;
     72             *dst = SkPMSrcOver(*(src++), *dst);
     73             dst += 1;
     74         }
     75 #else
     76         do {
     77             *dst = SkPMSrcOver(*src, *dst);
     78             src += 1;
     79             dst += 1;
     80         } while (--count > 0);
     81 #endif
     82     }
     83 }
     84 
     85 static void S32A_Blend_BlitRow32(SkPMColor* SK_RESTRICT dst,
     86                                  const SkPMColor* SK_RESTRICT src,
     87                                  int count, U8CPU alpha) {
     88     SkASSERT(alpha <= 255);
     89     if (count > 0) {
     90 #ifdef UNROLL
     91         if (count & 1) {
     92             *dst = SkBlendARGB32(*(src++), *dst, alpha);
     93             dst += 1;
     94             count -= 1;
     95         }
     96 
     97         const SkPMColor* SK_RESTRICT srcEnd = src + count;
     98         while (src != srcEnd) {
     99             *dst = SkBlendARGB32(*(src++), *dst, alpha);
    100             dst += 1;
    101             *dst = SkBlendARGB32(*(src++), *dst, alpha);
    102             dst += 1;
    103         }
    104 #else
    105         do {
    106             *dst = SkBlendARGB32(*src, *dst, alpha);
    107             src += 1;
    108             dst += 1;
    109         } while (--count > 0);
    110 #endif
    111     }
    112 }
    113 
    114 ///////////////////////////////////////////////////////////////////////////////
    115 
    116 static const SkBlitRow::Proc32 gDefault_Procs32[] = {
    117     S32_Opaque_BlitRow32,
    118     S32_Blend_BlitRow32,
    119     S32A_Opaque_BlitRow32,
    120     S32A_Blend_BlitRow32
    121 };
    122 
    123 SkBlitRow::Proc32 SkBlitRow::Factory32(unsigned flags) {
    124     SkASSERT(flags < SK_ARRAY_COUNT(gDefault_Procs32));
    125     // just so we don't crash
    126     flags &= kFlags32_Mask;
    127 
    128     SkBlitRow::Proc32 proc = PlatformProcs32(flags);
    129     if (NULL == proc) {
    130         proc = gDefault_Procs32[flags];
    131     }
    132     SkASSERT(proc);
    133     return proc;
    134 }
    135 
    136 SkBlitRow::Proc32 SkBlitRow::ColorProcFactory() {
    137     SkBlitRow::ColorProc proc = PlatformColorProc();
    138     if (NULL == proc) {
    139         proc = Color32;
    140     }
    141     SkASSERT(proc);
    142     return proc;
    143 }
    144 
    145 void SkBlitRow::Color32(SkPMColor* SK_RESTRICT dst,
    146                         const SkPMColor* SK_RESTRICT src,
    147                         int count, SkPMColor color) {
    148     if (count > 0) {
    149         if (0 == color) {
    150             if (src != dst) {
    151                 memcpy(dst, src, count * sizeof(SkPMColor));
    152             }
    153             return;
    154         }
    155         unsigned colorA = SkGetPackedA32(color);
    156         if (255 == colorA) {
    157             sk_memset32(dst, color, count);
    158         } else {
    159             unsigned scale = 256 - SkAlpha255To256(colorA);
    160             do {
    161                 *dst = color + SkAlphaMulQ(*src, scale);
    162                 src += 1;
    163                 dst += 1;
    164             } while (--count);
    165         }
    166     }
    167 }
    168 
    169 template <size_t N> void assignLoop(SkPMColor* dst, SkPMColor color) {
    170     for (size_t i = 0; i < N; ++i) {
    171         *dst++ = color;
    172     }
    173 }
    174 
    175 static inline void assignLoop(SkPMColor dst[], SkPMColor color, int count) {
    176     while (count >= 4) {
    177         *dst++ = color;
    178         *dst++ = color;
    179         *dst++ = color;
    180         *dst++ = color;
    181         count -= 4;
    182     }
    183     if (count >= 2) {
    184         *dst++ = color;
    185         *dst++ = color;
    186         count -= 2;
    187     }
    188     if (count > 0) {
    189         *dst++ = color;
    190     }
    191 }
    192 
    193 void SkBlitRow::ColorRect32(SkPMColor* dst, int width, int height,
    194                             size_t rowBytes, SkPMColor color) {
    195     if (width <= 0 || height <= 0 || 0 == color) {
    196         return;
    197     }
    198 
    199     // Just made up this value, since I saw it once in a SSE2 file.
    200     // We should consider writing some tests to find the optimimal break-point
    201     // (or query the Platform proc?)
    202     static const int MIN_WIDTH_FOR_SCANLINE_PROC = 32;
    203 
    204     bool isOpaque = (0xFF == SkGetPackedA32(color));
    205 
    206     if (!isOpaque || width >= MIN_WIDTH_FOR_SCANLINE_PROC) {
    207         SkBlitRow::ColorProc proc = SkBlitRow::ColorProcFactory();
    208         while (--height >= 0) {
    209             (*proc)(dst, dst, width, color);
    210             dst = (SkPMColor*) ((char*)dst + rowBytes);
    211         }
    212     } else {
    213         switch (width) {
    214             case 1:
    215                 while (--height >= 0) {
    216                     assignLoop<1>(dst, color);
    217                     dst = (SkPMColor*) ((char*)dst + rowBytes);
    218                 }
    219                 break;
    220             case 2:
    221                 while (--height >= 0) {
    222                     assignLoop<2>(dst, color);
    223                     dst = (SkPMColor*) ((char*)dst + rowBytes);
    224                 }
    225                 break;
    226             case 3:
    227                 while (--height >= 0) {
    228                     assignLoop<3>(dst, color);
    229                     dst = (SkPMColor*) ((char*)dst + rowBytes);
    230                 }
    231                 break;
    232             default:
    233                 while (--height >= 0) {
    234                     assignLoop(dst, color, width);
    235                     dst = (SkPMColor*) ((char*)dst + rowBytes);
    236                 }
    237                 break;
    238         }
    239     }
    240 }
    241 
    242 SkBlitRow::ColorRectProc SkBlitRow::ColorRectProcFactory() {
    243     SkBlitRow::ColorRectProc proc = PlatformColorRectProcFactory();
    244     if (NULL == proc) {
    245         proc = ColorRect32;
    246     }
    247     SkASSERT(proc);
    248     return proc;
    249 }
    250