| /* |
| * 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" |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| 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; |
| unsigned dst_scale = 255 - SkMulDiv255Round(SkGetPackedA32(sc), alpha); |
| unsigned dr = SkMulS16(SkPacked32ToR16(sc), alpha) + SkMulS16(SkGetPackedR16(dc), dst_scale); |
| unsigned dg = SkMulS16(SkPacked32ToG16(sc), alpha) + SkMulS16(SkGetPackedG16(dc), dst_scale); |
| unsigned db = SkMulS16(SkPacked32ToB16(sc), alpha) + SkMulS16(SkGetPackedB16(dc), dst_scale); |
| *dst = SkPackRGB16(SkDiv255Round(dr), SkDiv255Round(dg), SkDiv255Round(db)); |
| } |
| 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 |
| }; |
| |
| extern SkBlitRow::Proc SkBlitRow_Factory_4444(unsigned flags); |
| |
| SkBlitRow::Proc SkBlitRow::Factory(unsigned flags, SkBitmap::Config config) { |
| SkASSERT(flags < SK_ARRAY_COUNT(gDefault_565_Procs)); |
| // just so we don't crash |
| flags &= kFlags16_Mask; |
| |
| SkBlitRow::Proc proc = NULL; |
| |
| switch (config) { |
| case SkBitmap::kRGB_565_Config: |
| proc = PlatformProcs565(flags); |
| if (NULL == proc) { |
| proc = gDefault_565_Procs[flags]; |
| } |
| break; |
| case SkBitmap::kARGB_4444_Config: |
| proc = PlatformProcs4444(flags); |
| if (NULL == proc) { |
| proc = SkBlitRow_Factory_4444(flags); |
| } |
| break; |
| default: |
| break; |
| } |
| return proc; |
| } |
| |