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 14static 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 28static 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 47static 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 65static 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 89static 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 107static 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 136static 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 170static 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 210static 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 226extern SkBlitRow::Proc SkBlitRow_Factory_4444(unsigned flags); 227 228SkBlitRow::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