grab from latest android



git-svn-id: http://skia.googlecode.com/svn/trunk@27 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkBlitRow_D16.cpp b/src/core/SkBlitRow_D16.cpp
new file mode 100644
index 0000000..f40df36
--- /dev/null
+++ b/src/core/SkBlitRow_D16.cpp
@@ -0,0 +1,258 @@
+#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);
+            SkASSERT(SkGetPackedA32(c) == 255);
+            *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);
+            SkASSERT(SkGetPackedA32(c) == 255);
+            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) {
+        int src_scale = SkAlpha255To256(alpha);
+        do {
+            SkPMColor sc = *src++;
+            SkPMColorAssert(sc);
+            if (sc)
+            {
+                uint16_t dc = *dst;
+                unsigned sa = SkGetPackedA32(sc);
+                unsigned dr, dg, db;
+                
+                if (sa == 255) {
+                    dr = SkAlphaBlend(SkPacked32ToR16(sc), SkGetPackedR16(dc), src_scale);
+                    dg = SkAlphaBlend(SkPacked32ToG16(sc), SkGetPackedG16(dc), src_scale);
+                    db = SkAlphaBlend(SkPacked32ToB16(sc), SkGetPackedB16(dc), src_scale);
+                } else {
+                    unsigned dst_scale = 255 - SkAlphaMul(sa, src_scale);
+                    dr = (SkPacked32ToR16(sc) * src_scale + SkGetPackedR16(dc) * dst_scale) >> 8;
+                    dg = (SkPacked32ToG16(sc) * src_scale + SkGetPackedG16(dc) * dst_scale) >> 8;
+                    db = (SkPacked32ToB16(sc) * src_scale + SkGetPackedB16(dc) * dst_scale) >> 8;
+                }
+                *dst = SkPackRGB16(dr, dg, 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);
+            SkASSERT(SkGetPackedA32(c) == 255);
+
+            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);
+            SkASSERT(SkGetPackedA32(c) == 255);
+
+            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);
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef USE_T32CB16BLEND_ASM
+    extern "C" void scanline_t32cb16blend_arm(uint16_t*, uint32_t*, size_t);
+#endif
+
+static const SkBlitRow::Proc gProcs16[] = {
+    // no dither
+    S32_D565_Opaque,
+    S32_D565_Blend,
+
+#ifdef USE_T32CB16BLEND_ASM
+    (SkBlitRow::Proc)scanline_t32cb16blend_arm,
+#else
+    S32A_D565_Opaque,
+#endif
+
+    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(gProcs16));
+    
+    switch (config) {
+        case SkBitmap::kRGB_565_Config:
+            return gProcs16[flags];
+        case SkBitmap::kARGB_4444_Config:
+            return SkBlitRow_Factory_4444(flags);
+        default:
+            break;
+    }
+    return NULL;
+}
+