1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
758af9a64701540c7f8083bc22a42d0bae3a5583creed@google.com
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitRow.h"
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDither.h"
114b163ed2c22facbe8891616874ae07ba7827d9c9reed@google.com#include "SkMathPriv.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void S32_D565_Opaque(uint16_t* SK_RESTRICT dst,
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const SkPMColor* SK_RESTRICT src, int count,
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            U8CPU alpha, int /*x*/, int /*y*/) {
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(255 == alpha);
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (count > 0) {
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkPMColor c = *src++;
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkPMColorAssert(c);
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            *dst++ = SkPixel32ToPixel16_ToU16(c);
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (--count != 0);
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void S32_D565_Blend(uint16_t* SK_RESTRICT dst,
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             const SkPMColor* SK_RESTRICT src, int count,
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             U8CPU alpha, int /*x*/, int /*y*/) {
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(255 > alpha);
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (count > 0) {
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int scale = SkAlpha255To256(alpha);
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkPMColor c = *src++;
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkPMColorAssert(c);
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            uint16_t d = *dst;
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            *dst++ = SkPackRGB16(
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    SkAlphaBlend(SkPacked32ToR16(c), SkGetPackedR16(d), scale),
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    SkAlphaBlend(SkPacked32ToG16(c), SkGetPackedG16(d), scale),
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    SkAlphaBlend(SkPacked32ToB16(c), SkGetPackedB16(d), scale));
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (--count != 0);
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void S32A_D565_Opaque(uint16_t* SK_RESTRICT dst,
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                               const SkPMColor* SK_RESTRICT src, int count,
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                               U8CPU alpha, int /*x*/, int /*y*/) {
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(255 == alpha);
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (count > 0) {
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkPMColor c = *src++;
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkPMColorAssert(c);
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//            if (__builtin_expect(c!=0, 1))
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (c) {
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *dst = SkSrcOver32To16(c, *dst);
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            dst += 1;
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (--count != 0);
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void S32A_D565_Blend(uint16_t* SK_RESTRICT dst,
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const SkPMColor* SK_RESTRICT src, int count,
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                               U8CPU alpha, int /*x*/, int /*y*/) {
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(255 > alpha);
70fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (count > 0) {
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkPMColor sc = *src++;
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkPMColorAssert(sc);
758e4c93b04cdaa8caeba6b76d612fb2dd58a57a61reed@android.com            if (sc) {
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                uint16_t dc = *dst;
77233c295980d54347ca1eda9095cd54b63a0268ecreed                SkPMColor res = SkBlendARGB32(sc, SkPixel16ToPixel32(dc), alpha);
78233c295980d54347ca1eda9095cd54b63a0268ecreed                *dst = SkPixel32ToPixel16(res);
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            dst += 1;
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (--count != 0);
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
86fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void S32_D565_Opaque_Dither(uint16_t* SK_RESTRICT dst,
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                     const SkPMColor* SK_RESTRICT src,
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                     int count, U8CPU alpha, int x, int y) {
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(255 == alpha);
91fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (count > 0) {
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        DITHER_565_SCAN(y);
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkPMColor c = *src++;
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkPMColorAssert(c);
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            unsigned dither = DITHER_VALUE(x);
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            *dst++ = SkDitherRGB32To565(c, dither);
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            DITHER_INC_X(x);
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (--count != 0);
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void S32_D565_Blend_Dither(uint16_t* SK_RESTRICT dst,
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                    const SkPMColor* SK_RESTRICT src,
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                    int count, U8CPU alpha, int x, int y) {
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(255 > alpha);
109fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (count > 0) {
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int scale = SkAlpha255To256(alpha);
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        DITHER_565_SCAN(y);
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkPMColor c = *src++;
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkPMColorAssert(c);
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
117fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            int dither = DITHER_VALUE(x);
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int sr = SkGetPackedR32(c);
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int sg = SkGetPackedG32(c);
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int sb = SkGetPackedB32(c);
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            sr = SkDITHER_R32To565(sr, dither);
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            sg = SkDITHER_G32To565(sg, dither);
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            sb = SkDITHER_B32To565(sb, dither);
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            uint16_t d = *dst;
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            *dst++ = SkPackRGB16(SkAlphaBlend(sr, SkGetPackedR16(d), scale),
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                 SkAlphaBlend(sg, SkGetPackedG16(d), scale),
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                 SkAlphaBlend(sb, SkGetPackedB16(d), scale));
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            DITHER_INC_X(x);
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (--count != 0);
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void S32A_D565_Opaque_Dither(uint16_t* SK_RESTRICT dst,
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                      const SkPMColor* SK_RESTRICT src,
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                      int count, U8CPU alpha, int x, int y) {
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(255 == alpha);
138fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (count > 0) {
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        DITHER_565_SCAN(y);
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkPMColor c = *src++;
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkPMColorAssert(c);
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (c) {
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned a = SkGetPackedA32(c);
146fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                int d = SkAlphaMul(DITHER_VALUE(x), SkAlpha255To256(a));
148fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned sr = SkGetPackedR32(c);
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned sg = SkGetPackedG32(c);
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned sb = SkGetPackedB32(c);
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                sr = SkDITHER_R32_FOR_565(sr, d);
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                sg = SkDITHER_G32_FOR_565(sg, d);
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                sb = SkDITHER_B32_FOR_565(sb, d);
155fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                uint32_t src_expanded = (sg << 24) | (sr << 13) | (sb << 2);
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                uint32_t dst_expanded = SkExpand_rgb_16(*dst);
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                dst_expanded = dst_expanded * (SkAlpha255To256(255 - a) >> 3);
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                // now src and dst expanded are in g:11 r:10 x:1 b:10
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *dst = SkCompact_rgb_16((src_expanded + dst_expanded) >> 5);
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            dst += 1;
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            DITHER_INC_X(x);
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (--count != 0);
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void S32A_D565_Blend_Dither(uint16_t* SK_RESTRICT dst,
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                     const SkPMColor* SK_RESTRICT src,
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                     int count, U8CPU alpha, int x, int y) {
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(255 > alpha);
172fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (count > 0) {
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int src_scale = SkAlpha255To256(alpha);
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        DITHER_565_SCAN(y);
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do {
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkPMColor c = *src++;
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkPMColorAssert(c);
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (c)
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            {
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned d = *dst;
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                int sa = SkGetPackedA32(c);
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                int dst_scale = SkAlpha255To256(255 - SkAlphaMul(sa, src_scale));
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                int dither = DITHER_VALUE(x);
185fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                int sr = SkGetPackedR32(c);
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                int sg = SkGetPackedG32(c);
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                int sb = SkGetPackedB32(c);
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                sr = SkDITHER_R32To565(sr, dither);
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                sg = SkDITHER_G32To565(sg, dither);
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                sb = SkDITHER_B32To565(sb, dither);
192fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                int dr = (sr * src_scale + SkGetPackedR16(d) * dst_scale) >> 8;
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                int dg = (sg * src_scale + SkGetPackedG16(d) * dst_scale) >> 8;
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                int db = (sb * src_scale + SkGetPackedB16(d) * dst_scale) >> 8;
196fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *dst = SkPackRGB16(dr, dg, db);
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            dst += 1;
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            DITHER_INC_X(x);
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } while (--count != 0);
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
206a7f11918d92621507f35b228a290f05dcaf0f4b6reed
207a7f11918d92621507f35b228a290f05dcaf0f4b6reedstatic uint32_t pmcolor_to_expand16(SkPMColor c) {
208a7f11918d92621507f35b228a290f05dcaf0f4b6reed    unsigned r = SkGetPackedR32(c);
209a7f11918d92621507f35b228a290f05dcaf0f4b6reed    unsigned g = SkGetPackedG32(c);
210a7f11918d92621507f35b228a290f05dcaf0f4b6reed    unsigned b = SkGetPackedB32(c);
211a7f11918d92621507f35b228a290f05dcaf0f4b6reed    return (g << 24) | (r << 13) | (b << 2);
212a7f11918d92621507f35b228a290f05dcaf0f4b6reed}
213a7f11918d92621507f35b228a290f05dcaf0f4b6reed
214a7f11918d92621507f35b228a290f05dcaf0f4b6reedstatic void Color32A_D565(uint16_t dst[], SkPMColor src, int count, int x, int y) {
215a7f11918d92621507f35b228a290f05dcaf0f4b6reed    SkASSERT(count > 0);
216a7f11918d92621507f35b228a290f05dcaf0f4b6reed    uint32_t src_expand = pmcolor_to_expand16(src);
217a7f11918d92621507f35b228a290f05dcaf0f4b6reed    unsigned scale = SkAlpha255To256(0xFF - SkGetPackedA32(src)) >> 3;
218a7f11918d92621507f35b228a290f05dcaf0f4b6reed    do {
21970840cbd898df67f603987213164c798415d76bfhenrik.smiding        *dst = SkBlend32_RGB16(src_expand, *dst, scale);
220a7f11918d92621507f35b228a290f05dcaf0f4b6reed        dst += 1;
221a7f11918d92621507f35b228a290f05dcaf0f4b6reed    } while (--count != 0);
222a7f11918d92621507f35b228a290f05dcaf0f4b6reed}
223a7f11918d92621507f35b228a290f05dcaf0f4b6reed
224a7f11918d92621507f35b228a290f05dcaf0f4b6reed///////////////////////////////////////////////////////////////////////////////
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
227a7f11918d92621507f35b228a290f05dcaf0f4b6reedstatic const SkBlitRow::Proc16 gDefault_565_Procs[] = {
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // no dither
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    S32_D565_Opaque,
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    S32_D565_Blend,
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    S32A_D565_Opaque,
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    S32A_D565_Blend,
2347d2e322beeb9361f93a7983193bdf20ac972d341reed@android.com
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // dither
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    S32_D565_Opaque_Dither,
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    S32_D565_Blend_Dither,
2387d2e322beeb9361f93a7983193bdf20ac972d341reed@android.com
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    S32A_D565_Opaque_Dither,
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    S32A_D565_Blend_Dither
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
243a7f11918d92621507f35b228a290f05dcaf0f4b6reedSkBlitRow::Proc16 SkBlitRow::Factory16(unsigned flags) {
2447d2e322beeb9361f93a7983193bdf20ac972d341reed@android.com    SkASSERT(flags < SK_ARRAY_COUNT(gDefault_565_Procs));
245c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    // just so we don't crash
246c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    flags &= kFlags16_Mask;
2477d2e322beeb9361f93a7983193bdf20ac972d341reed@android.com
248a7f11918d92621507f35b228a290f05dcaf0f4b6reed    SkBlitRow::Proc16 proc = PlatformFactory565(flags);
2492880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    if (nullptr == proc) {
250a7f11918d92621507f35b228a290f05dcaf0f4b6reed        proc = gDefault_565_Procs[flags];
251a7f11918d92621507f35b228a290f05dcaf0f4b6reed    }
252a7f11918d92621507f35b228a290f05dcaf0f4b6reed    return proc;
253a7f11918d92621507f35b228a290f05dcaf0f4b6reed}
254a7f11918d92621507f35b228a290f05dcaf0f4b6reed
255a7f11918d92621507f35b228a290f05dcaf0f4b6reedstatic const SkBlitRow::ColorProc16 gDefault_565_ColorProcs[] = {
256a7f11918d92621507f35b228a290f05dcaf0f4b6reed#if 0
257a7f11918d92621507f35b228a290f05dcaf0f4b6reed    Color32A_D565,
258a7f11918d92621507f35b228a290f05dcaf0f4b6reed    Color32A_D565_Dither
259a7f11918d92621507f35b228a290f05dcaf0f4b6reed#else
260e6b1a60758aa16c0456ff8e1cf717c369e4e84b0henrik.smiding    // TODO: stop cheating and fill dither from the above specializations!
261a7f11918d92621507f35b228a290f05dcaf0f4b6reed    Color32A_D565,
262a7f11918d92621507f35b228a290f05dcaf0f4b6reed    Color32A_D565,
263a7f11918d92621507f35b228a290f05dcaf0f4b6reed#endif
264a7f11918d92621507f35b228a290f05dcaf0f4b6reed};
265a7f11918d92621507f35b228a290f05dcaf0f4b6reed
266a7f11918d92621507f35b228a290f05dcaf0f4b6reedSkBlitRow::ColorProc16 SkBlitRow::ColorFactory16(unsigned flags) {
267a7f11918d92621507f35b228a290f05dcaf0f4b6reed    SkASSERT((flags & ~kFlags16_Mask) == 0);
268a7f11918d92621507f35b228a290f05dcaf0f4b6reed    // just so we don't crash
269a7f11918d92621507f35b228a290f05dcaf0f4b6reed    flags &= kFlags16_Mask;
270e6b1a60758aa16c0456ff8e1cf717c369e4e84b0henrik.smiding    // we ignore both kGlobalAlpha_Flag and kSrcPixelAlpha_Flag, so shift down
27170840cbd898df67f603987213164c798415d76bfhenrik.smiding    // no need for the additional code specializing on opaque alpha at this time
272e6b1a60758aa16c0456ff8e1cf717c369e4e84b0henrik.smiding    flags >>= 2;
273a7f11918d92621507f35b228a290f05dcaf0f4b6reed
274a7f11918d92621507f35b228a290f05dcaf0f4b6reed    SkASSERT(flags < SK_ARRAY_COUNT(gDefault_565_ColorProcs));
2757d2e322beeb9361f93a7983193bdf20ac972d341reed@android.com
276a7f11918d92621507f35b228a290f05dcaf0f4b6reed    SkBlitRow::ColorProc16 proc = PlatformColorFactory565(flags);
2772880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    if (nullptr == proc) {
278a7f11918d92621507f35b228a290f05dcaf0f4b6reed        proc = gDefault_565_ColorProcs[flags];
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2807d2e322beeb9361f93a7983193bdf20ac972d341reed@android.com    return proc;
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
282