• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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