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