| /* | |
| * Copyright 2011 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "SkBlitRow.h" | |
| #include "SkColorPriv.h" | |
| #include "SkDither.h" | |
| #include "SkMathPriv.h" | |
| /////////////////////////////////////////////////////////////////////////////// | |
| static void S32_D565_Opaque(uint16_t* SK_RESTRICT dst, | |
| const SkPMColor* SK_RESTRICT src, int count, | |
| U8CPU alpha, int /*x*/, int /*y*/) { | |
| SkASSERT(255 == alpha); | |
| if (count > 0) { | |
| do { | |
| SkPMColor c = *src++; | |
| SkPMColorAssert(c); | |
| *dst++ = SkPixel32ToPixel16_ToU16(c); | |
| } while (--count != 0); | |
| } | |
| } | |
| static void S32_D565_Blend(uint16_t* SK_RESTRICT dst, | |
| const SkPMColor* SK_RESTRICT src, int count, | |
| U8CPU alpha, int /*x*/, int /*y*/) { | |
| SkASSERT(255 > alpha); | |
| if (count > 0) { | |
| int scale = SkAlpha255To256(alpha); | |
| do { | |
| SkPMColor c = *src++; | |
| SkPMColorAssert(c); | |
| uint16_t d = *dst; | |
| *dst++ = SkPackRGB16( | |
| SkAlphaBlend(SkPacked32ToR16(c), SkGetPackedR16(d), scale), | |
| SkAlphaBlend(SkPacked32ToG16(c), SkGetPackedG16(d), scale), | |
| SkAlphaBlend(SkPacked32ToB16(c), SkGetPackedB16(d), scale)); | |
| } while (--count != 0); | |
| } | |
| } | |
| static void S32A_D565_Opaque(uint16_t* SK_RESTRICT dst, | |
| const SkPMColor* SK_RESTRICT src, int count, | |
| U8CPU alpha, int /*x*/, int /*y*/) { | |
| SkASSERT(255 == alpha); | |
| if (count > 0) { | |
| do { | |
| SkPMColor c = *src++; | |
| SkPMColorAssert(c); | |
| // if (__builtin_expect(c!=0, 1)) | |
| if (c) { | |
| *dst = SkSrcOver32To16(c, *dst); | |
| } | |
| dst += 1; | |
| } while (--count != 0); | |
| } | |
| } | |
| static void S32A_D565_Blend(uint16_t* SK_RESTRICT dst, | |
| const SkPMColor* SK_RESTRICT src, int count, | |
| U8CPU alpha, int /*x*/, int /*y*/) { | |
| SkASSERT(255 > alpha); | |
| if (count > 0) { | |
| do { | |
| SkPMColor sc = *src++; | |
| SkPMColorAssert(sc); | |
| if (sc) { | |
| uint16_t dc = *dst; | |
| SkPMColor res = SkBlendARGB32(sc, SkPixel16ToPixel32(dc), alpha); | |
| *dst = SkPixel32ToPixel16(res); | |
| } | |
| dst += 1; | |
| } while (--count != 0); | |
| } | |
| } | |
| ///////////////////////////////////////////////////////////////////////////// | |
| static void S32_D565_Opaque_Dither(uint16_t* SK_RESTRICT dst, | |
| const SkPMColor* SK_RESTRICT src, | |
| int count, U8CPU alpha, int x, int y) { | |
| SkASSERT(255 == alpha); | |
| if (count > 0) { | |
| DITHER_565_SCAN(y); | |
| do { | |
| SkPMColor c = *src++; | |
| SkPMColorAssert(c); | |
| unsigned dither = DITHER_VALUE(x); | |
| *dst++ = SkDitherRGB32To565(c, dither); | |
| DITHER_INC_X(x); | |
| } while (--count != 0); | |
| } | |
| } | |
| static void S32_D565_Blend_Dither(uint16_t* SK_RESTRICT dst, | |
| const SkPMColor* SK_RESTRICT src, | |
| int count, U8CPU alpha, int x, int y) { | |
| SkASSERT(255 > alpha); | |
| if (count > 0) { | |
| int scale = SkAlpha255To256(alpha); | |
| DITHER_565_SCAN(y); | |
| do { | |
| SkPMColor c = *src++; | |
| SkPMColorAssert(c); | |
| int dither = DITHER_VALUE(x); | |
| int sr = SkGetPackedR32(c); | |
| int sg = SkGetPackedG32(c); | |
| int sb = SkGetPackedB32(c); | |
| sr = SkDITHER_R32To565(sr, dither); | |
| sg = SkDITHER_G32To565(sg, dither); | |
| sb = SkDITHER_B32To565(sb, dither); | |
| uint16_t d = *dst; | |
| *dst++ = SkPackRGB16(SkAlphaBlend(sr, SkGetPackedR16(d), scale), | |
| SkAlphaBlend(sg, SkGetPackedG16(d), scale), | |
| SkAlphaBlend(sb, SkGetPackedB16(d), scale)); | |
| DITHER_INC_X(x); | |
| } while (--count != 0); | |
| } | |
| } | |
| static void S32A_D565_Opaque_Dither(uint16_t* SK_RESTRICT dst, | |
| const SkPMColor* SK_RESTRICT src, | |
| int count, U8CPU alpha, int x, int y) { | |
| SkASSERT(255 == alpha); | |
| if (count > 0) { | |
| DITHER_565_SCAN(y); | |
| do { | |
| SkPMColor c = *src++; | |
| SkPMColorAssert(c); | |
| if (c) { | |
| unsigned a = SkGetPackedA32(c); | |
| int d = SkAlphaMul(DITHER_VALUE(x), SkAlpha255To256(a)); | |
| unsigned sr = SkGetPackedR32(c); | |
| unsigned sg = SkGetPackedG32(c); | |
| unsigned sb = SkGetPackedB32(c); | |
| sr = SkDITHER_R32_FOR_565(sr, d); | |
| sg = SkDITHER_G32_FOR_565(sg, d); | |
| sb = SkDITHER_B32_FOR_565(sb, d); | |
| uint32_t src_expanded = (sg << 24) | (sr << 13) | (sb << 2); | |
| uint32_t dst_expanded = SkExpand_rgb_16(*dst); | |
| dst_expanded = dst_expanded * (SkAlpha255To256(255 - a) >> 3); | |
| // now src and dst expanded are in g:11 r:10 x:1 b:10 | |
| *dst = SkCompact_rgb_16((src_expanded + dst_expanded) >> 5); | |
| } | |
| dst += 1; | |
| DITHER_INC_X(x); | |
| } while (--count != 0); | |
| } | |
| } | |
| static void S32A_D565_Blend_Dither(uint16_t* SK_RESTRICT dst, | |
| const SkPMColor* SK_RESTRICT src, | |
| int count, U8CPU alpha, int x, int y) { | |
| SkASSERT(255 > alpha); | |
| if (count > 0) { | |
| int src_scale = SkAlpha255To256(alpha); | |
| DITHER_565_SCAN(y); | |
| do { | |
| SkPMColor c = *src++; | |
| SkPMColorAssert(c); | |
| if (c) | |
| { | |
| unsigned d = *dst; | |
| int sa = SkGetPackedA32(c); | |
| int dst_scale = SkAlpha255To256(255 - SkAlphaMul(sa, src_scale)); | |
| int dither = DITHER_VALUE(x); | |
| int sr = SkGetPackedR32(c); | |
| int sg = SkGetPackedG32(c); | |
| int sb = SkGetPackedB32(c); | |
| sr = SkDITHER_R32To565(sr, dither); | |
| sg = SkDITHER_G32To565(sg, dither); | |
| sb = SkDITHER_B32To565(sb, dither); | |
| int dr = (sr * src_scale + SkGetPackedR16(d) * dst_scale) >> 8; | |
| int dg = (sg * src_scale + SkGetPackedG16(d) * dst_scale) >> 8; | |
| int db = (sb * src_scale + SkGetPackedB16(d) * dst_scale) >> 8; | |
| *dst = SkPackRGB16(dr, dg, db); | |
| } | |
| dst += 1; | |
| DITHER_INC_X(x); | |
| } while (--count != 0); | |
| } | |
| } | |
| /////////////////////////////////////////////////////////////////////////////// | |
| /////////////////////////////////////////////////////////////////////////////// | |
| static const SkBlitRow::Proc gDefault_565_Procs[] = { | |
| // no dither | |
| S32_D565_Opaque, | |
| S32_D565_Blend, | |
| S32A_D565_Opaque, | |
| S32A_D565_Blend, | |
| // dither | |
| S32_D565_Opaque_Dither, | |
| S32_D565_Blend_Dither, | |
| S32A_D565_Opaque_Dither, | |
| S32A_D565_Blend_Dither | |
| }; | |
| SkBlitRow::Proc SkBlitRow::Factory(unsigned flags, SkColorType ct) { | |
| SkASSERT(flags < SK_ARRAY_COUNT(gDefault_565_Procs)); | |
| // just so we don't crash | |
| flags &= kFlags16_Mask; | |
| SkBlitRow::Proc proc = NULL; | |
| switch (ct) { | |
| case kRGB_565_SkColorType: | |
| proc = PlatformProcs565(flags); | |
| if (NULL == proc) { | |
| proc = gDefault_565_Procs[flags]; | |
| } | |
| break; | |
| default: | |
| break; | |
| } | |
| return proc; | |
| } |