1/*
2 * Copyright 2014 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8
9#include "SkBitmapProcState.h"
10#include "SkBitmapScaler.h"
11#include "SkColorPriv.h"
12#include "SkPaint.h"
13#include "SkUtils.h"
14
15static void SI8_D16_nofilter_DX_mips_dsp(const SkBitmapProcState& s,
16                                         const uint32_t* SK_RESTRICT xy,
17                                         int count, uint16_t* SK_RESTRICT colors) {
18    SkASSERT(count > 0 && colors != NULL);
19    SkASSERT(s.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask));
20    SkASSERT(kNone_SkFilterQuality == s.fFilterLevel);
21    const uint16_t* SK_RESTRICT table = s.fBitmap->getColorTable()->read16BitCache();
22    const uint8_t* SK_RESTRICT srcAddr = (const uint8_t*)s.fBitmap->getPixels();
23    SkASSERT((unsigned)xy[0] < (unsigned)s.fBitmap->height());
24    srcAddr = (const uint8_t*)((const char*)srcAddr + xy[0] * s.fBitmap->rowBytes());
25    uint8_t src;
26
27    if (1 == s.fBitmap->width()) {
28        src = srcAddr[0];
29        uint16_t dstValue = table[src];
30        sk_memset16(colors, dstValue, count);
31    } else {
32        int count8;
33        const uint16_t* SK_RESTRICT xx = (const uint16_t*)(xy + 1);
34
35        __asm__ volatile (
36            ".set    push                                \n\t"
37            ".set    noreorder                           \n\t"
38            ".set    noat                                \n\t"
39            "sra     %[count8], %[count],      3         \n\t"
40            "beqz    %[count8], 3f                       \n\t"
41            " addiu  %[count8], %[count8],     -1        \n\t"
42        "1:                                              \n\t"
43            "beqz    %[count8], 2f                       \n\t"
44            " addiu  %[count8], %[count8],     -1        \n\t"
45            "pref    0,         16(%[xx])                \n\t"
46            "lhu     $t0,       0(%[xx])                 \n\t"
47            "lhu     $t1,       2(%[xx])                 \n\t"
48            "lhu     $t2,       4(%[xx])                 \n\t"
49            "lhu     $t3,       6(%[xx])                 \n\t"
50            "lhu     $t4,       8(%[xx])                 \n\t"
51            "lhu     $t5,       10(%[xx])                \n\t"
52            "lhu     $t6,       12(%[xx])                \n\t"
53            "lhu     $t7,       14(%[xx])                \n\t"
54            "pref    0,         8(%[srcAddr])            \n\t"
55            "lbux    $t0,       $t0(%[srcAddr])          \n\t"
56            "lbux    $t1,       $t1(%[srcAddr])          \n\t"
57            "lbux    $t2,       $t2(%[srcAddr])          \n\t"
58            "lbux    $t3,       $t3(%[srcAddr])          \n\t"
59            "lbux    $t4,       $t4(%[srcAddr])          \n\t"
60            "lbux    $t5,       $t5(%[srcAddr])          \n\t"
61            "lbux    $t6,       $t6(%[srcAddr])          \n\t"
62            "lbux    $t7,       $t7(%[srcAddr])          \n\t"
63            "addu    $t0,       $t0,           $t0       \n\t"
64            "addu    $t1,       $t1,           $t1       \n\t"
65            "addu    $t2,       $t2,           $t2       \n\t"
66            "addu    $t3,       $t3,           $t3       \n\t"
67            "addu    $t4,       $t4,           $t4       \n\t"
68            "addu    $t5,       $t5,           $t5       \n\t"
69            "addu    $t6,       $t6,           $t6       \n\t"
70            "addu    $t7,       $t7,           $t7       \n\t"
71            "pref    0,         16(%[table])             \n\t"
72            "lhx     $t0,       $t0(%[table])            \n\t"
73            "lhx     $t1,       $t1(%[table])            \n\t"
74            "lhx     $t2,       $t2(%[table])            \n\t"
75            "lhx     $t3,       $t3(%[table])            \n\t"
76            "lhx     $t4,       $t4(%[table])            \n\t"
77            "lhx     $t5,       $t5(%[table])            \n\t"
78            "lhx     $t6,       $t6(%[table])            \n\t"
79            "lhx     $t7,       $t7(%[table])            \n\t"
80            "sh      $t0,       0(%[colors])             \n\t"
81            "sh      $t1,       2(%[colors])             \n\t"
82            "sh      $t2,       4(%[colors])             \n\t"
83            "sh      $t3,       6(%[colors])             \n\t"
84            "sh      $t4,       8(%[colors])             \n\t"
85            "sh      $t5,       10(%[colors])            \n\t"
86            "sh      $t6,       12(%[colors])            \n\t"
87            "sh      $t7,       14(%[colors])            \n\t"
88            "addiu   %[xx],     %[xx],         16        \n\t"
89            "bgtz    %[count8], 1b                       \n\t"
90            " addiu  %[colors], %[colors],     16        \n\t"
91        "2:                                              \n\t"
92            "lhu     $t0,       0(%[xx])                 \n\t"
93            "lhu     $t1,       2(%[xx])                 \n\t"
94            "lhu     $t2,       4(%[xx])                 \n\t"
95            "lhu     $t3,       6(%[xx])                 \n\t"
96            "lhu     $t4,       8(%[xx])                 \n\t"
97            "lhu     $t5,       10(%[xx])                \n\t"
98            "lhu     $t6,       12(%[xx])                \n\t"
99            "lhu     $t7,       14(%[xx])                \n\t"
100            "lbux    $t0,       $t0(%[srcAddr])          \n\t"
101            "lbux    $t1,       $t1(%[srcAddr])          \n\t"
102            "lbux    $t2,       $t2(%[srcAddr])          \n\t"
103            "lbux    $t3,       $t3(%[srcAddr])          \n\t"
104            "lbux    $t4,       $t4(%[srcAddr])          \n\t"
105            "lbux    $t5,       $t5(%[srcAddr])          \n\t"
106            "lbux    $t6,       $t6(%[srcAddr])          \n\t"
107            "lbux    $t7,       $t7(%[srcAddr])          \n\t"
108            "addu    $t0,       $t0,           $t0       \n\t"
109            "addu    $t1,       $t1,           $t1       \n\t"
110            "addu    $t2,       $t2,           $t2       \n\t"
111            "addu    $t3,       $t3,           $t3       \n\t"
112            "addu    $t4,       $t4,           $t4       \n\t"
113            "addu    $t5,       $t5,           $t5       \n\t"
114            "addu    $t6,       $t6,           $t6       \n\t"
115            "addu    $t7,       $t7,           $t7       \n\t"
116            "lhx     $t0,       $t0(%[table])            \n\t"
117            "lhx     $t1,       $t1(%[table])            \n\t"
118            "lhx     $t2,       $t2(%[table])            \n\t"
119            "lhx     $t3,       $t3(%[table])            \n\t"
120            "lhx     $t4,       $t4(%[table])            \n\t"
121            "lhx     $t5,       $t5(%[table])            \n\t"
122            "lhx     $t6,       $t6(%[table])            \n\t"
123            "lhx     $t7,       $t7(%[table])            \n\t"
124            "sh      $t0,       0(%[colors])             \n\t"
125            "sh      $t1,       2(%[colors])             \n\t"
126            "sh      $t2,       4(%[colors])             \n\t"
127            "sh      $t3,       6(%[colors])             \n\t"
128            "sh      $t4,       8(%[colors])             \n\t"
129            "sh      $t5,       10(%[colors])            \n\t"
130            "sh      $t6,       12(%[colors])            \n\t"
131            "sh      $t7,       14(%[colors])            \n\t"
132            "addiu   %[xx],     %[xx],         16        \n\t"
133            "addiu   %[colors], %[colors],     16        \n\t"
134        "3:                                              \n\t"
135            ".set    pop                                 \n\t"
136            : [xx]"+r"(xx), [count8]"=&r"(count8), [colors]"+r"(colors)
137            : [table]"r"(table), [srcAddr]"r"(srcAddr), [count]"r"(count)
138            : "memory","t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"
139        );
140
141        for (int i = (count & 7); i > 0; --i) {
142            src = srcAddr[*xx++]; *colors++ = table[src];
143        }
144    }
145}
146
147static void SI8_opaque_D32_nofilter_DX_mips_dsp(const SkBitmapProcState& s,
148                                                const uint32_t* SK_RESTRICT xy,
149                                                int count, SkPMColor* SK_RESTRICT colors) {
150    SkASSERT(count > 0 && colors != NULL);
151    SkASSERT(s.fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask));
152    SkASSERT(kNone_SkFilterQuality == s.fFilterLevel);
153    const SkPMColor* SK_RESTRICT table = s.fBitmap->getColorTable()->readColors();
154    const uint8_t* SK_RESTRICT srcAddr = (const uint8_t*)s.fBitmap->getPixels();
155    srcAddr = (const uint8_t*)((const char*)srcAddr + xy[0] * s.fBitmap->rowBytes());
156
157    if (1 == s.fBitmap->width()) {
158        uint8_t src = srcAddr[0];
159        SkPMColor dstValue = table[src];
160        sk_memset32(colors, dstValue, count);
161    } else {
162        const uint16_t* xx = (const uint16_t*)(xy + 1);
163        int s0, s1, s2, s3, s4, s5, s6, s7;
164        __asm__ volatile (
165            ".set    push                                \n\t"
166            ".set    noreorder                           \n\t"
167            ".set    noat                                \n\t"
168            "srl     $t8,       %[count],    4           \n\t"
169            "beqz    $t8,       3f                       \n\t"
170            " nop                                        \n\t"
171        "1:                                              \n\t"
172            "addiu   $t8,       $t8,         -1          \n\t"
173            "beqz    $t8,       2f                       \n\t"
174            " addiu  %[count],  %[count],    -16         \n\t"
175            "pref    0,         32(%[xx])                \n\t"
176            "lhu     $t0,       0(%[xx])                 \n\t"
177            "lhu     $t1,       2(%[xx])                 \n\t"
178            "lhu     $t2,       4(%[xx])                 \n\t"
179            "lhu     $t3,       6(%[xx])                 \n\t"
180            "lhu     $t4,       8(%[xx])                 \n\t"
181            "lhu     $t5,       10(%[xx])                \n\t"
182            "lhu     $t6,       12(%[xx])                \n\t"
183            "lhu     $t7,       14(%[xx])                \n\t"
184            "lhu     %[s0],     16(%[xx])                \n\t"
185            "lhu     %[s1],     18(%[xx])                \n\t"
186            "lhu     %[s2],     20(%[xx])                \n\t"
187            "lhu     %[s3],     22(%[xx])                \n\t"
188            "lhu     %[s4],     24(%[xx])                \n\t"
189            "lhu     %[s5],     26(%[xx])                \n\t"
190            "lhu     %[s6],     28(%[xx])                \n\t"
191            "lhu     %[s7],     30(%[xx])                \n\t"
192            "lbux    $t0,       $t0(%[srcAddr])          \n\t"
193            "lbux    $t1,       $t1(%[srcAddr])          \n\t"
194            "lbux    $t2,       $t2(%[srcAddr])          \n\t"
195            "lbux    $t3,       $t3(%[srcAddr])          \n\t"
196            "lbux    $t4,       $t4(%[srcAddr])          \n\t"
197            "lbux    $t5,       $t5(%[srcAddr])          \n\t"
198            "lbux    $t6,       $t6(%[srcAddr])          \n\t"
199            "lbux    $t7,       $t7(%[srcAddr])          \n\t"
200            "lbux    %[s0],     %[s0](%[srcAddr])        \n\t"
201            "lbux    %[s1],     %[s1](%[srcAddr])        \n\t"
202            "lbux    %[s2],     %[s2](%[srcAddr])        \n\t"
203            "lbux    %[s3],     %[s3](%[srcAddr])        \n\t"
204            "lbux    %[s4],     %[s4](%[srcAddr])        \n\t"
205            "lbux    %[s5],     %[s5](%[srcAddr])        \n\t"
206            "lbux    %[s6],     %[s6](%[srcAddr])        \n\t"
207            "lbux    %[s7],     %[s7](%[srcAddr])        \n\t"
208            "sll     $t0,       $t0,         2           \n\t"
209            "sll     $t1,       $t1,         2           \n\t"
210            "sll     $t2,       $t2,         2           \n\t"
211            "sll     $t3,       $t3,         2           \n\t"
212            "sll     $t4,       $t4,         2           \n\t"
213            "sll     $t5,       $t5,         2           \n\t"
214            "sll     $t6,       $t6,         2           \n\t"
215            "sll     $t7,       $t7,         2           \n\t"
216            "sll     %[s0],     %[s0],       2           \n\t"
217            "sll     %[s1],     %[s1],       2           \n\t"
218            "sll     %[s2],     %[s2],       2           \n\t"
219            "sll     %[s3],     %[s3],       2           \n\t"
220            "sll     %[s4],     %[s4],       2           \n\t"
221            "sll     %[s5],     %[s5],       2           \n\t"
222            "sll     %[s6],     %[s6],       2           \n\t"
223            "sll     %[s7],     %[s7],       2           \n\t"
224            "pref    0,         64(%[table])             \n\t"
225            "lwx     $t0,       $t0(%[table])            \n\t"
226            "lwx     $t1,       $t1(%[table])            \n\t"
227            "lwx     $t2,       $t2(%[table])            \n\t"
228            "lwx     $t3,       $t3(%[table])            \n\t"
229            "lwx     $t4,       $t4(%[table])            \n\t"
230            "lwx     $t5,       $t5(%[table])            \n\t"
231            "lwx     $t6,       $t6(%[table])            \n\t"
232            "lwx     $t7,       $t7(%[table])            \n\t"
233            "lwx     %[s0],     %[s0](%[table])          \n\t"
234            "lwx     %[s1],     %[s1](%[table])          \n\t"
235            "lwx     %[s2],     %[s2](%[table])          \n\t"
236            "lwx     %[s3],     %[s3](%[table])          \n\t"
237            "lwx     %[s4],     %[s4](%[table])          \n\t"
238            "lwx     %[s5],     %[s5](%[table])          \n\t"
239            "lwx     %[s6],     %[s6](%[table])          \n\t"
240            "lwx     %[s7],     %[s7](%[table])          \n\t"
241            "pref    30,        64(%[colors])            \n\t"
242            "sw      $t0,       0(%[colors])             \n\t"
243            "sw      $t1,       4(%[colors])             \n\t"
244            "sw      $t2,       8(%[colors])             \n\t"
245            "sw      $t3,       12(%[colors])            \n\t"
246            "sw      $t4,       16(%[colors])            \n\t"
247            "sw      $t5,       20(%[colors])            \n\t"
248            "sw      $t6,       24(%[colors])            \n\t"
249            "sw      $t7,       28(%[colors])            \n\t"
250            "sw      %[s0],     32(%[colors])            \n\t"
251            "sw      %[s1],     36(%[colors])            \n\t"
252            "sw      %[s2],     40(%[colors])            \n\t"
253            "sw      %[s3],     44(%[colors])            \n\t"
254            "sw      %[s4],     48(%[colors])            \n\t"
255            "sw      %[s5],     52(%[colors])            \n\t"
256            "sw      %[s6],     56(%[colors])            \n\t"
257            "sw      %[s7],     60(%[colors])            \n\t"
258            "addiu   %[xx],     %[xx],       32          \n\t"
259            "b       1b                                  \n\t"
260            " addiu  %[colors], %[colors],   64          \n\t"
261        "2:                                              \n\t"
262            "lhu     $t0,       0(%[xx])                 \n\t"
263            "lhu     $t1,       2(%[xx])                 \n\t"
264            "lhu     $t2,       4(%[xx])                 \n\t"
265            "lhu     $t3,       6(%[xx])                 \n\t"
266            "lhu     $t4,       8(%[xx])                 \n\t"
267            "lhu     $t5,       10(%[xx])                \n\t"
268            "lhu     $t6,       12(%[xx])                \n\t"
269            "lhu     $t7,       14(%[xx])                \n\t"
270            "lhu     %[s0],     16(%[xx])                \n\t"
271            "lhu     %[s1],     18(%[xx])                \n\t"
272            "lhu     %[s2],     20(%[xx])                \n\t"
273            "lhu     %[s3],     22(%[xx])                \n\t"
274            "lhu     %[s4],     24(%[xx])                \n\t"
275            "lhu     %[s5],     26(%[xx])                \n\t"
276            "lhu     %[s6],     28(%[xx])                \n\t"
277            "lhu     %[s7],     30(%[xx])                \n\t"
278            "lbux    $t0,       $t0(%[srcAddr])          \n\t"
279            "lbux    $t1,       $t1(%[srcAddr])          \n\t"
280            "lbux    $t2,       $t2(%[srcAddr])          \n\t"
281            "lbux    $t3,       $t3(%[srcAddr])          \n\t"
282            "lbux    $t4,       $t4(%[srcAddr])          \n\t"
283            "lbux    $t5,       $t5(%[srcAddr])          \n\t"
284            "lbux    $t6,       $t6(%[srcAddr])          \n\t"
285            "lbux    $t7,       $t7(%[srcAddr])          \n\t"
286            "lbux    %[s0],     %[s0](%[srcAddr])        \n\t"
287            "lbux    %[s1],     %[s1](%[srcAddr])        \n\t"
288            "lbux    %[s2],     %[s2](%[srcAddr])        \n\t"
289            "lbux    %[s3],     %[s3](%[srcAddr])        \n\t"
290            "lbux    %[s4],     %[s4](%[srcAddr])        \n\t"
291            "lbux    %[s5],     %[s5](%[srcAddr])        \n\t"
292            "lbux    %[s6],     %[s6](%[srcAddr])        \n\t"
293            "lbux    %[s7],     %[s7](%[srcAddr])        \n\t"
294            "sll     $t0,       $t0,         2           \n\t"
295            "sll     $t1,       $t1,         2           \n\t"
296            "sll     $t2,       $t2,         2           \n\t"
297            "sll     $t3,       $t3,         2           \n\t"
298            "sll     $t4,       $t4,         2           \n\t"
299            "sll     $t5,       $t5,         2           \n\t"
300            "sll     $t6,       $t6,         2           \n\t"
301            "sll     $t7,       $t7,         2           \n\t"
302            "sll     %[s0],     %[s0],       2           \n\t"
303            "sll     %[s1],     %[s1],       2           \n\t"
304            "sll     %[s2],     %[s2],       2           \n\t"
305            "sll     %[s3],     %[s3],       2           \n\t"
306            "sll     %[s4],     %[s4],       2           \n\t"
307            "sll     %[s5],     %[s5],       2           \n\t"
308            "sll     %[s6],     %[s6],       2           \n\t"
309            "sll     %[s7],     %[s7],       2           \n\t"
310            "lwx     $t0,       $t0(%[table])            \n\t"
311            "lwx     $t1,       $t1(%[table])            \n\t"
312            "lwx     $t2,       $t2(%[table])            \n\t"
313            "lwx     $t3,       $t3(%[table])            \n\t"
314            "lwx     $t4,       $t4(%[table])            \n\t"
315            "lwx     $t5,       $t5(%[table])            \n\t"
316            "lwx     $t6,       $t6(%[table])            \n\t"
317            "lwx     $t7,       $t7(%[table])            \n\t"
318            "lwx     %[s0],     %[s0](%[table])          \n\t"
319            "lwx     %[s1],     %[s1](%[table])          \n\t"
320            "lwx     %[s2],     %[s2](%[table])          \n\t"
321            "lwx     %[s3],     %[s3](%[table])          \n\t"
322            "lwx     %[s4],     %[s4](%[table])          \n\t"
323            "lwx     %[s5],     %[s5](%[table])          \n\t"
324            "lwx     %[s6],     %[s6](%[table])          \n\t"
325            "lwx     %[s7],     %[s7](%[table])          \n\t"
326            "sw      $t0,       0(%[colors])             \n\t"
327            "sw      $t1,       4(%[colors])             \n\t"
328            "sw      $t2,       8(%[colors])             \n\t"
329            "sw      $t3,       12(%[colors])            \n\t"
330            "sw      $t4,       16(%[colors])            \n\t"
331            "sw      $t5,       20(%[colors])            \n\t"
332            "sw      $t6,       24(%[colors])            \n\t"
333            "sw      $t7,       28(%[colors])            \n\t"
334            "sw      %[s0],     32(%[colors])            \n\t"
335            "sw      %[s1],     36(%[colors])            \n\t"
336            "sw      %[s2],     40(%[colors])            \n\t"
337            "sw      %[s3],     44(%[colors])            \n\t"
338            "sw      %[s4],     48(%[colors])            \n\t"
339            "sw      %[s5],     52(%[colors])            \n\t"
340            "sw      %[s6],     56(%[colors])            \n\t"
341            "sw      %[s7],     60(%[colors])            \n\t"
342            "addiu   %[xx],     %[xx],       32          \n\t"
343            "beqz    %[count],  4f                       \n\t"
344            " addiu  %[colors], %[colors],   64          \n\t"
345        "3:                                              \n\t"
346            "addiu   %[count],  %[count],    -1          \n\t"
347            "lhu     $t0,       0(%[xx])                 \n\t"
348            "lbux    $t1,       $t0(%[srcAddr])          \n\t"
349            "sll     $t1,       $t1,         2           \n\t"
350            "lwx     $t2,       $t1(%[table])            \n\t"
351            "sw      $t2,       0(%[colors])             \n\t"
352            "addiu   %[xx],     %[xx],       2           \n\t"
353            "bnez    %[count],  3b                       \n\t"
354            " addiu  %[colors], %[colors],   4           \n\t"
355        "4:                                              \n\t"
356            ".set    pop                                 \n\t"
357            : [xx]"+r"(xx), [count]"+r"(count), [colors]"+r"(colors),
358              [s0]"=&r"(s0), [s1]"=&r"(s1), [s2]"=&r"(s2), [s3]"=&r"(s3),
359              [s4]"=&r"(s4), [s5]"=&r"(s5), [s6]"=&r"(s6), [s7]"=&r"(s7)
360            : [table]"r"(table), [srcAddr]"r"(srcAddr)
361            : "memory", "t0", "t1", "t2", "t3",
362              "t4", "t5", "t6", "t7", "t8"
363        );
364    }
365}
366
367/*  If we replace a sampleproc, then we null-out the associated shaderproc,
368    otherwise the shader won't even look at the matrix/sampler
369 */
370
371void SkBitmapProcState::platformProcs() {
372    bool isOpaque = 256 == fAlphaScale;
373    bool justDx = false;
374
375    if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
376        justDx = true;
377    }
378
379    switch (fBitmap->colorType()) {
380        case kIndex_8_SkColorType:
381            if (justDx && kNone_SkFilterQuality == fFilterLevel) {
382                fSampleProc16 = SI8_D16_nofilter_DX_mips_dsp;
383                fShaderProc16 = NULL;
384                if (isOpaque) {
385                    fSampleProc32 = SI8_opaque_D32_nofilter_DX_mips_dsp;
386                    fShaderProc32 = NULL;
387                }
388            }
389            break;
390        default:
391            break;
392    }
393}
394
395void SkBitmapScaler::PlatformConvolutionProcs(SkConvolutionProcs*) {}
396