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