Line data Source code
1 : /*
2 : * Copyright 2009 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 : #include <emmintrin.h>
9 : #include "SkBitmapProcState_opts_SSE2.h"
10 : #include "SkBitmapProcState_utils.h"
11 : #include "SkColorPriv.h"
12 : #include "SkPaint.h"
13 : #include "SkUtils.h"
14 :
15 0 : void S32_opaque_D32_filter_DX_SSE2(const SkBitmapProcState& s,
16 : const uint32_t* xy,
17 : int count, uint32_t* colors) {
18 0 : SkASSERT(count > 0 && colors != nullptr);
19 0 : SkASSERT(s.fFilterQuality != kNone_SkFilterQuality);
20 0 : SkASSERT(kN32_SkColorType == s.fPixmap.colorType());
21 0 : SkASSERT(s.fAlphaScale == 256);
22 :
23 0 : const char* srcAddr = static_cast<const char*>(s.fPixmap.addr());
24 0 : size_t rb = s.fPixmap.rowBytes();
25 0 : uint32_t XY = *xy++;
26 0 : unsigned y0 = XY >> 14;
27 0 : const uint32_t* row0 = reinterpret_cast<const uint32_t*>(srcAddr + (y0 >> 4) * rb);
28 0 : const uint32_t* row1 = reinterpret_cast<const uint32_t*>(srcAddr + (XY & 0x3FFF) * rb);
29 0 : unsigned subY = y0 & 0xF;
30 :
31 : // ( 0, 0, 0, 0, 0, 0, 0, 16)
32 0 : __m128i sixteen = _mm_cvtsi32_si128(16);
33 :
34 : // ( 0, 0, 0, 0, 16, 16, 16, 16)
35 0 : sixteen = _mm_shufflelo_epi16(sixteen, 0);
36 :
37 : // ( 0, 0, 0, 0, 0, 0, 0, y)
38 0 : __m128i allY = _mm_cvtsi32_si128(subY);
39 :
40 : // ( 0, 0, 0, 0, y, y, y, y)
41 0 : allY = _mm_shufflelo_epi16(allY, 0);
42 :
43 : // ( 0, 0, 0, 0, 16-y, 16-y, 16-y, 16-y)
44 0 : __m128i negY = _mm_sub_epi16(sixteen, allY);
45 :
46 : // (16-y, 16-y, 16-y, 16-y, y, y, y, y)
47 0 : allY = _mm_unpacklo_epi64(allY, negY);
48 :
49 : // (16, 16, 16, 16, 16, 16, 16, 16 )
50 0 : sixteen = _mm_shuffle_epi32(sixteen, 0);
51 :
52 : // ( 0, 0, 0, 0, 0, 0, 0, 0)
53 0 : __m128i zero = _mm_setzero_si128();
54 0 : do {
55 0 : uint32_t XX = *xy++; // x0:14 | 4 | x1:14
56 0 : unsigned x0 = XX >> 18;
57 0 : unsigned x1 = XX & 0x3FFF;
58 :
59 : // (0, 0, 0, 0, 0, 0, 0, x)
60 0 : __m128i allX = _mm_cvtsi32_si128((XX >> 14) & 0x0F);
61 :
62 : // (0, 0, 0, 0, x, x, x, x)
63 0 : allX = _mm_shufflelo_epi16(allX, 0);
64 :
65 : // (x, x, x, x, x, x, x, x)
66 0 : allX = _mm_shuffle_epi32(allX, 0);
67 :
68 : // (16-x, 16-x, 16-x, 16-x, 16-x, 16-x, 16-x)
69 0 : __m128i negX = _mm_sub_epi16(sixteen, allX);
70 :
71 : // Load 4 samples (pixels).
72 0 : __m128i a00 = _mm_cvtsi32_si128(row0[x0]);
73 0 : __m128i a01 = _mm_cvtsi32_si128(row0[x1]);
74 0 : __m128i a10 = _mm_cvtsi32_si128(row1[x0]);
75 0 : __m128i a11 = _mm_cvtsi32_si128(row1[x1]);
76 :
77 : // (0, 0, a00, a10)
78 0 : __m128i a00a10 = _mm_unpacklo_epi32(a10, a00);
79 :
80 : // Expand to 16 bits per component.
81 0 : a00a10 = _mm_unpacklo_epi8(a00a10, zero);
82 :
83 : // ((a00 * (16-y)), (a10 * y)).
84 0 : a00a10 = _mm_mullo_epi16(a00a10, allY);
85 :
86 : // (a00 * (16-y) * (16-x), a10 * y * (16-x)).
87 0 : a00a10 = _mm_mullo_epi16(a00a10, negX);
88 :
89 : // (0, 0, a01, a10)
90 0 : __m128i a01a11 = _mm_unpacklo_epi32(a11, a01);
91 :
92 : // Expand to 16 bits per component.
93 0 : a01a11 = _mm_unpacklo_epi8(a01a11, zero);
94 :
95 : // (a01 * (16-y)), (a11 * y)
96 0 : a01a11 = _mm_mullo_epi16(a01a11, allY);
97 :
98 : // (a01 * (16-y) * x), (a11 * y * x)
99 0 : a01a11 = _mm_mullo_epi16(a01a11, allX);
100 :
101 : // (a00*w00 + a01*w01, a10*w10 + a11*w11)
102 0 : __m128i sum = _mm_add_epi16(a00a10, a01a11);
103 :
104 : // (DC, a00*w00 + a01*w01)
105 0 : __m128i shifted = _mm_shuffle_epi32(sum, 0xEE);
106 :
107 : // (DC, a00*w00 + a01*w01 + a10*w10 + a11*w11)
108 0 : sum = _mm_add_epi16(sum, shifted);
109 :
110 : // Divide each 16 bit component by 256.
111 0 : sum = _mm_srli_epi16(sum, 8);
112 :
113 : // Pack lower 4 16 bit values of sum into lower 4 bytes.
114 0 : sum = _mm_packus_epi16(sum, zero);
115 :
116 : // Extract low int and store.
117 0 : *colors++ = _mm_cvtsi128_si32(sum);
118 : } while (--count > 0);
119 0 : }
120 :
121 0 : void S32_alpha_D32_filter_DX_SSE2(const SkBitmapProcState& s,
122 : const uint32_t* xy,
123 : int count, uint32_t* colors) {
124 0 : SkASSERT(count > 0 && colors != nullptr);
125 0 : SkASSERT(s.fFilterQuality != kNone_SkFilterQuality);
126 0 : SkASSERT(kN32_SkColorType == s.fPixmap.colorType());
127 0 : SkASSERT(s.fAlphaScale < 256);
128 :
129 0 : const char* srcAddr = static_cast<const char*>(s.fPixmap.addr());
130 0 : size_t rb = s.fPixmap.rowBytes();
131 0 : uint32_t XY = *xy++;
132 0 : unsigned y0 = XY >> 14;
133 0 : const uint32_t* row0 = reinterpret_cast<const uint32_t*>(srcAddr + (y0 >> 4) * rb);
134 0 : const uint32_t* row1 = reinterpret_cast<const uint32_t*>(srcAddr + (XY & 0x3FFF) * rb);
135 0 : unsigned subY = y0 & 0xF;
136 :
137 : // ( 0, 0, 0, 0, 0, 0, 0, 16)
138 0 : __m128i sixteen = _mm_cvtsi32_si128(16);
139 :
140 : // ( 0, 0, 0, 0, 16, 16, 16, 16)
141 0 : sixteen = _mm_shufflelo_epi16(sixteen, 0);
142 :
143 : // ( 0, 0, 0, 0, 0, 0, 0, y)
144 0 : __m128i allY = _mm_cvtsi32_si128(subY);
145 :
146 : // ( 0, 0, 0, 0, y, y, y, y)
147 0 : allY = _mm_shufflelo_epi16(allY, 0);
148 :
149 : // ( 0, 0, 0, 0, 16-y, 16-y, 16-y, 16-y)
150 0 : __m128i negY = _mm_sub_epi16(sixteen, allY);
151 :
152 : // (16-y, 16-y, 16-y, 16-y, y, y, y, y)
153 0 : allY = _mm_unpacklo_epi64(allY, negY);
154 :
155 : // (16, 16, 16, 16, 16, 16, 16, 16 )
156 0 : sixteen = _mm_shuffle_epi32(sixteen, 0);
157 :
158 : // ( 0, 0, 0, 0, 0, 0, 0, 0)
159 0 : __m128i zero = _mm_setzero_si128();
160 :
161 : // ( alpha, alpha, alpha, alpha, alpha, alpha, alpha, alpha )
162 0 : __m128i alpha = _mm_set1_epi16(s.fAlphaScale);
163 :
164 0 : do {
165 0 : uint32_t XX = *xy++; // x0:14 | 4 | x1:14
166 0 : unsigned x0 = XX >> 18;
167 0 : unsigned x1 = XX & 0x3FFF;
168 :
169 : // (0, 0, 0, 0, 0, 0, 0, x)
170 0 : __m128i allX = _mm_cvtsi32_si128((XX >> 14) & 0x0F);
171 :
172 : // (0, 0, 0, 0, x, x, x, x)
173 0 : allX = _mm_shufflelo_epi16(allX, 0);
174 :
175 : // (x, x, x, x, x, x, x, x)
176 0 : allX = _mm_shuffle_epi32(allX, 0);
177 :
178 : // (16-x, 16-x, 16-x, 16-x, 16-x, 16-x, 16-x)
179 0 : __m128i negX = _mm_sub_epi16(sixteen, allX);
180 :
181 : // Load 4 samples (pixels).
182 0 : __m128i a00 = _mm_cvtsi32_si128(row0[x0]);
183 0 : __m128i a01 = _mm_cvtsi32_si128(row0[x1]);
184 0 : __m128i a10 = _mm_cvtsi32_si128(row1[x0]);
185 0 : __m128i a11 = _mm_cvtsi32_si128(row1[x1]);
186 :
187 : // (0, 0, a00, a10)
188 0 : __m128i a00a10 = _mm_unpacklo_epi32(a10, a00);
189 :
190 : // Expand to 16 bits per component.
191 0 : a00a10 = _mm_unpacklo_epi8(a00a10, zero);
192 :
193 : // ((a00 * (16-y)), (a10 * y)).
194 0 : a00a10 = _mm_mullo_epi16(a00a10, allY);
195 :
196 : // (a00 * (16-y) * (16-x), a10 * y * (16-x)).
197 0 : a00a10 = _mm_mullo_epi16(a00a10, negX);
198 :
199 : // (0, 0, a01, a10)
200 0 : __m128i a01a11 = _mm_unpacklo_epi32(a11, a01);
201 :
202 : // Expand to 16 bits per component.
203 0 : a01a11 = _mm_unpacklo_epi8(a01a11, zero);
204 :
205 : // (a01 * (16-y)), (a11 * y)
206 0 : a01a11 = _mm_mullo_epi16(a01a11, allY);
207 :
208 : // (a01 * (16-y) * x), (a11 * y * x)
209 0 : a01a11 = _mm_mullo_epi16(a01a11, allX);
210 :
211 : // (a00*w00 + a01*w01, a10*w10 + a11*w11)
212 0 : __m128i sum = _mm_add_epi16(a00a10, a01a11);
213 :
214 : // (DC, a00*w00 + a01*w01)
215 0 : __m128i shifted = _mm_shuffle_epi32(sum, 0xEE);
216 :
217 : // (DC, a00*w00 + a01*w01 + a10*w10 + a11*w11)
218 0 : sum = _mm_add_epi16(sum, shifted);
219 :
220 : // Divide each 16 bit component by 256.
221 0 : sum = _mm_srli_epi16(sum, 8);
222 :
223 : // Multiply by alpha.
224 0 : sum = _mm_mullo_epi16(sum, alpha);
225 :
226 : // Divide each 16 bit component by 256.
227 0 : sum = _mm_srli_epi16(sum, 8);
228 :
229 : // Pack lower 4 16 bit values of sum into lower 4 bytes.
230 0 : sum = _mm_packus_epi16(sum, zero);
231 :
232 : // Extract low int and store.
233 0 : *colors++ = _mm_cvtsi128_si32(sum);
234 : } while (--count > 0);
235 0 : }
236 :
237 2342 : static inline uint32_t ClampX_ClampY_pack_filter(SkFixed f, unsigned max,
238 : SkFixed one) {
239 2342 : unsigned i = SkClampMax(f >> 16, max);
240 2342 : i = (i << 4) | ((f >> 12) & 0xF);
241 2342 : return (i << 14) | SkClampMax((f + one) >> 16, max);
242 : }
243 :
244 : /* SSE version of ClampX_ClampY_filter_scale()
245 : * portable version is in core/SkBitmapProcState_matrix.h
246 : */
247 726 : void ClampX_ClampY_filter_scale_SSE2(const SkBitmapProcState& s, uint32_t xy[],
248 : int count, int x, int y) {
249 726 : SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
250 : SkMatrix::kScale_Mask)) == 0);
251 726 : SkASSERT(s.fInvKy == 0);
252 :
253 726 : const unsigned maxX = s.fPixmap.width() - 1;
254 726 : const SkFixed one = s.fFilterOneX;
255 726 : const SkFixed dx = s.fInvSx;
256 :
257 726 : const SkBitmapProcStateAutoMapper mapper(s, x, y);
258 726 : const SkFixed fy = mapper.fixedY();
259 726 : const unsigned maxY = s.fPixmap.height() - 1;
260 : // compute our two Y values up front
261 726 : *xy++ = ClampX_ClampY_pack_filter(fy, maxY, s.fFilterOneY);
262 : // now initialize fx
263 726 : SkFixed fx = mapper.fixedX();
264 :
265 : // test if we don't need to apply the tile proc
266 726 : if (can_truncate_to_fixed_for_decal(fx, dx, count, maxX)) {
267 246 : if (count >= 4) {
268 : // SSE version of decal_filter_scale
269 1281 : while ((size_t(xy) & 0x0F) != 0) {
270 549 : SkASSERT((fx >> (16 + 14)) == 0);
271 549 : *xy++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
272 549 : fx += dx;
273 549 : count--;
274 : }
275 :
276 183 : __m128i wide_1 = _mm_set1_epi32(1);
277 366 : __m128i wide_dx4 = _mm_set1_epi32(dx * 4);
278 183 : __m128i wide_fx = _mm_set_epi32(fx + dx * 3, fx + dx * 2,
279 183 : fx + dx, fx);
280 :
281 1311 : while (count >= 4) {
282 : __m128i wide_out;
283 :
284 1128 : wide_out = _mm_slli_epi32(_mm_srai_epi32(wide_fx, 12), 14);
285 1128 : wide_out = _mm_or_si128(wide_out, _mm_add_epi32(
286 564 : _mm_srai_epi32(wide_fx, 16), wide_1));
287 :
288 : _mm_store_si128(reinterpret_cast<__m128i*>(xy), wide_out);
289 :
290 564 : xy += 4;
291 564 : fx += dx * 4;
292 564 : wide_fx = _mm_add_epi32(wide_fx, wide_dx4);
293 564 : count -= 4;
294 : } // while count >= 4
295 : } // if count >= 4
296 :
297 786 : while (count-- > 0) {
298 270 : SkASSERT((fx >> (16 + 14)) == 0);
299 270 : *xy++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
300 270 : fx += dx;
301 : }
302 : } else {
303 : // SSE2 only support 16bit interger max & min, so only process the case
304 : // maxX less than the max 16bit interger. Actually maxX is the bitmap's
305 : // height, there should be rare bitmap whose height will be greater
306 : // than max 16bit interger in the real world.
307 480 : if ((count >= 4) && (maxX <= 0xFFFF)) {
308 2576 : while (((size_t)xy & 0x0F) != 0) {
309 1104 : *xy++ = ClampX_ClampY_pack_filter(fx, maxX, one);
310 1104 : fx += dx;
311 1104 : count--;
312 : }
313 :
314 368 : __m128i wide_fx = _mm_set_epi32(fx + dx * 3, fx + dx * 2,
315 368 : fx + dx, fx);
316 736 : __m128i wide_dx4 = _mm_set1_epi32(dx * 4);
317 368 : __m128i wide_one = _mm_set1_epi32(one);
318 736 : __m128i wide_maxX = _mm_set1_epi32(maxX);
319 368 : __m128i wide_mask = _mm_set1_epi32(0xF);
320 :
321 2608 : while (count >= 4) {
322 : __m128i wide_i;
323 : __m128i wide_lo;
324 : __m128i wide_fx1;
325 :
326 : // i = SkClampMax(f>>16,maxX)
327 2240 : wide_i = _mm_max_epi16(_mm_srli_epi32(wide_fx, 16),
328 1120 : _mm_setzero_si128());
329 1120 : wide_i = _mm_min_epi16(wide_i, wide_maxX);
330 :
331 : // i<<4 | EXTRACT_LOW_BITS(fx)
332 1120 : wide_lo = _mm_srli_epi32(wide_fx, 12);
333 1120 : wide_lo = _mm_and_si128(wide_lo, wide_mask);
334 1120 : wide_i = _mm_slli_epi32(wide_i, 4);
335 1120 : wide_i = _mm_or_si128(wide_i, wide_lo);
336 :
337 : // i<<14
338 1120 : wide_i = _mm_slli_epi32(wide_i, 14);
339 :
340 : // SkClampMax(((f+one))>>16,max)
341 1120 : wide_fx1 = _mm_add_epi32(wide_fx, wide_one);
342 2240 : wide_fx1 = _mm_max_epi16(_mm_srli_epi32(wide_fx1, 16),
343 1120 : _mm_setzero_si128());
344 1120 : wide_fx1 = _mm_min_epi16(wide_fx1, wide_maxX);
345 :
346 : // final combination
347 1120 : wide_i = _mm_or_si128(wide_i, wide_fx1);
348 : _mm_store_si128(reinterpret_cast<__m128i*>(xy), wide_i);
349 :
350 1120 : wide_fx = _mm_add_epi32(wide_fx, wide_dx4);
351 1120 : fx += dx * 4;
352 1120 : xy += 4;
353 1120 : count -= 4;
354 : } // while count >= 4
355 : } // if count >= 4
356 :
357 1504 : while (count-- > 0) {
358 512 : *xy++ = ClampX_ClampY_pack_filter(fx, maxX, one);
359 512 : fx += dx;
360 : }
361 : }
362 726 : }
363 :
364 : /* SSE version of ClampX_ClampY_nofilter_scale()
365 : * portable version is in core/SkBitmapProcState_matrix.h
366 : */
367 0 : void ClampX_ClampY_nofilter_scale_SSE2(const SkBitmapProcState& s,
368 : uint32_t xy[], int count, int x, int y) {
369 0 : SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
370 : SkMatrix::kScale_Mask)) == 0);
371 :
372 : // we store y, x, x, x, x, x
373 0 : const unsigned maxX = s.fPixmap.width() - 1;
374 0 : const SkBitmapProcStateAutoMapper mapper(s, x, y);
375 0 : const unsigned maxY = s.fPixmap.height() - 1;
376 0 : *xy++ = SkClampMax(mapper.intY(), maxY);
377 0 : SkFixed fx = mapper.fixedX();
378 :
379 0 : if (0 == maxX) {
380 : // all of the following X values must be 0
381 0 : memset(xy, 0, count * sizeof(uint16_t));
382 0 : return;
383 : }
384 :
385 0 : const SkFixed dx = s.fInvSx;
386 :
387 : // test if we don't need to apply the tile proc
388 0 : if ((unsigned)(fx >> 16) <= maxX &&
389 0 : (unsigned)((fx + dx * (count - 1)) >> 16) <= maxX) {
390 : // SSE version of decal_nofilter_scale
391 0 : if (count >= 8) {
392 0 : while (((size_t)xy & 0x0F) != 0) {
393 0 : *xy++ = pack_two_shorts(fx >> 16, (fx + dx) >> 16);
394 0 : fx += 2 * dx;
395 0 : count -= 2;
396 : }
397 :
398 0 : __m128i wide_dx4 = _mm_set1_epi32(dx * 4);
399 0 : __m128i wide_dx8 = _mm_add_epi32(wide_dx4, wide_dx4);
400 :
401 0 : __m128i wide_low = _mm_set_epi32(fx + dx * 3, fx + dx * 2,
402 0 : fx + dx, fx);
403 0 : __m128i wide_high = _mm_add_epi32(wide_low, wide_dx4);
404 :
405 0 : while (count >= 8) {
406 0 : __m128i wide_out_low = _mm_srli_epi32(wide_low, 16);
407 0 : __m128i wide_out_high = _mm_srli_epi32(wide_high, 16);
408 :
409 : __m128i wide_result = _mm_packs_epi32(wide_out_low,
410 0 : wide_out_high);
411 : _mm_store_si128(reinterpret_cast<__m128i*>(xy), wide_result);
412 :
413 0 : wide_low = _mm_add_epi32(wide_low, wide_dx8);
414 0 : wide_high = _mm_add_epi32(wide_high, wide_dx8);
415 :
416 0 : xy += 4;
417 0 : fx += dx * 8;
418 0 : count -= 8;
419 : }
420 : } // if count >= 8
421 :
422 0 : uint16_t* xx = reinterpret_cast<uint16_t*>(xy);
423 0 : while (count-- > 0) {
424 0 : *xx++ = SkToU16(fx >> 16);
425 0 : fx += dx;
426 0 : }
427 : } else {
428 : // SSE2 only support 16bit interger max & min, so only process the case
429 : // maxX less than the max 16bit interger. Actually maxX is the bitmap's
430 : // height, there should be rare bitmap whose height will be greater
431 : // than max 16bit interger in the real world.
432 0 : if ((count >= 8) && (maxX <= 0xFFFF)) {
433 0 : while (((size_t)xy & 0x0F) != 0) {
434 0 : *xy++ = pack_two_shorts(SkClampMax((fx + dx) >> 16, maxX),
435 0 : SkClampMax(fx >> 16, maxX));
436 0 : fx += 2 * dx;
437 0 : count -= 2;
438 : }
439 :
440 0 : __m128i wide_dx4 = _mm_set1_epi32(dx * 4);
441 0 : __m128i wide_dx8 = _mm_add_epi32(wide_dx4, wide_dx4);
442 :
443 0 : __m128i wide_low = _mm_set_epi32(fx + dx * 3, fx + dx * 2,
444 0 : fx + dx, fx);
445 0 : __m128i wide_high = _mm_add_epi32(wide_low, wide_dx4);
446 0 : __m128i wide_maxX = _mm_set1_epi32(maxX);
447 :
448 0 : while (count >= 8) {
449 0 : __m128i wide_out_low = _mm_srli_epi32(wide_low, 16);
450 0 : __m128i wide_out_high = _mm_srli_epi32(wide_high, 16);
451 :
452 0 : wide_out_low = _mm_max_epi16(wide_out_low,
453 0 : _mm_setzero_si128());
454 0 : wide_out_low = _mm_min_epi16(wide_out_low, wide_maxX);
455 0 : wide_out_high = _mm_max_epi16(wide_out_high,
456 0 : _mm_setzero_si128());
457 0 : wide_out_high = _mm_min_epi16(wide_out_high, wide_maxX);
458 :
459 : __m128i wide_result = _mm_packs_epi32(wide_out_low,
460 0 : wide_out_high);
461 : _mm_store_si128(reinterpret_cast<__m128i*>(xy), wide_result);
462 :
463 0 : wide_low = _mm_add_epi32(wide_low, wide_dx8);
464 0 : wide_high = _mm_add_epi32(wide_high, wide_dx8);
465 :
466 0 : xy += 4;
467 0 : fx += dx * 8;
468 0 : count -= 8;
469 : }
470 : } // if count >= 8
471 :
472 0 : uint16_t* xx = reinterpret_cast<uint16_t*>(xy);
473 0 : while (count-- > 0) {
474 0 : *xx++ = SkClampMax(fx >> 16, maxX);
475 0 : fx += dx;
476 : }
477 : }
478 : }
479 :
480 : /* SSE version of ClampX_ClampY_filter_affine()
481 : * portable version is in core/SkBitmapProcState_matrix.h
482 : */
483 0 : void ClampX_ClampY_filter_affine_SSE2(const SkBitmapProcState& s,
484 : uint32_t xy[], int count, int x, int y) {
485 0 : const SkBitmapProcStateAutoMapper mapper(s, x, y);
486 :
487 0 : SkFixed oneX = s.fFilterOneX;
488 0 : SkFixed oneY = s.fFilterOneY;
489 0 : SkFixed fx = mapper.fixedX();
490 0 : SkFixed fy = mapper.fixedY();
491 0 : SkFixed dx = s.fInvSx;
492 0 : SkFixed dy = s.fInvKy;
493 0 : unsigned maxX = s.fPixmap.width() - 1;
494 0 : unsigned maxY = s.fPixmap.height() - 1;
495 :
496 0 : if (count >= 2 && (maxX <= 0xFFFF)) {
497 0 : SkFixed dx2 = dx + dx;
498 0 : SkFixed dy2 = dy + dy;
499 :
500 0 : __m128i wide_f = _mm_set_epi32(fx + dx, fy + dy, fx, fy);
501 0 : __m128i wide_d2 = _mm_set_epi32(dx2, dy2, dx2, dy2);
502 0 : __m128i wide_one = _mm_set_epi32(oneX, oneY, oneX, oneY);
503 0 : __m128i wide_max = _mm_set_epi32(maxX, maxY, maxX, maxY);
504 0 : __m128i wide_mask = _mm_set1_epi32(0xF);
505 :
506 0 : while (count >= 2) {
507 : // i = SkClampMax(f>>16,maxX)
508 0 : __m128i wide_i = _mm_max_epi16(_mm_srli_epi32(wide_f, 16),
509 0 : _mm_setzero_si128());
510 0 : wide_i = _mm_min_epi16(wide_i, wide_max);
511 :
512 : // i<<4 | EXTRACT_LOW_BITS(f)
513 0 : __m128i wide_lo = _mm_srli_epi32(wide_f, 12);
514 0 : wide_lo = _mm_and_si128(wide_lo, wide_mask);
515 0 : wide_i = _mm_slli_epi32(wide_i, 4);
516 0 : wide_i = _mm_or_si128(wide_i, wide_lo);
517 :
518 : // i<<14
519 0 : wide_i = _mm_slli_epi32(wide_i, 14);
520 :
521 : // SkClampMax(((f+one))>>16,max)
522 0 : __m128i wide_f1 = _mm_add_epi32(wide_f, wide_one);
523 0 : wide_f1 = _mm_max_epi16(_mm_srli_epi32(wide_f1, 16),
524 0 : _mm_setzero_si128());
525 0 : wide_f1 = _mm_min_epi16(wide_f1, wide_max);
526 :
527 : // final combination
528 0 : wide_i = _mm_or_si128(wide_i, wide_f1);
529 : _mm_storeu_si128(reinterpret_cast<__m128i*>(xy), wide_i);
530 :
531 0 : wide_f = _mm_add_epi32(wide_f, wide_d2);
532 :
533 0 : fx += dx2;
534 0 : fy += dy2;
535 0 : xy += 4;
536 0 : count -= 2;
537 : } // while count >= 2
538 : } // if count >= 2
539 :
540 0 : while (count-- > 0) {
541 0 : *xy++ = ClampX_ClampY_pack_filter(fy, maxY, oneY);
542 0 : fy += dy;
543 0 : *xy++ = ClampX_ClampY_pack_filter(fx, maxX, oneX);
544 0 : fx += dx;
545 : }
546 0 : }
547 :
548 : /* SSE version of ClampX_ClampY_nofilter_affine()
549 : * portable version is in core/SkBitmapProcState_matrix.h
550 : */
551 0 : void ClampX_ClampY_nofilter_affine_SSE2(const SkBitmapProcState& s,
552 : uint32_t xy[], int count, int x, int y) {
553 0 : SkASSERT(s.fInvType & SkMatrix::kAffine_Mask);
554 0 : SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
555 : SkMatrix::kScale_Mask |
556 : SkMatrix::kAffine_Mask)) == 0);
557 :
558 0 : const SkBitmapProcStateAutoMapper mapper(s, x, y);
559 :
560 0 : SkFixed fx = mapper.fixedX();
561 0 : SkFixed fy = mapper.fixedY();
562 0 : SkFixed dx = s.fInvSx;
563 0 : SkFixed dy = s.fInvKy;
564 0 : int maxX = s.fPixmap.width() - 1;
565 0 : int maxY = s.fPixmap.height() - 1;
566 :
567 0 : if (count >= 4 && (maxX <= 0xFFFF)) {
568 0 : while (((size_t)xy & 0x0F) != 0) {
569 0 : *xy++ = (SkClampMax(fy >> 16, maxY) << 16) |
570 0 : SkClampMax(fx >> 16, maxX);
571 0 : fx += dx;
572 0 : fy += dy;
573 0 : count--;
574 : }
575 :
576 0 : SkFixed dx4 = dx * 4;
577 0 : SkFixed dy4 = dy * 4;
578 :
579 0 : __m128i wide_fx = _mm_set_epi32(fx + dx * 3, fx + dx * 2,
580 0 : fx + dx, fx);
581 0 : __m128i wide_fy = _mm_set_epi32(fy + dy * 3, fy + dy * 2,
582 0 : fy + dy, fy);
583 0 : __m128i wide_dx4 = _mm_set1_epi32(dx4);
584 0 : __m128i wide_dy4 = _mm_set1_epi32(dy4);
585 :
586 0 : __m128i wide_maxX = _mm_set1_epi32(maxX);
587 0 : __m128i wide_maxY = _mm_set1_epi32(maxY);
588 :
589 0 : while (count >= 4) {
590 : // SkClampMax(fx>>16,maxX)
591 0 : __m128i wide_lo = _mm_max_epi16(_mm_srli_epi32(wide_fx, 16),
592 0 : _mm_setzero_si128());
593 0 : wide_lo = _mm_min_epi16(wide_lo, wide_maxX);
594 :
595 : // SkClampMax(fy>>16,maxY)
596 0 : __m128i wide_hi = _mm_max_epi16(_mm_srli_epi32(wide_fy, 16),
597 0 : _mm_setzero_si128());
598 0 : wide_hi = _mm_min_epi16(wide_hi, wide_maxY);
599 :
600 : // final combination
601 0 : __m128i wide_i = _mm_or_si128(_mm_slli_epi32(wide_hi, 16),
602 0 : wide_lo);
603 : _mm_store_si128(reinterpret_cast<__m128i*>(xy), wide_i);
604 :
605 0 : wide_fx = _mm_add_epi32(wide_fx, wide_dx4);
606 0 : wide_fy = _mm_add_epi32(wide_fy, wide_dy4);
607 :
608 0 : fx += dx4;
609 0 : fy += dy4;
610 0 : xy += 4;
611 0 : count -= 4;
612 : } // while count >= 4
613 : } // if count >= 4
614 :
615 0 : while (count-- > 0) {
616 0 : *xy++ = (SkClampMax(fy >> 16, maxY) << 16) |
617 0 : SkClampMax(fx >> 16, maxX);
618 0 : fx += dx;
619 0 : fy += dy;
620 : }
621 0 : }
|