SkBlitRow_opts_arm_neon.cpp revision 0060159457453ca45a47828648c8f29d5695983c
1a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com/*
2a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * Copyright 2012 The Android Open Source Project
3a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com *
4a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * Use of this source code is governed by a BSD-style license that can be
5a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * found in the LICENSE file.
6a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com */
7a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
8a111e492b84c312a6bd5d5d9ef100dca48f4941ddjsollen@google.com#include "SkBlitRow_opts_arm_neon.h"
9a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
10a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#include "SkBlitMask.h"
11a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#include "SkBlitRow.h"
12a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#include "SkColorPriv.h"
13a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#include "SkDither.h"
14a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#include "SkMathPriv.h"
15a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#include "SkUtils.h"
16a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
17a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#include "SkCachePreload_arm.h"
180060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org#include "SkColor_opts_neon.h"
19a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#include <arm_neon.h>
20a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
210060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.orgvoid S32_D565_Opaque_neon(uint16_t* SK_RESTRICT dst,
220060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org                           const SkPMColor* SK_RESTRICT src, int count,
230060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org                           U8CPU alpha, int /*x*/, int /*y*/) {
240060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org    SkASSERT(255 == alpha);
250060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org
260060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org    while (count >= 8) {
270060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        uint8x8x4_t vsrc;
280060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        uint16x8_t vdst;
290060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org
300060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        // Load
310060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        vsrc = vld4_u8((uint8_t*)src);
320060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org
330060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        // Convert src to 565
340060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        vdst = vshll_n_u8(vsrc.val[NEON_R], 8);
350060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        vdst = vsriq_n_u16(vdst, vshll_n_u8(vsrc.val[NEON_G], 8), 5);
360060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        vdst = vsriq_n_u16(vdst, vshll_n_u8(vsrc.val[NEON_B], 8), 5+6);
370060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org
380060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        // Store
390060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        vst1q_u16(dst, vdst);
400060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org
410060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        // Prepare next iteration
420060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        dst += 8;
430060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        src += 8;
440060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        count -= 8;
450060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org    };
460060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org
470060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org    // Leftovers
480060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org    while (count > 0) {
490060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        SkPMColor c = *src++;
500060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        SkPMColorAssert(c);
510060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        *dst = SkPixel32ToPixel16_ToU16(c);
520060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        dst++;
530060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        count--;
540060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org    };
550060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org}
560060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org
57a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comvoid S32A_D565_Opaque_neon(uint16_t* SK_RESTRICT dst,
58a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                           const SkPMColor* SK_RESTRICT src, int count,
59a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                           U8CPU alpha, int /*x*/, int /*y*/) {
60a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    SkASSERT(255 == alpha);
61a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
62a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    if (count >= 8) {
63efbe8e9bedda21a3e061ebf3d96431a0f250a654djsollen@google.com        uint16_t* SK_RESTRICT keep_dst = 0;
64fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
65a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        asm volatile (
66a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "ands       ip, %[count], #7            \n\t"
67a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmov.u8    d31, #1<<7                  \n\t"
68a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vld1.16    {q12}, [%[dst]]             \n\t"
69a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vld4.8     {d0-d3}, [%[src]]           \n\t"
70a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // Thumb does not support the standard ARM conditional
71a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // instructions but instead requires the 'it' instruction
72a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // to signal conditional execution
73a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "it eq                                  \n\t"
74a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "moveq      ip, #8                      \n\t"
75a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "mov        %[keep_dst], %[dst]         \n\t"
76fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
77a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "add        %[src], %[src], ip, LSL#2   \n\t"
78a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "add        %[dst], %[dst], ip, LSL#1   \n\t"
79a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "subs       %[count], %[count], ip      \n\t"
80a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "b          9f                          \n\t"
81a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // LOOP
82a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "2:                                         \n\t"
83fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
84a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vld1.16    {q12}, [%[dst]]!            \n\t"
85a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vld4.8     {d0-d3}, [%[src]]!          \n\t"
86a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vst1.16    {q10}, [%[keep_dst]]        \n\t"
87a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "sub        %[keep_dst], %[dst], #8*2   \n\t"
88a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "subs       %[count], %[count], #8      \n\t"
89a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "9:                                         \n\t"
90a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "pld        [%[dst],#32]                \n\t"
91a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // expand 0565 q12 to 8888 {d4-d7}
92a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmovn.u16  d4, q12                     \n\t"
93a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshr.u16   q11, q12, #5                \n\t"
94a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshr.u16   q10, q12, #6+5              \n\t"
95a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmovn.u16  d5, q11                     \n\t"
96a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmovn.u16  d6, q10                     \n\t"
97a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshl.u8    d4, d4, #3                  \n\t"
98a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshl.u8    d5, d5, #2                  \n\t"
99a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshl.u8    d6, d6, #3                  \n\t"
100fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
101a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmovl.u8   q14, d31                    \n\t"
102a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmovl.u8   q13, d31                    \n\t"
103a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmovl.u8   q12, d31                    \n\t"
104fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
105a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // duplicate in 4/2/1 & 8pix vsns
106a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmvn.8     d30, d3                     \n\t"
107a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmlal.u8   q14, d30, d6                \n\t"
108a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmlal.u8   q13, d30, d5                \n\t"
109a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmlal.u8   q12, d30, d4                \n\t"
110a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshr.u16   q8, q14, #5                 \n\t"
111a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshr.u16   q9, q13, #6                 \n\t"
112a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vaddhn.u16 d6, q14, q8                 \n\t"
113a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshr.u16   q8, q12, #5                 \n\t"
114a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vaddhn.u16 d5, q13, q9                 \n\t"
115a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vqadd.u8   d6, d6, d0                  \n\t"  // moved up
116a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vaddhn.u16 d4, q12, q8                 \n\t"
117a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // intentionally don't calculate alpha
118a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // result in d4-d6
119fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
120a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vqadd.u8   d5, d5, d1                  \n\t"
121a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vqadd.u8   d4, d4, d2                  \n\t"
122fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
123a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // pack 8888 {d4-d6} to 0565 q10
124a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshll.u8   q10, d6, #8                 \n\t"
125a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshll.u8   q3, d5, #8                  \n\t"
126a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshll.u8   q2, d4, #8                  \n\t"
127a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vsri.u16   q10, q3, #5                 \n\t"
128a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vsri.u16   q10, q2, #11                \n\t"
129fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
130a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "bne        2b                          \n\t"
131fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
132a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "1:                                         \n\t"
133a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vst1.16      {q10}, [%[keep_dst]]      \n\t"
134a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      : [count] "+r" (count)
135fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com                      : [dst] "r" (dst), [keep_dst] "r" (keep_dst), [src] "r" (src)
136a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      : "ip", "cc", "memory", "d0","d1","d2","d3","d4","d5","d6","d7",
137a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "d16","d17","d18","d19","d20","d21","d22","d23","d24","d25","d26","d27","d28","d29",
138a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "d30","d31"
139a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      );
140a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
141fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    else
142a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    {   // handle count < 8
143efbe8e9bedda21a3e061ebf3d96431a0f250a654djsollen@google.com        uint16_t* SK_RESTRICT keep_dst = 0;
144fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
145a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        asm volatile (
146a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmov.u8    d31, #1<<7                  \n\t"
147a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "mov        %[keep_dst], %[dst]         \n\t"
148fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
149a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "tst        %[count], #4                \n\t"
150a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "beq        14f                         \n\t"
151a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vld1.16    {d25}, [%[dst]]!            \n\t"
152a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vld1.32    {q1}, [%[src]]!             \n\t"
153fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
154a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "14:                                        \n\t"
155a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "tst        %[count], #2                \n\t"
156a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "beq        12f                         \n\t"
157a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vld1.32    {d24[1]}, [%[dst]]!         \n\t"
158a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vld1.32    {d1}, [%[src]]!             \n\t"
159fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
160a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "12:                                        \n\t"
161a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "tst        %[count], #1                \n\t"
162a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "beq        11f                         \n\t"
163a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vld1.16    {d24[1]}, [%[dst]]!         \n\t"
164a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vld1.32    {d0[1]}, [%[src]]!          \n\t"
165fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
166a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "11:                                        \n\t"
167a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // unzips achieve the same as a vld4 operation
168a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vuzpq.u16  q0, q1                      \n\t"
169a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vuzp.u8    d0, d1                      \n\t"
170a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vuzp.u8    d2, d3                      \n\t"
171a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // expand 0565 q12 to 8888 {d4-d7}
172a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmovn.u16  d4, q12                     \n\t"
173a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshr.u16   q11, q12, #5                \n\t"
174a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshr.u16   q10, q12, #6+5              \n\t"
175a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmovn.u16  d5, q11                     \n\t"
176a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmovn.u16  d6, q10                     \n\t"
177a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshl.u8    d4, d4, #3                  \n\t"
178a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshl.u8    d5, d5, #2                  \n\t"
179a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshl.u8    d6, d6, #3                  \n\t"
180fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
181a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmovl.u8   q14, d31                    \n\t"
182a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmovl.u8   q13, d31                    \n\t"
183a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmovl.u8   q12, d31                    \n\t"
184fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
185a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // duplicate in 4/2/1 & 8pix vsns
186a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmvn.8     d30, d3                     \n\t"
187a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmlal.u8   q14, d30, d6                \n\t"
188a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmlal.u8   q13, d30, d5                \n\t"
189a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmlal.u8   q12, d30, d4                \n\t"
190a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshr.u16   q8, q14, #5                 \n\t"
191a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshr.u16   q9, q13, #6                 \n\t"
192a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vaddhn.u16 d6, q14, q8                 \n\t"
193a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshr.u16   q8, q12, #5                 \n\t"
194a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vaddhn.u16 d5, q13, q9                 \n\t"
195a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vqadd.u8   d6, d6, d0                  \n\t"  // moved up
196a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vaddhn.u16 d4, q12, q8                 \n\t"
197a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // intentionally don't calculate alpha
198a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // result in d4-d6
199fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
200a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vqadd.u8   d5, d5, d1                  \n\t"
201a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vqadd.u8   d4, d4, d2                  \n\t"
202fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
203a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // pack 8888 {d4-d6} to 0565 q10
204a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshll.u8   q10, d6, #8                 \n\t"
205a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshll.u8   q3, d5, #8                  \n\t"
206a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshll.u8   q2, d4, #8                  \n\t"
207a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vsri.u16   q10, q3, #5                 \n\t"
208a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vsri.u16   q10, q2, #11                \n\t"
209fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
210a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // store
211a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "tst        %[count], #4                \n\t"
212a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "beq        24f                         \n\t"
213a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vst1.16    {d21}, [%[keep_dst]]!       \n\t"
214fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
215a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "24:                                        \n\t"
216a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "tst        %[count], #2                \n\t"
217a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "beq        22f                         \n\t"
218a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vst1.32    {d20[1]}, [%[keep_dst]]!    \n\t"
219fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
220a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "22:                                        \n\t"
221a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "tst        %[count], #1                \n\t"
222a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "beq        21f                         \n\t"
223a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vst1.16    {d20[1]}, [%[keep_dst]]!    \n\t"
224fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
225a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "21:                                        \n\t"
226a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      : [count] "+r" (count)
227a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      : [dst] "r" (dst), [keep_dst] "r" (keep_dst), [src] "r" (src)
228a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      : "ip", "cc", "memory", "d0","d1","d2","d3","d4","d5","d6","d7",
229a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "d16","d17","d18","d19","d20","d21","d22","d23","d24","d25","d26","d27","d28","d29",
230a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "d30","d31"
231a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      );
232a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
233a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com}
234a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
235a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comvoid S32A_D565_Blend_neon(uint16_t* SK_RESTRICT dst,
236a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                          const SkPMColor* SK_RESTRICT src, int count,
237a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                          U8CPU alpha, int /*x*/, int /*y*/) {
238a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
239a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    U8CPU alpha_for_asm = alpha;
240a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
241a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    asm volatile (
242a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    /* This code implements a Neon version of S32A_D565_Blend. The output differs from
243a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com     * the original in two respects:
244a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com     *  1. The results have a few mismatches compared to the original code. These mismatches
245a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com     *     never exceed 1. It's possible to improve accuracy vs. a floating point
246a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com     *     implementation by introducing rounding right shifts (vrshr) for the final stage.
247a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com     *     Rounding is not present in the code below, because although results would be closer
248fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com     *     to a floating point implementation, the number of mismatches compared to the
249a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com     *     original code would be far greater.
250a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com     *  2. On certain inputs, the original code can overflow, causing colour channels to
251a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com     *     mix. Although the Neon code can also overflow, it doesn't allow one colour channel
252a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com     *     to affect another.
253a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com     */
254fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
255a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#if 1
256fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* reflects SkAlpha255To256()'s change from a+a>>7 to a+1 */
257a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "add        %[alpha], %[alpha], #1         \n\t"   // adjust range of alpha 0-256
258a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#else
259a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "add        %[alpha], %[alpha], %[alpha], lsr #7    \n\t"   // adjust range of alpha 0-256
260a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
261a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vmov.u16   q3, #255                        \n\t"   // set up constant
262a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "movs       r4, %[count], lsr #3            \n\t"   // calc. count>>3
263a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vmov.u16   d2[0], %[alpha]                 \n\t"   // move alpha to Neon
264a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "beq        2f                              \n\t"   // if count8 == 0, exit
265a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vmov.u16   q15, #0x1f                      \n\t"   // set up blue mask
266fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
267a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "1:                                             \n\t"
268a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vld1.u16   {d0, d1}, [%[dst]]              \n\t"   // load eight dst RGB565 pixels
269a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "subs       r4, r4, #1                      \n\t"   // decrement loop counter
270a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vld4.u8    {d24, d25, d26, d27}, [%[src]]! \n\t"   // load eight src ABGR32 pixels
271a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  //  and deinterleave
272fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
273a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vshl.u16   q9, q0, #5                      \n\t"   // shift green to top of lanes
274a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vand       q10, q0, q15                    \n\t"   // extract blue
275a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vshr.u16   q8, q0, #11                     \n\t"   // extract red
276a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vshr.u16   q9, q9, #10                     \n\t"   // extract green
277a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  // dstrgb = {q8, q9, q10}
278fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
279a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vshr.u8    d24, d24, #3                    \n\t"   // shift red to 565 range
280a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vshr.u8    d25, d25, #2                    \n\t"   // shift green to 565 range
281a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vshr.u8    d26, d26, #3                    \n\t"   // shift blue to 565 range
282fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
283a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vmovl.u8   q11, d24                        \n\t"   // widen red to 16 bits
284a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vmovl.u8   q12, d25                        \n\t"   // widen green to 16 bits
285a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vmovl.u8   q14, d27                        \n\t"   // widen alpha to 16 bits
286a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vmovl.u8   q13, d26                        \n\t"   // widen blue to 16 bits
287a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  // srcrgba = {q11, q12, q13, q14}
288fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
289a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vmul.u16   q2, q14, d2[0]                  \n\t"   // sa * src_scale
290a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vmul.u16   q11, q11, d2[0]                 \n\t"   // red result = src_red * src_scale
291a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vmul.u16   q12, q12, d2[0]                 \n\t"   // grn result = src_grn * src_scale
292a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vmul.u16   q13, q13, d2[0]                 \n\t"   // blu result = src_blu * src_scale
293fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
294a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vshr.u16   q2, q2, #8                      \n\t"   // sa * src_scale >> 8
295a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vsub.u16   q2, q3, q2                      \n\t"   // 255 - (sa * src_scale >> 8)
296a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  // dst_scale = q2
297fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
298a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vmla.u16   q11, q8, q2                     \n\t"   // red result += dst_red * dst_scale
299a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vmla.u16   q12, q9, q2                     \n\t"   // grn result += dst_grn * dst_scale
300a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vmla.u16   q13, q10, q2                    \n\t"   // blu result += dst_blu * dst_scale
301a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
302a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#if 1
303fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    // trying for a better match with SkDiv255Round(a)
304fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    // C alg is:  a+=128; (a+a>>8)>>8
305fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    // we'll use just a rounding shift [q2 is available for scratch]
306a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vrshr.u16   q11, q11, #8                    \n\t"   // shift down red
307a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vrshr.u16   q12, q12, #8                    \n\t"   // shift down green
308a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vrshr.u16   q13, q13, #8                    \n\t"   // shift down blue
309a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#else
310fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    // arm's original "truncating divide by 256"
311a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vshr.u16   q11, q11, #8                    \n\t"   // shift down red
312a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vshr.u16   q12, q12, #8                    \n\t"   // shift down green
313a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vshr.u16   q13, q13, #8                    \n\t"   // shift down blue
314a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
315fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
316a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vsli.u16   q13, q12, #5                    \n\t"   // insert green into blue
317a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vsli.u16   q13, q11, #11                   \n\t"   // insert red into green/blue
318a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vst1.16    {d26, d27}, [%[dst]]!           \n\t"   // write pixel back to dst, update ptr
319fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
320a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "bne        1b                              \n\t"   // if counter != 0, loop
321a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "2:                                             \n\t"   // exit
322fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
323a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  : [src] "+r" (src), [dst] "+r" (dst), [count] "+r" (count), [alpha] "+r" (alpha_for_asm)
324a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  :
325a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  : "cc", "memory", "r4", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"
326a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  );
327a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
328a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    count &= 7;
329a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    if (count > 0) {
330a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        do {
331a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            SkPMColor sc = *src++;
332a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            if (sc) {
333a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                uint16_t dc = *dst;
334a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                unsigned dst_scale = 255 - SkMulDiv255Round(SkGetPackedA32(sc), alpha);
335a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                unsigned dr = SkMulS16(SkPacked32ToR16(sc), alpha) + SkMulS16(SkGetPackedR16(dc), dst_scale);
336a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                unsigned dg = SkMulS16(SkPacked32ToG16(sc), alpha) + SkMulS16(SkGetPackedG16(dc), dst_scale);
337a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                unsigned db = SkMulS16(SkPacked32ToB16(sc), alpha) + SkMulS16(SkGetPackedB16(dc), dst_scale);
338a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                *dst = SkPackRGB16(SkDiv255Round(dr), SkDiv255Round(dg), SkDiv255Round(db));
339a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            }
340a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            dst += 1;
341a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        } while (--count != 0);
342a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
343a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com}
344a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
345a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com/* dither matrix for Neon, derived from gDitherMatrix_3Bit_16.
346a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * each dither value is spaced out into byte lanes, and repeated
347a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * to allow an 8-byte load from offsets 0, 1, 2 or 3 from the
348a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * start of each row.
349a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com */
350a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comstatic const uint8_t gDitherMatrix_Neon[48] = {
351a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    0, 4, 1, 5, 0, 4, 1, 5, 0, 4, 1, 5,
352a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    6, 2, 7, 3, 6, 2, 7, 3, 6, 2, 7, 3,
353a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    1, 5, 0, 4, 1, 5, 0, 4, 1, 5, 0, 4,
354a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    7, 3, 6, 2, 7, 3, 6, 2, 7, 3, 6, 2,
355fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
356a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com};
357a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
358a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comvoid S32_D565_Blend_Dither_neon(uint16_t *dst, const SkPMColor *src,
359a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                                int count, U8CPU alpha, int x, int y)
360a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com{
361a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    /* select row and offset for dither array */
362a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    const uint8_t *dstart = &gDitherMatrix_Neon[(y&3)*12 + (x&3)];
363fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
364a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    /* rescale alpha to range 0 - 256 */
365a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    int scale = SkAlpha255To256(alpha);
366fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
367a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    asm volatile (
368a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vld1.8         {d31}, [%[dstart]]              \n\t"   // load dither values
369a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vshr.u8        d30, d31, #1                    \n\t"   // calc. green dither values
370a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vdup.16        d6, %[scale]                    \n\t"   // duplicate scale into neon reg
371a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vmov.i8        d29, #0x3f                      \n\t"   // set up green mask
372a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vmov.i8        d28, #0x1f                      \n\t"   // set up blue mask
373a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "1:                                                 \n\t"
374a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vld4.8         {d0, d1, d2, d3}, [%[src]]!     \n\t"   // load 8 pixels and split into argb
375a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vshr.u8        d22, d0, #5                     \n\t"   // calc. red >> 5
376a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vshr.u8        d23, d1, #6                     \n\t"   // calc. green >> 6
377a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vshr.u8        d24, d2, #5                     \n\t"   // calc. blue >> 5
378a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vaddl.u8       q8, d0, d31                     \n\t"   // add in dither to red and widen
379a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vaddl.u8       q9, d1, d30                     \n\t"   // add in dither to green and widen
380a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vaddl.u8       q10, d2, d31                    \n\t"   // add in dither to blue and widen
381a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vsubw.u8       q8, q8, d22                     \n\t"   // sub shifted red from result
382a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vsubw.u8       q9, q9, d23                     \n\t"   // sub shifted green from result
383a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vsubw.u8       q10, q10, d24                   \n\t"   // sub shifted blue from result
384a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vshrn.i16      d22, q8, #3                     \n\t"   // shift right and narrow to 5 bits
385a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vshrn.i16      d23, q9, #2                     \n\t"   // shift right and narrow to 6 bits
386a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vshrn.i16      d24, q10, #3                    \n\t"   // shift right and narrow to 5 bits
387a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  // load 8 pixels from dst, extract rgb
388a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vld1.16        {d0, d1}, [%[dst]]              \n\t"   // load 8 pixels
389a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vshrn.i16      d17, q0, #5                     \n\t"   // shift green down to bottom 6 bits
390a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vmovn.i16      d18, q0                         \n\t"   // narrow to get blue as bytes
391a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vshr.u16       q0, q0, #11                     \n\t"   // shift down to extract red
392a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vand           d17, d17, d29                   \n\t"   // and green with green mask
393a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vand           d18, d18, d28                   \n\t"   // and blue with blue mask
394a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vmovn.i16      d16, q0                         \n\t"   // narrow to get red as bytes
395a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  // src = {d22 (r), d23 (g), d24 (b)}
396a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  // dst = {d16 (r), d17 (g), d18 (b)}
397a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  // subtract dst from src and widen
398a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vsubl.s8       q0, d22, d16                    \n\t"   // subtract red src from dst
399a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vsubl.s8       q1, d23, d17                    \n\t"   // subtract green src from dst
400a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vsubl.s8       q2, d24, d18                    \n\t"   // subtract blue src from dst
401a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  // multiply diffs by scale and shift
402a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vmul.i16       q0, q0, d6[0]                   \n\t"   // multiply red by scale
403a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vmul.i16       q1, q1, d6[0]                   \n\t"   // multiply blue by scale
404a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vmul.i16       q2, q2, d6[0]                   \n\t"   // multiply green by scale
405a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "subs           %[count], %[count], #8          \n\t"   // decrement loop counter
406a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vshrn.i16      d0, q0, #8                      \n\t"   // shift down red by 8 and narrow
407a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vshrn.i16      d2, q1, #8                      \n\t"   // shift down green by 8 and narrow
408a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vshrn.i16      d4, q2, #8                      \n\t"   // shift down blue by 8 and narrow
409a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  // add dst to result
410a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vaddl.s8       q0, d0, d16                     \n\t"   // add dst to red
411a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vaddl.s8       q1, d2, d17                     \n\t"   // add dst to green
412a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vaddl.s8       q2, d4, d18                     \n\t"   // add dst to blue
413a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  // put result into 565 format
414a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vsli.i16       q2, q1, #5                      \n\t"   // shift up green and insert into blue
415a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vsli.i16       q2, q0, #11                     \n\t"   // shift up red and insert into blue
416a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "vst1.16        {d4, d5}, [%[dst]]!             \n\t"   // store result
417a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "bgt            1b                              \n\t"   // loop if count > 0
418a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  : [src] "+r" (src), [dst] "+r" (dst), [count] "+r" (count)
419a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  : [dstart] "r" (dstart), [scale] "r" (scale)
420a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  : "cc", "memory", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", "d24", "d28", "d29", "d30", "d31"
421a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  );
422fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
423a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    DITHER_565_SCAN(y);
424fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
425a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    while((count & 7) > 0)
426a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    {
427a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        SkPMColor c = *src++;
428fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
429a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        int dither = DITHER_VALUE(x);
430a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        int sr = SkGetPackedR32(c);
431a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        int sg = SkGetPackedG32(c);
432a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        int sb = SkGetPackedB32(c);
433a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        sr = SkDITHER_R32To565(sr, dither);
434a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        sg = SkDITHER_G32To565(sg, dither);
435a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        sb = SkDITHER_B32To565(sb, dither);
436fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
437a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        uint16_t d = *dst;
438a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        *dst++ = SkPackRGB16(SkAlphaBlend(sr, SkGetPackedR16(d), scale),
439a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                             SkAlphaBlend(sg, SkGetPackedG16(d), scale),
440a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                             SkAlphaBlend(sb, SkGetPackedB16(d), scale));
441a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        DITHER_INC_X(x);
442a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        count--;
443a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
444a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com}
445a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
446a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comvoid S32A_Opaque_BlitRow32_neon(SkPMColor* SK_RESTRICT dst,
447a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                                const SkPMColor* SK_RESTRICT src,
448a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                                int count, U8CPU alpha) {
449a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
450a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    SkASSERT(255 == alpha);
451a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    if (count > 0) {
452a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
453a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
454fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    uint8x8_t alpha_mask;
455a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
456fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    static const uint8_t alpha_mask_setup[] = {3,3,3,3,7,7,7,7};
457fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    alpha_mask = vld1_u8(alpha_mask_setup);
458a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
459fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    /* do the NEON unrolled code */
460fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#define    UNROLL    4
461fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    while (count >= UNROLL) {
462fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint8x8_t src_raw, dst_raw, dst_final;
463fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint8x8_t src_raw_2, dst_raw_2, dst_final_2;
464a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
4650a5699ee482c3b5ef1e857de8a2de06c6a1fa298commit-bot@chromium.org        /* The two prefetches below may make the code slighlty
4660a5699ee482c3b5ef1e857de8a2de06c6a1fa298commit-bot@chromium.org         * slower for small values of count but are worth having
4670a5699ee482c3b5ef1e857de8a2de06c6a1fa298commit-bot@chromium.org         * in the general case.
4680a5699ee482c3b5ef1e857de8a2de06c6a1fa298commit-bot@chromium.org         */
4690a5699ee482c3b5ef1e857de8a2de06c6a1fa298commit-bot@chromium.org        __builtin_prefetch(src+32);
4700a5699ee482c3b5ef1e857de8a2de06c6a1fa298commit-bot@chromium.org        __builtin_prefetch(dst+32);
4710a5699ee482c3b5ef1e857de8a2de06c6a1fa298commit-bot@chromium.org
472fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* get the source */
473fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        src_raw = vreinterpret_u8_u32(vld1_u32(src));
474fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if    UNROLL > 2
475fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        src_raw_2 = vreinterpret_u8_u32(vld1_u32(src+2));
476a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
477a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
478fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* get and hold the dst too */
479fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_raw = vreinterpret_u8_u32(vld1_u32(dst));
480fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if    UNROLL > 2
481fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_raw_2 = vreinterpret_u8_u32(vld1_u32(dst+2));
482a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
483a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
484fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    /* 1st and 2nd bits of the unrolling */
485fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    {
486fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint8x8_t dst_cooked;
487fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint16x8_t dst_wide;
488fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint8x8_t alpha_narrow;
489fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint16x8_t alpha_wide;
490a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
491fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* get the alphas spread out properly */
492fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        alpha_narrow = vtbl1_u8(src_raw, alpha_mask);
493fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        alpha_wide = vsubw_u8(vdupq_n_u16(256), alpha_narrow);
494a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
495fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* spread the dest */
496fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_wide = vmovl_u8(dst_raw);
497a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
498fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* alpha mul the dest */
499fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_wide = vmulq_u16 (dst_wide, alpha_wide);
500fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_cooked = vshrn_n_u16(dst_wide, 8);
501a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
502fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* sum -- ignoring any byte lane overflows */
503fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_final = vadd_u8(src_raw, dst_cooked);
504fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
505a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
506fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if    UNROLL > 2
507fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    /* the 3rd and 4th bits of our unrolling */
508fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    {
509fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint8x8_t dst_cooked;
510fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint16x8_t dst_wide;
511fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint8x8_t alpha_narrow;
512fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint16x8_t alpha_wide;
513a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
514fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        alpha_narrow = vtbl1_u8(src_raw_2, alpha_mask);
515fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        alpha_wide = vsubw_u8(vdupq_n_u16(256), alpha_narrow);
516a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
517fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* spread the dest */
518fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_wide = vmovl_u8(dst_raw_2);
519a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
520fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* alpha mul the dest */
521fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_wide = vmulq_u16 (dst_wide, alpha_wide);
522fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_cooked = vshrn_n_u16(dst_wide, 8);
523a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
524fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* sum -- ignoring any byte lane overflows */
525fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_final_2 = vadd_u8(src_raw_2, dst_cooked);
526fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
527a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
528a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
529fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        vst1_u32(dst, vreinterpret_u32_u8(dst_final));
530fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if    UNROLL > 2
531fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        vst1_u32(dst+2, vreinterpret_u32_u8(dst_final_2));
532a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
533a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
534fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        src += UNROLL;
535fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst += UNROLL;
536fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        count -= UNROLL;
537fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
538fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#undef    UNROLL
539a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
540fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    /* do any residual iterations */
541a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        while (--count >= 0) {
542a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            *dst = SkPMSrcOver(*src, *dst);
543a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            src += 1;
544a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            dst += 1;
545a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        }
546a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
547a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com}
548a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
549c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.comvoid S32A_Opaque_BlitRow32_neon_src_alpha(SkPMColor* SK_RESTRICT dst,
550c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com                                const SkPMColor* SK_RESTRICT src,
551c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com                                int count, U8CPU alpha) {
552c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    SkASSERT(255 == alpha);
553c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
554c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    if (count <= 0)
555c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    return;
556c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
557c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    /* Use these to check if src is transparent or opaque */
558c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    const unsigned int ALPHA_OPAQ  = 0xFF000000;
559c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    const unsigned int ALPHA_TRANS = 0x00FFFFFF;
560c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
561c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com#define UNROLL  4
562c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    const SkPMColor* SK_RESTRICT src_end = src + count - (UNROLL + 1);
563c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    const SkPMColor* SK_RESTRICT src_temp = src;
564c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
565c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    /* set up the NEON variables */
566c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    uint8x8_t alpha_mask;
567c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    static const uint8_t alpha_mask_setup[] = {3,3,3,3,7,7,7,7};
568c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    alpha_mask = vld1_u8(alpha_mask_setup);
569c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
570c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    uint8x8_t src_raw, dst_raw, dst_final;
571c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    uint8x8_t src_raw_2, dst_raw_2, dst_final_2;
572c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    uint8x8_t dst_cooked;
573c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    uint16x8_t dst_wide;
574c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    uint8x8_t alpha_narrow;
575c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    uint16x8_t alpha_wide;
576c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
577c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    /* choose the first processing type */
578c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    if( src >= src_end)
579c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        goto TAIL;
580c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    if(*src <= ALPHA_TRANS)
581c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        goto ALPHA_0;
582c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    if(*src >= ALPHA_OPAQ)
583c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        goto ALPHA_255;
584c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    /* fall-thru */
585c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
586c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.comALPHA_1_TO_254:
587c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    do {
588c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
589c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* get the source */
590c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        src_raw = vreinterpret_u8_u32(vld1_u32(src));
591c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        src_raw_2 = vreinterpret_u8_u32(vld1_u32(src+2));
592c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
593c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* get and hold the dst too */
594c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst_raw = vreinterpret_u8_u32(vld1_u32(dst));
595c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst_raw_2 = vreinterpret_u8_u32(vld1_u32(dst+2));
596c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
597c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
598c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* get the alphas spread out properly */
599c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        alpha_narrow = vtbl1_u8(src_raw, alpha_mask);
600c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* reflect SkAlpha255To256() semantics a+1 vs a+a>>7 */
601c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* we collapsed (255-a)+1 ... */
602c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        alpha_wide = vsubw_u8(vdupq_n_u16(256), alpha_narrow);
603c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
604c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* spread the dest */
605c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst_wide = vmovl_u8(dst_raw);
606c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
607c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* alpha mul the dest */
608c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst_wide = vmulq_u16 (dst_wide, alpha_wide);
609c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst_cooked = vshrn_n_u16(dst_wide, 8);
610c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
611c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* sum -- ignoring any byte lane overflows */
612c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst_final = vadd_u8(src_raw, dst_cooked);
613c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
614c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        alpha_narrow = vtbl1_u8(src_raw_2, alpha_mask);
615c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* reflect SkAlpha255To256() semantics a+1 vs a+a>>7 */
616c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* we collapsed (255-a)+1 ... */
617c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        alpha_wide = vsubw_u8(vdupq_n_u16(256), alpha_narrow);
618c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
619c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* spread the dest */
620c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst_wide = vmovl_u8(dst_raw_2);
621c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
622c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* alpha mul the dest */
623c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst_wide = vmulq_u16 (dst_wide, alpha_wide);
624c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst_cooked = vshrn_n_u16(dst_wide, 8);
625c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
626c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* sum -- ignoring any byte lane overflows */
627c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst_final_2 = vadd_u8(src_raw_2, dst_cooked);
628c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
629c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        vst1_u32(dst, vreinterpret_u32_u8(dst_final));
630c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        vst1_u32(dst+2, vreinterpret_u32_u8(dst_final_2));
631c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
632c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        src += UNROLL;
633c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst += UNROLL;
634c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
635c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* if 2 of the next pixels aren't between 1 and 254
636c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        it might make sense to go to the optimized loops */
637c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        if((src[0] <= ALPHA_TRANS && src[1] <= ALPHA_TRANS) || (src[0] >= ALPHA_OPAQ && src[1] >= ALPHA_OPAQ))
638c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com            break;
639c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
640c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    } while(src < src_end);
641c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
642c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    if (src >= src_end)
643c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        goto TAIL;
644c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
645c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    if(src[0] >= ALPHA_OPAQ && src[1] >= ALPHA_OPAQ)
646c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        goto ALPHA_255;
647c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
648c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    /*fall-thru*/
649c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
650c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.comALPHA_0:
651c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
652c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    /*In this state, we know the current alpha is 0 and
653c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com     we optimize for the next alpha also being zero. */
654c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    src_temp = src;  //so we don't have to increment dst every time
655c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    do {
656c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        if(*(++src) > ALPHA_TRANS)
657c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com            break;
658c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        if(*(++src) > ALPHA_TRANS)
659c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com            break;
660c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        if(*(++src) > ALPHA_TRANS)
661c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com            break;
662c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        if(*(++src) > ALPHA_TRANS)
663c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com            break;
664c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    } while(src < src_end);
665c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
666c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    dst += (src - src_temp);
667c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
668c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    /* no longer alpha 0, so determine where to go next. */
669c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    if( src >= src_end)
670c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        goto TAIL;
671c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    if(*src >= ALPHA_OPAQ)
672c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        goto ALPHA_255;
673c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    else
674c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        goto ALPHA_1_TO_254;
675c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
676c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.comALPHA_255:
677c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    while((src[0] & src[1] & src[2] & src[3]) >= ALPHA_OPAQ) {
678c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst[0]=src[0];
679c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst[1]=src[1];
680c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst[2]=src[2];
681c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst[3]=src[3];
682c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        src+=UNROLL;
683c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst+=UNROLL;
684c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        if(src >= src_end)
685c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com            goto TAIL;
686c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    }
687c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
688c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    //Handle remainder.
689c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    if(*src >= ALPHA_OPAQ) { *dst++ = *src++;
690c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        if(*src >= ALPHA_OPAQ) { *dst++ = *src++;
691c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com            if(*src >= ALPHA_OPAQ) { *dst++ = *src++; }
692c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        }
693c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    }
694c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
695c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    if( src >= src_end)
696c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        goto TAIL;
697c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    if(*src <= ALPHA_TRANS)
698c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        goto ALPHA_0;
699c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    else
700c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        goto ALPHA_1_TO_254;
701c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
702c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.comTAIL:
703c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    /* do any residual iterations */
704c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    src_end += UNROLL + 1;  //goto the real end
705c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    while(src != src_end) {
706c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        if( *src != 0 ) {
707c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com            if( *src >= ALPHA_OPAQ ) {
708c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com                *dst = *src;
709c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com            }
710c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com            else {
711c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com                *dst = SkPMSrcOver(*src, *dst);
712c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com            }
713c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        }
714c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        src++;
715c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst++;
716c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    }
717c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
718c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com#undef    UNROLL
719c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    return;
720c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com}
721a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
722a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com/* Neon version of S32_Blend_BlitRow32()
723a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * portable version is in src/core/SkBlitRow_D32.cpp
724a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com */
725a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comvoid S32_Blend_BlitRow32_neon(SkPMColor* SK_RESTRICT dst,
726a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                              const SkPMColor* SK_RESTRICT src,
727a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                              int count, U8CPU alpha) {
728a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    SkASSERT(alpha <= 255);
729a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    if (count > 0) {
730a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        uint16_t src_scale = SkAlpha255To256(alpha);
731a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        uint16_t dst_scale = 256 - src_scale;
732a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
733fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    /* run them N at a time through the NEON unit */
734fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    /* note that each 1 is 4 bytes, each treated exactly the same,
735fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com     * so we can work under that guise. We *do* know that the src&dst
736fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com     * will be 32-bit aligned quantities, so we can specify that on
737fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com     * the load/store ops and do a neon 'reinterpret' to get us to
738fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com     * byte-sized (pun intended) pieces that we widen/multiply/shift
739fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com     * we're limited at 128 bits in the wide ops, which is 8x16bits
740fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com     * or a pair of 32 bit src/dsts.
741fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com     */
742fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    /* we *could* manually unroll this loop so that we load 128 bits
743fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com     * (as a pair of 64s) from each of src and dst, processing them
744fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com     * in pieces. This might give us a little better management of
745fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com     * the memory latency, but my initial attempts here did not
746fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com     * produce an instruction stream that looked all that nice.
747fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com     */
748fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#define    UNROLL    2
749fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    while (count >= UNROLL) {
750fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint8x8_t  src_raw, dst_raw, dst_final;
751fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint16x8_t  src_wide, dst_wide;
752fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
753fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* get 64 bits of src, widen it, multiply by src_scale */
754fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        src_raw = vreinterpret_u8_u32(vld1_u32(src));
755fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        src_wide = vmovl_u8(src_raw);
756fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* gcc hoists vdupq_n_u16(), better than using vmulq_n_u16() */
757fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        src_wide = vmulq_u16 (src_wide, vdupq_n_u16(src_scale));
758fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
759fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* ditto with dst */
760fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_raw = vreinterpret_u8_u32(vld1_u32(dst));
761fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_wide = vmovl_u8(dst_raw);
762fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
763fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* combine add with dst multiply into mul-accumulate */
764fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_wide = vmlaq_u16(src_wide, dst_wide, vdupq_n_u16(dst_scale));
765fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
766fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_final = vshrn_n_u16(dst_wide, 8);
767fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        vst1_u32(dst, vreinterpret_u32_u8(dst_final));
768fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
769fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        src += UNROLL;
770fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst += UNROLL;
771fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        count -= UNROLL;
772fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
773fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    /* RBE: well, i don't like how gcc manages src/dst across the above
774fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com     * loop it's constantly calculating src+bias, dst+bias and it only
775fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com     * adjusts the real ones when we leave the loop. Not sure why
776fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com     * it's "hoisting down" (hoisting implies above in my lexicon ;))
777fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com     * the adjustments to src/dst/count, but it does...
778fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com     * (might be SSA-style internal logic...
779fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com     */
780fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
781fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if    UNROLL == 2
782fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    if (count == 1) {
783a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            *dst = SkAlphaMulQ(*src, src_scale) + SkAlphaMulQ(*dst, dst_scale);
784fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
785a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#else
786fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    if (count > 0) {
787a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            do {
788a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                *dst = SkAlphaMulQ(*src, src_scale) + SkAlphaMulQ(*dst, dst_scale);
789a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                src += 1;
790a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                dst += 1;
791a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            } while (--count > 0);
792fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
793a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
794a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
795fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#undef    UNROLL
796a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
797a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com}
798a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
7991fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.orgvoid S32A_Blend_BlitRow32_neon(SkPMColor* SK_RESTRICT dst,
8001fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org                         const SkPMColor* SK_RESTRICT src,
8011fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org                         int count, U8CPU alpha) {
8021fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8031fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org    SkASSERT(255 >= alpha);
8041fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8051fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org    if (count <= 0) {
8061fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        return;
8071fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org    }
8081fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8091fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org    unsigned alpha256 = SkAlpha255To256(alpha);
8101fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8111fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org    // First deal with odd counts
8121fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org    if (count & 1) {
8131fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        uint8x8_t vsrc = vdup_n_u8(0), vdst = vdup_n_u8(0), vres;
8141fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        uint16x8_t vdst_wide, vsrc_wide;
8151fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        unsigned dst_scale;
8161fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8171fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        // Load
8181fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        vsrc = vreinterpret_u8_u32(vld1_lane_u32(src, vreinterpret_u32_u8(vsrc), 0));
8191fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        vdst = vreinterpret_u8_u32(vld1_lane_u32(dst, vreinterpret_u32_u8(vdst), 0));
8201fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8211fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        // Calc dst_scale
8221fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        dst_scale = vget_lane_u8(vsrc, 3);
8231fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        dst_scale *= alpha256;
8241fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        dst_scale >>= 8;
8251fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        dst_scale = 256 - dst_scale;
8261fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8271fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        // Process src
8281fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        vsrc_wide = vmovl_u8(vsrc);
8291fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        vsrc_wide = vmulq_n_u16(vsrc_wide, alpha256);
8301fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8311fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        // Process dst
8321fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        vdst_wide = vmovl_u8(vdst);
8331fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        vdst_wide = vmulq_n_u16(vdst_wide, dst_scale);
8341fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8351fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        // Combine
8361fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        vres = vshrn_n_u16(vdst_wide, 8) + vshrn_n_u16(vsrc_wide, 8);
8371fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8381fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        vst1_lane_u32(dst, vreinterpret_u32_u8(vres), 0);
8391fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        dst++;
8401fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        src++;
8411fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        count--;
8421fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org    }
8431fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8441fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org    if (count) {
8451fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        uint8x8_t alpha_mask;
8461fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        static const uint8_t alpha_mask_setup[] = {3,3,3,3,7,7,7,7};
8471fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        alpha_mask = vld1_u8(alpha_mask_setup);
8481fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8491fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        do {
8501fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8511fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            uint8x8_t vsrc, vdst, vres, vsrc_alphas;
8521fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            uint16x8_t vdst_wide, vsrc_wide, vsrc_scale, vdst_scale;
8531fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8541fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            __builtin_prefetch(src+32);
8551fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            __builtin_prefetch(dst+32);
8561fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8571fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            // Load
8581fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vsrc = vreinterpret_u8_u32(vld1_u32(src));
8591fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vdst = vreinterpret_u8_u32(vld1_u32(dst));
8601fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8611fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            // Prepare src_scale
8621fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vsrc_scale = vdupq_n_u16(alpha256);
8631fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8641fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            // Calc dst_scale
8651fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vsrc_alphas = vtbl1_u8(vsrc, alpha_mask);
8661fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vdst_scale = vmovl_u8(vsrc_alphas);
8671fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vdst_scale *= vsrc_scale;
8681fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vdst_scale = vshrq_n_u16(vdst_scale, 8);
8691fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vdst_scale = vsubq_u16(vdupq_n_u16(256), vdst_scale);
8701fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8711fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            // Process src
8721fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vsrc_wide = vmovl_u8(vsrc);
8731fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vsrc_wide *= vsrc_scale;
8741fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8751fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            // Process dst
8761fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vdst_wide = vmovl_u8(vdst);
8771fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vdst_wide *= vdst_scale;
8781fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8791fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            // Combine
8801fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vres = vshrn_n_u16(vdst_wide, 8) + vshrn_n_u16(vsrc_wide, 8);
8811fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8821fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vst1_u32(dst, vreinterpret_u32_u8(vres));
8831fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8841fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            src += 2;
8851fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            dst += 2;
8861fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            count -= 2;
8871fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        } while(count);
8881fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org    }
8891fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org}
8901fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
891a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com///////////////////////////////////////////////////////////////////////////////
892a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
893fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#undef    DEBUG_OPAQUE_DITHER
894a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
895fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if    defined(DEBUG_OPAQUE_DITHER)
896a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comstatic void showme8(char *str, void *p, int len)
897a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com{
898fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    static char buf[256];
899fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    char tbuf[32];
900fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    int i;
901fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    char *pc = (char*) p;
902fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    sprintf(buf,"%8s:", str);
903fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    for(i=0;i<len;i++) {
904fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        sprintf(tbuf, "   %02x", pc[i]);
905fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        strcat(buf, tbuf);
906fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
907fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    SkDebugf("%s\n", buf);
908a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com}
909a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comstatic void showme16(char *str, void *p, int len)
910a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com{
911fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    static char buf[256];
912fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    char tbuf[32];
913fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    int i;
914fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    uint16_t *pc = (uint16_t*) p;
915fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    sprintf(buf,"%8s:", str);
916fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    len = (len / sizeof(uint16_t));    /* passed as bytes */
917fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    for(i=0;i<len;i++) {
918fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        sprintf(tbuf, " %04x", pc[i]);
919fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        strcat(buf, tbuf);
920fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
921fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    SkDebugf("%s\n", buf);
922a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com}
923a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
924a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
925a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comvoid S32A_D565_Opaque_Dither_neon (uint16_t * SK_RESTRICT dst,
926a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                                   const SkPMColor* SK_RESTRICT src,
927a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                                   int count, U8CPU alpha, int x, int y) {
928a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    SkASSERT(255 == alpha);
929a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
930fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#define    UNROLL    8
931a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
932a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    if (count >= UNROLL) {
933fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    uint8x8_t dbase;
934fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
935fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if    defined(DEBUG_OPAQUE_DITHER)
936fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    uint16_t tmpbuf[UNROLL];
937fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    int td[UNROLL];
938fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    int tdv[UNROLL];
939fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    int ta[UNROLL];
940fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    int tap[UNROLL];
941fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    uint16_t in_dst[UNROLL];
942fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    int offset = 0;
943fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    int noisy = 0;
944a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
945a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
946fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    const uint8_t *dstart = &gDitherMatrix_Neon[(y&3)*12 + (x&3)];
947fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    dbase = vld1_u8(dstart);
948a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
949a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        do {
950fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint8x8_t sr, sg, sb, sa, d;
951fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint16x8_t dst8, scale8, alpha8;
952fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint16x8_t dst_r, dst_g, dst_b;
953fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
954fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if    defined(DEBUG_OPAQUE_DITHER)
955fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    /* calculate 8 elements worth into a temp buffer */
956fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    {
957fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com      int my_y = y;
958fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com      int my_x = x;
959fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com      SkPMColor* my_src = (SkPMColor*)src;
960fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com      uint16_t* my_dst = dst;
961fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com      int i;
962a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
963a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com          DITHER_565_SCAN(my_y);
964a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com          for(i=0;i<UNROLL;i++) {
965a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            SkPMColor c = *my_src++;
966a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            SkPMColorAssert(c);
967a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            if (c) {
968a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                unsigned a = SkGetPackedA32(c);
969fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
970a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                int d = SkAlphaMul(DITHER_VALUE(my_x), SkAlpha255To256(a));
971fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        tdv[i] = DITHER_VALUE(my_x);
972fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        ta[i] = a;
973fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        tap[i] = SkAlpha255To256(a);
974fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        td[i] = d;
975fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
976a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                unsigned sr = SkGetPackedR32(c);
977a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                unsigned sg = SkGetPackedG32(c);
978a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                unsigned sb = SkGetPackedB32(c);
979a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                sr = SkDITHER_R32_FOR_565(sr, d);
980a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                sg = SkDITHER_G32_FOR_565(sg, d);
981a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                sb = SkDITHER_B32_FOR_565(sb, d);
982fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
983a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                uint32_t src_expanded = (sg << 24) | (sr << 13) | (sb << 2);
984a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                uint32_t dst_expanded = SkExpand_rgb_16(*my_dst);
985a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                dst_expanded = dst_expanded * (SkAlpha255To256(255 - a) >> 3);
986a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // now src and dst expanded are in g:11 r:10 x:1 b:10
987a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                tmpbuf[i] = SkCompact_rgb_16((src_expanded + dst_expanded) >> 5);
988fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        td[i] = d;
989a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
990a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            } else {
991fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        tmpbuf[i] = *my_dst;
992fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        ta[i] = tdv[i] = td[i] = 0xbeef;
993fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        }
994fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        in_dst[i] = *my_dst;
995a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            my_dst += 1;
996a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            DITHER_INC_X(my_x);
997a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com          }
998fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
999a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
1000a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1001fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* source is in ABGR */
1002fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        {
1003fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        register uint8x8_t d0 asm("d0");
1004fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        register uint8x8_t d1 asm("d1");
1005fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        register uint8x8_t d2 asm("d2");
1006fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        register uint8x8_t d3 asm("d3");
1007a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1008fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        asm ("vld4.8    {d0-d3},[%4]  /* r=%P0 g=%P1 b=%P2 a=%P3 */"
1009fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            : "=w" (d0), "=w" (d1), "=w" (d2), "=w" (d3)
1010fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            : "r" (src)
1011a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                    );
1012fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            sr = d0; sg = d1; sb = d2; sa = d3;
1013fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        }
1014a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1015fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* calculate 'd', which will be 0..7 */
1016fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* dbase[] is 0..7; alpha is 0..256; 16 bits suffice */
1017a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#if defined(SK_BUILD_FOR_ANDROID)
1018fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* SkAlpha255To256() semantic a+1 vs a+a>>7 */
1019fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        alpha8 = vaddw_u8(vmovl_u8(sa), vdup_n_u8(1));
1020a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#else
1021fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        alpha8 = vaddw_u8(vmovl_u8(sa), vshr_n_u8(sa, 7));
1022a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
1023fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        alpha8 = vmulq_u16(alpha8, vmovl_u8(dbase));
1024fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        d = vshrn_n_u16(alpha8, 8);    /* narrowing too */
1025fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1026fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* sr = sr - (sr>>5) + d */
1027fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* watching for 8-bit overflow.  d is 0..7; risky range of
1028fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com         * sr is >248; and then (sr>>5) is 7 so it offsets 'd';
1029fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com         * safe  as long as we do ((sr-sr>>5) + d) */
1030fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        sr = vsub_u8(sr, vshr_n_u8(sr, 5));
1031fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        sr = vadd_u8(sr, d);
1032fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1033fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* sb = sb - (sb>>5) + d */
1034fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        sb = vsub_u8(sb, vshr_n_u8(sb, 5));
1035fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        sb = vadd_u8(sb, d);
1036fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1037fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* sg = sg - (sg>>6) + d>>1; similar logic for overflows */
1038fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        sg = vsub_u8(sg, vshr_n_u8(sg, 6));
1039fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        sg = vadd_u8(sg, vshr_n_u8(d,1));
1040fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1041fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* need to pick up 8 dst's -- at 16 bits each, 128 bits */
1042fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst8 = vld1q_u16(dst);
1043fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_b = vandq_u16(dst8, vdupq_n_u16(0x001F));
1044fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_g = vandq_u16(vshrq_n_u16(dst8,5), vdupq_n_u16(0x003F));
1045fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_r = vshrq_n_u16(dst8,11);    /* clearing hi bits */
1046fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1047fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* blend */
1048a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#if 1
1049fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* SkAlpha255To256() semantic a+1 vs a+a>>7 */
1050fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* originally 255-sa + 1 */
1051fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        scale8 = vsubw_u8(vdupq_n_u16(256), sa);
1052a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#else
1053fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        scale8 = vsubw_u8(vdupq_n_u16(255), sa);
1054fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        scale8 = vaddq_u16(scale8, vshrq_n_u16(scale8, 7));
1055a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
1056a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1057a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#if 1
1058fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* combine the addq and mul, save 3 insns */
1059fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        scale8 = vshrq_n_u16(scale8, 3);
1060fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_b = vmlaq_u16(vshll_n_u8(sb,2), dst_b, scale8);
1061fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_g = vmlaq_u16(vshll_n_u8(sg,3), dst_g, scale8);
1062fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_r = vmlaq_u16(vshll_n_u8(sr,2), dst_r, scale8);
1063a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#else
1064fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* known correct, but +3 insns over above */
1065fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        scale8 = vshrq_n_u16(scale8, 3);
1066fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_b = vmulq_u16(dst_b, scale8);
1067fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_g = vmulq_u16(dst_g, scale8);
1068fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_r = vmulq_u16(dst_r, scale8);
1069fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1070fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* combine */
1071fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* NB: vshll widens, need to preserve those bits */
1072fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_b = vaddq_u16(dst_b, vshll_n_u8(sb,2));
1073fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_g = vaddq_u16(dst_g, vshll_n_u8(sg,3));
1074fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_r = vaddq_u16(dst_r, vshll_n_u8(sr,2));
1075a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
1076a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1077fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* repack to store */
1078fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst8 = vandq_u16(vshrq_n_u16(dst_b, 5), vdupq_n_u16(0x001F));
1079fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst8 = vsliq_n_u16(dst8, vshrq_n_u16(dst_g, 5), 5);
1080fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst8 = vsliq_n_u16(dst8, vshrq_n_u16(dst_r,5), 11);
1081fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1082fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        vst1q_u16(dst, dst8);
1083fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1084fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if    defined(DEBUG_OPAQUE_DITHER)
1085fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* verify my 8 elements match the temp buffer */
1086fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    {
1087fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com       int i, bad=0;
1088fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com       static int invocation;
1089fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1090fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com       for (i=0;i<UNROLL;i++)
1091fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        if (tmpbuf[i] != dst[i]) bad=1;
1092fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com       if (bad) {
1093fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        SkDebugf("BAD S32A_D565_Opaque_Dither_neon(); invocation %d offset %d\n",
1094fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            invocation, offset);
1095fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        SkDebugf("  alpha 0x%x\n", alpha);
1096fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        for (i=0;i<UNROLL;i++)
1097fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            SkDebugf("%2d: %s %04x w %04x id %04x s %08x d %04x %04x %04x %04x\n",
1098fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            i, ((tmpbuf[i] != dst[i])?"BAD":"got"),
1099fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            dst[i], tmpbuf[i], in_dst[i], src[i], td[i], tdv[i], tap[i], ta[i]);
1100fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1101fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        showme16("alpha8", &alpha8, sizeof(alpha8));
1102fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        showme16("scale8", &scale8, sizeof(scale8));
1103fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        showme8("d", &d, sizeof(d));
1104fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        showme16("dst8", &dst8, sizeof(dst8));
1105fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        showme16("dst_b", &dst_b, sizeof(dst_b));
1106fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        showme16("dst_g", &dst_g, sizeof(dst_g));
1107fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        showme16("dst_r", &dst_r, sizeof(dst_r));
1108fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        showme8("sb", &sb, sizeof(sb));
1109fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        showme8("sg", &sg, sizeof(sg));
1110fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        showme8("sr", &sr, sizeof(sr));
1111fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1112fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* cop out */
1113fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        return;
1114fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com       }
1115fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com       offset += UNROLL;
1116fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com       invocation++;
1117fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
1118a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
1119a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1120a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            dst += UNROLL;
1121fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        src += UNROLL;
1122fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        count -= UNROLL;
1123fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* skip x += UNROLL, since it's unchanged mod-4 */
1124a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        } while (count >= UNROLL);
1125a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
1126fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#undef    UNROLL
1127a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1128a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    /* residuals */
1129a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    if (count > 0) {
1130a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        DITHER_565_SCAN(y);
1131a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        do {
1132a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            SkPMColor c = *src++;
1133a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            SkPMColorAssert(c);
1134a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            if (c) {
1135a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                unsigned a = SkGetPackedA32(c);
1136fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1137a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // dither and alpha are just temporary variables to work-around
1138a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // an ICE in debug.
1139a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                unsigned dither = DITHER_VALUE(x);
1140a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                unsigned alpha = SkAlpha255To256(a);
1141a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                int d = SkAlphaMul(dither, alpha);
1142fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1143a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                unsigned sr = SkGetPackedR32(c);
1144a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                unsigned sg = SkGetPackedG32(c);
1145a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                unsigned sb = SkGetPackedB32(c);
1146a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                sr = SkDITHER_R32_FOR_565(sr, d);
1147a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                sg = SkDITHER_G32_FOR_565(sg, d);
1148a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                sb = SkDITHER_B32_FOR_565(sb, d);
1149fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1150a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                uint32_t src_expanded = (sg << 24) | (sr << 13) | (sb << 2);
1151a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                uint32_t dst_expanded = SkExpand_rgb_16(*dst);
1152a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                dst_expanded = dst_expanded * (SkAlpha255To256(255 - a) >> 3);
1153a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // now src and dst expanded are in g:11 r:10 x:1 b:10
1154a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                *dst = SkCompact_rgb_16((src_expanded + dst_expanded) >> 5);
1155a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            }
1156a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            dst += 1;
1157a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            DITHER_INC_X(x);
1158a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        } while (--count != 0);
1159a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
1160a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com}
1161a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1162a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com///////////////////////////////////////////////////////////////////////////////
1163a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1164fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#undef    DEBUG_S32_OPAQUE_DITHER
1165a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1166a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comvoid S32_D565_Opaque_Dither_neon(uint16_t* SK_RESTRICT dst,
1167a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                                 const SkPMColor* SK_RESTRICT src,
1168a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                                 int count, U8CPU alpha, int x, int y) {
1169a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    SkASSERT(255 == alpha);
1170a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1171fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#define    UNROLL    8
1172a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    if (count >= UNROLL) {
1173fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    uint8x8_t d;
1174fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    const uint8_t *dstart = &gDitherMatrix_Neon[(y&3)*12 + (x&3)];
1175fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    d = vld1_u8(dstart);
1176fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1177fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    while (count >= UNROLL) {
1178efbe8e9bedda21a3e061ebf3d96431a0f250a654djsollen@google.com        uint8x8_t sr, sg, sb;
1179efbe8e9bedda21a3e061ebf3d96431a0f250a654djsollen@google.com        uint16x8_t dr, dg, db;
1180fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint16x8_t dst8;
1181fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1182fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        {
1183fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        register uint8x8_t d0 asm("d0");
1184fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        register uint8x8_t d1 asm("d1");
1185fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        register uint8x8_t d2 asm("d2");
1186fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        register uint8x8_t d3 asm("d3");
1187fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1188688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        asm (
1189688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org            "vld4.8    {d0-d3},[%[src]]!  /* r=%P0 g=%P1 b=%P2 a=%P3 */"
1190688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org            : "=w" (d0), "=w" (d1), "=w" (d2), "=w" (d3), [src] "+&r" (src)
1191688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org            :
1192688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        );
1193688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        sg = d1;
1194688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
1195688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        sr = d2; sb = d0;
1196688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
1197688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        sr = d0; sb = d2;
1198688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org#endif
1199fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        }
1200fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* XXX: if we want to prefetch, hide it in the above asm()
1201fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com         * using the gcc __builtin_prefetch(), the prefetch will
1202fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com         * fall to the bottom of the loop -- it won't stick up
1203fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com         * at the top of the loop, just after the vld4.
1204fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com         */
1205fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1206688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        // sr = sr - (sr>>5) + d
1207fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        sr = vsub_u8(sr, vshr_n_u8(sr, 5));
1208fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dr = vaddl_u8(sr, d);
1209fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1210688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        // sb = sb - (sb>>5) + d
1211fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        sb = vsub_u8(sb, vshr_n_u8(sb, 5));
1212fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        db = vaddl_u8(sb, d);
1213fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1214688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        // sg = sg - (sg>>6) + d>>1; similar logic for overflows
1215fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        sg = vsub_u8(sg, vshr_n_u8(sg, 6));
1216688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        dg = vaddl_u8(sg, vshr_n_u8(d, 1));
1217fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1218688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        // pack high bits of each into 565 format  (rgb, b is lsb)
1219fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst8 = vshrq_n_u16(db, 3);
1220fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst8 = vsliq_n_u16(dst8, vshrq_n_u16(dg, 2), 5);
1221688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        dst8 = vsliq_n_u16(dst8, vshrq_n_u16(dr, 3), 11);
1222fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1223688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        // store it
1224fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        vst1q_u16(dst, dst8);
1225fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1226fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if    defined(DEBUG_S32_OPAQUE_DITHER)
1227688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        // always good to know if we generated good results
1228fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        {
1229fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        int i, myx = x, myy = y;
1230fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        DITHER_565_SCAN(myy);
1231fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        for (i=0;i<UNROLL;i++) {
1232688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org            // the '!' in the asm block above post-incremented src by the 8 pixels it reads.
1233688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org            SkPMColor c = src[i-8];
1234fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            unsigned dither = DITHER_VALUE(myx);
1235fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            uint16_t val = SkDitherRGB32To565(c, dither);
1236fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            if (val != dst[i]) {
1237fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            SkDebugf("RBE: src %08x dither %02x, want %04x got %04x dbas[i] %02x\n",
1238fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com                c, dither, val, dst[i], dstart[i]);
1239fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            }
1240fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            DITHER_INC_X(myx);
1241fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        }
1242fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        }
1243a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
1244a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1245fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst += UNROLL;
1246688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        // we don't need to increment src as the asm above has already done it
1247fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        count -= UNROLL;
1248688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        x += UNROLL;        // probably superfluous
1249fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
1250a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
1251fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#undef    UNROLL
1252a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1253688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org    // residuals
1254a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    if (count > 0) {
1255a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        DITHER_565_SCAN(y);
1256a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        do {
1257a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            SkPMColor c = *src++;
1258a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            SkPMColorAssert(c);
1259a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            SkASSERT(SkGetPackedA32(c) == 255);
1260a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1261a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            unsigned dither = DITHER_VALUE(x);
1262a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            *dst++ = SkDitherRGB32To565(c, dither);
1263a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            DITHER_INC_X(x);
1264a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        } while (--count != 0);
1265a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
1266a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com}
1267a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1268a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comvoid Color32_arm_neon(SkPMColor* dst, const SkPMColor* src, int count,
1269a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      SkPMColor color) {
1270a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    if (count <= 0) {
1271a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        return;
1272a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
1273a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1274a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    if (0 == color) {
1275a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        if (src != dst) {
1276a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            memcpy(dst, src, count * sizeof(SkPMColor));
1277a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        }
1278a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        return;
1279a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
1280a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1281a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    unsigned colorA = SkGetPackedA32(color);
1282a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    if (255 == colorA) {
1283a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        sk_memset32(dst, color, count);
1284a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    } else {
1285a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        unsigned scale = 256 - SkAlpha255To256(colorA);
1286a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1287a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        if (count >= 8) {
1288a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            // at the end of this assembly, count will have been decremented
1289a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            // to a negative value. That is, if count mod 8 = x, it will be
1290a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            // -8 +x coming out.
1291a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            asm volatile (
1292a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                PLD128(src, 0)
1293a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1294a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vdup.32    q0, %[color]                \n\t"
1295a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1296a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                PLD128(src, 128)
1297a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1298a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // scale numerical interval [0-255], so load as 8 bits
1299a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vdup.8     d2, %[scale]                \n\t"
1300a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1301a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                PLD128(src, 256)
1302a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1303a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "subs       %[count], %[count], #8      \n\t"
1304a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1305a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                PLD128(src, 384)
1306a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1307a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "Loop_Color32:                          \n\t"
1308a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1309a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // load src color, 8 pixels, 4 64 bit registers
1310a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // (and increment src).
1311a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vld1.32    {d4-d7}, [%[src]]!          \n\t"
1312a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1313a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                PLD128(src, 384)
1314a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1315a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // multiply long by scale, 64 bits at a time,
1316a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // destination into a 128 bit register.
1317a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vmull.u8   q4, d4, d2                  \n\t"
1318a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vmull.u8   q5, d5, d2                  \n\t"
1319a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vmull.u8   q6, d6, d2                  \n\t"
1320a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vmull.u8   q7, d7, d2                  \n\t"
1321a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1322a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // shift the 128 bit registers, containing the 16
1323a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // bit scaled values back to 8 bits, narrowing the
1324a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // results to 64 bit registers.
1325a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vshrn.i16  d8, q4, #8                  \n\t"
1326a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vshrn.i16  d9, q5, #8                  \n\t"
1327a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vshrn.i16  d10, q6, #8                 \n\t"
1328a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vshrn.i16  d11, q7, #8                 \n\t"
1329a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1330a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // adding back the color, using 128 bit registers.
1331a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vadd.i8    q6, q4, q0                  \n\t"
1332a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vadd.i8    q7, q5, q0                  \n\t"
1333a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1334a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // store back the 8 calculated pixels (2 128 bit
1335a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // registers), and increment dst.
1336a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vst1.32    {d12-d15}, [%[dst]]!        \n\t"
1337a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1338a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "subs       %[count], %[count], #8      \n\t"
1339a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "bge        Loop_Color32                \n\t"
1340a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                : [src] "+r" (src), [dst] "+r" (dst), [count] "+r" (count)
1341a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                : [color] "r" (color), [scale] "r" (scale)
1342a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                : "cc", "memory",
1343a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
1344a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15"
1345a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                          );
1346a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            // At this point, if we went through the inline assembly, count is
1347a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            // a negative value:
1348a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            // if the value is -8, there is no pixel left to process.
1349a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            // if the value is -7, there is one pixel left to process
1350a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            // ...
1351a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            // And'ing it with 7 will give us the number of pixels
1352a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            // left to process.
1353a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            count = count & 0x7;
1354a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        }
1355a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1356a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        while (count > 0) {
1357a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            *dst = color + SkAlphaMulQ(*src, scale);
1358a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            src += 1;
1359a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            dst += 1;
1360a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            count--;
1361a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        }
1362a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
1363a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com}
1364a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1365a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com///////////////////////////////////////////////////////////////////////////////
1366a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1367a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comconst SkBlitRow::Proc sk_blitrow_platform_565_procs_arm_neon[] = {
1368a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    // no dither
13690060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org    // NOTE: For the S32_D565_Blend function below, we don't have a special
13700060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org    //       version that assumes that each source pixel is opaque. But our
13710060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org    //       S32A is still faster than the default, so use it.
13720060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org    S32_D565_Opaque_neon,
1373a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    S32A_D565_Blend_neon,   // really S32_D565_Blend
1374a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    S32A_D565_Opaque_neon,
1375a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    S32A_D565_Blend_neon,
1376a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1377a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    // dither
1378a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    S32_D565_Opaque_Dither_neon,
1379a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    S32_D565_Blend_Dither_neon,
1380a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    S32A_D565_Opaque_Dither_neon,
1381a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    NULL,   // S32A_D565_Blend_Dither
1382a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com};
1383a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1384a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comconst SkBlitRow::Proc32 sk_blitrow_platform_32_procs_arm_neon[] = {
1385a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    NULL,   // S32_Opaque,
1386fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    S32_Blend_BlitRow32_neon,        // S32_Blend,
1387c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    /*
1388c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com     * We have two choices for S32A_Opaque procs. The one reads the src alpha
1389c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com     * value and attempts to optimize accordingly.  The optimization is
1390c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com     * sensitive to the source content and is not a win in all cases. For
1391c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com     * example, if there are a lot of transitions between the alpha states,
1392c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com     * the performance will almost certainly be worse.  However, for many
1393c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com     * common cases the performance is equivalent or better than the standard
1394c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com     * case where we do not inspect the src alpha.
1395c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com     */
1396c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com#if SK_A32_SHIFT == 24
1397c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    // This proc assumes the alpha value occupies bits 24-32 of each SkPMColor
1398c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    S32A_Opaque_BlitRow32_neon_src_alpha,   // S32A_Opaque,
1399c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com#else
1400c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    S32A_Opaque_BlitRow32_neon,     // S32A_Opaque,
1401c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com#endif
14021fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org    S32A_Blend_BlitRow32_neon        // S32A_Blend
1403a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com};
1404