jsimd_mips.c revision 2ccf4d1a70d6311484f2f8aeb386b2ed747ad95c
1/*
2 * jsimd_mips.c
3 *
4 * Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
5 * Copyright 2009-2011 D. R. Commander
6 * Copyright (C) 2013, MIPS Technologies, Inc., California
7 *
8 * Based on the x86 SIMD extension for IJG JPEG library,
9 * Copyright (C) 1999-2006, MIYASAKA Masaru.
10 * For conditions of distribution and use, see copyright notice in jsimdext.inc
11 *
12 * This file contains the interface between the "normal" portions
13 * of the library and the SIMD implementations when running on
14 * MIPS architecture.
15 *
16 * Based on the stubs from 'jsimd_none.c'
17 */
18
19#define JPEG_INTERNALS
20#include "../jinclude.h"
21#include "../jpeglib.h"
22#include "../jsimd.h"
23#include "../jdct.h"
24#include "../jsimddct.h"
25#include "jsimd.h"
26
27#include <stdio.h>
28#include <string.h>
29#include <ctype.h>
30
31static unsigned int simd_support = ~0;
32
33#if defined(__linux__)
34
35LOCAL(int)
36parse_proc_cpuinfo(const char* search_string)
37{
38  const char* file_name = "/proc/cpuinfo";
39  char cpuinfo_line[256];
40  FILE* f = NULL;
41  simd_support = 0;
42
43  if ((f = fopen(file_name, "r")) != NULL) {
44    while (fgets(cpuinfo_line, sizeof(cpuinfo_line), f) != NULL) {
45      if (strstr(cpuinfo_line, search_string) != NULL) {
46        fclose(f);
47        simd_support |= JSIMD_MIPS_DSPR2;
48        return 1;
49      }
50    }
51    fclose(f);
52  }
53  /* Did not find string in the proc file, or not Linux ELF. */
54  return 0;
55}
56#endif
57
58/*
59 * Check what SIMD accelerations are supported.
60 *
61 * FIXME: This code is racy under a multi-threaded environment.
62 */
63LOCAL(void)
64init_simd (void)
65{
66  if (simd_support != ~0U)
67    return;
68
69  simd_support = 0;
70
71#if defined(__mips__) && defined(__mips_dsp) && (__mips_dsp_rev >= 2)
72  simd_support |= JSIMD_MIPS_DSPR2;
73#elif defined(__linux__)
74  /* We still have a chance to use MIPS DSPR2 regardless of globally used
75   * -mdspr2 options passed to gcc by performing runtime detection via
76   * /proc/cpuinfo parsing on linux */
77  if (!parse_proc_cpuinfo("MIPS 74K"))
78    return;
79#endif
80}
81
82GLOBAL(int)
83jsimd_can_rgb_ycc (void)
84{
85  init_simd();
86
87  /* The code is optimised for these values only */
88  if (BITS_IN_JSAMPLE != 8)
89    return 0;
90  if (sizeof(JDIMENSION) != 4)
91    return 0;
92  if ((RGB_PIXELSIZE != 3) && (RGB_PIXELSIZE != 4))
93    return 0;
94  if (simd_support & JSIMD_MIPS_DSPR2)
95    return 1;
96
97  return 0;
98}
99
100GLOBAL(int)
101jsimd_can_rgb_gray (void)
102{
103  init_simd();
104
105  /* The code is optimised for these values only */
106  if (BITS_IN_JSAMPLE != 8)
107    return 0;
108  if (sizeof(JDIMENSION) != 4)
109    return 0;
110  if ((RGB_PIXELSIZE != 3) && (RGB_PIXELSIZE != 4))
111    return 0;
112  if (simd_support & JSIMD_MIPS_DSPR2)
113    return 1;
114
115  return 0;
116}
117
118GLOBAL(int)
119jsimd_can_ycc_rgb (void)
120{
121  init_simd();
122
123  /* The code is optimised for these values only */
124  if (BITS_IN_JSAMPLE != 8)
125    return 0;
126  if (sizeof(JDIMENSION) != 4)
127    return 0;
128  if ((RGB_PIXELSIZE != 3) && (RGB_PIXELSIZE != 4))
129    return 0;
130  if (simd_support & JSIMD_MIPS_DSPR2)
131    return 1;
132
133  return 0;
134}
135
136GLOBAL(void)
137jsimd_rgb_ycc_convert (j_compress_ptr cinfo,
138                       JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
139                       JDIMENSION output_row, int num_rows)
140{
141  void (*mipsdspr2fct)(JDIMENSION, JSAMPARRAY, JSAMPIMAGE, JDIMENSION, int);
142  switch(cinfo->in_color_space)
143  {
144    case JCS_EXT_RGB:
145      mipsdspr2fct=jsimd_extrgb_ycc_convert_mips_dspr2;
146      break;
147    case JCS_EXT_RGBX:
148    case JCS_EXT_RGBA:
149      mipsdspr2fct=jsimd_extrgbx_ycc_convert_mips_dspr2;
150      break;
151    case JCS_EXT_BGR:
152      mipsdspr2fct=jsimd_extbgr_ycc_convert_mips_dspr2;
153      break;
154    case JCS_EXT_BGRX:
155    case JCS_EXT_BGRA:
156      mipsdspr2fct=jsimd_extbgrx_ycc_convert_mips_dspr2;
157      break;
158    case JCS_EXT_XBGR:
159    case JCS_EXT_ABGR:
160      mipsdspr2fct=jsimd_extxbgr_ycc_convert_mips_dspr2;
161
162      break;
163    case JCS_EXT_XRGB:
164    case JCS_EXT_ARGB:
165      mipsdspr2fct=jsimd_extxrgb_ycc_convert_mips_dspr2;
166      break;
167    default:
168      mipsdspr2fct=jsimd_extrgb_ycc_convert_mips_dspr2;
169      break;
170  }
171
172  if (simd_support & JSIMD_MIPS_DSPR2)
173    mipsdspr2fct(cinfo->image_width, input_buf,
174        output_buf, output_row, num_rows);
175}
176
177GLOBAL(void)
178jsimd_rgb_gray_convert (j_compress_ptr cinfo,
179                        JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
180                        JDIMENSION output_row, int num_rows)
181{
182  void (*mipsdspr2fct)(JDIMENSION, JSAMPARRAY, JSAMPIMAGE, JDIMENSION, int);
183  switch(cinfo->in_color_space)
184  {
185    case JCS_EXT_RGB:
186      mipsdspr2fct=jsimd_extrgb_gray_convert_mips_dspr2;
187      break;
188    case JCS_EXT_RGBX:
189    case JCS_EXT_RGBA:
190      mipsdspr2fct=jsimd_extrgbx_gray_convert_mips_dspr2;
191      break;
192    case JCS_EXT_BGR:
193      mipsdspr2fct=jsimd_extbgr_gray_convert_mips_dspr2;
194      break;
195    case JCS_EXT_BGRX:
196    case JCS_EXT_BGRA:
197      mipsdspr2fct=jsimd_extbgrx_gray_convert_mips_dspr2;
198      break;
199    case JCS_EXT_XBGR:
200    case JCS_EXT_ABGR:
201      mipsdspr2fct=jsimd_extxbgr_gray_convert_mips_dspr2;
202      break;
203    case JCS_EXT_XRGB:
204    case JCS_EXT_ARGB:
205      mipsdspr2fct=jsimd_extxrgb_gray_convert_mips_dspr2;
206      break;
207    default:
208      mipsdspr2fct=jsimd_extrgb_gray_convert_mips_dspr2;
209      break;
210  }
211
212  if (simd_support & JSIMD_MIPS_DSPR2)
213    mipsdspr2fct(cinfo->image_width, input_buf,
214        output_buf, output_row, num_rows);
215
216}
217
218GLOBAL(void)
219jsimd_ycc_rgb_convert (j_decompress_ptr cinfo,
220                       JSAMPIMAGE input_buf, JDIMENSION input_row,
221                       JSAMPARRAY output_buf, int num_rows)
222{
223  void (*mipsdspr2fct)(JDIMENSION, JSAMPIMAGE, JDIMENSION, JSAMPARRAY, int);
224
225  switch(cinfo->out_color_space)
226  {
227    case JCS_EXT_RGB:
228      mipsdspr2fct=jsimd_ycc_extrgb_convert_mips_dspr2;
229      break;
230    case JCS_EXT_RGBX:
231    case JCS_EXT_RGBA:
232      mipsdspr2fct=jsimd_ycc_extrgbx_convert_mips_dspr2;
233      break;
234    case JCS_EXT_BGR:
235      mipsdspr2fct=jsimd_ycc_extbgr_convert_mips_dspr2;
236      break;
237    case JCS_EXT_BGRX:
238    case JCS_EXT_BGRA:
239      mipsdspr2fct=jsimd_ycc_extbgrx_convert_mips_dspr2;
240      break;
241    case JCS_EXT_XBGR:
242    case JCS_EXT_ABGR:
243      mipsdspr2fct=jsimd_ycc_extxbgr_convert_mips_dspr2;
244      break;
245    case JCS_EXT_XRGB:
246    case JCS_EXT_ARGB:
247      mipsdspr2fct=jsimd_ycc_extxrgb_convert_mips_dspr2;
248      break;
249  default:
250      mipsdspr2fct=jsimd_ycc_extrgb_convert_mips_dspr2;
251      break;
252  }
253
254  if (simd_support & JSIMD_MIPS_DSPR2)
255    mipsdspr2fct(cinfo->output_width, input_buf,
256        input_row, output_buf, num_rows);
257}
258
259GLOBAL(int)
260jsimd_can_h2v2_downsample (void)
261{
262  init_simd();
263
264  /* The code is optimised for these values only */
265  if (BITS_IN_JSAMPLE != 8)
266    return 0;
267  if (sizeof(JDIMENSION) != 4)
268    return 0;
269  if (simd_support & JSIMD_MIPS_DSPR2)
270    return 1;
271
272  return 0;
273}
274
275GLOBAL(int)
276jsimd_can_h2v1_downsample (void)
277{
278  init_simd();
279
280  /* The code is optimised for these values only */
281  if (BITS_IN_JSAMPLE != 8)
282    return 0;
283  if (sizeof(JDIMENSION) != 4)
284    return 0;
285  if (simd_support & JSIMD_MIPS_DSPR2)
286    return 1;
287
288  return 0;
289}
290
291GLOBAL(void)
292jsimd_h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
293                       JSAMPARRAY input_data, JSAMPARRAY output_data)
294{
295  if (simd_support & JSIMD_MIPS_DSPR2)
296    jsimd_h2v2_downsample_mips_dspr2(cinfo->image_width,
297        cinfo->max_v_samp_factor, compptr->v_samp_factor,
298        compptr->width_in_blocks, input_data, output_data);
299}
300
301GLOBAL(void)
302jsimd_h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
303                       JSAMPARRAY input_data, JSAMPARRAY output_data)
304{
305  if (simd_support & JSIMD_MIPS_DSPR2)
306    jsimd_h2v1_downsample_mips_dspr2(cinfo->image_width,
307        cinfo->max_v_samp_factor, compptr->v_samp_factor,
308        compptr->width_in_blocks, input_data, output_data);
309}
310
311GLOBAL(int)
312jsimd_can_h2v2_upsample (void)
313{
314  init_simd();
315
316  /* The code is optimised for these values only */
317  if (BITS_IN_JSAMPLE != 8)
318    return 0;
319  if (sizeof(JDIMENSION) != 4)
320    return 0;
321  if (simd_support & JSIMD_MIPS_DSPR2)
322    return 1;
323
324  return 0;
325}
326
327GLOBAL(int)
328jsimd_can_h2v1_upsample (void)
329{
330  init_simd();
331
332  /* The code is optimised for these values only */
333  if (BITS_IN_JSAMPLE != 8)
334    return 0;
335  if (sizeof(JDIMENSION) != 4)
336    return 0;
337  if (simd_support & JSIMD_MIPS_DSPR2)
338    return 1;
339
340  return 0;
341}
342
343GLOBAL(void)
344jsimd_h2v2_upsample (j_decompress_ptr cinfo,
345                     jpeg_component_info * compptr,
346                     JSAMPARRAY input_data,
347                     JSAMPARRAY * output_data_ptr)
348{
349  if (simd_support & JSIMD_MIPS_DSPR2)
350    jsimd_h2v2_upsample_mips_dspr2(cinfo->max_v_samp_factor,
351        cinfo->output_width, input_data, output_data_ptr);
352}
353
354GLOBAL(void)
355jsimd_h2v1_upsample (j_decompress_ptr cinfo,
356                     jpeg_component_info * compptr,
357                     JSAMPARRAY input_data,
358                     JSAMPARRAY * output_data_ptr)
359{
360  if (simd_support & JSIMD_MIPS_DSPR2)
361    jsimd_h2v1_upsample_mips_dspr2(cinfo->max_v_samp_factor,
362        cinfo->output_width, input_data, output_data_ptr);
363}
364
365GLOBAL(int)
366jsimd_can_h2v2_fancy_upsample (void)
367{
368  init_simd();
369
370  /* The code is optimised for these values only */
371  if (BITS_IN_JSAMPLE != 8)
372    return 0;
373  if (sizeof(JDIMENSION) != 4)
374    return 0;
375  if (simd_support & JSIMD_MIPS_DSPR2)
376    return 1;
377
378  return 0;
379}
380
381GLOBAL(int)
382jsimd_can_h2v1_fancy_upsample (void)
383{
384  init_simd();
385
386  /* The code is optimised for these values only */
387  if (BITS_IN_JSAMPLE != 8)
388    return 0;
389  if (sizeof(JDIMENSION) != 4)
390    return 0;
391  if (simd_support & JSIMD_MIPS_DSPR2)
392    return 1;
393
394  return 0;
395}
396
397GLOBAL(void)
398jsimd_h2v2_fancy_upsample (j_decompress_ptr cinfo,
399                           jpeg_component_info * compptr,
400                           JSAMPARRAY input_data,
401                           JSAMPARRAY * output_data_ptr)
402{
403  if (simd_support & JSIMD_MIPS_DSPR2)
404    jsimd_h2v2_fancy_upsample_mips_dspr2(cinfo->max_v_samp_factor,
405        compptr->downsampled_width, input_data, output_data_ptr);
406}
407
408GLOBAL(void)
409jsimd_h2v1_fancy_upsample (j_decompress_ptr cinfo,
410                           jpeg_component_info * compptr,
411                           JSAMPARRAY input_data,
412                           JSAMPARRAY * output_data_ptr)
413{
414  if (simd_support & JSIMD_MIPS_DSPR2)
415    jsimd_h2v1_fancy_upsample_mips_dspr2(cinfo->max_v_samp_factor,
416        compptr->downsampled_width, input_data, output_data_ptr);
417}
418
419GLOBAL(int)
420jsimd_can_h2v2_merged_upsample (void)
421{
422  return 0;
423}
424
425GLOBAL(int)
426jsimd_can_h2v1_merged_upsample (void)
427{
428  return 0;
429}
430
431GLOBAL(void)
432jsimd_h2v2_merged_upsample (j_decompress_ptr cinfo,
433                            JSAMPIMAGE input_buf,
434                            JDIMENSION in_row_group_ctr,
435                            JSAMPARRAY output_buf)
436{
437}
438
439GLOBAL(void)
440jsimd_h2v1_merged_upsample (j_decompress_ptr cinfo,
441                            JSAMPIMAGE input_buf,
442                            JDIMENSION in_row_group_ctr,
443                            JSAMPARRAY output_buf)
444{
445}
446
447GLOBAL(int)
448jsimd_can_convsamp (void)
449{
450  return 0;
451}
452
453GLOBAL(int)
454jsimd_can_convsamp_float (void)
455{
456  return 0;
457}
458
459GLOBAL(void)
460jsimd_convsamp (JSAMPARRAY sample_data, JDIMENSION start_col,
461                DCTELEM * workspace)
462{
463}
464
465GLOBAL(void)
466jsimd_convsamp_float (JSAMPARRAY sample_data, JDIMENSION start_col,
467                      FAST_FLOAT * workspace)
468{
469}
470
471GLOBAL(int)
472jsimd_can_fdct_islow (void)
473{
474  return 0;
475}
476
477GLOBAL(int)
478jsimd_can_fdct_ifast (void)
479{
480  return 0;
481}
482
483GLOBAL(int)
484jsimd_can_fdct_float (void)
485{
486  return 0;
487}
488
489GLOBAL(void)
490jsimd_fdct_islow (DCTELEM * data)
491{
492}
493
494GLOBAL(void)
495jsimd_fdct_ifast (DCTELEM * data)
496{
497}
498
499GLOBAL(void)
500jsimd_fdct_float (FAST_FLOAT * data)
501{
502}
503
504GLOBAL(int)
505jsimd_can_quantize (void)
506{
507  return 0;
508}
509
510GLOBAL(int)
511jsimd_can_quantize_float (void)
512{
513  return 0;
514}
515
516GLOBAL(void)
517jsimd_quantize (JCOEFPTR coef_block, DCTELEM * divisors,
518                DCTELEM * workspace)
519{
520}
521
522GLOBAL(void)
523jsimd_quantize_float (JCOEFPTR coef_block, FAST_FLOAT * divisors,
524                      FAST_FLOAT * workspace)
525{
526}
527
528GLOBAL(int)
529jsimd_can_idct_2x2 (void)
530{
531  init_simd();
532
533  /* The code is optimised for these values only */
534  if (DCTSIZE != 8)
535    return 0;
536  if (sizeof(JCOEF) != 2)
537    return 0;
538  if (BITS_IN_JSAMPLE != 8)
539    return 0;
540  if (sizeof(JDIMENSION) != 4)
541    return 0;
542  if (sizeof(ISLOW_MULT_TYPE) != 2)
543    return 0;
544
545  if ((simd_support & JSIMD_MIPS_DSPR2))
546    return 1;
547
548  return 0;
549}
550
551GLOBAL(int)
552jsimd_can_idct_4x4 (void)
553{
554  init_simd();
555
556  /* The code is optimised for these values only */
557  if (DCTSIZE != 8)
558    return 0;
559  if (sizeof(JCOEF) != 2)
560    return 0;
561  if (BITS_IN_JSAMPLE != 8)
562    return 0;
563  if (sizeof(JDIMENSION) != 4)
564    return 0;
565  if (sizeof(ISLOW_MULT_TYPE) != 2)
566    return 0;
567
568  if ((simd_support & JSIMD_MIPS_DSPR2))
569    return 1;
570
571  return 0;
572}
573
574GLOBAL(void)
575jsimd_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
576                JCOEFPTR coef_block, JSAMPARRAY output_buf,
577                JDIMENSION output_col)
578{
579  if ((simd_support & JSIMD_MIPS_DSPR2))
580    jsimd_idct_2x2_mips_dspr2(compptr->dct_table, coef_block,
581                              output_buf, output_col);
582}
583
584GLOBAL(void)
585jsimd_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
586                JCOEFPTR coef_block, JSAMPARRAY output_buf,
587                JDIMENSION output_col)
588{
589  if ((simd_support & JSIMD_MIPS_DSPR2))
590  {
591    int workspace[DCTSIZE*4];  /* buffers data between passes */
592    jsimd_idct_4x4_mips_dspr2(compptr->dct_table, coef_block,
593                              output_buf, output_col, workspace);
594  }
595}
596
597GLOBAL(int)
598jsimd_can_idct_islow (void)
599{
600  return 0;
601}
602
603GLOBAL(int)
604jsimd_can_idct_ifast (void)
605{
606  return 0;
607}
608
609GLOBAL(int)
610jsimd_can_idct_float (void)
611{
612  return 0;
613}
614
615GLOBAL(void)
616jsimd_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr,
617                JCOEFPTR coef_block, JSAMPARRAY output_buf,
618                JDIMENSION output_col)
619{
620}
621
622GLOBAL(void)
623jsimd_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr,
624                JCOEFPTR coef_block, JSAMPARRAY output_buf,
625                JDIMENSION output_col)
626{
627}
628
629GLOBAL(void)
630jsimd_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr,
631                JCOEFPTR coef_block, JSAMPARRAY output_buf,
632                JDIMENSION output_col)
633{
634}
635