SkBlitRow_opts_arm_neon.cpp revision dfff2737f8ad3e945a4dcbe175380d4b2a91a260
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
34bc25dfc798fff225ce65355ecda19d2b85bd0e74commit-bot@chromium.org        vdst = SkPixel32ToPixel16_neon8(vsrc);
350060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org
360060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        // Store
370060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        vst1q_u16(dst, vdst);
380060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org
390060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        // Prepare next iteration
400060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        dst += 8;
410060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        src += 8;
420060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        count -= 8;
430060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org    };
440060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org
450060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org    // Leftovers
460060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org    while (count > 0) {
470060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        SkPMColor c = *src++;
480060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        SkPMColorAssert(c);
490060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        *dst = SkPixel32ToPixel16_ToU16(c);
500060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        dst++;
510060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org        count--;
520060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org    };
530060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org}
540060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org
55a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comvoid S32A_D565_Opaque_neon(uint16_t* SK_RESTRICT dst,
56a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                           const SkPMColor* SK_RESTRICT src, int count,
57a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                           U8CPU alpha, int /*x*/, int /*y*/) {
58a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    SkASSERT(255 == alpha);
59a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
60a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    if (count >= 8) {
61efbe8e9bedda21a3e061ebf3d96431a0f250a654djsollen@google.com        uint16_t* SK_RESTRICT keep_dst = 0;
62fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
63a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        asm volatile (
64a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "ands       ip, %[count], #7            \n\t"
65a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmov.u8    d31, #1<<7                  \n\t"
66a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vld1.16    {q12}, [%[dst]]             \n\t"
67a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vld4.8     {d0-d3}, [%[src]]           \n\t"
68a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // Thumb does not support the standard ARM conditional
69a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // instructions but instead requires the 'it' instruction
70a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // to signal conditional execution
71a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "it eq                                  \n\t"
72a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "moveq      ip, #8                      \n\t"
73a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "mov        %[keep_dst], %[dst]         \n\t"
74fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
75a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "add        %[src], %[src], ip, LSL#2   \n\t"
76a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "add        %[dst], %[dst], ip, LSL#1   \n\t"
77a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "subs       %[count], %[count], ip      \n\t"
78a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "b          9f                          \n\t"
79a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // LOOP
80a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "2:                                         \n\t"
81fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
82a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vld1.16    {q12}, [%[dst]]!            \n\t"
83a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vld4.8     {d0-d3}, [%[src]]!          \n\t"
84a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vst1.16    {q10}, [%[keep_dst]]        \n\t"
85a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "sub        %[keep_dst], %[dst], #8*2   \n\t"
86a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "subs       %[count], %[count], #8      \n\t"
87a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "9:                                         \n\t"
88a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "pld        [%[dst],#32]                \n\t"
89a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // expand 0565 q12 to 8888 {d4-d7}
90a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmovn.u16  d4, q12                     \n\t"
91a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshr.u16   q11, q12, #5                \n\t"
92a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshr.u16   q10, q12, #6+5              \n\t"
93a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmovn.u16  d5, q11                     \n\t"
94a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmovn.u16  d6, q10                     \n\t"
95a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshl.u8    d4, d4, #3                  \n\t"
96a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshl.u8    d5, d5, #2                  \n\t"
97a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshl.u8    d6, d6, #3                  \n\t"
98fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
99a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmovl.u8   q14, d31                    \n\t"
100a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmovl.u8   q13, d31                    \n\t"
101a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmovl.u8   q12, d31                    \n\t"
102fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
103a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // duplicate in 4/2/1 & 8pix vsns
104a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmvn.8     d30, d3                     \n\t"
105a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmlal.u8   q14, d30, d6                \n\t"
106a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmlal.u8   q13, d30, d5                \n\t"
107a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmlal.u8   q12, d30, d4                \n\t"
108a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshr.u16   q8, q14, #5                 \n\t"
109a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshr.u16   q9, q13, #6                 \n\t"
110a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vaddhn.u16 d6, q14, q8                 \n\t"
111a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshr.u16   q8, q12, #5                 \n\t"
112a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vaddhn.u16 d5, q13, q9                 \n\t"
113a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vqadd.u8   d6, d6, d0                  \n\t"  // moved up
114a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vaddhn.u16 d4, q12, q8                 \n\t"
115a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // intentionally don't calculate alpha
116a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // result in d4-d6
117fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
118a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vqadd.u8   d5, d5, d1                  \n\t"
119a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vqadd.u8   d4, d4, d2                  \n\t"
120fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
121a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // pack 8888 {d4-d6} to 0565 q10
122a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshll.u8   q10, d6, #8                 \n\t"
123a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshll.u8   q3, d5, #8                  \n\t"
124a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshll.u8   q2, d4, #8                  \n\t"
125a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vsri.u16   q10, q3, #5                 \n\t"
126a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vsri.u16   q10, q2, #11                \n\t"
127fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
128a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "bne        2b                          \n\t"
129fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
130a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "1:                                         \n\t"
131a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vst1.16      {q10}, [%[keep_dst]]      \n\t"
132a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      : [count] "+r" (count)
133fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com                      : [dst] "r" (dst), [keep_dst] "r" (keep_dst), [src] "r" (src)
134a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      : "ip", "cc", "memory", "d0","d1","d2","d3","d4","d5","d6","d7",
135a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "d16","d17","d18","d19","d20","d21","d22","d23","d24","d25","d26","d27","d28","d29",
136a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "d30","d31"
137a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      );
138a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
139fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    else
140a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    {   // handle count < 8
141efbe8e9bedda21a3e061ebf3d96431a0f250a654djsollen@google.com        uint16_t* SK_RESTRICT keep_dst = 0;
142fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
143a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        asm volatile (
144a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmov.u8    d31, #1<<7                  \n\t"
145a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "mov        %[keep_dst], %[dst]         \n\t"
146fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
147a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "tst        %[count], #4                \n\t"
148a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "beq        14f                         \n\t"
149a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vld1.16    {d25}, [%[dst]]!            \n\t"
150a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vld1.32    {q1}, [%[src]]!             \n\t"
151fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
152a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "14:                                        \n\t"
153a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "tst        %[count], #2                \n\t"
154a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "beq        12f                         \n\t"
155a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vld1.32    {d24[1]}, [%[dst]]!         \n\t"
156a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vld1.32    {d1}, [%[src]]!             \n\t"
157fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
158a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "12:                                        \n\t"
159a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "tst        %[count], #1                \n\t"
160a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "beq        11f                         \n\t"
161a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vld1.16    {d24[1]}, [%[dst]]!         \n\t"
162a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vld1.32    {d0[1]}, [%[src]]!          \n\t"
163fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
164a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "11:                                        \n\t"
165a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // unzips achieve the same as a vld4 operation
166a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vuzpq.u16  q0, q1                      \n\t"
167a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vuzp.u8    d0, d1                      \n\t"
168a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vuzp.u8    d2, d3                      \n\t"
169a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // expand 0565 q12 to 8888 {d4-d7}
170a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmovn.u16  d4, q12                     \n\t"
171a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshr.u16   q11, q12, #5                \n\t"
172a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshr.u16   q10, q12, #6+5              \n\t"
173a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmovn.u16  d5, q11                     \n\t"
174a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmovn.u16  d6, q10                     \n\t"
175a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshl.u8    d4, d4, #3                  \n\t"
176a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshl.u8    d5, d5, #2                  \n\t"
177a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshl.u8    d6, d6, #3                  \n\t"
178fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
179a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmovl.u8   q14, d31                    \n\t"
180a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmovl.u8   q13, d31                    \n\t"
181a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmovl.u8   q12, d31                    \n\t"
182fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
183a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // duplicate in 4/2/1 & 8pix vsns
184a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmvn.8     d30, d3                     \n\t"
185a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmlal.u8   q14, d30, d6                \n\t"
186a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmlal.u8   q13, d30, d5                \n\t"
187a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vmlal.u8   q12, d30, d4                \n\t"
188a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshr.u16   q8, q14, #5                 \n\t"
189a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshr.u16   q9, q13, #6                 \n\t"
190a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vaddhn.u16 d6, q14, q8                 \n\t"
191a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshr.u16   q8, q12, #5                 \n\t"
192a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vaddhn.u16 d5, q13, q9                 \n\t"
193a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vqadd.u8   d6, d6, d0                  \n\t"  // moved up
194a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vaddhn.u16 d4, q12, q8                 \n\t"
195a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // intentionally don't calculate alpha
196a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // result in d4-d6
197fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
198a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vqadd.u8   d5, d5, d1                  \n\t"
199a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vqadd.u8   d4, d4, d2                  \n\t"
200fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
201a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // pack 8888 {d4-d6} to 0565 q10
202a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshll.u8   q10, d6, #8                 \n\t"
203a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshll.u8   q3, d5, #8                  \n\t"
204a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vshll.u8   q2, d4, #8                  \n\t"
205a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vsri.u16   q10, q3, #5                 \n\t"
206a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vsri.u16   q10, q2, #11                \n\t"
207fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
208a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      // store
209a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "tst        %[count], #4                \n\t"
210a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "beq        24f                         \n\t"
211a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vst1.16    {d21}, [%[keep_dst]]!       \n\t"
212fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
213a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "24:                                        \n\t"
214a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "tst        %[count], #2                \n\t"
215a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "beq        22f                         \n\t"
216a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vst1.32    {d20[1]}, [%[keep_dst]]!    \n\t"
217fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
218a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "22:                                        \n\t"
219a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "tst        %[count], #1                \n\t"
220a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "beq        21f                         \n\t"
221a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "vst1.16    {d20[1]}, [%[keep_dst]]!    \n\t"
222fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
223a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "21:                                        \n\t"
224a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      : [count] "+r" (count)
225a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      : [dst] "r" (dst), [keep_dst] "r" (keep_dst), [src] "r" (src)
226a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      : "ip", "cc", "memory", "d0","d1","d2","d3","d4","d5","d6","d7",
227a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "d16","d17","d18","d19","d20","d21","d22","d23","d24","d25","d26","d27","d28","d29",
228a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      "d30","d31"
229a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      );
230a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
231a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com}
232a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
233be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.orgstatic inline uint16x8_t SkDiv255Round_neon8(uint16x8_t prod) {
234be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org    prod += vdupq_n_u16(128);
235be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org    prod += vshrq_n_u16(prod, 8);
236be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org    return vshrq_n_u16(prod, 8);
237be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org}
238be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org
239a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comvoid S32A_D565_Blend_neon(uint16_t* SK_RESTRICT dst,
240a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                          const SkPMColor* SK_RESTRICT src, int count,
241a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                          U8CPU alpha, int /*x*/, int /*y*/) {
242be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org   SkASSERT(255 > alpha);
243a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
244be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org    /* This code implements a Neon version of S32A_D565_Blend. The results have
245be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org     * a few mismatches compared to the original code. These mismatches never
246be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org     * exceed 1.
247a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com     */
248fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
249be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org    if (count >= 8) {
250be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org        uint16x8_t valpha_max, vmask_blue;
251be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org        uint8x8_t valpha;
252be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org
253be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org        // prepare constants
254be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org        valpha_max = vmovq_n_u16(255);
255be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org        valpha = vdup_n_u8(alpha);
256be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org        vmask_blue = vmovq_n_u16(SK_B16_MASK);
257be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org
258be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org        do {
259be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            uint16x8_t vdst, vdst_r, vdst_g, vdst_b;
260be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            uint16x8_t vres_a, vres_r, vres_g, vres_b;
261be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            uint8x8x4_t vsrc;
262be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org
263be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            // load pixels
264be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vdst = vld1q_u16(dst);
265be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 6))
266be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            asm (
267be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org                "vld4.u8 %h[vsrc], [%[src]]!"
268be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org                : [vsrc] "=w" (vsrc), [src] "+&r" (src)
269be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org                : :
270be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            );
271a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#else
272be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            register uint8x8_t d0 asm("d0");
273be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            register uint8x8_t d1 asm("d1");
274be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            register uint8x8_t d2 asm("d2");
275be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            register uint8x8_t d3 asm("d3");
276be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org
277be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            asm volatile (
278be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org                "vld4.u8    {d0-d3},[%[src]]!;"
279be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org                : "=w" (d0), "=w" (d1), "=w" (d2), "=w" (d3),
280be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org                  [src] "+&r" (src)
281be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org                : :
282be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            );
283be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vsrc.val[0] = d0;
284be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vsrc.val[1] = d1;
285be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vsrc.val[2] = d2;
286be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vsrc.val[3] = d3;
287a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
288fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
289fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
290be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            // deinterleave dst
291be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vdst_g = vshlq_n_u16(vdst, SK_R16_BITS);        // shift green to top of lanes
292be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vdst_b = vdst & vmask_blue;                     // extract blue
293be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vdst_r = vshrq_n_u16(vdst, SK_R16_SHIFT);       // extract red
294be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vdst_g = vshrq_n_u16(vdst_g, SK_R16_BITS + SK_B16_BITS); // extract green
295be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org
296be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            // shift src to 565
297be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vsrc.val[NEON_R] = vshr_n_u8(vsrc.val[NEON_R], 8 - SK_R16_BITS);
298be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vsrc.val[NEON_G] = vshr_n_u8(vsrc.val[NEON_G], 8 - SK_G16_BITS);
299be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vsrc.val[NEON_B] = vshr_n_u8(vsrc.val[NEON_B], 8 - SK_B16_BITS);
300be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org
301be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            // calc src * src_scale
302be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vres_a = vmull_u8(vsrc.val[NEON_A], valpha);
303be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vres_r = vmull_u8(vsrc.val[NEON_R], valpha);
304be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vres_g = vmull_u8(vsrc.val[NEON_G], valpha);
305be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vres_b = vmull_u8(vsrc.val[NEON_B], valpha);
306be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org
307be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            // prepare dst_scale
308be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vres_a = SkDiv255Round_neon8(vres_a);
309be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vres_a = valpha_max - vres_a; // 255 - (sa * src_scale) / 255
310be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org
311be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            // add dst * dst_scale to previous result
312be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vres_r = vmlaq_u16(vres_r, vdst_r, vres_a);
313be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vres_g = vmlaq_u16(vres_g, vdst_g, vres_a);
314be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vres_b = vmlaq_u16(vres_b, vdst_b, vres_a);
315be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org
316be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org#ifdef S32A_D565_BLEND_EXACT
317be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            // It is possible to get exact results with this but it is slow,
318be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            // even slower than C code in some cases
319be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vres_r = SkDiv255Round_neon8(vres_r);
320be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vres_g = SkDiv255Round_neon8(vres_g);
321be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vres_b = SkDiv255Round_neon8(vres_b);
322be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org#else
323be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vres_r = vrshrq_n_u16(vres_r, 8);
324be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vres_g = vrshrq_n_u16(vres_g, 8);
325be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vres_b = vrshrq_n_u16(vres_b, 8);
326be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org#endif
327be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            // pack result
328be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vres_b = vsliq_n_u16(vres_b, vres_g, SK_G16_SHIFT); // insert green into blue
329be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vres_b = vsliq_n_u16(vres_b, vres_r, SK_R16_SHIFT); // insert red into green/blue
330be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org
331be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            // store
332be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            vst1q_u16(dst, vres_b);
333be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            dst += 8;
334be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            count -= 8;
335be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org        } while (count >= 8);
336be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org    }
337a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
338be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org    // leftovers
339be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org    while (count-- > 0) {
340be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org        SkPMColor sc = *src++;
341be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org        if (sc) {
342be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            uint16_t dc = *dst;
343be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            unsigned dst_scale = 255 - SkMulDiv255Round(SkGetPackedA32(sc), alpha);
344be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            unsigned dr = SkMulS16(SkPacked32ToR16(sc), alpha) + SkMulS16(SkGetPackedR16(dc), dst_scale);
345be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            unsigned dg = SkMulS16(SkPacked32ToG16(sc), alpha) + SkMulS16(SkGetPackedG16(dc), dst_scale);
346be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            unsigned db = SkMulS16(SkPacked32ToB16(sc), alpha) + SkMulS16(SkGetPackedB16(dc), dst_scale);
347be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org            *dst = SkPackRGB16(SkDiv255Round(dr), SkDiv255Round(dg), SkDiv255Round(db));
348be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org        }
349be233d63ca015c2991f4fe0802e4a31a71642062commit-bot@chromium.org        dst += 1;
350a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
351a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com}
352a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
353a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com/* dither matrix for Neon, derived from gDitherMatrix_3Bit_16.
354a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * each dither value is spaced out into byte lanes, and repeated
355a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * to allow an 8-byte load from offsets 0, 1, 2 or 3 from the
356a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * start of each row.
357a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com */
358a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comstatic const uint8_t gDitherMatrix_Neon[48] = {
359a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    0, 4, 1, 5, 0, 4, 1, 5, 0, 4, 1, 5,
360a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    6, 2, 7, 3, 6, 2, 7, 3, 6, 2, 7, 3,
361a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    1, 5, 0, 4, 1, 5, 0, 4, 1, 5, 0, 4,
362a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    7, 3, 6, 2, 7, 3, 6, 2, 7, 3, 6, 2,
363fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
364a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com};
365a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
366a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comvoid S32_D565_Blend_Dither_neon(uint16_t *dst, const SkPMColor *src,
367a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                                int count, U8CPU alpha, int x, int y)
368a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com{
369fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3704cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org    SkASSERT(255 > alpha);
3714cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org
3724cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org    // rescale alpha to range 1 - 256
373a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    int scale = SkAlpha255To256(alpha);
374fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3754cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org    if (count >= 8) {
3764cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org        /* select row and offset for dither array */
3774cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org        const uint8_t *dstart = &gDitherMatrix_Neon[(y&3)*12 + (x&3)];
378fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3794cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org        uint8x8_t vdither = vld1_u8(dstart);         // load dither values
3804cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org        uint8x8_t vdither_g = vshr_n_u8(vdither, 1); // calc. green dither values
381fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3824cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org        int16x8_t vscale = vdupq_n_s16(scale);        // duplicate scale into neon reg
3834cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org        uint16x8_t vmask_b = vdupq_n_u16(0x1F);         // set up blue mask
384fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3854cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org        do {
3864cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org
3874cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            uint8x8_t vsrc_r, vsrc_g, vsrc_b;
3884cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            uint8x8_t vsrc565_r, vsrc565_g, vsrc565_b;
3894cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            uint16x8_t vsrc_dit_r, vsrc_dit_g, vsrc_dit_b;
3904cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            uint16x8_t vsrc_res_r, vsrc_res_g, vsrc_res_b;
3914cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            uint16x8_t vdst;
3924cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            uint16x8_t vdst_r, vdst_g, vdst_b;
3934cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            int16x8_t vres_r, vres_g, vres_b;
3944cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            int8x8_t vres8_r, vres8_g, vres8_b;
3954cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org
3964cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            // Load source and add dither
3974cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            {
3984cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            register uint8x8_t d0 asm("d0");
3994cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            register uint8x8_t d1 asm("d1");
4004cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            register uint8x8_t d2 asm("d2");
4014cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            register uint8x8_t d3 asm("d3");
4024cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org
4034cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            asm (
4044cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org                "vld4.8    {d0-d3},[%[src]]!  /* r=%P0 g=%P1 b=%P2 a=%P3 */"
4054cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org                : "=w" (d0), "=w" (d1), "=w" (d2), "=w" (d3), [src] "+&r" (src)
4064cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org                :
4074cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            );
4084cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vsrc_g = d1;
4094cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
4104cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vsrc_r = d2; vsrc_b = d0;
4114cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
4124cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vsrc_r = d0; vsrc_b = d2;
4134cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org#endif
4144cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            }
4154cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org
4164cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vsrc565_g = vshr_n_u8(vsrc_g, 6); // calc. green >> 6
4174cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vsrc565_r = vshr_n_u8(vsrc_r, 5); // calc. red >> 5
4184cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vsrc565_b = vshr_n_u8(vsrc_b, 5); // calc. blue >> 5
4194cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org
4204cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vsrc_dit_g = vaddl_u8(vsrc_g, vdither_g); // add in dither to green and widen
4214cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vsrc_dit_r = vaddl_u8(vsrc_r, vdither);   // add in dither to red and widen
4224cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vsrc_dit_b = vaddl_u8(vsrc_b, vdither);   // add in dither to blue and widen
4234cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org
4244cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vsrc_dit_r = vsubw_u8(vsrc_dit_r, vsrc565_r);  // sub shifted red from result
4254cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vsrc_dit_g = vsubw_u8(vsrc_dit_g, vsrc565_g);  // sub shifted green from result
4264cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vsrc_dit_b = vsubw_u8(vsrc_dit_b, vsrc565_b);  // sub shifted blue from result
4274cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org
4284cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vsrc_res_r = vshrq_n_u16(vsrc_dit_r, 3);
4294cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vsrc_res_g = vshrq_n_u16(vsrc_dit_g, 2);
4304cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vsrc_res_b = vshrq_n_u16(vsrc_dit_b, 3);
4314cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org
4324cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            // Load dst and unpack
4334cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vdst = vld1q_u16(dst);
4344cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vdst_g = vshrq_n_u16(vdst, 5);                   // shift down to get green
4354cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vdst_r = vshrq_n_u16(vshlq_n_u16(vdst, 5), 5+5); // double shift to extract red
4364cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vdst_b = vandq_u16(vdst, vmask_b);               // mask to get blue
4374cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org
4384cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            // subtract dst from src and widen
4394cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vres_r = vsubq_s16(vreinterpretq_s16_u16(vsrc_res_r), vreinterpretq_s16_u16(vdst_r));
4404cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vres_g = vsubq_s16(vreinterpretq_s16_u16(vsrc_res_g), vreinterpretq_s16_u16(vdst_g));
4414cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vres_b = vsubq_s16(vreinterpretq_s16_u16(vsrc_res_b), vreinterpretq_s16_u16(vdst_b));
4424cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org
4434cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            // multiply diffs by scale and shift
4444cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vres_r = vmulq_s16(vres_r, vscale);
4454cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vres_g = vmulq_s16(vres_g, vscale);
4464cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vres_b = vmulq_s16(vres_b, vscale);
4474cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org
4484cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vres8_r = vshrn_n_s16(vres_r, 8);
4494cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vres8_g = vshrn_n_s16(vres_g, 8);
4504cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vres8_b = vshrn_n_s16(vres_b, 8);
4514cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org
4524cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            // add dst to result
4534cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vres_r = vaddw_s8(vreinterpretq_s16_u16(vdst_r), vres8_r);
4544cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vres_g = vaddw_s8(vreinterpretq_s16_u16(vdst_g), vres8_g);
4554cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vres_b = vaddw_s8(vreinterpretq_s16_u16(vdst_b), vres8_b);
4564cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org
4574cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            // put result into 565 format
4584cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vres_b = vsliq_n_s16(vres_b, vres_g, 5);   // shift up green and insert into blue
4594cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vres_b = vsliq_n_s16(vres_b, vres_r, 6+5); // shift up red and insert into blue
4604cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org
4614cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            // Store result
4624cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            vst1q_u16(dst, vreinterpretq_u16_s16(vres_b));
4634cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org
4644cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            // Next iteration
4654cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            dst += 8;
4664cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            count -= 8;
4674cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org
4684cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org        } while (count >= 8);
4694cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org    }
4704cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org
4714cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org    // Leftovers
4724cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org    if (count > 0) {
4734cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org        int scale = SkAlpha255To256(alpha);
4744cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org        DITHER_565_SCAN(y);
4754cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org        do {
4764cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            SkPMColor c = *src++;
4774cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            SkPMColorAssert(c);
4784cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org
4794cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            int dither = DITHER_VALUE(x);
4804cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            int sr = SkGetPackedR32(c);
4814cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            int sg = SkGetPackedG32(c);
4824cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            int sb = SkGetPackedB32(c);
4834cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            sr = SkDITHER_R32To565(sr, dither);
4844cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            sg = SkDITHER_G32To565(sg, dither);
4854cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            sb = SkDITHER_B32To565(sb, dither);
4864cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org
4874cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            uint16_t d = *dst;
4884cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            *dst++ = SkPackRGB16(SkAlphaBlend(sr, SkGetPackedR16(d), scale),
4894cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org                                 SkAlphaBlend(sg, SkGetPackedG16(d), scale),
4904cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org                                 SkAlphaBlend(sb, SkGetPackedB16(d), scale));
4914cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org            DITHER_INC_X(x);
4924cc26324e3be5258fae9dc102aa6a3af7d1c96eacommit-bot@chromium.org        } while (--count != 0);
493a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
494a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com}
495a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
496a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comvoid S32A_Opaque_BlitRow32_neon(SkPMColor* SK_RESTRICT dst,
497a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                                const SkPMColor* SK_RESTRICT src,
498a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                                int count, U8CPU alpha) {
499a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
500a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    SkASSERT(255 == alpha);
501a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    if (count > 0) {
502a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
503a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
504fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    uint8x8_t alpha_mask;
505a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
506fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    static const uint8_t alpha_mask_setup[] = {3,3,3,3,7,7,7,7};
507fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    alpha_mask = vld1_u8(alpha_mask_setup);
508a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
509fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    /* do the NEON unrolled code */
510fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#define    UNROLL    4
511fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    while (count >= UNROLL) {
512fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint8x8_t src_raw, dst_raw, dst_final;
513fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint8x8_t src_raw_2, dst_raw_2, dst_final_2;
514a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
5150a5699ee482c3b5ef1e857de8a2de06c6a1fa298commit-bot@chromium.org        /* The two prefetches below may make the code slighlty
5160a5699ee482c3b5ef1e857de8a2de06c6a1fa298commit-bot@chromium.org         * slower for small values of count but are worth having
5170a5699ee482c3b5ef1e857de8a2de06c6a1fa298commit-bot@chromium.org         * in the general case.
5180a5699ee482c3b5ef1e857de8a2de06c6a1fa298commit-bot@chromium.org         */
5190a5699ee482c3b5ef1e857de8a2de06c6a1fa298commit-bot@chromium.org        __builtin_prefetch(src+32);
5200a5699ee482c3b5ef1e857de8a2de06c6a1fa298commit-bot@chromium.org        __builtin_prefetch(dst+32);
5210a5699ee482c3b5ef1e857de8a2de06c6a1fa298commit-bot@chromium.org
522fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* get the source */
523fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        src_raw = vreinterpret_u8_u32(vld1_u32(src));
524fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if    UNROLL > 2
525fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        src_raw_2 = vreinterpret_u8_u32(vld1_u32(src+2));
526a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
527a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
528fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* get and hold the dst too */
529fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_raw = vreinterpret_u8_u32(vld1_u32(dst));
530fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if    UNROLL > 2
531fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_raw_2 = vreinterpret_u8_u32(vld1_u32(dst+2));
532a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
533a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
534fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    /* 1st and 2nd bits of the unrolling */
535fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    {
536fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint8x8_t dst_cooked;
537fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint16x8_t dst_wide;
538fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint8x8_t alpha_narrow;
539fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint16x8_t alpha_wide;
540a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
541fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* get the alphas spread out properly */
542fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        alpha_narrow = vtbl1_u8(src_raw, alpha_mask);
543fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        alpha_wide = vsubw_u8(vdupq_n_u16(256), alpha_narrow);
544a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
545fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* spread the dest */
546fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_wide = vmovl_u8(dst_raw);
547a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
548fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* alpha mul the dest */
549fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_wide = vmulq_u16 (dst_wide, alpha_wide);
550fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_cooked = vshrn_n_u16(dst_wide, 8);
551a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
552fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* sum -- ignoring any byte lane overflows */
553fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_final = vadd_u8(src_raw, dst_cooked);
554fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
555a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
556fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if    UNROLL > 2
557fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    /* the 3rd and 4th bits of our unrolling */
558fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    {
559fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint8x8_t dst_cooked;
560fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint16x8_t dst_wide;
561fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint8x8_t alpha_narrow;
562fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint16x8_t alpha_wide;
563a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
564fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        alpha_narrow = vtbl1_u8(src_raw_2, alpha_mask);
565fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        alpha_wide = vsubw_u8(vdupq_n_u16(256), alpha_narrow);
566a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
567fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* spread the dest */
568fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_wide = vmovl_u8(dst_raw_2);
569a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
570fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* alpha mul the dest */
571fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_wide = vmulq_u16 (dst_wide, alpha_wide);
572fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_cooked = vshrn_n_u16(dst_wide, 8);
573a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
574fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* sum -- ignoring any byte lane overflows */
575fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_final_2 = vadd_u8(src_raw_2, dst_cooked);
576fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
577a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
578a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
579fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        vst1_u32(dst, vreinterpret_u32_u8(dst_final));
580fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if    UNROLL > 2
581fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        vst1_u32(dst+2, vreinterpret_u32_u8(dst_final_2));
582a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
583a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
584fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        src += UNROLL;
585fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst += UNROLL;
586fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        count -= UNROLL;
587fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
588fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#undef    UNROLL
589a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
590fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    /* do any residual iterations */
591a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        while (--count >= 0) {
592a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            *dst = SkPMSrcOver(*src, *dst);
593a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            src += 1;
594a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            dst += 1;
595a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        }
596a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
597a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com}
598a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
599c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.comvoid S32A_Opaque_BlitRow32_neon_src_alpha(SkPMColor* SK_RESTRICT dst,
600c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com                                const SkPMColor* SK_RESTRICT src,
601c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com                                int count, U8CPU alpha) {
602c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    SkASSERT(255 == alpha);
603c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
604c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    if (count <= 0)
605c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    return;
606c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
607c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    /* Use these to check if src is transparent or opaque */
608c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    const unsigned int ALPHA_OPAQ  = 0xFF000000;
609c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    const unsigned int ALPHA_TRANS = 0x00FFFFFF;
610c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
611c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com#define UNROLL  4
612c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    const SkPMColor* SK_RESTRICT src_end = src + count - (UNROLL + 1);
613c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    const SkPMColor* SK_RESTRICT src_temp = src;
614c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
615c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    /* set up the NEON variables */
616c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    uint8x8_t alpha_mask;
617c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    static const uint8_t alpha_mask_setup[] = {3,3,3,3,7,7,7,7};
618c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    alpha_mask = vld1_u8(alpha_mask_setup);
619c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
620c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    uint8x8_t src_raw, dst_raw, dst_final;
621c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    uint8x8_t src_raw_2, dst_raw_2, dst_final_2;
622c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    uint8x8_t dst_cooked;
623c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    uint16x8_t dst_wide;
624c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    uint8x8_t alpha_narrow;
625c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    uint16x8_t alpha_wide;
626c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
627c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    /* choose the first processing type */
628c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    if( src >= src_end)
629c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        goto TAIL;
630c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    if(*src <= ALPHA_TRANS)
631c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        goto ALPHA_0;
632c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    if(*src >= ALPHA_OPAQ)
633c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        goto ALPHA_255;
634c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    /* fall-thru */
635c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
636c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.comALPHA_1_TO_254:
637c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    do {
638c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
639c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* get the source */
640c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        src_raw = vreinterpret_u8_u32(vld1_u32(src));
641c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        src_raw_2 = vreinterpret_u8_u32(vld1_u32(src+2));
642c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
643c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* get and hold the dst too */
644c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst_raw = vreinterpret_u8_u32(vld1_u32(dst));
645c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst_raw_2 = vreinterpret_u8_u32(vld1_u32(dst+2));
646c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
647c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
648c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* get the alphas spread out properly */
649c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        alpha_narrow = vtbl1_u8(src_raw, alpha_mask);
650c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* reflect SkAlpha255To256() semantics a+1 vs a+a>>7 */
651c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* we collapsed (255-a)+1 ... */
652c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        alpha_wide = vsubw_u8(vdupq_n_u16(256), alpha_narrow);
653c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
654c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* spread the dest */
655c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst_wide = vmovl_u8(dst_raw);
656c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
657c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* alpha mul the dest */
658c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst_wide = vmulq_u16 (dst_wide, alpha_wide);
659c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst_cooked = vshrn_n_u16(dst_wide, 8);
660c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
661c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* sum -- ignoring any byte lane overflows */
662c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst_final = vadd_u8(src_raw, dst_cooked);
663c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
664c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        alpha_narrow = vtbl1_u8(src_raw_2, alpha_mask);
665c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* reflect SkAlpha255To256() semantics a+1 vs a+a>>7 */
666c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* we collapsed (255-a)+1 ... */
667c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        alpha_wide = vsubw_u8(vdupq_n_u16(256), alpha_narrow);
668c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
669c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* spread the dest */
670c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst_wide = vmovl_u8(dst_raw_2);
671c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
672c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* alpha mul the dest */
673c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst_wide = vmulq_u16 (dst_wide, alpha_wide);
674c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst_cooked = vshrn_n_u16(dst_wide, 8);
675c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
676c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* sum -- ignoring any byte lane overflows */
677c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst_final_2 = vadd_u8(src_raw_2, dst_cooked);
678c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
679c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        vst1_u32(dst, vreinterpret_u32_u8(dst_final));
680c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        vst1_u32(dst+2, vreinterpret_u32_u8(dst_final_2));
681c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
682c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        src += UNROLL;
683c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst += UNROLL;
684c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
685c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        /* if 2 of the next pixels aren't between 1 and 254
686c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        it might make sense to go to the optimized loops */
687c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        if((src[0] <= ALPHA_TRANS && src[1] <= ALPHA_TRANS) || (src[0] >= ALPHA_OPAQ && src[1] >= ALPHA_OPAQ))
688c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com            break;
689c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
690c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    } while(src < src_end);
691c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
692c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    if (src >= src_end)
693c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        goto TAIL;
694c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
695c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    if(src[0] >= ALPHA_OPAQ && src[1] >= ALPHA_OPAQ)
696c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        goto ALPHA_255;
697c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
698c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    /*fall-thru*/
699c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
700c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.comALPHA_0:
701c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
702c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    /*In this state, we know the current alpha is 0 and
703c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com     we optimize for the next alpha also being zero. */
704c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    src_temp = src;  //so we don't have to increment dst every time
705c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    do {
706c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        if(*(++src) > ALPHA_TRANS)
707c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com            break;
708c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        if(*(++src) > ALPHA_TRANS)
709c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com            break;
710c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        if(*(++src) > ALPHA_TRANS)
711c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com            break;
712c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        if(*(++src) > ALPHA_TRANS)
713c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com            break;
714c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    } while(src < src_end);
715c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
716c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    dst += (src - src_temp);
717c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
718c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    /* no longer alpha 0, so determine where to go next. */
719c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    if( src >= src_end)
720c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        goto TAIL;
721c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    if(*src >= ALPHA_OPAQ)
722c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        goto ALPHA_255;
723c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    else
724c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        goto ALPHA_1_TO_254;
725c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
726c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.comALPHA_255:
727c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    while((src[0] & src[1] & src[2] & src[3]) >= ALPHA_OPAQ) {
728c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst[0]=src[0];
729c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst[1]=src[1];
730c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst[2]=src[2];
731c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst[3]=src[3];
732c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        src+=UNROLL;
733c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst+=UNROLL;
734c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        if(src >= src_end)
735c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com            goto TAIL;
736c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    }
737c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
738c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    //Handle remainder.
739c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    if(*src >= ALPHA_OPAQ) { *dst++ = *src++;
740c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        if(*src >= ALPHA_OPAQ) { *dst++ = *src++;
741c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com            if(*src >= ALPHA_OPAQ) { *dst++ = *src++; }
742c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        }
743c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    }
744c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
745c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    if( src >= src_end)
746c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        goto TAIL;
747c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    if(*src <= ALPHA_TRANS)
748c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        goto ALPHA_0;
749c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    else
750c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        goto ALPHA_1_TO_254;
751c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
752c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.comTAIL:
753c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    /* do any residual iterations */
754c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    src_end += UNROLL + 1;  //goto the real end
755c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    while(src != src_end) {
756c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        if( *src != 0 ) {
757c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com            if( *src >= ALPHA_OPAQ ) {
758c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com                *dst = *src;
759c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com            }
760c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com            else {
761c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com                *dst = SkPMSrcOver(*src, *dst);
762c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com            }
763c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        }
764c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        src++;
765c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com        dst++;
766c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    }
767c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com
768c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com#undef    UNROLL
769c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    return;
770c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com}
771a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
772a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com/* Neon version of S32_Blend_BlitRow32()
773a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com * portable version is in src/core/SkBlitRow_D32.cpp
774a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com */
775a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comvoid S32_Blend_BlitRow32_neon(SkPMColor* SK_RESTRICT dst,
776a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                              const SkPMColor* SK_RESTRICT src,
777a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                              int count, U8CPU alpha) {
778a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    SkASSERT(alpha <= 255);
779fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
780dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org    if (count <= 0) {
781dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        return;
782dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org    }
783fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
784dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org    uint16_t src_scale = SkAlpha255To256(alpha);
785dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org    uint16_t dst_scale = 256 - src_scale;
786fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
787dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org    while (count >= 2) {
788dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        uint8x8_t vsrc, vdst, vres;
789dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        uint16x8_t vsrc_wide, vdst_wide;
790fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
791dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        /* These commented prefetches are a big win for count
792dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org         * values > 64 on an A9 (Pandaboard) but hurt by 10% for count = 4.
793dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org         * They also hurt a little (<5%) on an A15
794dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org         */
795dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        //__builtin_prefetch(src+32);
796dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        //__builtin_prefetch(dst+32);
797fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
798dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        // Load
799dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        vsrc = vreinterpret_u8_u32(vld1_u32(src));
800dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        vdst = vreinterpret_u8_u32(vld1_u32(dst));
801dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org
802dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        // Process src
803dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        vsrc_wide = vmovl_u8(vsrc);
804dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        vsrc_wide = vmulq_u16(vsrc_wide, vdupq_n_u16(src_scale));
805dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org
806dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        // Process dst
807dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        vdst_wide = vmull_u8(vdst, vdup_n_u8(dst_scale));
808dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org
809dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        // Combine
810dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        vres = vshrn_n_u16(vdst_wide, 8) + vshrn_n_u16(vsrc_wide, 8);
811dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org
812dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        // Store
813dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        vst1_u32(dst, vreinterpret_u32_u8(vres));
814dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org
815dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        src += 2;
816dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        dst += 2;
817dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        count -= 2;
818fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
819fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
820fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    if (count == 1) {
821dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        uint8x8_t vsrc, vdst, vres;
822dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        uint16x8_t vsrc_wide, vdst_wide;
823a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
824dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        // Load
825dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        vsrc = vreinterpret_u8_u32(vld1_lane_u32(src, vreinterpret_u32_u8(vsrc), 0));
826dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        vdst = vreinterpret_u8_u32(vld1_lane_u32(dst, vreinterpret_u32_u8(vdst), 0));
827dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org
828dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        // Process
829dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        vsrc_wide = vmovl_u8(vsrc);
830dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        vsrc_wide = vmulq_u16(vsrc_wide, vdupq_n_u16(src_scale));
831dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        vdst_wide = vmull_u8(vdst, vdup_n_u8(dst_scale));
832dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        vres = vshrn_n_u16(vdst_wide, 8) + vshrn_n_u16(vsrc_wide, 8);
833dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org
834dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        // Store
835dfff2737f8ad3e945a4dcbe175380d4b2a91a260commit-bot@chromium.org        vst1_lane_u32(dst, vreinterpret_u32_u8(vres), 0);
836a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
837a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com}
838a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
8391fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.orgvoid S32A_Blend_BlitRow32_neon(SkPMColor* SK_RESTRICT dst,
8401fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org                         const SkPMColor* SK_RESTRICT src,
8411fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org                         int count, U8CPU alpha) {
8421fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8431fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org    SkASSERT(255 >= alpha);
8441fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8451fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org    if (count <= 0) {
8461fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        return;
8471fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org    }
8481fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8491fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org    unsigned alpha256 = SkAlpha255To256(alpha);
8501fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8511fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org    // First deal with odd counts
8521fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org    if (count & 1) {
8531fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        uint8x8_t vsrc = vdup_n_u8(0), vdst = vdup_n_u8(0), vres;
8541fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        uint16x8_t vdst_wide, vsrc_wide;
8551fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        unsigned dst_scale;
8561fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8571fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        // Load
8581fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        vsrc = vreinterpret_u8_u32(vld1_lane_u32(src, vreinterpret_u32_u8(vsrc), 0));
8591fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        vdst = vreinterpret_u8_u32(vld1_lane_u32(dst, vreinterpret_u32_u8(vdst), 0));
8601fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8611fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        // Calc dst_scale
8621fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        dst_scale = vget_lane_u8(vsrc, 3);
8631fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        dst_scale *= alpha256;
8641fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        dst_scale >>= 8;
8651fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        dst_scale = 256 - dst_scale;
8661fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8671fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        // Process src
8681fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        vsrc_wide = vmovl_u8(vsrc);
8691fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        vsrc_wide = vmulq_n_u16(vsrc_wide, alpha256);
8701fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8711fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        // Process dst
8721fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        vdst_wide = vmovl_u8(vdst);
8731fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        vdst_wide = vmulq_n_u16(vdst_wide, dst_scale);
8741fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8751fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        // Combine
8761fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        vres = vshrn_n_u16(vdst_wide, 8) + vshrn_n_u16(vsrc_wide, 8);
8771fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8781fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        vst1_lane_u32(dst, vreinterpret_u32_u8(vres), 0);
8791fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        dst++;
8801fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        src++;
8811fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        count--;
8821fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org    }
8831fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8841fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org    if (count) {
8851fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        uint8x8_t alpha_mask;
8861fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        static const uint8_t alpha_mask_setup[] = {3,3,3,3,7,7,7,7};
8871fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        alpha_mask = vld1_u8(alpha_mask_setup);
8881fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8891fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        do {
8901fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8911fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            uint8x8_t vsrc, vdst, vres, vsrc_alphas;
8921fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            uint16x8_t vdst_wide, vsrc_wide, vsrc_scale, vdst_scale;
8931fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8941fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            __builtin_prefetch(src+32);
8951fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            __builtin_prefetch(dst+32);
8961fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
8971fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            // Load
8981fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vsrc = vreinterpret_u8_u32(vld1_u32(src));
8991fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vdst = vreinterpret_u8_u32(vld1_u32(dst));
9001fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
9011fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            // Prepare src_scale
9021fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vsrc_scale = vdupq_n_u16(alpha256);
9031fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
9041fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            // Calc dst_scale
9051fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vsrc_alphas = vtbl1_u8(vsrc, alpha_mask);
9061fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vdst_scale = vmovl_u8(vsrc_alphas);
9071fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vdst_scale *= vsrc_scale;
9081fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vdst_scale = vshrq_n_u16(vdst_scale, 8);
9091fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vdst_scale = vsubq_u16(vdupq_n_u16(256), vdst_scale);
9101fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
9111fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            // Process src
9121fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vsrc_wide = vmovl_u8(vsrc);
9131fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vsrc_wide *= vsrc_scale;
9141fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
9151fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            // Process dst
9161fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vdst_wide = vmovl_u8(vdst);
9171fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vdst_wide *= vdst_scale;
9181fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
9191fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            // Combine
9201fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vres = vshrn_n_u16(vdst_wide, 8) + vshrn_n_u16(vsrc_wide, 8);
9211fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
9221fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            vst1_u32(dst, vreinterpret_u32_u8(vres));
9231fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
9241fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            src += 2;
9251fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            dst += 2;
9261fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org            count -= 2;
9271fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org        } while(count);
9281fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org    }
9291fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org}
9301fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org
931a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com///////////////////////////////////////////////////////////////////////////////
932a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
933fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#undef    DEBUG_OPAQUE_DITHER
934a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
935fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if    defined(DEBUG_OPAQUE_DITHER)
936a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comstatic void showme8(char *str, void *p, int len)
937a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com{
938fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    static char buf[256];
939fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    char tbuf[32];
940fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    int i;
941fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    char *pc = (char*) p;
942fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    sprintf(buf,"%8s:", str);
943fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    for(i=0;i<len;i++) {
944fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        sprintf(tbuf, "   %02x", pc[i]);
945fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        strcat(buf, tbuf);
946fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
947fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    SkDebugf("%s\n", buf);
948a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com}
949a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comstatic void showme16(char *str, void *p, int len)
950a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com{
951fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    static char buf[256];
952fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    char tbuf[32];
953fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    int i;
954fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    uint16_t *pc = (uint16_t*) p;
955fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    sprintf(buf,"%8s:", str);
956fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    len = (len / sizeof(uint16_t));    /* passed as bytes */
957fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    for(i=0;i<len;i++) {
958fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        sprintf(tbuf, " %04x", pc[i]);
959fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        strcat(buf, tbuf);
960fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
961fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    SkDebugf("%s\n", buf);
962a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com}
963a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
964a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
965a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comvoid S32A_D565_Opaque_Dither_neon (uint16_t * SK_RESTRICT dst,
966a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                                   const SkPMColor* SK_RESTRICT src,
967a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                                   int count, U8CPU alpha, int x, int y) {
968a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    SkASSERT(255 == alpha);
969a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
970fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#define    UNROLL    8
971a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
972a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    if (count >= UNROLL) {
973fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    uint8x8_t dbase;
974fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
975fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if    defined(DEBUG_OPAQUE_DITHER)
976fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    uint16_t tmpbuf[UNROLL];
977fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    int td[UNROLL];
978fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    int tdv[UNROLL];
979fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    int ta[UNROLL];
980fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    int tap[UNROLL];
981fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    uint16_t in_dst[UNROLL];
982fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    int offset = 0;
983fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    int noisy = 0;
984a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
985a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
986fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    const uint8_t *dstart = &gDitherMatrix_Neon[(y&3)*12 + (x&3)];
987fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    dbase = vld1_u8(dstart);
988a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
989a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        do {
990fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint8x8_t sr, sg, sb, sa, d;
991fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint16x8_t dst8, scale8, alpha8;
992fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint16x8_t dst_r, dst_g, dst_b;
993fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
994fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if    defined(DEBUG_OPAQUE_DITHER)
995fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    /* calculate 8 elements worth into a temp buffer */
996fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    {
997fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com      int my_y = y;
998fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com      int my_x = x;
999fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com      SkPMColor* my_src = (SkPMColor*)src;
1000fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com      uint16_t* my_dst = dst;
1001fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com      int i;
1002a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1003a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com          DITHER_565_SCAN(my_y);
1004a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com          for(i=0;i<UNROLL;i++) {
1005a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            SkPMColor c = *my_src++;
1006a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            SkPMColorAssert(c);
1007a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            if (c) {
1008a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                unsigned a = SkGetPackedA32(c);
1009fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1010a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                int d = SkAlphaMul(DITHER_VALUE(my_x), SkAlpha255To256(a));
1011fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        tdv[i] = DITHER_VALUE(my_x);
1012fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        ta[i] = a;
1013fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        tap[i] = SkAlpha255To256(a);
1014fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        td[i] = d;
1015fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1016a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                unsigned sr = SkGetPackedR32(c);
1017a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                unsigned sg = SkGetPackedG32(c);
1018a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                unsigned sb = SkGetPackedB32(c);
1019a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                sr = SkDITHER_R32_FOR_565(sr, d);
1020a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                sg = SkDITHER_G32_FOR_565(sg, d);
1021a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                sb = SkDITHER_B32_FOR_565(sb, d);
1022fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1023a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                uint32_t src_expanded = (sg << 24) | (sr << 13) | (sb << 2);
1024a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                uint32_t dst_expanded = SkExpand_rgb_16(*my_dst);
1025a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                dst_expanded = dst_expanded * (SkAlpha255To256(255 - a) >> 3);
1026a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // now src and dst expanded are in g:11 r:10 x:1 b:10
1027a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                tmpbuf[i] = SkCompact_rgb_16((src_expanded + dst_expanded) >> 5);
1028fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        td[i] = d;
1029a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1030a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            } else {
1031fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        tmpbuf[i] = *my_dst;
1032fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        ta[i] = tdv[i] = td[i] = 0xbeef;
1033fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        }
1034fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        in_dst[i] = *my_dst;
1035a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            my_dst += 1;
1036a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            DITHER_INC_X(my_x);
1037a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com          }
1038fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
1039a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
1040a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1041fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* source is in ABGR */
1042fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        {
1043fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        register uint8x8_t d0 asm("d0");
1044fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        register uint8x8_t d1 asm("d1");
1045fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        register uint8x8_t d2 asm("d2");
1046fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        register uint8x8_t d3 asm("d3");
1047a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1048fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        asm ("vld4.8    {d0-d3},[%4]  /* r=%P0 g=%P1 b=%P2 a=%P3 */"
1049fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            : "=w" (d0), "=w" (d1), "=w" (d2), "=w" (d3)
1050fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            : "r" (src)
1051a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                    );
1052fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            sr = d0; sg = d1; sb = d2; sa = d3;
1053fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        }
1054a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1055fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* calculate 'd', which will be 0..7 */
1056fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* dbase[] is 0..7; alpha is 0..256; 16 bits suffice */
1057a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#if defined(SK_BUILD_FOR_ANDROID)
1058fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* SkAlpha255To256() semantic a+1 vs a+a>>7 */
1059fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        alpha8 = vaddw_u8(vmovl_u8(sa), vdup_n_u8(1));
1060a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#else
1061fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        alpha8 = vaddw_u8(vmovl_u8(sa), vshr_n_u8(sa, 7));
1062a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
1063fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        alpha8 = vmulq_u16(alpha8, vmovl_u8(dbase));
1064fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        d = vshrn_n_u16(alpha8, 8);    /* narrowing too */
1065fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1066fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* sr = sr - (sr>>5) + d */
1067fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* watching for 8-bit overflow.  d is 0..7; risky range of
1068fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com         * sr is >248; and then (sr>>5) is 7 so it offsets 'd';
1069fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com         * safe  as long as we do ((sr-sr>>5) + d) */
1070fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        sr = vsub_u8(sr, vshr_n_u8(sr, 5));
1071fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        sr = vadd_u8(sr, d);
1072fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1073fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* sb = sb - (sb>>5) + d */
1074fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        sb = vsub_u8(sb, vshr_n_u8(sb, 5));
1075fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        sb = vadd_u8(sb, d);
1076fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1077fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* sg = sg - (sg>>6) + d>>1; similar logic for overflows */
1078fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        sg = vsub_u8(sg, vshr_n_u8(sg, 6));
1079fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        sg = vadd_u8(sg, vshr_n_u8(d,1));
1080fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1081fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* need to pick up 8 dst's -- at 16 bits each, 128 bits */
1082fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst8 = vld1q_u16(dst);
1083fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_b = vandq_u16(dst8, vdupq_n_u16(0x001F));
1084fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_g = vandq_u16(vshrq_n_u16(dst8,5), vdupq_n_u16(0x003F));
1085fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_r = vshrq_n_u16(dst8,11);    /* clearing hi bits */
1086fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1087fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* blend */
1088a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#if 1
1089fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* SkAlpha255To256() semantic a+1 vs a+a>>7 */
1090fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* originally 255-sa + 1 */
1091fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        scale8 = vsubw_u8(vdupq_n_u16(256), sa);
1092a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#else
1093fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        scale8 = vsubw_u8(vdupq_n_u16(255), sa);
1094fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        scale8 = vaddq_u16(scale8, vshrq_n_u16(scale8, 7));
1095a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
1096a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1097a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#if 1
1098fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* combine the addq and mul, save 3 insns */
1099fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        scale8 = vshrq_n_u16(scale8, 3);
1100fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_b = vmlaq_u16(vshll_n_u8(sb,2), dst_b, scale8);
1101fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_g = vmlaq_u16(vshll_n_u8(sg,3), dst_g, scale8);
1102fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_r = vmlaq_u16(vshll_n_u8(sr,2), dst_r, scale8);
1103a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#else
1104fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* known correct, but +3 insns over above */
1105fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        scale8 = vshrq_n_u16(scale8, 3);
1106fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_b = vmulq_u16(dst_b, scale8);
1107fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_g = vmulq_u16(dst_g, scale8);
1108fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_r = vmulq_u16(dst_r, scale8);
1109fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1110fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* combine */
1111fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* NB: vshll widens, need to preserve those bits */
1112fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_b = vaddq_u16(dst_b, vshll_n_u8(sb,2));
1113fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_g = vaddq_u16(dst_g, vshll_n_u8(sg,3));
1114fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst_r = vaddq_u16(dst_r, vshll_n_u8(sr,2));
1115a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
1116a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1117fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* repack to store */
1118fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst8 = vandq_u16(vshrq_n_u16(dst_b, 5), vdupq_n_u16(0x001F));
1119fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst8 = vsliq_n_u16(dst8, vshrq_n_u16(dst_g, 5), 5);
1120fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst8 = vsliq_n_u16(dst8, vshrq_n_u16(dst_r,5), 11);
1121fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1122fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        vst1q_u16(dst, dst8);
1123fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1124fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if    defined(DEBUG_OPAQUE_DITHER)
1125fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* verify my 8 elements match the temp buffer */
1126fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    {
1127fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com       int i, bad=0;
1128fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com       static int invocation;
1129fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1130fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com       for (i=0;i<UNROLL;i++)
1131fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        if (tmpbuf[i] != dst[i]) bad=1;
1132fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com       if (bad) {
1133fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        SkDebugf("BAD S32A_D565_Opaque_Dither_neon(); invocation %d offset %d\n",
1134fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            invocation, offset);
1135fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        SkDebugf("  alpha 0x%x\n", alpha);
1136fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        for (i=0;i<UNROLL;i++)
1137fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            SkDebugf("%2d: %s %04x w %04x id %04x s %08x d %04x %04x %04x %04x\n",
1138fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            i, ((tmpbuf[i] != dst[i])?"BAD":"got"),
1139fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            dst[i], tmpbuf[i], in_dst[i], src[i], td[i], tdv[i], tap[i], ta[i]);
1140fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1141fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        showme16("alpha8", &alpha8, sizeof(alpha8));
1142fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        showme16("scale8", &scale8, sizeof(scale8));
1143fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        showme8("d", &d, sizeof(d));
1144fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        showme16("dst8", &dst8, sizeof(dst8));
1145fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        showme16("dst_b", &dst_b, sizeof(dst_b));
1146fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        showme16("dst_g", &dst_g, sizeof(dst_g));
1147fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        showme16("dst_r", &dst_r, sizeof(dst_r));
1148fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        showme8("sb", &sb, sizeof(sb));
1149fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        showme8("sg", &sg, sizeof(sg));
1150fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        showme8("sr", &sr, sizeof(sr));
1151fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1152fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* cop out */
1153fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        return;
1154fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com       }
1155fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com       offset += UNROLL;
1156fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com       invocation++;
1157fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
1158a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
1159a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1160a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            dst += UNROLL;
1161fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        src += UNROLL;
1162fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        count -= UNROLL;
1163fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* skip x += UNROLL, since it's unchanged mod-4 */
1164a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        } while (count >= UNROLL);
1165a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
1166fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#undef    UNROLL
1167a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1168a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    /* residuals */
1169a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    if (count > 0) {
1170a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        DITHER_565_SCAN(y);
1171a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        do {
1172a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            SkPMColor c = *src++;
1173a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            SkPMColorAssert(c);
1174a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            if (c) {
1175a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                unsigned a = SkGetPackedA32(c);
1176fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1177a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // dither and alpha are just temporary variables to work-around
1178a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // an ICE in debug.
1179a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                unsigned dither = DITHER_VALUE(x);
1180a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                unsigned alpha = SkAlpha255To256(a);
1181a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                int d = SkAlphaMul(dither, alpha);
1182fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1183a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                unsigned sr = SkGetPackedR32(c);
1184a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                unsigned sg = SkGetPackedG32(c);
1185a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                unsigned sb = SkGetPackedB32(c);
1186a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                sr = SkDITHER_R32_FOR_565(sr, d);
1187a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                sg = SkDITHER_G32_FOR_565(sg, d);
1188a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                sb = SkDITHER_B32_FOR_565(sb, d);
1189fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1190a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                uint32_t src_expanded = (sg << 24) | (sr << 13) | (sb << 2);
1191a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                uint32_t dst_expanded = SkExpand_rgb_16(*dst);
1192a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                dst_expanded = dst_expanded * (SkAlpha255To256(255 - a) >> 3);
1193a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // now src and dst expanded are in g:11 r:10 x:1 b:10
1194a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                *dst = SkCompact_rgb_16((src_expanded + dst_expanded) >> 5);
1195a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            }
1196a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            dst += 1;
1197a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            DITHER_INC_X(x);
1198a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        } while (--count != 0);
1199a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
1200a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com}
1201a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1202a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com///////////////////////////////////////////////////////////////////////////////
1203a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1204fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#undef    DEBUG_S32_OPAQUE_DITHER
1205a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1206a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comvoid S32_D565_Opaque_Dither_neon(uint16_t* SK_RESTRICT dst,
1207a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                                 const SkPMColor* SK_RESTRICT src,
1208a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                                 int count, U8CPU alpha, int x, int y) {
1209a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    SkASSERT(255 == alpha);
1210a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1211fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#define    UNROLL    8
1212a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    if (count >= UNROLL) {
1213fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    uint8x8_t d;
1214fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    const uint8_t *dstart = &gDitherMatrix_Neon[(y&3)*12 + (x&3)];
1215fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    d = vld1_u8(dstart);
1216fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1217fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    while (count >= UNROLL) {
1218efbe8e9bedda21a3e061ebf3d96431a0f250a654djsollen@google.com        uint8x8_t sr, sg, sb;
1219efbe8e9bedda21a3e061ebf3d96431a0f250a654djsollen@google.com        uint16x8_t dr, dg, db;
1220fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        uint16x8_t dst8;
1221fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1222fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        {
1223fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        register uint8x8_t d0 asm("d0");
1224fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        register uint8x8_t d1 asm("d1");
1225fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        register uint8x8_t d2 asm("d2");
1226fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        register uint8x8_t d3 asm("d3");
1227fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1228688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        asm (
1229688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org            "vld4.8    {d0-d3},[%[src]]!  /* r=%P0 g=%P1 b=%P2 a=%P3 */"
1230688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org            : "=w" (d0), "=w" (d1), "=w" (d2), "=w" (d3), [src] "+&r" (src)
1231688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org            :
1232688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        );
1233688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        sg = d1;
1234688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
1235688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        sr = d2; sb = d0;
1236688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
1237688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        sr = d0; sb = d2;
1238688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org#endif
1239fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        }
1240fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        /* XXX: if we want to prefetch, hide it in the above asm()
1241fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com         * using the gcc __builtin_prefetch(), the prefetch will
1242fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com         * fall to the bottom of the loop -- it won't stick up
1243fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com         * at the top of the loop, just after the vld4.
1244fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com         */
1245fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1246688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        // sr = sr - (sr>>5) + d
1247fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        sr = vsub_u8(sr, vshr_n_u8(sr, 5));
1248fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dr = vaddl_u8(sr, d);
1249fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1250688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        // sb = sb - (sb>>5) + d
1251fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        sb = vsub_u8(sb, vshr_n_u8(sb, 5));
1252fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        db = vaddl_u8(sb, d);
1253fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1254688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        // sg = sg - (sg>>6) + d>>1; similar logic for overflows
1255fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        sg = vsub_u8(sg, vshr_n_u8(sg, 6));
1256688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        dg = vaddl_u8(sg, vshr_n_u8(d, 1));
1257fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1258688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        // pack high bits of each into 565 format  (rgb, b is lsb)
1259fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst8 = vshrq_n_u16(db, 3);
1260fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst8 = vsliq_n_u16(dst8, vshrq_n_u16(dg, 2), 5);
1261688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        dst8 = vsliq_n_u16(dst8, vshrq_n_u16(dr, 3), 11);
1262fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1263688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        // store it
1264fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        vst1q_u16(dst, dst8);
1265fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1266fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#if    defined(DEBUG_S32_OPAQUE_DITHER)
1267688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        // always good to know if we generated good results
1268fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        {
1269fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        int i, myx = x, myy = y;
1270fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        DITHER_565_SCAN(myy);
1271fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        for (i=0;i<UNROLL;i++) {
1272688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org            // the '!' in the asm block above post-incremented src by the 8 pixels it reads.
1273688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org            SkPMColor c = src[i-8];
1274fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            unsigned dither = DITHER_VALUE(myx);
1275fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            uint16_t val = SkDitherRGB32To565(c, dither);
1276fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            if (val != dst[i]) {
1277fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            SkDebugf("RBE: src %08x dither %02x, want %04x got %04x dbas[i] %02x\n",
1278fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com                c, dither, val, dst[i], dstart[i]);
1279fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            }
1280fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            DITHER_INC_X(myx);
1281fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        }
1282fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        }
1283a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com#endif
1284a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1285fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        dst += UNROLL;
1286688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        // we don't need to increment src as the asm above has already done it
1287fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        count -= UNROLL;
1288688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org        x += UNROLL;        // probably superfluous
1289fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
1290a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
1291fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com#undef    UNROLL
1292a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1293688d362b4545e1beadebb7ba5886813d7038883ccommit-bot@chromium.org    // residuals
1294a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    if (count > 0) {
1295a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        DITHER_565_SCAN(y);
1296a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        do {
1297a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            SkPMColor c = *src++;
1298a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            SkPMColorAssert(c);
1299a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            SkASSERT(SkGetPackedA32(c) == 255);
1300a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1301a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            unsigned dither = DITHER_VALUE(x);
1302a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            *dst++ = SkDitherRGB32To565(c, dither);
1303a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            DITHER_INC_X(x);
1304a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        } while (--count != 0);
1305a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
1306a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com}
1307a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1308a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comvoid Color32_arm_neon(SkPMColor* dst, const SkPMColor* src, int count,
1309a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                      SkPMColor color) {
1310a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    if (count <= 0) {
1311a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        return;
1312a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
1313a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1314a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    if (0 == color) {
1315a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        if (src != dst) {
1316a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            memcpy(dst, src, count * sizeof(SkPMColor));
1317a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        }
1318a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        return;
1319a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
1320a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1321a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    unsigned colorA = SkGetPackedA32(color);
1322a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    if (255 == colorA) {
1323a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        sk_memset32(dst, color, count);
1324a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    } else {
1325a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        unsigned scale = 256 - SkAlpha255To256(colorA);
1326a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1327a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        if (count >= 8) {
1328a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            // at the end of this assembly, count will have been decremented
1329a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            // to a negative value. That is, if count mod 8 = x, it will be
1330a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            // -8 +x coming out.
1331a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            asm volatile (
1332a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                PLD128(src, 0)
1333a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1334a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vdup.32    q0, %[color]                \n\t"
1335a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1336a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                PLD128(src, 128)
1337a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1338a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // scale numerical interval [0-255], so load as 8 bits
1339a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vdup.8     d2, %[scale]                \n\t"
1340a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1341a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                PLD128(src, 256)
1342a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1343a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "subs       %[count], %[count], #8      \n\t"
1344a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1345a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                PLD128(src, 384)
1346a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1347a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "Loop_Color32:                          \n\t"
1348a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1349a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // load src color, 8 pixels, 4 64 bit registers
1350a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // (and increment src).
1351a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vld1.32    {d4-d7}, [%[src]]!          \n\t"
1352a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1353a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                PLD128(src, 384)
1354a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1355a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // multiply long by scale, 64 bits at a time,
1356a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // destination into a 128 bit register.
1357a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vmull.u8   q4, d4, d2                  \n\t"
1358a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vmull.u8   q5, d5, d2                  \n\t"
1359a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vmull.u8   q6, d6, d2                  \n\t"
1360a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vmull.u8   q7, d7, d2                  \n\t"
1361a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1362a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // shift the 128 bit registers, containing the 16
1363a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // bit scaled values back to 8 bits, narrowing the
1364a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // results to 64 bit registers.
1365a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vshrn.i16  d8, q4, #8                  \n\t"
1366a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vshrn.i16  d9, q5, #8                  \n\t"
1367a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vshrn.i16  d10, q6, #8                 \n\t"
1368a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vshrn.i16  d11, q7, #8                 \n\t"
1369a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1370a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // adding back the color, using 128 bit registers.
1371a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vadd.i8    q6, q4, q0                  \n\t"
1372a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vadd.i8    q7, q5, q0                  \n\t"
1373a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1374a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // store back the 8 calculated pixels (2 128 bit
1375a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                // registers), and increment dst.
1376a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "vst1.32    {d12-d15}, [%[dst]]!        \n\t"
1377a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1378a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "subs       %[count], %[count], #8      \n\t"
1379a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                "bge        Loop_Color32                \n\t"
1380a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                : [src] "+r" (src), [dst] "+r" (dst), [count] "+r" (count)
1381a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                : [color] "r" (color), [scale] "r" (scale)
1382a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                : "cc", "memory",
1383a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
1384a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                  "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15"
1385a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com                          );
1386a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            // At this point, if we went through the inline assembly, count is
1387a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            // a negative value:
1388a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            // if the value is -8, there is no pixel left to process.
1389a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            // if the value is -7, there is one pixel left to process
1390a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            // ...
1391a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            // And'ing it with 7 will give us the number of pixels
1392a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            // left to process.
1393a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            count = count & 0x7;
1394a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        }
1395a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1396a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        while (count > 0) {
1397a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            *dst = color + SkAlphaMulQ(*src, scale);
1398a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            src += 1;
1399a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            dst += 1;
1400a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com            count--;
1401a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com        }
1402a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    }
1403a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com}
1404a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1405a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com///////////////////////////////////////////////////////////////////////////////
1406a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1407a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comconst SkBlitRow::Proc sk_blitrow_platform_565_procs_arm_neon[] = {
1408a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    // no dither
14090060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org    // NOTE: For the S32_D565_Blend function below, we don't have a special
14100060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org    //       version that assumes that each source pixel is opaque. But our
14110060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org    //       S32A is still faster than the default, so use it.
14120060159457453ca45a47828648c8f29d5695983ccommit-bot@chromium.org    S32_D565_Opaque_neon,
1413a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    S32A_D565_Blend_neon,   // really S32_D565_Blend
1414a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    S32A_D565_Opaque_neon,
1415a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    S32A_D565_Blend_neon,
1416a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1417a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    // dither
1418a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    S32_D565_Opaque_Dither_neon,
1419a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    S32_D565_Blend_Dither_neon,
1420a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    S32A_D565_Opaque_Dither_neon,
1421a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    NULL,   // S32A_D565_Blend_Dither
1422a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com};
1423a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com
1424a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.comconst SkBlitRow::Proc32 sk_blitrow_platform_32_procs_arm_neon[] = {
1425a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com    NULL,   // S32_Opaque,
1426fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    S32_Blend_BlitRow32_neon,        // S32_Blend,
1427c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    /*
1428c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com     * We have two choices for S32A_Opaque procs. The one reads the src alpha
1429c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com     * value and attempts to optimize accordingly.  The optimization is
1430c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com     * sensitive to the source content and is not a win in all cases. For
1431c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com     * example, if there are a lot of transitions between the alpha states,
1432c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com     * the performance will almost certainly be worse.  However, for many
1433c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com     * common cases the performance is equivalent or better than the standard
1434c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com     * case where we do not inspect the src alpha.
1435c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com     */
1436c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com#if SK_A32_SHIFT == 24
1437c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    // This proc assumes the alpha value occupies bits 24-32 of each SkPMColor
1438c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    S32A_Opaque_BlitRow32_neon_src_alpha,   // S32A_Opaque,
1439c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com#else
1440c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com    S32A_Opaque_BlitRow32_neon,     // S32A_Opaque,
1441c2532dd0b89e03ed158229872cb1ee06ae7f10fedjsollen@google.com#endif
14421fdc6774280ffc18dd7e1247e430931aa2f58790commit-bot@chromium.org    S32A_Blend_BlitRow32_neon        // S32A_Blend
1443a8dd1ce930811a51cc841f583424d507d95e7e78digit@google.com};
1444