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