Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
1 /* NEON optimized code (C) COPYRIGHT 2009 Motorola
2 *
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
7 #include "SkBitmapProcState.h"
8 #include "SkPerspIter.h"
9 #include "SkShader.h"
10 #include "SkUtils.h"
11 #include "SkUtilsArm.h"
12 #include "SkBitmapProcState_utils.h"
14 /* returns 0...(n-1) given any x (positive or negative).
16 As an example, if n (which is always positive) is 5...
18 x: -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8
19 returns: 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3
20 */
21 static inline int sk_int_mod(int x, int n) {
22 SkASSERT(n > 0);
23 if ((unsigned)x >= (unsigned)n) {
24 if (x < 0) {
25 x = n + ~(~x % n);
26 } else {
27 x = x % n;
28 }
29 }
30 return x;
31 }
33 void decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count);
34 void decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count);
36 // Compile neon code paths if needed
37 #if !SK_ARM_NEON_IS_NONE
39 // These are defined in src/opts/SkBitmapProcState_matrixProcs_neon.cpp
40 extern const SkBitmapProcState::MatrixProc ClampX_ClampY_Procs_neon[];
41 extern const SkBitmapProcState::MatrixProc RepeatX_RepeatY_Procs_neon[];
43 #endif // !SK_ARM_NEON_IS_NONE
45 // Compile non-neon code path if needed
46 #if !SK_ARM_NEON_IS_ALWAYS
47 #define MAKENAME(suffix) ClampX_ClampY ## suffix
48 #define TILEX_PROCF(fx, max) SkClampMax((fx) >> 16, max)
49 #define TILEY_PROCF(fy, max) SkClampMax((fy) >> 16, max)
50 #define TILEX_LOW_BITS(fx, max) (((fx) >> 12) & 0xF)
51 #define TILEY_LOW_BITS(fy, max) (((fy) >> 12) & 0xF)
52 #define CHECK_FOR_DECAL
53 #include "SkBitmapProcState_matrix.h"
55 #define MAKENAME(suffix) RepeatX_RepeatY ## suffix
56 #define TILEX_PROCF(fx, max) SK_USHIFT16(((fx) & 0xFFFF) * ((max) + 1))
57 #define TILEY_PROCF(fy, max) SK_USHIFT16(((fy) & 0xFFFF) * ((max) + 1))
58 #define TILEX_LOW_BITS(fx, max) ((((fx) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
59 #define TILEY_LOW_BITS(fy, max) ((((fy) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
60 #include "SkBitmapProcState_matrix.h"
61 #endif
63 #define MAKENAME(suffix) GeneralXY ## suffix
64 #define PREAMBLE(state) SkBitmapProcState::FixedTileProc tileProcX = (state).fTileProcX; (void) tileProcX; \
65 SkBitmapProcState::FixedTileProc tileProcY = (state).fTileProcY; (void) tileProcY; \
66 SkBitmapProcState::FixedTileLowBitsProc tileLowBitsProcX = (state).fTileLowBitsProcX; (void) tileLowBitsProcX; \
67 SkBitmapProcState::FixedTileLowBitsProc tileLowBitsProcY = (state).fTileLowBitsProcY; (void) tileLowBitsProcY
68 #define PREAMBLE_PARAM_X , SkBitmapProcState::FixedTileProc tileProcX, SkBitmapProcState::FixedTileLowBitsProc tileLowBitsProcX
69 #define PREAMBLE_PARAM_Y , SkBitmapProcState::FixedTileProc tileProcY, SkBitmapProcState::FixedTileLowBitsProc tileLowBitsProcY
70 #define PREAMBLE_ARG_X , tileProcX, tileLowBitsProcX
71 #define PREAMBLE_ARG_Y , tileProcY, tileLowBitsProcY
72 #define TILEX_PROCF(fx, max) SK_USHIFT16(tileProcX(fx) * ((max) + 1))
73 #define TILEY_PROCF(fy, max) SK_USHIFT16(tileProcY(fy) * ((max) + 1))
74 #define TILEX_LOW_BITS(fx, max) tileLowBitsProcX(fx, (max) + 1)
75 #define TILEY_LOW_BITS(fy, max) tileLowBitsProcY(fy, (max) + 1)
76 #include "SkBitmapProcState_matrix.h"
78 static inline U16CPU fixed_clamp(SkFixed x)
79 {
80 if (x < 0) {
81 x = 0;
82 }
83 if (x >> 16) {
84 x = 0xFFFF;
85 }
86 return x;
87 }
89 static inline U16CPU fixed_repeat(SkFixed x)
90 {
91 return x & 0xFFFF;
92 }
94 // Visual Studio 2010 (MSC_VER=1600) optimizes bit-shift code incorrectly.
95 // See http://code.google.com/p/skia/issues/detail?id=472
96 #if defined(_MSC_VER) && (_MSC_VER >= 1600)
97 #pragma optimize("", off)
98 #endif
100 static inline U16CPU fixed_mirror(SkFixed x)
101 {
102 SkFixed s = x << 15 >> 31;
103 // s is FFFFFFFF if we're on an odd interval, or 0 if an even interval
104 return (x ^ s) & 0xFFFF;
105 }
107 #if defined(_MSC_VER) && (_MSC_VER >= 1600)
108 #pragma optimize("", on)
109 #endif
111 static SkBitmapProcState::FixedTileProc choose_tile_proc(unsigned m)
112 {
113 if (SkShader::kClamp_TileMode == m)
114 return fixed_clamp;
115 if (SkShader::kRepeat_TileMode == m)
116 return fixed_repeat;
117 SkASSERT(SkShader::kMirror_TileMode == m);
118 return fixed_mirror;
119 }
121 static inline U16CPU fixed_clamp_lowbits(SkFixed x, int) {
122 return (x >> 12) & 0xF;
123 }
125 static inline U16CPU fixed_repeat_or_mirrow_lowbits(SkFixed x, int scale) {
126 return ((x * scale) >> 12) & 0xF;
127 }
129 static SkBitmapProcState::FixedTileLowBitsProc choose_tile_lowbits_proc(unsigned m) {
130 if (SkShader::kClamp_TileMode == m) {
131 return fixed_clamp_lowbits;
132 } else {
133 SkASSERT(SkShader::kMirror_TileMode == m ||
134 SkShader::kRepeat_TileMode == m);
135 // mirror and repeat have the same behavior for the low bits.
136 return fixed_repeat_or_mirrow_lowbits;
137 }
138 }
140 static inline U16CPU int_clamp(int x, int n) {
141 if (x >= n) {
142 x = n - 1;
143 }
144 if (x < 0) {
145 x = 0;
146 }
147 return x;
148 }
150 static inline U16CPU int_repeat(int x, int n) {
151 return sk_int_mod(x, n);
152 }
154 static inline U16CPU int_mirror(int x, int n) {
155 x = sk_int_mod(x, 2 * n);
156 if (x >= n) {
157 x = n + ~(x - n);
158 }
159 return x;
160 }
162 #if 0
163 static void test_int_tileprocs() {
164 for (int i = -8; i <= 8; i++) {
165 SkDebugf(" int_mirror(%2d, 3) = %d\n", i, int_mirror(i, 3));
166 }
167 }
168 #endif
170 static SkBitmapProcState::IntTileProc choose_int_tile_proc(unsigned tm) {
171 if (SkShader::kClamp_TileMode == tm)
172 return int_clamp;
173 if (SkShader::kRepeat_TileMode == tm)
174 return int_repeat;
175 SkASSERT(SkShader::kMirror_TileMode == tm);
176 return int_mirror;
177 }
179 //////////////////////////////////////////////////////////////////////////////
181 void decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count)
182 {
183 int i;
185 for (i = (count >> 2); i > 0; --i)
186 {
187 *dst++ = pack_two_shorts(fx >> 16, (fx + dx) >> 16);
188 fx += dx+dx;
189 *dst++ = pack_two_shorts(fx >> 16, (fx + dx) >> 16);
190 fx += dx+dx;
191 }
192 count &= 3;
194 uint16_t* xx = (uint16_t*)dst;
195 for (i = count; i > 0; --i) {
196 *xx++ = SkToU16(fx >> 16); fx += dx;
197 }
198 }
200 void decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count)
201 {
204 if (count & 1)
205 {
206 SkASSERT((fx >> (16 + 14)) == 0);
207 *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
208 fx += dx;
209 }
210 while ((count -= 2) >= 0)
211 {
212 SkASSERT((fx >> (16 + 14)) == 0);
213 *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
214 fx += dx;
216 *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
217 fx += dx;
218 }
219 }
221 ///////////////////////////////////////////////////////////////////////////////
222 // stores the same as SCALE, but is cheaper to compute. Also since there is no
223 // scale, we don't need/have a FILTER version
225 static void fill_sequential(uint16_t xptr[], int start, int count) {
226 #if 1
227 if (reinterpret_cast<intptr_t>(xptr) & 0x2) {
228 *xptr++ = start++;
229 count -= 1;
230 }
231 if (count > 3) {
232 uint32_t* xxptr = reinterpret_cast<uint32_t*>(xptr);
233 uint32_t pattern0 = PACK_TWO_SHORTS(start + 0, start + 1);
234 uint32_t pattern1 = PACK_TWO_SHORTS(start + 2, start + 3);
235 start += count & ~3;
236 int qcount = count >> 2;
237 do {
238 *xxptr++ = pattern0;
239 pattern0 += 0x40004;
240 *xxptr++ = pattern1;
241 pattern1 += 0x40004;
242 } while (--qcount != 0);
243 xptr = reinterpret_cast<uint16_t*>(xxptr);
244 count &= 3;
245 }
246 while (--count >= 0) {
247 *xptr++ = start++;
248 }
249 #else
250 for (int i = 0; i < count; i++) {
251 *xptr++ = start++;
252 }
253 #endif
254 }
256 static int nofilter_trans_preamble(const SkBitmapProcState& s, uint32_t** xy,
257 int x, int y) {
258 SkPoint pt;
259 s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
260 SkIntToScalar(y) + SK_ScalarHalf, &pt);
261 **xy = s.fIntTileProcY(SkScalarToFixed(pt.fY) >> 16,
262 s.fBitmap->height());
263 *xy += 1; // bump the ptr
264 // return our starting X position
265 return SkScalarToFixed(pt.fX) >> 16;
266 }
268 static void clampx_nofilter_trans(const SkBitmapProcState& s,
269 uint32_t xy[], int count, int x, int y) {
270 SkASSERT((s.fInvType & ~SkMatrix::kTranslate_Mask) == 0);
272 int xpos = nofilter_trans_preamble(s, &xy, x, y);
273 const int width = s.fBitmap->width();
274 if (1 == width) {
275 // all of the following X values must be 0
276 memset(xy, 0, count * sizeof(uint16_t));
277 return;
278 }
280 uint16_t* xptr = reinterpret_cast<uint16_t*>(xy);
281 int n;
283 // fill before 0 as needed
284 if (xpos < 0) {
285 n = -xpos;
286 if (n > count) {
287 n = count;
288 }
289 memset(xptr, 0, n * sizeof(uint16_t));
290 count -= n;
291 if (0 == count) {
292 return;
293 }
294 xptr += n;
295 xpos = 0;
296 }
298 // fill in 0..width-1 if needed
299 if (xpos < width) {
300 n = width - xpos;
301 if (n > count) {
302 n = count;
303 }
304 fill_sequential(xptr, xpos, n);
305 count -= n;
306 if (0 == count) {
307 return;
308 }
309 xptr += n;
310 }
312 // fill the remaining with the max value
313 sk_memset16(xptr, width - 1, count);
314 }
316 static void repeatx_nofilter_trans(const SkBitmapProcState& s,
317 uint32_t xy[], int count, int x, int y) {
318 SkASSERT((s.fInvType & ~SkMatrix::kTranslate_Mask) == 0);
320 int xpos = nofilter_trans_preamble(s, &xy, x, y);
321 const int width = s.fBitmap->width();
322 if (1 == width) {
323 // all of the following X values must be 0
324 memset(xy, 0, count * sizeof(uint16_t));
325 return;
326 }
328 uint16_t* xptr = reinterpret_cast<uint16_t*>(xy);
329 int start = sk_int_mod(xpos, width);
330 int n = width - start;
331 if (n > count) {
332 n = count;
333 }
334 fill_sequential(xptr, start, n);
335 xptr += n;
336 count -= n;
338 while (count >= width) {
339 fill_sequential(xptr, 0, width);
340 xptr += width;
341 count -= width;
342 }
344 if (count > 0) {
345 fill_sequential(xptr, 0, count);
346 }
347 }
349 static void fill_backwards(uint16_t xptr[], int pos, int count) {
350 for (int i = 0; i < count; i++) {
351 SkASSERT(pos >= 0);
352 xptr[i] = pos--;
353 }
354 }
356 static void mirrorx_nofilter_trans(const SkBitmapProcState& s,
357 uint32_t xy[], int count, int x, int y) {
358 SkASSERT((s.fInvType & ~SkMatrix::kTranslate_Mask) == 0);
360 int xpos = nofilter_trans_preamble(s, &xy, x, y);
361 const int width = s.fBitmap->width();
362 if (1 == width) {
363 // all of the following X values must be 0
364 memset(xy, 0, count * sizeof(uint16_t));
365 return;
366 }
368 uint16_t* xptr = reinterpret_cast<uint16_t*>(xy);
369 // need to know our start, and our initial phase (forward or backward)
370 bool forward;
371 int n;
372 int start = sk_int_mod(xpos, 2 * width);
373 if (start >= width) {
374 start = width + ~(start - width);
375 forward = false;
376 n = start + 1; // [start .. 0]
377 } else {
378 forward = true;
379 n = width - start; // [start .. width)
380 }
381 if (n > count) {
382 n = count;
383 }
384 if (forward) {
385 fill_sequential(xptr, start, n);
386 } else {
387 fill_backwards(xptr, start, n);
388 }
389 forward = !forward;
390 xptr += n;
391 count -= n;
393 while (count >= width) {
394 if (forward) {
395 fill_sequential(xptr, 0, width);
396 } else {
397 fill_backwards(xptr, width - 1, width);
398 }
399 forward = !forward;
400 xptr += width;
401 count -= width;
402 }
404 if (count > 0) {
405 if (forward) {
406 fill_sequential(xptr, 0, count);
407 } else {
408 fill_backwards(xptr, width - 1, count);
409 }
410 }
411 }
413 ///////////////////////////////////////////////////////////////////////////////
415 SkBitmapProcState::MatrixProc
416 SkBitmapProcState::chooseMatrixProc(bool trivial_matrix) {
417 // test_int_tileprocs();
418 // check for our special case when there is no scale/affine/perspective
419 if (trivial_matrix) {
420 SkASSERT(SkPaint::kNone_FilterLevel == fFilterLevel);
421 fIntTileProcY = choose_int_tile_proc(fTileModeY);
422 switch (fTileModeX) {
423 case SkShader::kClamp_TileMode:
424 return clampx_nofilter_trans;
425 case SkShader::kRepeat_TileMode:
426 return repeatx_nofilter_trans;
427 case SkShader::kMirror_TileMode:
428 return mirrorx_nofilter_trans;
429 }
430 }
432 int index = 0;
433 if (fFilterLevel != SkPaint::kNone_FilterLevel) {
434 index = 1;
435 }
436 if (fInvType & SkMatrix::kPerspective_Mask) {
437 index += 4;
438 } else if (fInvType & SkMatrix::kAffine_Mask) {
439 index += 2;
440 }
442 if (SkShader::kClamp_TileMode == fTileModeX &&
443 SkShader::kClamp_TileMode == fTileModeY)
444 {
445 // clamp gets special version of filterOne
446 fFilterOneX = SK_Fixed1;
447 fFilterOneY = SK_Fixed1;
448 return SK_ARM_NEON_WRAP(ClampX_ClampY_Procs)[index];
449 }
451 // all remaining procs use this form for filterOne
452 fFilterOneX = SK_Fixed1 / fBitmap->width();
453 fFilterOneY = SK_Fixed1 / fBitmap->height();
455 if (SkShader::kRepeat_TileMode == fTileModeX &&
456 SkShader::kRepeat_TileMode == fTileModeY)
457 {
458 return SK_ARM_NEON_WRAP(RepeatX_RepeatY_Procs)[index];
459 }
461 fTileProcX = choose_tile_proc(fTileModeX);
462 fTileProcY = choose_tile_proc(fTileModeY);
463 fTileLowBitsProcX = choose_tile_lowbits_proc(fTileModeX);
464 fTileLowBitsProcY = choose_tile_lowbits_proc(fTileModeY);
465 return GeneralXY_Procs[index];
466 }