mips_init.c (6599B)
1 /* mips_init.c - MSA optimised filter functions 2 * 3 * Copyright (c) 2018-2024 Cosmin Truta 4 * Copyright (c) 2016 Glenn Randers-Pehrson 5 * Written by Mandar Sahastrabuddhe, 2016 6 * Updated by guxiwei, 2023 7 * 8 * This code is released under the libpng license. 9 * For conditions of distribution and use, see the disclaimer 10 * and license in png.h 11 */ 12 13 /* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are 14 * called. 15 */ 16 #define _POSIX_SOURCE 1 17 18 #include <stdio.h> 19 #include "../pngpriv.h" 20 21 #ifdef PNG_READ_SUPPORTED 22 23 #if PNG_MIPS_MSA_IMPLEMENTATION == 1 || PNG_MIPS_MMI_IMPLEMENTATION > 0 24 25 #ifdef PNG_MIPS_MSA_CHECK_SUPPORTED /* Do MIPS MSA run-time checks */ 26 /* WARNING: it is strongly recommended that you do not build libpng with 27 * run-time checks for CPU features if at all possible. In the case of the MIPS 28 * MSA instructions there is no processor-specific way of detecting the 29 * presence of the required support, therefore run-time detection is extremely 30 * OS specific. 31 * 32 * You may set the macro PNG_MIPS_MSA_FILE to the file name of file containing 33 * a fragment of C source code which defines the png_have_msa function. There 34 * are a number of implementations in contrib/mips-msa, but the only one that 35 * has partial support is contrib/mips-msa/linux.c - a generic Linux 36 * implementation which reads /proc/cpufino. 37 */ 38 #ifndef PNG_MIPS_MSA_FILE 39 # ifdef __linux__ 40 # define PNG_MIPS_MSA_FILE "contrib/mips-msa/linux.c" 41 # endif 42 #endif 43 44 #ifdef PNG_MIPS_MSA_FILE 45 46 #include <signal.h> /* for sig_atomic_t */ 47 static int png_have_msa(png_structp png_ptr); 48 #include PNG_MIPS_MSA_FILE 49 50 #else /* PNG_MIPS_MSA_FILE */ 51 # error PNG_MIPS_MSA_FILE undefined: no support for run-time MIPS MSA checks 52 #endif /* PNG_MIPS_MSA_FILE */ 53 #endif /* PNG_MIPS_MSA_CHECK_SUPPORTED */ 54 55 #ifdef PNG_MIPS_MMI_CHECK_SUPPORTED /* Do MIPS MMI run-times checks */ 56 #ifndef PNG_MIPS_MMI_FILE 57 # ifdef __linux__ 58 # define PNG_MIPS_MMI_FILE "contrib/mips-mmi/linux.c" 59 # endif 60 #endif 61 62 #ifdef PNG_MIPS_MMI_FILE 63 64 #include <signal.h> /* for sig_atomic_t */ 65 static int png_have_mmi(); 66 #include PNG_MIPS_MMI_FILE 67 68 #else /* PNG_MIPS_MMI_FILE */ 69 # error PNG_MIPS_MMI_FILE undefined: no support for run-time MIPS MMI checks 70 #endif /* PNG_MIPS_MMI_FILE */ 71 #endif /* PNG_MIPS_MMI_CHECK_SUPPORTED*/ 72 73 #ifndef PNG_ALIGNED_MEMORY_SUPPORTED 74 # error ALIGNED_MEMORY is required; please define PNG_ALIGNED_MEMORY_SUPPORTED 75 #endif 76 77 /* MIPS supports two optimizations: MMI and MSA. The appropriate 78 * optimization is chosen at runtime 79 */ 80 void 81 png_init_filter_functions_mips(png_structp pp, unsigned int bpp) 82 { 83 #if PNG_MIPS_MMI_IMPLEMENTATION > 0 84 #ifdef PNG_MIPS_MMI_API_SUPPORTED 85 switch ((pp->options >> PNG_MIPS_MMI) & 3) 86 { 87 case PNG_OPTION_UNSET: 88 #endif /* PNG_MIPS_MMI_API_SUPPORTED */ 89 #ifdef PNG_MIPS_MMI_CHECK_SUPPORTED 90 { 91 static volatile sig_atomic_t no_mmi = -1; /* not checked */ 92 93 if (no_mmi < 0) 94 no_mmi = !png_have_mmi(); 95 96 if (no_mmi) 97 goto MIPS_MSA_INIT; 98 } 99 #ifdef PNG_MIPS_MMI_API_SUPPORTED 100 break; 101 #endif 102 #endif /* PNG_MIPS_MMI_CHECK_SUPPORTED */ 103 104 #ifdef PNG_MIPS_MMI_API_SUPPORTED 105 default: /* OFF or INVALID */ 106 goto MIPS_MSA_INIT; 107 108 case PNG_OPTION_ON: 109 /* Option turned on */ 110 break; 111 } 112 #endif 113 pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_mmi; 114 if (bpp == 3) 115 { 116 pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_mmi; 117 pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_mmi; 118 pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = 119 png_read_filter_row_paeth3_mmi; 120 } 121 else if (bpp == 4) 122 { 123 pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_mmi; 124 pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_mmi; 125 pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = 126 png_read_filter_row_paeth4_mmi; 127 } 128 #endif /* PNG_MIPS_MMI_IMPLEMENTATION > 0 */ 129 130 MIPS_MSA_INIT: 131 #if PNG_MIPS_MSA_IMPLEMENTATION == 1 132 /* The switch statement is compiled in for MIPS_MSA_API, the call to 133 * png_have_msa is compiled in for MIPS_MSA_CHECK. If both are defined 134 * the check is only performed if the API has not set the MSA option on 135 * or off explicitly. In this case the check controls what happens. 136 */ 137 138 #ifdef PNG_MIPS_MSA_API_SUPPORTED 139 switch ((pp->options >> PNG_MIPS_MSA) & 3) 140 { 141 case PNG_OPTION_UNSET: 142 /* Allow the run-time check to execute if it has been enabled - 143 * thus both API and CHECK can be turned on. If it isn't supported 144 * this case will fall through to the 'default' below, which just 145 * returns. 146 */ 147 #endif /* PNG_MIPS_MSA_API_SUPPORTED */ 148 #ifdef PNG_MIPS_MSA_CHECK_SUPPORTED 149 { 150 static volatile sig_atomic_t no_msa = -1; /* not checked */ 151 152 if (no_msa < 0) 153 no_msa = !png_have_msa(pp); 154 155 if (no_msa) 156 return; 157 } 158 #ifdef PNG_MIPS_MSA_API_SUPPORTED 159 break; 160 #endif 161 #endif /* PNG_MIPS_MSA_CHECK_SUPPORTED */ 162 163 #ifdef PNG_MIPS_MSA_API_SUPPORTED 164 default: /* OFF or INVALID */ 165 return; 166 167 case PNG_OPTION_ON: 168 /* Option turned on */ 169 break; 170 } 171 #endif 172 173 /* IMPORTANT: any new external functions used here must be declared using 174 * PNG_INTERNAL_FUNCTION in ../pngpriv.h. This is required so that the 175 * 'prefix' option to configure works: 176 * 177 * ./configure --with-libpng-prefix=foobar_ 178 * 179 * Verify you have got this right by running the above command, doing a build 180 * and examining pngprefix.h; it must contain a #define for every external 181 * function you add. (Notice that this happens automatically for the 182 * initialization function.) 183 */ 184 pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_msa; 185 186 if (bpp == 3) 187 { 188 pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_msa; 189 pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_msa; 190 pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth3_msa; 191 } 192 193 else if (bpp == 4) 194 { 195 pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_msa; 196 pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_msa; 197 pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth4_msa; 198 } 199 #endif /* PNG_MIPS_MSA_IMPLEMENTATION == 1 */ 200 return; 201 } 202 #endif /* PNG_MIPS_MSA_IMPLEMENTATION == 1 || PNG_MIPS_MMI_IMPLEMENTATION > 0 */ 203 #endif /* READ */