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 15static 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 29static 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 48static 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 66static 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 87static 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 105static 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 134static 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 168static 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 208static const SkBlitRow::Proc gDefault_565_Procs[] = { 209 // no dither 210 S32_D565_Opaque, 211 S32_D565_Blend, 212 213 S32A_D565_Opaque, 214 S32A_D565_Blend, 215 216 // dither 217 S32_D565_Opaque_Dither, 218 S32_D565_Blend_Dither, 219 220 S32A_D565_Opaque_Dither, 221 S32A_D565_Blend_Dither 222}; 223 224SkBlitRow::Proc SkBlitRow::Factory(unsigned flags, SkColorType ct) { 225 SkASSERT(flags < SK_ARRAY_COUNT(gDefault_565_Procs)); 226 // just so we don't crash 227 flags &= kFlags16_Mask; 228 229 SkBlitRow::Proc proc = NULL; 230 231 switch (ct) { 232 case kRGB_565_SkColorType: 233 proc = PlatformProcs565(flags); 234 if (NULL == proc) { 235 proc = gDefault_565_Procs[flags]; 236 } 237 break; 238 default: 239 break; 240 } 241 return proc; 242} 243