920f7656ebfe51b26b61c94f8fe3add9678b04c6
[platform/upstream/libjpeg-turbo.git] / simd / arm / aarch32 / jsimd.c
1 /*
2  * jsimd_arm.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, 2018, 2022, D. R. Commander.
7  * Copyright (C) 2015-2016, 2018, Matthieu Darbois.
8  * Copyright (C) 2019, Google LLC.
9  * Copyright (C) 2020, Arm Limited.
10  *
11  * Based on the x86 SIMD extension for IJG JPEG library,
12  * Copyright (C) 1999-2006, MIYASAKA Masaru.
13  * For conditions of distribution and use, see copyright notice in jsimdext.inc
14  *
15  * This file contains the interface between the "normal" portions
16  * of the library and the SIMD implementations when running on a
17  * 32-bit Arm architecture.
18  */
19
20 #define JPEG_INTERNALS
21 #include "../../../jinclude.h"
22 #include "../../../jpeglib.h"
23 #include "../../../jsimd.h"
24 #include "../../../jdct.h"
25 #include "../../../jsimddct.h"
26 #include "../../jsimd.h"
27
28 #include <ctype.h>
29
30 static unsigned int simd_support = ~0;
31 static unsigned int simd_huffman = 1;
32
33 #if !defined(__ARM_NEON__) && (defined(__linux__) || defined(ANDROID) || defined(__ANDROID__))
34
35 #define SOMEWHAT_SANE_PROC_CPUINFO_SIZE_LIMIT  (1024 * 1024)
36
37 LOCAL(int)
38 check_feature(char *buffer, char *feature)
39 {
40   char *p;
41
42   if (*feature == 0)
43     return 0;
44   if (strncmp(buffer, "Features", 8) != 0)
45     return 0;
46   buffer += 8;
47   while (isspace(*buffer))
48     buffer++;
49
50   /* Check if 'feature' is present in the buffer as a separate word */
51   while ((p = strstr(buffer, feature))) {
52     if (p > buffer && !isspace(*(p - 1))) {
53       buffer++;
54       continue;
55     }
56     p += strlen(feature);
57     if (*p != 0 && !isspace(*p)) {
58       buffer++;
59       continue;
60     }
61     return 1;
62   }
63   return 0;
64 }
65
66 LOCAL(int)
67 parse_proc_cpuinfo(int bufsize)
68 {
69   char *buffer = (char *)malloc(bufsize);
70   FILE *fd;
71
72   simd_support = 0;
73
74   if (!buffer)
75     return 0;
76
77   fd = fopen("/proc/cpuinfo", "r");
78   if (fd) {
79     while (fgets(buffer, bufsize, fd)) {
80       if (!strchr(buffer, '\n') && !feof(fd)) {
81         /* "impossible" happened - insufficient size of the buffer! */
82         fclose(fd);
83         free(buffer);
84         return 0;
85       }
86       if (check_feature(buffer, "neon"))
87         simd_support |= JSIMD_NEON;
88     }
89     fclose(fd);
90   }
91   free(buffer);
92   return 1;
93 }
94
95 #endif
96
97 /*
98  * Check what SIMD accelerations are supported.
99  *
100  * FIXME: This code is racy under a multi-threaded environment.
101  */
102 LOCAL(void)
103 init_simd(void)
104 {
105 #ifndef NO_GETENV
106   char env[2] = { 0 };
107 #endif
108 #if !defined(__ARM_NEON__) && (defined(__linux__) || defined(ANDROID) || defined(__ANDROID__))
109   int bufsize = 1024; /* an initial guess for the line buffer size limit */
110 #endif
111
112   if (simd_support != ~0U)
113     return;
114
115   simd_support = 0;
116
117 #if defined(__ARM_NEON__)
118   simd_support |= JSIMD_NEON;
119 #elif defined(__linux__) || defined(ANDROID) || defined(__ANDROID__)
120   /* We still have a chance to use Neon regardless of globally used
121    * -mcpu/-mfpu options passed to gcc by performing runtime detection via
122    * /proc/cpuinfo parsing on linux/android */
123   while (!parse_proc_cpuinfo(bufsize)) {
124     bufsize *= 2;
125     if (bufsize > SOMEWHAT_SANE_PROC_CPUINFO_SIZE_LIMIT)
126       break;
127   }
128 #endif
129
130 #ifndef NO_GETENV
131   /* Force different settings through environment variables */
132   if (!GETENV_S(env, 2, "JSIMD_FORCENEON") && !strcmp(env, "1"))
133     simd_support = JSIMD_NEON;
134   if (!GETENV_S(env, 2, "JSIMD_FORCENONE") && !strcmp(env, "1"))
135     simd_support = 0;
136   if (!GETENV_S(env, 2, "JSIMD_NOHUFFENC") && !strcmp(env, "1"))
137     simd_huffman = 0;
138 #endif
139 }
140
141 GLOBAL(int)
142 jsimd_can_rgb_ycc(void)
143 {
144   init_simd();
145
146   /* The code is optimised for these values only */
147   if (BITS_IN_JSAMPLE != 8)
148     return 0;
149   if (sizeof(JDIMENSION) != 4)
150     return 0;
151   if ((RGB_PIXELSIZE != 3) && (RGB_PIXELSIZE != 4))
152     return 0;
153
154   if (simd_support & JSIMD_NEON)
155     return 1;
156
157   return 0;
158 }
159
160 GLOBAL(int)
161 jsimd_can_rgb_gray(void)
162 {
163   init_simd();
164
165   /* The code is optimised for these values only */
166   if (BITS_IN_JSAMPLE != 8)
167     return 0;
168   if (sizeof(JDIMENSION) != 4)
169     return 0;
170   if ((RGB_PIXELSIZE != 3) && (RGB_PIXELSIZE != 4))
171     return 0;
172
173   if (simd_support & JSIMD_NEON)
174     return 1;
175
176   return 0;
177 }
178
179 GLOBAL(int)
180 jsimd_can_ycc_rgb(void)
181 {
182   init_simd();
183
184   /* The code is optimised for these values only */
185   if (BITS_IN_JSAMPLE != 8)
186     return 0;
187   if (sizeof(JDIMENSION) != 4)
188     return 0;
189   if ((RGB_PIXELSIZE != 3) && (RGB_PIXELSIZE != 4))
190     return 0;
191
192   if (simd_support & JSIMD_NEON)
193     return 1;
194
195   return 0;
196 }
197
198 GLOBAL(int)
199 jsimd_can_ycc_rgb565(void)
200 {
201   init_simd();
202
203   /* The code is optimised for these values only */
204   if (BITS_IN_JSAMPLE != 8)
205     return 0;
206   if (sizeof(JDIMENSION) != 4)
207     return 0;
208
209   if (simd_support & JSIMD_NEON)
210     return 1;
211
212   return 0;
213 }
214
215 GLOBAL(void)
216 jsimd_rgb_ycc_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
217                       JSAMPIMAGE output_buf, JDIMENSION output_row,
218                       int num_rows)
219 {
220   void (*neonfct) (JDIMENSION, JSAMPARRAY, JSAMPIMAGE, JDIMENSION, int);
221
222   switch (cinfo->in_color_space) {
223   case JCS_EXT_RGB:
224     neonfct = jsimd_extrgb_ycc_convert_neon;
225     break;
226   case JCS_EXT_RGBX:
227   case JCS_EXT_RGBA:
228     neonfct = jsimd_extrgbx_ycc_convert_neon;
229     break;
230   case JCS_EXT_BGR:
231     neonfct = jsimd_extbgr_ycc_convert_neon;
232     break;
233   case JCS_EXT_BGRX:
234   case JCS_EXT_BGRA:
235     neonfct = jsimd_extbgrx_ycc_convert_neon;
236     break;
237   case JCS_EXT_XBGR:
238   case JCS_EXT_ABGR:
239     neonfct = jsimd_extxbgr_ycc_convert_neon;
240     break;
241   case JCS_EXT_XRGB:
242   case JCS_EXT_ARGB:
243     neonfct = jsimd_extxrgb_ycc_convert_neon;
244     break;
245   default:
246     neonfct = jsimd_extrgb_ycc_convert_neon;
247     break;
248   }
249
250   neonfct(cinfo->image_width, input_buf, output_buf, output_row, num_rows);
251 }
252
253 GLOBAL(void)
254 jsimd_rgb_gray_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
255                        JSAMPIMAGE output_buf, JDIMENSION output_row,
256                        int num_rows)
257 {
258   void (*neonfct) (JDIMENSION, JSAMPARRAY, JSAMPIMAGE, JDIMENSION, int);
259
260   switch (cinfo->in_color_space) {
261   case JCS_EXT_RGB:
262     neonfct = jsimd_extrgb_gray_convert_neon;
263     break;
264   case JCS_EXT_RGBX:
265   case JCS_EXT_RGBA:
266     neonfct = jsimd_extrgbx_gray_convert_neon;
267     break;
268   case JCS_EXT_BGR:
269     neonfct = jsimd_extbgr_gray_convert_neon;
270     break;
271   case JCS_EXT_BGRX:
272   case JCS_EXT_BGRA:
273     neonfct = jsimd_extbgrx_gray_convert_neon;
274     break;
275   case JCS_EXT_XBGR:
276   case JCS_EXT_ABGR:
277     neonfct = jsimd_extxbgr_gray_convert_neon;
278     break;
279   case JCS_EXT_XRGB:
280   case JCS_EXT_ARGB:
281     neonfct = jsimd_extxrgb_gray_convert_neon;
282     break;
283   default:
284     neonfct = jsimd_extrgb_gray_convert_neon;
285     break;
286   }
287
288   neonfct(cinfo->image_width, input_buf, output_buf, output_row, num_rows);
289 }
290
291 GLOBAL(void)
292 jsimd_ycc_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
293                       JDIMENSION input_row, JSAMPARRAY output_buf,
294                       int num_rows)
295 {
296   void (*neonfct) (JDIMENSION, JSAMPIMAGE, JDIMENSION, JSAMPARRAY, int);
297
298   switch (cinfo->out_color_space) {
299   case JCS_EXT_RGB:
300     neonfct = jsimd_ycc_extrgb_convert_neon;
301     break;
302   case JCS_EXT_RGBX:
303   case JCS_EXT_RGBA:
304     neonfct = jsimd_ycc_extrgbx_convert_neon;
305     break;
306   case JCS_EXT_BGR:
307     neonfct = jsimd_ycc_extbgr_convert_neon;
308     break;
309   case JCS_EXT_BGRX:
310   case JCS_EXT_BGRA:
311     neonfct = jsimd_ycc_extbgrx_convert_neon;
312     break;
313   case JCS_EXT_XBGR:
314   case JCS_EXT_ABGR:
315     neonfct = jsimd_ycc_extxbgr_convert_neon;
316     break;
317   case JCS_EXT_XRGB:
318   case JCS_EXT_ARGB:
319     neonfct = jsimd_ycc_extxrgb_convert_neon;
320     break;
321   default:
322     neonfct = jsimd_ycc_extrgb_convert_neon;
323     break;
324   }
325
326   neonfct(cinfo->output_width, input_buf, input_row, output_buf, num_rows);
327 }
328
329 GLOBAL(void)
330 jsimd_ycc_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
331                          JDIMENSION input_row, JSAMPARRAY output_buf,
332                          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)
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_NEON)
352     return 1;
353
354   return 0;
355 }
356
357 GLOBAL(int)
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_NEON)
371     return 1;
372
373   return 0;
374 }
375
376 GLOBAL(void)
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)
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)
395 jsimd_can_h2v2_upsample(void)
396 {
397   init_simd();
398
399   /* The code is optimised for these values only */
400   if (BITS_IN_JSAMPLE != 8)
401     return 0;
402   if (sizeof(JDIMENSION) != 4)
403     return 0;
404
405   if (simd_support & JSIMD_NEON)
406     return 1;
407
408   return 0;
409 }
410
411 GLOBAL(int)
412 jsimd_can_h2v1_upsample(void)
413 {
414   init_simd();
415
416   /* The code is optimised for these values only */
417   if (BITS_IN_JSAMPLE != 8)
418     return 0;
419   if (sizeof(JDIMENSION) != 4)
420     return 0;
421   if (simd_support & JSIMD_NEON)
422     return 1;
423
424   return 0;
425 }
426
427 GLOBAL(void)
428 jsimd_h2v2_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
429                     JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
430 {
431   jsimd_h2v2_upsample_neon(cinfo->max_v_samp_factor, cinfo->output_width,
432                            input_data, output_data_ptr);
433 }
434
435 GLOBAL(void)
436 jsimd_h2v1_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
437                     JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
438 {
439   jsimd_h2v1_upsample_neon(cinfo->max_v_samp_factor, cinfo->output_width,
440                            input_data, output_data_ptr);
441 }
442
443 GLOBAL(int)
444 jsimd_can_h2v2_fancy_upsample(void)
445 {
446   init_simd();
447
448   /* The code is optimised for these values only */
449   if (BITS_IN_JSAMPLE != 8)
450     return 0;
451   if (sizeof(JDIMENSION) != 4)
452     return 0;
453
454   if (simd_support & JSIMD_NEON)
455     return 1;
456
457   return 0;
458 }
459
460 GLOBAL(int)
461 jsimd_can_h2v1_fancy_upsample(void)
462 {
463   init_simd();
464
465   /* The code is optimised for these values only */
466   if (BITS_IN_JSAMPLE != 8)
467     return 0;
468   if (sizeof(JDIMENSION) != 4)
469     return 0;
470
471   if (simd_support & JSIMD_NEON)
472     return 1;
473
474   return 0;
475 }
476
477 GLOBAL(int)
478 jsimd_can_h1v2_fancy_upsample(void)
479 {
480   init_simd();
481
482   /* The code is optimised for these values only */
483   if (BITS_IN_JSAMPLE != 8)
484     return 0;
485   if (sizeof(JDIMENSION) != 4)
486     return 0;
487
488   if (simd_support & JSIMD_NEON)
489     return 1;
490
491   return 0;
492 }
493
494 GLOBAL(void)
495 jsimd_h2v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
496                           JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
497 {
498   jsimd_h2v2_fancy_upsample_neon(cinfo->max_v_samp_factor,
499                                  compptr->downsampled_width, input_data,
500                                  output_data_ptr);
501 }
502
503 GLOBAL(void)
504 jsimd_h2v1_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
505                           JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
506 {
507   jsimd_h2v1_fancy_upsample_neon(cinfo->max_v_samp_factor,
508                                  compptr->downsampled_width, input_data,
509                                  output_data_ptr);
510 }
511
512 GLOBAL(void)
513 jsimd_h1v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
514                           JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
515 {
516   jsimd_h1v2_fancy_upsample_neon(cinfo->max_v_samp_factor,
517                                  compptr->downsampled_width, input_data,
518                                  output_data_ptr);
519 }
520
521 GLOBAL(int)
522 jsimd_can_h2v2_merged_upsample(void)
523 {
524   init_simd();
525
526   /* The code is optimised for these values only */
527   if (BITS_IN_JSAMPLE != 8)
528     return 0;
529   if (sizeof(JDIMENSION) != 4)
530     return 0;
531
532   if (simd_support & JSIMD_NEON)
533     return 1;
534
535   return 0;
536 }
537
538 GLOBAL(int)
539 jsimd_can_h2v1_merged_upsample(void)
540 {
541   init_simd();
542
543   /* The code is optimised for these values only */
544   if (BITS_IN_JSAMPLE != 8)
545     return 0;
546   if (sizeof(JDIMENSION) != 4)
547     return 0;
548
549   if (simd_support & JSIMD_NEON)
550     return 1;
551
552   return 0;
553 }
554
555 GLOBAL(void)
556 jsimd_h2v2_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
557                            JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf)
558 {
559   void (*neonfct) (JDIMENSION, JSAMPIMAGE, JDIMENSION, JSAMPARRAY);
560
561   switch (cinfo->out_color_space) {
562     case JCS_EXT_RGB:
563       neonfct = jsimd_h2v2_extrgb_merged_upsample_neon;
564       break;
565     case JCS_EXT_RGBX:
566     case JCS_EXT_RGBA:
567       neonfct = jsimd_h2v2_extrgbx_merged_upsample_neon;
568       break;
569     case JCS_EXT_BGR:
570       neonfct = jsimd_h2v2_extbgr_merged_upsample_neon;
571       break;
572     case JCS_EXT_BGRX:
573     case JCS_EXT_BGRA:
574       neonfct = jsimd_h2v2_extbgrx_merged_upsample_neon;
575       break;
576     case JCS_EXT_XBGR:
577     case JCS_EXT_ABGR:
578       neonfct = jsimd_h2v2_extxbgr_merged_upsample_neon;
579       break;
580     case JCS_EXT_XRGB:
581     case JCS_EXT_ARGB:
582       neonfct = jsimd_h2v2_extxrgb_merged_upsample_neon;
583       break;
584     default:
585       neonfct = jsimd_h2v2_extrgb_merged_upsample_neon;
586       break;
587   }
588
589   neonfct(cinfo->output_width, input_buf, in_row_group_ctr, output_buf);
590 }
591
592 GLOBAL(void)
593 jsimd_h2v1_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
594                            JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf)
595 {
596   void (*neonfct) (JDIMENSION, JSAMPIMAGE, JDIMENSION, JSAMPARRAY);
597
598   switch (cinfo->out_color_space) {
599     case JCS_EXT_RGB:
600       neonfct = jsimd_h2v1_extrgb_merged_upsample_neon;
601       break;
602     case JCS_EXT_RGBX:
603     case JCS_EXT_RGBA:
604       neonfct = jsimd_h2v1_extrgbx_merged_upsample_neon;
605       break;
606     case JCS_EXT_BGR:
607       neonfct = jsimd_h2v1_extbgr_merged_upsample_neon;
608       break;
609     case JCS_EXT_BGRX:
610     case JCS_EXT_BGRA:
611       neonfct = jsimd_h2v1_extbgrx_merged_upsample_neon;
612       break;
613     case JCS_EXT_XBGR:
614     case JCS_EXT_ABGR:
615       neonfct = jsimd_h2v1_extxbgr_merged_upsample_neon;
616       break;
617     case JCS_EXT_XRGB:
618     case JCS_EXT_ARGB:
619       neonfct = jsimd_h2v1_extxrgb_merged_upsample_neon;
620       break;
621     default:
622       neonfct = jsimd_h2v1_extrgb_merged_upsample_neon;
623       break;
624   }
625
626   neonfct(cinfo->output_width, input_buf, in_row_group_ctr, output_buf);
627 }
628
629 GLOBAL(int)
630 jsimd_can_convsamp(void)
631 {
632   init_simd();
633
634   /* The code is optimised for these values only */
635   if (DCTSIZE != 8)
636     return 0;
637   if (BITS_IN_JSAMPLE != 8)
638     return 0;
639   if (sizeof(JDIMENSION) != 4)
640     return 0;
641   if (sizeof(DCTELEM) != 2)
642     return 0;
643
644   if (simd_support & JSIMD_NEON)
645     return 1;
646
647   return 0;
648 }
649
650 GLOBAL(int)
651 jsimd_can_convsamp_float(void)
652 {
653   return 0;
654 }
655
656 GLOBAL(void)
657 jsimd_convsamp(JSAMPARRAY sample_data, JDIMENSION start_col,
658                DCTELEM *workspace)
659 {
660   jsimd_convsamp_neon(sample_data, start_col, workspace);
661 }
662
663 GLOBAL(void)
664 jsimd_convsamp_float(JSAMPARRAY sample_data, JDIMENSION start_col,
665                      FAST_FLOAT *workspace)
666 {
667 }
668
669 GLOBAL(int)
670 jsimd_can_fdct_islow(void)
671 {
672   init_simd();
673
674   /* The code is optimised for these values only */
675   if (DCTSIZE != 8)
676     return 0;
677   if (sizeof(DCTELEM) != 2)
678     return 0;
679
680   if (simd_support & JSIMD_NEON)
681     return 1;
682
683   return 0;
684 }
685
686 GLOBAL(int)
687 jsimd_can_fdct_ifast(void)
688 {
689   init_simd();
690
691   /* The code is optimised for these values only */
692   if (DCTSIZE != 8)
693     return 0;
694   if (sizeof(DCTELEM) != 2)
695     return 0;
696
697   if (simd_support & JSIMD_NEON)
698     return 1;
699
700   return 0;
701 }
702
703 GLOBAL(int)
704 jsimd_can_fdct_float(void)
705 {
706   return 0;
707 }
708
709 GLOBAL(void)
710 jsimd_fdct_islow(DCTELEM *data)
711 {
712   jsimd_fdct_islow_neon(data);
713 }
714
715 GLOBAL(void)
716 jsimd_fdct_ifast(DCTELEM *data)
717 {
718   jsimd_fdct_ifast_neon(data);
719 }
720
721 GLOBAL(void)
722 jsimd_fdct_float(FAST_FLOAT *data)
723 {
724 }
725
726 GLOBAL(int)
727 jsimd_can_quantize(void)
728 {
729   init_simd();
730
731   /* The code is optimised for these values only */
732   if (DCTSIZE != 8)
733     return 0;
734   if (sizeof(JCOEF) != 2)
735     return 0;
736   if (sizeof(DCTELEM) != 2)
737     return 0;
738
739   if (simd_support & JSIMD_NEON)
740     return 1;
741
742   return 0;
743 }
744
745 GLOBAL(int)
746 jsimd_can_quantize_float(void)
747 {
748   return 0;
749 }
750
751 GLOBAL(void)
752 jsimd_quantize(JCOEFPTR coef_block, DCTELEM *divisors, DCTELEM *workspace)
753 {
754   jsimd_quantize_neon(coef_block, divisors, workspace);
755 }
756
757 GLOBAL(void)
758 jsimd_quantize_float(JCOEFPTR coef_block, FAST_FLOAT *divisors,
759                      FAST_FLOAT *workspace)
760 {
761 }
762
763 GLOBAL(int)
764 jsimd_can_idct_2x2(void)
765 {
766   init_simd();
767
768   /* The code is optimised for these values only */
769   if (DCTSIZE != 8)
770     return 0;
771   if (sizeof(JCOEF) != 2)
772     return 0;
773   if (BITS_IN_JSAMPLE != 8)
774     return 0;
775   if (sizeof(JDIMENSION) != 4)
776     return 0;
777   if (sizeof(ISLOW_MULT_TYPE) != 2)
778     return 0;
779
780   if (simd_support & JSIMD_NEON)
781     return 1;
782
783   return 0;
784 }
785
786 GLOBAL(int)
787 jsimd_can_idct_4x4(void)
788 {
789   init_simd();
790
791   /* The code is optimised for these values only */
792   if (DCTSIZE != 8)
793     return 0;
794   if (sizeof(JCOEF) != 2)
795     return 0;
796   if (BITS_IN_JSAMPLE != 8)
797     return 0;
798   if (sizeof(JDIMENSION) != 4)
799     return 0;
800   if (sizeof(ISLOW_MULT_TYPE) != 2)
801     return 0;
802
803   if (simd_support & JSIMD_NEON)
804     return 1;
805
806   return 0;
807 }
808
809 GLOBAL(void)
810 jsimd_idct_2x2(j_decompress_ptr cinfo, jpeg_component_info *compptr,
811                JCOEFPTR coef_block, JSAMPARRAY output_buf,
812                JDIMENSION output_col)
813 {
814   jsimd_idct_2x2_neon(compptr->dct_table, coef_block, output_buf, output_col);
815 }
816
817 GLOBAL(void)
818 jsimd_idct_4x4(j_decompress_ptr cinfo, jpeg_component_info *compptr,
819                JCOEFPTR coef_block, JSAMPARRAY output_buf,
820                JDIMENSION output_col)
821 {
822   jsimd_idct_4x4_neon(compptr->dct_table, coef_block, output_buf, output_col);
823 }
824
825 GLOBAL(int)
826 jsimd_can_idct_islow(void)
827 {
828   init_simd();
829
830   /* The code is optimised for these values only */
831   if (DCTSIZE != 8)
832     return 0;
833   if (sizeof(JCOEF) != 2)
834     return 0;
835   if (BITS_IN_JSAMPLE != 8)
836     return 0;
837   if (sizeof(JDIMENSION) != 4)
838     return 0;
839   if (sizeof(ISLOW_MULT_TYPE) != 2)
840     return 0;
841
842   if (simd_support & JSIMD_NEON)
843     return 1;
844
845   return 0;
846 }
847
848 GLOBAL(int)
849 jsimd_can_idct_ifast(void)
850 {
851   init_simd();
852
853   /* The code is optimised for these values only */
854   if (DCTSIZE != 8)
855     return 0;
856   if (sizeof(JCOEF) != 2)
857     return 0;
858   if (BITS_IN_JSAMPLE != 8)
859     return 0;
860   if (sizeof(JDIMENSION) != 4)
861     return 0;
862   if (sizeof(IFAST_MULT_TYPE) != 2)
863     return 0;
864   if (IFAST_SCALE_BITS != 2)
865     return 0;
866
867   if (simd_support & JSIMD_NEON)
868     return 1;
869
870   return 0;
871 }
872
873 GLOBAL(int)
874 jsimd_can_idct_float(void)
875 {
876   return 0;
877 }
878
879 GLOBAL(void)
880 jsimd_idct_islow(j_decompress_ptr cinfo, jpeg_component_info *compptr,
881                  JCOEFPTR coef_block, JSAMPARRAY output_buf,
882                  JDIMENSION output_col)
883 {
884   jsimd_idct_islow_neon(compptr->dct_table, coef_block, output_buf,
885                         output_col);
886 }
887
888 GLOBAL(void)
889 jsimd_idct_ifast(j_decompress_ptr cinfo, jpeg_component_info *compptr,
890                  JCOEFPTR coef_block, JSAMPARRAY output_buf,
891                  JDIMENSION output_col)
892 {
893   jsimd_idct_ifast_neon(compptr->dct_table, coef_block, output_buf,
894                         output_col);
895 }
896
897 GLOBAL(void)
898 jsimd_idct_float(j_decompress_ptr cinfo, jpeg_component_info *compptr,
899                  JCOEFPTR coef_block, JSAMPARRAY output_buf,
900                  JDIMENSION output_col)
901 {
902 }
903
904 GLOBAL(int)
905 jsimd_can_huff_encode_one_block(void)
906 {
907   init_simd();
908
909   if (DCTSIZE != 8)
910     return 0;
911   if (sizeof(JCOEF) != 2)
912     return 0;
913
914   if (simd_support & JSIMD_NEON && simd_huffman)
915     return 1;
916
917   return 0;
918 }
919
920 GLOBAL(JOCTET *)
921 jsimd_huff_encode_one_block(void *state, JOCTET *buffer, JCOEFPTR block,
922                             int last_dc_val, c_derived_tbl *dctbl,
923                             c_derived_tbl *actbl)
924 {
925   return jsimd_huff_encode_one_block_neon(state, buffer, block, last_dc_val,
926                                           dctbl, actbl);
927 }
928
929 GLOBAL(int)
930 jsimd_can_encode_mcu_AC_first_prepare(void)
931 {
932   init_simd();
933
934   if (DCTSIZE != 8)
935     return 0;
936   if (sizeof(JCOEF) != 2)
937     return 0;
938
939   if (simd_support & JSIMD_NEON)
940     return 1;
941
942   return 0;
943 }
944
945 GLOBAL(void)
946 jsimd_encode_mcu_AC_first_prepare(const JCOEF *block,
947                                   const int *jpeg_natural_order_start, int Sl,
948                                   int Al, JCOEF *values, size_t *zerobits)
949 {
950   jsimd_encode_mcu_AC_first_prepare_neon(block, jpeg_natural_order_start,
951                                          Sl, Al, values, zerobits);
952 }
953
954 GLOBAL(int)
955 jsimd_can_encode_mcu_AC_refine_prepare(void)
956 {
957   init_simd();
958
959   if (DCTSIZE != 8)
960     return 0;
961   if (sizeof(JCOEF) != 2)
962     return 0;
963
964   if (simd_support & JSIMD_NEON)
965     return 1;
966
967   return 0;
968 }
969
970 GLOBAL(int)
971 jsimd_encode_mcu_AC_refine_prepare(const JCOEF *block,
972                                    const int *jpeg_natural_order_start, int Sl,
973                                    int Al, JCOEF *absvalues, size_t *bits)
974 {
975   return jsimd_encode_mcu_AC_refine_prepare_neon(block,
976                                                  jpeg_natural_order_start, Sl,
977                                                  Al, absvalues, bits);
978 }