1 /*
2 * jsimd_arm64.c
3 *
4 * Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
5 * Copyright (C) 2011, Nokia Corporation and/or its subsidiary(-ies).
6 * Copyright (C) 2009-2011, 2013-2014, 2016, D. R. Commander.
7 * Copyright (C) 2015-2016, Matthieu Darbois.
8 *
9 * Based on the x86 SIMD extension for IJG JPEG library,
10 * Copyright (C) 1999-2006, MIYASAKA Masaru.
11 * For conditions of distribution and use, see copyright notice in jsimdext.inc
12 *
13 * This file contains the interface between the "normal" portions
14 * of the library and the SIMD implementations when running on a
15 * 64-bit ARM architecture.
16 */
17
18 #define JPEG_INTERNALS
19 #include "../jinclude.h"
20 #include "../jpeglib.h"
21 #include "../jsimd.h"
22 #include "../jdct.h"
23 #include "../jsimddct.h"
24 #include "jsimd.h"
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <ctype.h>
29
30 #define JSIMD_FASTLD3 1
31 #define JSIMD_FASTST3 2
32 #define JSIMD_FASTTBL 4
33
34 static unsigned int simd_support = ~0;
35 static unsigned int simd_huffman = 1;
36 static unsigned int simd_features = JSIMD_FASTLD3 | JSIMD_FASTST3 |
37 JSIMD_FASTTBL;
38
39 #if defined(__linux__) || defined(ANDROID) || defined(__ANDROID__)
40
41 #define SOMEWHAT_SANE_PROC_CPUINFO_SIZE_LIMIT (1024 * 1024)
42
43 LOCAL(int)
check_cpuinfo(char * buffer,const char * field,char * value)44 check_cpuinfo (char *buffer, const char *field, char *value)
45 {
46 char *p;
47 if (*value == 0)
48 return 0;
49 if (strncmp(buffer, field, strlen(field)) != 0)
50 return 0;
51 buffer += strlen(field);
52 while (isspace(*buffer))
53 buffer++;
54
55 /* Check if 'value' is present in the buffer as a separate word */
56 while ((p = strstr(buffer, value))) {
57 if (p > buffer && !isspace(*(p - 1))) {
58 buffer++;
59 continue;
60 }
61 p += strlen(value);
62 if (*p != 0 && !isspace(*p)) {
63 buffer++;
64 continue;
65 }
66 return 1;
67 }
68 return 0;
69 }
70
71 LOCAL(int)
parse_proc_cpuinfo(int bufsize)72 parse_proc_cpuinfo (int bufsize)
73 {
74 char *buffer = (char *)malloc(bufsize);
75 FILE *fd;
76
77 if (!buffer)
78 return 0;
79
80 fd = fopen("/proc/cpuinfo", "r");
81 if (fd) {
82 while (fgets(buffer, bufsize, fd)) {
83 if (!strchr(buffer, '\n') && !feof(fd)) {
84 /* "impossible" happened - insufficient size of the buffer! */
85 fclose(fd);
86 free(buffer);
87 return 0;
88 }
89 if (check_cpuinfo(buffer, "CPU part", "0xd03") ||
90 check_cpuinfo(buffer, "CPU part", "0xd07"))
91 /* The Cortex-A53 has a slow tbl implementation. We can gain a few
92 percent speedup by disabling the use of that instruction. The
93 speedup on Cortex-A57 is more subtle but still measurable. */
94 simd_features &= ~JSIMD_FASTTBL;
95 else if (check_cpuinfo(buffer, "CPU part", "0x0a1"))
96 /* The SIMD version of Huffman encoding is slower than the C version on
97 Cavium ThunderX. Also, ld3 and st3 are abyssmally slow on that
98 CPU. */
99 simd_huffman = simd_features = 0;
100 }
101 fclose(fd);
102 }
103 free(buffer);
104 return 1;
105 }
106
107 #endif
108
109 /*
110 * Check what SIMD accelerations are supported.
111 *
112 * FIXME: This code is racy under a multi-threaded environment.
113 */
114
115 /*
116 * ARMv8 architectures support NEON extensions by default.
117 * It is no longer optional as it was with ARMv7.
118 */
119
120
121 LOCAL(void)
init_simd(void)122 init_simd (void)
123 {
124 char *env = NULL;
125 #if defined(__linux__) || defined(ANDROID) || defined(__ANDROID__)
126 int bufsize = 1024; /* an initial guess for the line buffer size limit */
127 #endif
128
129 if (simd_support != ~0U)
130 return;
131
132 simd_support = 0;
133
134 simd_support |= JSIMD_ARM_NEON;
135 #if defined(__linux__) || defined(ANDROID) || defined(__ANDROID__)
136 while (!parse_proc_cpuinfo(bufsize)) {
137 bufsize *= 2;
138 if (bufsize > SOMEWHAT_SANE_PROC_CPUINFO_SIZE_LIMIT)
139 break;
140 }
141 #endif
142
143 /* Force different settings through environment variables */
144 env = getenv("JSIMD_FORCENEON");
145 if ((env != NULL) && (strcmp(env, "1") == 0))
146 simd_support = JSIMD_ARM_NEON;
147 env = getenv("JSIMD_FORCENONE");
148 if ((env != NULL) && (strcmp(env, "1") == 0))
149 simd_support = 0;
150 env = getenv("JSIMD_NOHUFFENC");
151 if ((env != NULL) && (strcmp(env, "1") == 0))
152 simd_huffman = 0;
153 env = getenv("JSIMD_FASTLD3");
154 if ((env != NULL) && (strcmp(env, "1") == 0))
155 simd_features |= JSIMD_FASTLD3;
156 if ((env != NULL) && (strcmp(env, "0") == 0))
157 simd_features &= ~JSIMD_FASTLD3;
158 env = getenv("JSIMD_FASTST3");
159 if ((env != NULL) && (strcmp(env, "1") == 0))
160 simd_features |= JSIMD_FASTST3;
161 if ((env != NULL) && (strcmp(env, "0") == 0))
162 simd_features &= ~JSIMD_FASTST3;
163 }
164
165 GLOBAL(int)
jsimd_can_rgb_ycc(void)166 jsimd_can_rgb_ycc (void)
167 {
168 init_simd();
169
170 /* The code is optimised for these values only */
171 if (BITS_IN_JSAMPLE != 8)
172 return 0;
173 if (sizeof(JDIMENSION) != 4)
174 return 0;
175 if ((RGB_PIXELSIZE != 3) && (RGB_PIXELSIZE != 4))
176 return 0;
177
178 if (simd_support & JSIMD_ARM_NEON)
179 return 1;
180
181 return 0;
182 }
183
184 GLOBAL(int)
jsimd_can_rgb_gray(void)185 jsimd_can_rgb_gray (void)
186 {
187 init_simd();
188
189 return 0;
190 }
191
192 GLOBAL(int)
jsimd_can_ycc_rgb(void)193 jsimd_can_ycc_rgb (void)
194 {
195 init_simd();
196
197 /* The code is optimised for these values only */
198 if (BITS_IN_JSAMPLE != 8)
199 return 0;
200 if (sizeof(JDIMENSION) != 4)
201 return 0;
202 if ((RGB_PIXELSIZE != 3) && (RGB_PIXELSIZE != 4))
203 return 0;
204
205 if (simd_support & JSIMD_ARM_NEON)
206 return 1;
207
208 return 0;
209 }
210
211 GLOBAL(int)
jsimd_can_ycc_rgb565(void)212 jsimd_can_ycc_rgb565 (void)
213 {
214 init_simd();
215
216 /* The code is optimised for these values only */
217 if (BITS_IN_JSAMPLE != 8)
218 return 0;
219 if (sizeof(JDIMENSION) != 4)
220 return 0;
221
222 if (simd_support & JSIMD_ARM_NEON)
223 return 1;
224
225 return 0;
226 }
227
228 GLOBAL(void)
jsimd_rgb_ycc_convert(j_compress_ptr cinfo,JSAMPARRAY input_buf,JSAMPIMAGE output_buf,JDIMENSION output_row,int num_rows)229 jsimd_rgb_ycc_convert (j_compress_ptr cinfo,
230 JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
231 JDIMENSION output_row, int num_rows)
232 {
233 void (*neonfct)(JDIMENSION, JSAMPARRAY, JSAMPIMAGE, JDIMENSION, int);
234
235 switch(cinfo->in_color_space) {
236 case JCS_EXT_RGB:
237 if (simd_features & JSIMD_FASTLD3)
238 neonfct=jsimd_extrgb_ycc_convert_neon;
239 else
240 neonfct=jsimd_extrgb_ycc_convert_neon_slowld3;
241 break;
242 case JCS_EXT_RGBX:
243 case JCS_EXT_RGBA:
244 neonfct=jsimd_extrgbx_ycc_convert_neon;
245 break;
246 case JCS_EXT_BGR:
247 if (simd_features & JSIMD_FASTLD3)
248 neonfct=jsimd_extbgr_ycc_convert_neon;
249 else
250 neonfct=jsimd_extbgr_ycc_convert_neon_slowld3;
251 break;
252 case JCS_EXT_BGRX:
253 case JCS_EXT_BGRA:
254 neonfct=jsimd_extbgrx_ycc_convert_neon;
255 break;
256 case JCS_EXT_XBGR:
257 case JCS_EXT_ABGR:
258 neonfct=jsimd_extxbgr_ycc_convert_neon;
259 break;
260 case JCS_EXT_XRGB:
261 case JCS_EXT_ARGB:
262 neonfct=jsimd_extxrgb_ycc_convert_neon;
263 break;
264 default:
265 if (simd_features & JSIMD_FASTLD3)
266 neonfct=jsimd_extrgb_ycc_convert_neon;
267 else
268 neonfct=jsimd_extrgb_ycc_convert_neon_slowld3;
269 break;
270 }
271
272 neonfct(cinfo->image_width, input_buf, output_buf, output_row, num_rows);
273 }
274
275 GLOBAL(void)
jsimd_rgb_gray_convert(j_compress_ptr cinfo,JSAMPARRAY input_buf,JSAMPIMAGE output_buf,JDIMENSION output_row,int num_rows)276 jsimd_rgb_gray_convert (j_compress_ptr cinfo,
277 JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
278 JDIMENSION output_row, int num_rows)
279 {
280 }
281
282 GLOBAL(void)
jsimd_ycc_rgb_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)283 jsimd_ycc_rgb_convert (j_decompress_ptr cinfo,
284 JSAMPIMAGE input_buf, JDIMENSION input_row,
285 JSAMPARRAY output_buf, int num_rows)
286 {
287 void (*neonfct)(JDIMENSION, JSAMPIMAGE, JDIMENSION, JSAMPARRAY, int);
288
289 switch(cinfo->out_color_space) {
290 case JCS_EXT_RGB:
291 if (simd_features & JSIMD_FASTST3)
292 neonfct=jsimd_ycc_extrgb_convert_neon;
293 else
294 neonfct=jsimd_ycc_extrgb_convert_neon_slowst3;
295 break;
296 case JCS_EXT_RGBX:
297 case JCS_EXT_RGBA:
298 neonfct=jsimd_ycc_extrgbx_convert_neon;
299 break;
300 case JCS_EXT_BGR:
301 if (simd_features & JSIMD_FASTST3)
302 neonfct=jsimd_ycc_extbgr_convert_neon;
303 else
304 neonfct=jsimd_ycc_extbgr_convert_neon_slowst3;
305 break;
306 case JCS_EXT_BGRX:
307 case JCS_EXT_BGRA:
308 neonfct=jsimd_ycc_extbgrx_convert_neon;
309 break;
310 case JCS_EXT_XBGR:
311 case JCS_EXT_ABGR:
312 neonfct=jsimd_ycc_extxbgr_convert_neon;
313 break;
314 case JCS_EXT_XRGB:
315 case JCS_EXT_ARGB:
316 neonfct=jsimd_ycc_extxrgb_convert_neon;
317 break;
318 default:
319 if (simd_features & JSIMD_FASTST3)
320 neonfct=jsimd_ycc_extrgb_convert_neon;
321 else
322 neonfct=jsimd_ycc_extrgb_convert_neon_slowst3;
323 break;
324 }
325
326 neonfct(cinfo->output_width, input_buf, input_row, output_buf, num_rows);
327 }
328
329 GLOBAL(void)
jsimd_ycc_rgb565_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)330 jsimd_ycc_rgb565_convert (j_decompress_ptr cinfo,
331 JSAMPIMAGE input_buf, JDIMENSION input_row,
332 JSAMPARRAY output_buf, int num_rows)
333 {
334 jsimd_ycc_rgb565_convert_neon(cinfo->output_width, input_buf, input_row,
335 output_buf, num_rows);
336 }
337
338 GLOBAL(int)
jsimd_can_h2v2_downsample(void)339 jsimd_can_h2v2_downsample (void)
340 {
341 init_simd();
342
343 /* The code is optimised for these values only */
344 if (BITS_IN_JSAMPLE != 8)
345 return 0;
346 if (DCTSIZE != 8)
347 return 0;
348 if (sizeof(JDIMENSION) != 4)
349 return 0;
350
351 if (simd_support & JSIMD_ARM_NEON)
352 return 1;
353
354 return 0;
355 }
356
357 GLOBAL(int)
jsimd_can_h2v1_downsample(void)358 jsimd_can_h2v1_downsample (void)
359 {
360 init_simd();
361
362 /* The code is optimised for these values only */
363 if (BITS_IN_JSAMPLE != 8)
364 return 0;
365 if (DCTSIZE != 8)
366 return 0;
367 if (sizeof(JDIMENSION) != 4)
368 return 0;
369
370 if (simd_support & JSIMD_ARM_NEON)
371 return 1;
372
373 return 0;
374 }
375
376 GLOBAL(void)
jsimd_h2v2_downsample(j_compress_ptr cinfo,jpeg_component_info * compptr,JSAMPARRAY input_data,JSAMPARRAY output_data)377 jsimd_h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
378 JSAMPARRAY input_data, JSAMPARRAY output_data)
379 {
380 jsimd_h2v2_downsample_neon(cinfo->image_width, cinfo->max_v_samp_factor,
381 compptr->v_samp_factor, compptr->width_in_blocks,
382 input_data, output_data);
383 }
384
385 GLOBAL(void)
jsimd_h2v1_downsample(j_compress_ptr cinfo,jpeg_component_info * compptr,JSAMPARRAY input_data,JSAMPARRAY output_data)386 jsimd_h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
387 JSAMPARRAY input_data, JSAMPARRAY output_data)
388 {
389 jsimd_h2v1_downsample_neon(cinfo->image_width, cinfo->max_v_samp_factor,
390 compptr->v_samp_factor, compptr->width_in_blocks,
391 input_data, output_data);
392 }
393
394 GLOBAL(int)
jsimd_can_h2v2_upsample(void)395 jsimd_can_h2v2_upsample (void)
396 {
397 init_simd();
398
399 return 0;
400 }
401
402 GLOBAL(int)
jsimd_can_h2v1_upsample(void)403 jsimd_can_h2v1_upsample (void)
404 {
405 init_simd();
406
407 return 0;
408 }
409
410 GLOBAL(void)
jsimd_h2v2_upsample(j_decompress_ptr cinfo,jpeg_component_info * compptr,JSAMPARRAY input_data,JSAMPARRAY * output_data_ptr)411 jsimd_h2v2_upsample (j_decompress_ptr cinfo,
412 jpeg_component_info *compptr,
413 JSAMPARRAY input_data,
414 JSAMPARRAY *output_data_ptr)
415 {
416 }
417
418 GLOBAL(void)
jsimd_h2v1_upsample(j_decompress_ptr cinfo,jpeg_component_info * compptr,JSAMPARRAY input_data,JSAMPARRAY * output_data_ptr)419 jsimd_h2v1_upsample (j_decompress_ptr cinfo,
420 jpeg_component_info *compptr,
421 JSAMPARRAY input_data,
422 JSAMPARRAY *output_data_ptr)
423 {
424 }
425
426 GLOBAL(int)
jsimd_can_h2v2_fancy_upsample(void)427 jsimd_can_h2v2_fancy_upsample (void)
428 {
429 init_simd();
430
431 return 0;
432 }
433
434 GLOBAL(int)
jsimd_can_h2v1_fancy_upsample(void)435 jsimd_can_h2v1_fancy_upsample (void)
436 {
437 init_simd();
438
439 return 0;
440 }
441
442 GLOBAL(void)
jsimd_h2v2_fancy_upsample(j_decompress_ptr cinfo,jpeg_component_info * compptr,JSAMPARRAY input_data,JSAMPARRAY * output_data_ptr)443 jsimd_h2v2_fancy_upsample (j_decompress_ptr cinfo,
444 jpeg_component_info *compptr,
445 JSAMPARRAY input_data,
446 JSAMPARRAY *output_data_ptr)
447 {
448 }
449
450 GLOBAL(void)
jsimd_h2v1_fancy_upsample(j_decompress_ptr cinfo,jpeg_component_info * compptr,JSAMPARRAY input_data,JSAMPARRAY * output_data_ptr)451 jsimd_h2v1_fancy_upsample (j_decompress_ptr cinfo,
452 jpeg_component_info *compptr,
453 JSAMPARRAY input_data,
454 JSAMPARRAY *output_data_ptr)
455 {
456 }
457
458 GLOBAL(int)
jsimd_can_h2v2_merged_upsample(void)459 jsimd_can_h2v2_merged_upsample (void)
460 {
461 init_simd();
462
463 return 0;
464 }
465
466 GLOBAL(int)
jsimd_can_h2v1_merged_upsample(void)467 jsimd_can_h2v1_merged_upsample (void)
468 {
469 init_simd();
470
471 return 0;
472 }
473
474 GLOBAL(void)
jsimd_h2v2_merged_upsample(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION in_row_group_ctr,JSAMPARRAY output_buf)475 jsimd_h2v2_merged_upsample (j_decompress_ptr cinfo,
476 JSAMPIMAGE input_buf,
477 JDIMENSION in_row_group_ctr,
478 JSAMPARRAY output_buf)
479 {
480 }
481
482 GLOBAL(void)
jsimd_h2v1_merged_upsample(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION in_row_group_ctr,JSAMPARRAY output_buf)483 jsimd_h2v1_merged_upsample (j_decompress_ptr cinfo,
484 JSAMPIMAGE input_buf,
485 JDIMENSION in_row_group_ctr,
486 JSAMPARRAY output_buf)
487 {
488 }
489
490 GLOBAL(int)
jsimd_can_convsamp(void)491 jsimd_can_convsamp (void)
492 {
493 init_simd();
494
495 /* The code is optimised for these values only */
496 if (DCTSIZE != 8)
497 return 0;
498 if (BITS_IN_JSAMPLE != 8)
499 return 0;
500 if (sizeof(JDIMENSION) != 4)
501 return 0;
502 if (sizeof(DCTELEM) != 2)
503 return 0;
504
505 if (simd_support & JSIMD_ARM_NEON)
506 return 1;
507
508 return 0;
509 }
510
511 GLOBAL(int)
jsimd_can_convsamp_float(void)512 jsimd_can_convsamp_float (void)
513 {
514 init_simd();
515
516 return 0;
517 }
518
519 GLOBAL(void)
jsimd_convsamp(JSAMPARRAY sample_data,JDIMENSION start_col,DCTELEM * workspace)520 jsimd_convsamp (JSAMPARRAY sample_data, JDIMENSION start_col,
521 DCTELEM *workspace)
522 {
523 jsimd_convsamp_neon(sample_data, start_col, workspace);
524 }
525
526 GLOBAL(void)
jsimd_convsamp_float(JSAMPARRAY sample_data,JDIMENSION start_col,FAST_FLOAT * workspace)527 jsimd_convsamp_float (JSAMPARRAY sample_data, JDIMENSION start_col,
528 FAST_FLOAT *workspace)
529 {
530 }
531
532 GLOBAL(int)
jsimd_can_fdct_islow(void)533 jsimd_can_fdct_islow (void)
534 {
535 init_simd();
536
537 /* The code is optimised for these values only */
538 if (DCTSIZE != 8)
539 return 0;
540 if (sizeof(DCTELEM) != 2)
541 return 0;
542
543 if (simd_support & JSIMD_ARM_NEON)
544 return 1;
545
546 return 0;
547 }
548
549 GLOBAL(int)
jsimd_can_fdct_ifast(void)550 jsimd_can_fdct_ifast (void)
551 {
552 init_simd();
553
554 /* The code is optimised for these values only */
555 if (DCTSIZE != 8)
556 return 0;
557 if (sizeof(DCTELEM) != 2)
558 return 0;
559
560 if (simd_support & JSIMD_ARM_NEON)
561 return 1;
562
563 return 0;
564 }
565
566 GLOBAL(int)
jsimd_can_fdct_float(void)567 jsimd_can_fdct_float (void)
568 {
569 init_simd();
570
571 return 0;
572 }
573
574 GLOBAL(void)
jsimd_fdct_islow(DCTELEM * data)575 jsimd_fdct_islow (DCTELEM *data)
576 {
577 jsimd_fdct_islow_neon(data);
578 }
579
580 GLOBAL(void)
jsimd_fdct_ifast(DCTELEM * data)581 jsimd_fdct_ifast (DCTELEM *data)
582 {
583 jsimd_fdct_ifast_neon(data);
584 }
585
586 GLOBAL(void)
jsimd_fdct_float(FAST_FLOAT * data)587 jsimd_fdct_float (FAST_FLOAT *data)
588 {
589 }
590
591 GLOBAL(int)
jsimd_can_quantize(void)592 jsimd_can_quantize (void)
593 {
594 init_simd();
595
596 /* The code is optimised for these values only */
597 if (DCTSIZE != 8)
598 return 0;
599 if (sizeof(JCOEF) != 2)
600 return 0;
601 if (sizeof(DCTELEM) != 2)
602 return 0;
603
604 if (simd_support & JSIMD_ARM_NEON)
605 return 1;
606
607 return 0;
608 }
609
610 GLOBAL(int)
jsimd_can_quantize_float(void)611 jsimd_can_quantize_float (void)
612 {
613 init_simd();
614
615 return 0;
616 }
617
618 GLOBAL(void)
jsimd_quantize(JCOEFPTR coef_block,DCTELEM * divisors,DCTELEM * workspace)619 jsimd_quantize (JCOEFPTR coef_block, DCTELEM *divisors,
620 DCTELEM *workspace)
621 {
622 jsimd_quantize_neon(coef_block, divisors, workspace);
623 }
624
625 GLOBAL(void)
jsimd_quantize_float(JCOEFPTR coef_block,FAST_FLOAT * divisors,FAST_FLOAT * workspace)626 jsimd_quantize_float (JCOEFPTR coef_block, FAST_FLOAT *divisors,
627 FAST_FLOAT *workspace)
628 {
629 }
630
631 GLOBAL(int)
jsimd_can_idct_2x2(void)632 jsimd_can_idct_2x2 (void)
633 {
634 init_simd();
635
636 /* The code is optimised for these values only */
637 if (DCTSIZE != 8)
638 return 0;
639 if (sizeof(JCOEF) != 2)
640 return 0;
641 if (BITS_IN_JSAMPLE != 8)
642 return 0;
643 if (sizeof(JDIMENSION) != 4)
644 return 0;
645 if (sizeof(ISLOW_MULT_TYPE) != 2)
646 return 0;
647
648 if (simd_support & JSIMD_ARM_NEON)
649 return 1;
650
651 return 0;
652 }
653
654 GLOBAL(int)
jsimd_can_idct_4x4(void)655 jsimd_can_idct_4x4 (void)
656 {
657 init_simd();
658
659 /* The code is optimised for these values only */
660 if (DCTSIZE != 8)
661 return 0;
662 if (sizeof(JCOEF) != 2)
663 return 0;
664 if (BITS_IN_JSAMPLE != 8)
665 return 0;
666 if (sizeof(JDIMENSION) != 4)
667 return 0;
668 if (sizeof(ISLOW_MULT_TYPE) != 2)
669 return 0;
670
671 if (simd_support & JSIMD_ARM_NEON)
672 return 1;
673
674 return 0;
675 }
676
677 GLOBAL(void)
jsimd_idct_2x2(j_decompress_ptr cinfo,jpeg_component_info * compptr,JCOEFPTR coef_block,JSAMPARRAY output_buf,JDIMENSION output_col)678 jsimd_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
679 JCOEFPTR coef_block, JSAMPARRAY output_buf,
680 JDIMENSION output_col)
681 {
682 jsimd_idct_2x2_neon(compptr->dct_table, coef_block, output_buf,
683 output_col);
684 }
685
686 GLOBAL(void)
jsimd_idct_4x4(j_decompress_ptr cinfo,jpeg_component_info * compptr,JCOEFPTR coef_block,JSAMPARRAY output_buf,JDIMENSION output_col)687 jsimd_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
688 JCOEFPTR coef_block, JSAMPARRAY output_buf,
689 JDIMENSION output_col)
690 {
691 jsimd_idct_4x4_neon(compptr->dct_table, coef_block, output_buf,
692 output_col);
693 }
694
695 GLOBAL(int)
jsimd_can_idct_islow(void)696 jsimd_can_idct_islow (void)
697 {
698 init_simd();
699
700 /* The code is optimised for these values only */
701 if (DCTSIZE != 8)
702 return 0;
703 if (sizeof(JCOEF) != 2)
704 return 0;
705 if (BITS_IN_JSAMPLE != 8)
706 return 0;
707 if (sizeof(JDIMENSION) != 4)
708 return 0;
709 if (sizeof(ISLOW_MULT_TYPE) != 2)
710 return 0;
711
712 if (simd_support & JSIMD_ARM_NEON)
713 return 1;
714
715 return 0;
716 }
717
718 GLOBAL(int)
jsimd_can_idct_ifast(void)719 jsimd_can_idct_ifast (void)
720 {
721 init_simd();
722
723 /* The code is optimised for these values only */
724 if (DCTSIZE != 8)
725 return 0;
726 if (sizeof(JCOEF) != 2)
727 return 0;
728 if (BITS_IN_JSAMPLE != 8)
729 return 0;
730 if (sizeof(JDIMENSION) != 4)
731 return 0;
732 if (sizeof(IFAST_MULT_TYPE) != 2)
733 return 0;
734 if (IFAST_SCALE_BITS != 2)
735 return 0;
736
737 if (simd_support & JSIMD_ARM_NEON)
738 return 1;
739
740 return 0;
741 }
742
743 GLOBAL(int)
jsimd_can_idct_float(void)744 jsimd_can_idct_float (void)
745 {
746 init_simd();
747
748 return 0;
749 }
750
751 GLOBAL(void)
jsimd_idct_islow(j_decompress_ptr cinfo,jpeg_component_info * compptr,JCOEFPTR coef_block,JSAMPARRAY output_buf,JDIMENSION output_col)752 jsimd_idct_islow (j_decompress_ptr cinfo, jpeg_component_info *compptr,
753 JCOEFPTR coef_block, JSAMPARRAY output_buf,
754 JDIMENSION output_col)
755 {
756 jsimd_idct_islow_neon(compptr->dct_table, coef_block, output_buf,
757 output_col);
758 }
759
760 GLOBAL(void)
jsimd_idct_ifast(j_decompress_ptr cinfo,jpeg_component_info * compptr,JCOEFPTR coef_block,JSAMPARRAY output_buf,JDIMENSION output_col)761 jsimd_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info *compptr,
762 JCOEFPTR coef_block, JSAMPARRAY output_buf,
763 JDIMENSION output_col)
764 {
765 jsimd_idct_ifast_neon(compptr->dct_table, coef_block, output_buf,
766 output_col);
767 }
768
769 GLOBAL(void)
jsimd_idct_float(j_decompress_ptr cinfo,jpeg_component_info * compptr,JCOEFPTR coef_block,JSAMPARRAY output_buf,JDIMENSION output_col)770 jsimd_idct_float (j_decompress_ptr cinfo, jpeg_component_info *compptr,
771 JCOEFPTR coef_block, JSAMPARRAY output_buf,
772 JDIMENSION output_col)
773 {
774 }
775
776 GLOBAL(int)
jsimd_can_huff_encode_one_block(void)777 jsimd_can_huff_encode_one_block (void)
778 {
779 init_simd();
780
781 if (DCTSIZE != 8)
782 return 0;
783 if (sizeof(JCOEF) != 2)
784 return 0;
785
786 if (simd_support & JSIMD_ARM_NEON && simd_huffman)
787 return 1;
788
789 return 0;
790 }
791
792 GLOBAL(JOCTET*)
jsimd_huff_encode_one_block(void * state,JOCTET * buffer,JCOEFPTR block,int last_dc_val,c_derived_tbl * dctbl,c_derived_tbl * actbl)793 jsimd_huff_encode_one_block (void *state, JOCTET *buffer, JCOEFPTR block,
794 int last_dc_val, c_derived_tbl *dctbl,
795 c_derived_tbl *actbl)
796 {
797 if (simd_features & JSIMD_FASTTBL)
798 return jsimd_huff_encode_one_block_neon(state, buffer, block, last_dc_val,
799 dctbl, actbl);
800 else
801 return jsimd_huff_encode_one_block_neon_slowtbl(state, buffer, block,
802 last_dc_val, dctbl, actbl);
803 }
804