Home | History | Annotate | Download | only in simd
      1 /*
      2  * jsimd_arm64.c
      3  *
      4  * Copyright 2009 Pierre Ossman <ossman (at) 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)
     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)
     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)
    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)
    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)
    185 jsimd_can_rgb_gray (void)
    186 {
    187   init_simd();
    188 
    189   return 0;
    190 }
    191 
    192 GLOBAL(int)
    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)
    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)
    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)
    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)
    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)
    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)
    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)
    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)
    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   return 0;
    400 }
    401 
    402 GLOBAL(int)
    403 jsimd_can_h2v1_upsample (void)
    404 {
    405   init_simd();
    406 
    407   return 0;
    408 }
    409 
    410 GLOBAL(void)
    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)
    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)
    427 jsimd_can_h2v2_fancy_upsample (void)
    428 {
    429   init_simd();
    430 
    431   return 0;
    432 }
    433 
    434 GLOBAL(int)
    435 jsimd_can_h2v1_fancy_upsample (void)
    436 {
    437   init_simd();
    438 
    439   return 0;
    440 }
    441 
    442 GLOBAL(void)
    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)
    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)
    459 jsimd_can_h2v2_merged_upsample (void)
    460 {
    461   init_simd();
    462 
    463   return 0;
    464 }
    465 
    466 GLOBAL(int)
    467 jsimd_can_h2v1_merged_upsample (void)
    468 {
    469   init_simd();
    470 
    471   return 0;
    472 }
    473 
    474 GLOBAL(void)
    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)
    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)
    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)
    512 jsimd_can_convsamp_float (void)
    513 {
    514   init_simd();
    515 
    516   return 0;
    517 }
    518 
    519 GLOBAL(void)
    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)
    527 jsimd_convsamp_float (JSAMPARRAY sample_data, JDIMENSION start_col,
    528                       FAST_FLOAT *workspace)
    529 {
    530 }
    531 
    532 GLOBAL(int)
    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)
    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)
    567 jsimd_can_fdct_float (void)
    568 {
    569   init_simd();
    570 
    571   return 0;
    572 }
    573 
    574 GLOBAL(void)
    575 jsimd_fdct_islow (DCTELEM *data)
    576 {
    577   jsimd_fdct_islow_neon(data);
    578 }
    579 
    580 GLOBAL(void)
    581 jsimd_fdct_ifast (DCTELEM *data)
    582 {
    583   jsimd_fdct_ifast_neon(data);
    584 }
    585 
    586 GLOBAL(void)
    587 jsimd_fdct_float (FAST_FLOAT *data)
    588 {
    589 }
    590 
    591 GLOBAL(int)
    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)
    611 jsimd_can_quantize_float (void)
    612 {
    613   init_simd();
    614 
    615   return 0;
    616 }
    617 
    618 GLOBAL(void)
    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)
    626 jsimd_quantize_float (JCOEFPTR coef_block, FAST_FLOAT *divisors,
    627                       FAST_FLOAT *workspace)
    628 {
    629 }
    630 
    631 GLOBAL(int)
    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)
    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)
    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)
    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)
    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)
    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)
    744 jsimd_can_idct_float (void)
    745 {
    746   init_simd();
    747 
    748   return 0;
    749 }
    750 
    751 GLOBAL(void)
    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)
    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)
    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)
    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*)
    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