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 static uint32_t pmcolor_to_expand16(SkPMColor c) { 208 unsigned r = SkGetPackedR32(c); 209 unsigned g = SkGetPackedG32(c); 210 unsigned b = SkGetPackedB32(c); 211 return (g << 24) | (r << 13) | (b << 2); 212 } 213 214 static void Color32A_D565(uint16_t dst[], SkPMColor src, int count, int x, int y) { 215 SkASSERT(count > 0); 216 uint32_t src_expand = pmcolor_to_expand16(src); 217 unsigned scale = SkAlpha255To256(0xFF - SkGetPackedA32(src)) >> 3; 218 do { 219 *dst = SkBlend32_RGB16(src_expand, *dst, scale); 220 dst += 1; 221 } while (--count != 0); 222 } 223 224 /////////////////////////////////////////////////////////////////////////////// 225 /////////////////////////////////////////////////////////////////////////////// 226 227 static const SkBlitRow::Proc16 gDefault_565_Procs[] = { 228 // no dither 229 S32_D565_Opaque, 230 S32_D565_Blend, 231 232 S32A_D565_Opaque, 233 S32A_D565_Blend, 234 235 // dither 236 S32_D565_Opaque_Dither, 237 S32_D565_Blend_Dither, 238 239 S32A_D565_Opaque_Dither, 240 S32A_D565_Blend_Dither 241 }; 242 243 SkBlitRow::Proc16 SkBlitRow::Factory16(unsigned flags) { 244 SkASSERT(flags < SK_ARRAY_COUNT(gDefault_565_Procs)); 245 // just so we don't crash 246 flags &= kFlags16_Mask; 247 248 SkBlitRow::Proc16 proc = PlatformFactory565(flags); 249 if (nullptr == proc) { 250 proc = gDefault_565_Procs[flags]; 251 } 252 return proc; 253 } 254 255 static const SkBlitRow::ColorProc16 gDefault_565_ColorProcs[] = { 256 #if 0 257 Color32A_D565, 258 Color32A_D565_Dither 259 #else 260 // TODO: stop cheating and fill dither from the above specializations! 261 Color32A_D565, 262 Color32A_D565, 263 #endif 264 }; 265 266 SkBlitRow::ColorProc16 SkBlitRow::ColorFactory16(unsigned flags) { 267 SkASSERT((flags & ~kFlags16_Mask) == 0); 268 // just so we don't crash 269 flags &= kFlags16_Mask; 270 // we ignore both kGlobalAlpha_Flag and kSrcPixelAlpha_Flag, so shift down 271 // no need for the additional code specializing on opaque alpha at this time 272 flags >>= 2; 273 274 SkASSERT(flags < SK_ARRAY_COUNT(gDefault_565_ColorProcs)); 275 276 SkBlitRow::ColorProc16 proc = PlatformColorFactory565(flags); 277 if (nullptr == proc) { 278 proc = gDefault_565_ColorProcs[flags]; 279 } 280 return proc; 281 } 282