make some global var static (fix a build failure with shared lib on x86_64)
[ffmpeg.git] / libswscale / yuv2rgb_altivec.c
1 /*
2   marc.hoffman@analog.com    March 8, 2004
3
4   Altivec Acceleration for Color Space Conversion revision 0.2
5
6   convert I420 YV12 to RGB in various formats,
7     it rejects images that are not in 420 formats
8     it rejects images that don't have widths of multiples of 16
9     it rejects images that don't have heights of multiples of 2
10   reject defers to C simulation codes.
11
12   lots of optimizations to be done here
13
14   1. need to fix saturation code, I just couldn't get it to fly with packs and adds.
15      so we currently use max min to clip
16
17   2. the inefficient use of chroma loading needs a bit of brushing up
18
19   3. analysis of pipeline stalls needs to be done, use shark to identify pipeline stalls
20
21
22   MODIFIED to calculate coeffs from currently selected color space.
23   MODIFIED core to be a macro which you spec the output format.
24   ADDED UYVY conversion which is never called due to some thing in SWSCALE.
25   CORRECTED algorithim selection to be strict on input formats.
26   ADDED runtime detection of altivec.
27
28   ADDED altivec_yuv2packedX vertical scl + RGB converter
29
30   March 27,2004
31   PERFORMANCE ANALYSIS
32
33   The C version use 25% of the processor or ~250Mips for D1 video rawvideo used as test
34   The ALTIVEC version uses 10% of the processor or ~100Mips for D1 video same sequence
35
36   720*480*30  ~10MPS
37
38   so we have roughly 10clocks per pixel this is too high something has to be wrong.
39
40   OPTIMIZED clip codes to utilize vec_max and vec_packs removing the need for vec_min.
41
42   OPTIMIZED DST OUTPUT cache/dma controls. we are pretty much
43   guaranteed to have the input video frame it was just decompressed so
44   it probably resides in L1 caches.  However we are creating the
45   output video stream this needs to use the DSTST instruction to
46   optimize for the cache.  We couple this with the fact that we are
47   not going to be visiting the input buffer again so we mark it Least
48   Recently Used.  This shaves 25% of the processor cycles off.
49
50   Now MEMCPY is the largest mips consumer in the system, probably due
51   to the inefficient X11 stuff.
52
53   GL libraries seem to be very slow on this machine 1.33Ghz PB running
54   Jaguar, this is not the case for my 1Ghz PB.  I thought it might be
55   a versioning issues, however i have libGL.1.2.dylib for both
56   machines. ((We need to figure this out now))
57
58   GL2 libraries work now with patch for RGB32
59
60   NOTE quartz vo driver ARGB32_to_RGB24 consumes 30% of the processor
61
62   Integrated luma prescaling adjustment for saturation/contrast/brightness adjustment. 
63
64   This program is free software; you can redistribute it and/or modify
65   it under the terms of the GNU General Public License as published by
66   the Free Software Foundation; either version 2 of the License, or
67   (at your option) any later version.
68
69   This program is distributed in the hope that it will be useful,
70   but WITHOUT ANY WARRANTY; without even the implied warranty of
71   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
72   GNU General Public License for more details.
73
74   You should have received a copy of the GNU General Public License
75   along with this program; if not, write to the Free Software
76   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
77
78 */
79 #include <stdio.h>
80 #include <stdlib.h>
81 #include <string.h>
82 #include <inttypes.h>
83 #include <assert.h>
84 #include "config.h"
85 #ifdef HAVE_MALLOC_H
86 #include <malloc.h>
87 #endif
88 #include "rgb2rgb.h"
89 #include "swscale.h"
90 #include "swscale_internal.h"
91
92 #undef PROFILE_THE_BEAST
93 #undef INC_SCALING
94
95 typedef unsigned char ubyte;
96 typedef signed char   sbyte;
97
98
99 /* RGB interleaver, 16 planar pels 8-bit samples per channel in
100    homogeneous vector registers x0,x1,x2 are interleaved with the
101    following technique:
102
103       o0 = vec_mergeh (x0,x1);
104       o1 = vec_perm (o0, x2, perm_rgb_0);
105       o2 = vec_perm (o0, x2, perm_rgb_1);
106       o3 = vec_mergel (x0,x1);
107       o4 = vec_perm (o3,o2,perm_rgb_2);
108       o5 = vec_perm (o3,o2,perm_rgb_3);
109
110   perm_rgb_0:   o0(RG).h v1(B) --> o1*
111               0   1  2   3   4
112              rgbr|gbrg|brgb|rgbr
113              0010 0100 1001 0010
114              0102 3145 2673 894A
115
116   perm_rgb_1:   o0(RG).h v1(B) --> o2
117               0   1  2   3   4
118              gbrg|brgb|bbbb|bbbb
119              0100 1001 1111 1111
120              B5CD 6EF7 89AB CDEF
121
122   perm_rgb_2:   o3(RG).l o2(rgbB.l) --> o4*
123               0   1  2   3   4
124              gbrg|brgb|rgbr|gbrg
125              1111 1111 0010 0100
126              89AB CDEF 0182 3945
127
128   perm_rgb_2:   o3(RG).l o2(rgbB.l) ---> o5*
129               0   1  2   3   4
130              brgb|rgbr|gbrg|brgb
131              1001 0010 0100 1001
132              a67b 89cA BdCD eEFf
133
134 */
135 static
136 const vector unsigned char
137   perm_rgb_0 = (const vector unsigned char)AVV(0x00,0x01,0x10,0x02,0x03,0x11,0x04,0x05,
138                                       0x12,0x06,0x07,0x13,0x08,0x09,0x14,0x0a),
139   perm_rgb_1 = (const vector unsigned char)AVV(0x0b,0x15,0x0c,0x0d,0x16,0x0e,0x0f,0x17,
140                                       0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f),
141   perm_rgb_2 = (const vector unsigned char)AVV(0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
142                                       0x00,0x01,0x18,0x02,0x03,0x19,0x04,0x05),
143   perm_rgb_3 = (const vector unsigned char)AVV(0x1a,0x06,0x07,0x1b,0x08,0x09,0x1c,0x0a,
144                                       0x0b,0x1d,0x0c,0x0d,0x1e,0x0e,0x0f,0x1f);
145
146 #define vec_merge3(x2,x1,x0,y0,y1,y2)    \
147 do {                                     \
148   typeof(x0) o0,o2,o3;                   \
149       o0 = vec_mergeh (x0,x1);           \
150       y0 = vec_perm (o0, x2, perm_rgb_0);\
151       o2 = vec_perm (o0, x2, perm_rgb_1);\
152       o3 = vec_mergel (x0,x1);           \
153       y1 = vec_perm (o3,o2,perm_rgb_2);  \
154       y2 = vec_perm (o3,o2,perm_rgb_3);  \
155 } while(0)
156
157 #define vec_mstbgr24(x0,x1,x2,ptr)        \
158 do {                                     \
159   typeof(x0) _0,_1,_2;                   \
160   vec_merge3 (x0,x1,x2,_0,_1,_2);        \
161   vec_st (_0, 0, ptr++);                 \
162   vec_st (_1, 0, ptr++);                 \
163   vec_st (_2, 0, ptr++);                 \
164 }  while (0);
165
166 #define vec_mstrgb24(x0,x1,x2,ptr)       \
167 do {                                     \
168   typeof(x0) _0,_1,_2;                   \
169   vec_merge3 (x2,x1,x0,_0,_1,_2);        \
170   vec_st (_0, 0, ptr++);                 \
171   vec_st (_1, 0, ptr++);                 \
172   vec_st (_2, 0, ptr++);                 \
173 }  while (0);
174
175 /* pack the pixels in rgb0 format
176    msb R
177    lsb 0
178 */
179 #define vec_mstrgb32(T,x0,x1,x2,x3,ptr)                                                \
180 do {                                                                                   \
181   T _0,_1,_2,_3;                                                                       \
182   _0 = vec_mergeh (x0,x1);                                                             \
183   _1 = vec_mergeh (x2,x3);                                                             \
184   _2 = (T)vec_mergeh ((vector unsigned short)_0,(vector unsigned short)_1);            \
185   _3 = (T)vec_mergel ((vector unsigned short)_0,(vector unsigned short)_1);            \
186   vec_st (_2, 0*16, (T *)ptr);                                                         \
187   vec_st (_3, 1*16, (T *)ptr);                                                         \
188   _0 = vec_mergel (x0,x1);                                                             \
189   _1 = vec_mergel (x2,x3);                                                             \
190   _2 = (T)vec_mergeh ((vector unsigned short)_0,(vector unsigned short)_1);            \
191   _3 = (T)vec_mergel ((vector unsigned short)_0,(vector unsigned short)_1);            \
192   vec_st (_2, 2*16, (T *)ptr);                                                         \
193   vec_st (_3, 3*16, (T *)ptr);                                                         \
194   ptr += 4;                                                                            \
195 }  while (0);
196
197 /*
198
199   | 1     0       1.4021   | | Y |
200   | 1    -0.3441 -0.7142   |x| Cb|
201   | 1     1.7718  0        | | Cr|
202
203
204   Y:      [-128 127]
205   Cb/Cr : [-128 127]
206
207   typical yuv conversion work on Y: 0-255 this version has been optimized for jpeg decode.
208
209 */
210
211
212
213
214 #define vec_unh(x) \
215   (vector signed short) \
216     vec_perm(x,(typeof(x))AVV(0),\
217              (vector unsigned char)AVV(0x10,0x00,0x10,0x01,0x10,0x02,0x10,0x03,\
218                                     0x10,0x04,0x10,0x05,0x10,0x06,0x10,0x07))
219 #define vec_unl(x) \
220   (vector signed short) \
221     vec_perm(x,(typeof(x))AVV(0),\
222              (vector unsigned char)AVV(0x10,0x08,0x10,0x09,0x10,0x0A,0x10,0x0B,\
223                                     0x10,0x0C,0x10,0x0D,0x10,0x0E,0x10,0x0F))
224
225 #define vec_clip_s16(x) \
226   vec_max (vec_min (x, (vector signed short)AVV(235,235,235,235,235,235,235,235)),\
227                        (vector signed short)AVV(16, 16, 16, 16, 16, 16, 16, 16 ))
228
229 #define vec_packclp(x,y) \
230   (vector unsigned char)vec_packs \
231       ((vector unsigned short)vec_max (x,(vector signed short) AVV(0)), \
232        (vector unsigned short)vec_max (y,(vector signed short) AVV(0)))
233
234 //#define out_pixels(a,b,c,ptr) vec_mstrgb32(typeof(a),((typeof (a))AVV(0)),a,a,a,ptr)
235
236
237 static inline void cvtyuvtoRGB (SwsContext *c,
238                            vector signed short Y, vector signed short U, vector signed short V,
239                            vector signed short *R, vector signed short *G, vector signed short *B)
240 {
241   vector signed   short vx,ux,uvx;
242
243   Y = vec_mradds (Y, c->CY, c->OY);
244   U  = vec_sub (U,(vector signed short)
245                         vec_splat((vector signed short)AVV(128),0));
246   V  = vec_sub (V,(vector signed short)
247                         vec_splat((vector signed short)AVV(128),0));
248
249   //   ux  = (CBU*(u<<c->CSHIFT)+0x4000)>>15;
250   ux = vec_sl (U, c->CSHIFT);
251   *B = vec_mradds (ux, c->CBU, Y);
252
253   // vx  = (CRV*(v<<c->CSHIFT)+0x4000)>>15;
254   vx = vec_sl (V, c->CSHIFT);
255   *R = vec_mradds (vx, c->CRV, Y);
256
257   // uvx = ((CGU*u) + (CGV*v))>>15;
258   uvx = vec_mradds (U, c->CGU, Y);
259   *G = vec_mradds (V, c->CGV, uvx);
260 }
261
262
263 /*
264   ------------------------------------------------------------------------------
265   CS converters
266   ------------------------------------------------------------------------------
267 */
268
269
270 #define DEFCSP420_CVT(name,out_pixels)                                     \
271 static int altivec_##name (SwsContext *c,                                  \
272                                 unsigned char **in, int *instrides,        \
273                                 int srcSliceY,  int srcSliceH,             \
274                                 unsigned char **oplanes, int *outstrides)  \
275 {                                                                          \
276   int w = c->srcW;                                                         \
277   int h = srcSliceH;                                                       \
278   int i,j;                                                                 \
279   int instrides_scl[3];                                                    \
280   vector unsigned char y0,y1;                                              \
281                                                                            \
282   vector signed char  u,v;                                                 \
283                                                                            \
284   vector signed short Y0,Y1,Y2,Y3;                                         \
285   vector signed short U,V;                                                 \
286   vector signed short vx,ux,uvx;                                           \
287   vector signed short vx0,ux0,uvx0;                                        \
288   vector signed short vx1,ux1,uvx1;                                        \
289   vector signed short R0,G0,B0;                                            \
290   vector signed short R1,G1,B1;                                            \
291   vector unsigned char R,G,B;                                              \
292                                                                            \
293   vector unsigned char *y1ivP, *y2ivP, *uivP, *vivP;                       \
294   vector unsigned char align_perm;                                         \
295                                                                            \
296   vector signed short                                                      \
297     lCY  = c->CY,                                                          \
298     lOY  = c->OY,                                                          \
299     lCRV = c->CRV,                                                         \
300     lCBU = c->CBU,                                                         \
301     lCGU = c->CGU,                                                         \
302     lCGV = c->CGV;                                                         \
303                                                                            \
304   vector unsigned short lCSHIFT = c->CSHIFT;                               \
305                                                                            \
306   ubyte *y1i   = in[0];                                                    \
307   ubyte *y2i   = in[0]+instrides[0];                                       \
308   ubyte *ui    = in[1];                                                    \
309   ubyte *vi    = in[2];                                                    \
310                                                                            \
311   vector unsigned char *oute                                               \
312     = (vector unsigned char *)                                             \
313         (oplanes[0]+srcSliceY*outstrides[0]);                              \
314   vector unsigned char *outo                                               \
315     = (vector unsigned char *)                                             \
316         (oplanes[0]+srcSliceY*outstrides[0]+outstrides[0]);                \
317                                                                            \
318                                                                            \
319   instrides_scl[0] = instrides[0]*2-w;  /* the loop moves y{1,2}i by w */  \
320   instrides_scl[1] = instrides[1]-w/2;  /* the loop moves ui by w/2 */     \
321   instrides_scl[2] = instrides[2]-w/2;  /* the loop moves vi by w/2 */     \
322                                                                            \
323                                                                            \
324   for (i=0;i<h/2;i++) {                                                    \
325     vec_dstst (outo, (0x02000002|(((w*3+32)/32)<<16)), 0);                 \
326     vec_dstst (oute, (0x02000002|(((w*3+32)/32)<<16)), 1);                 \
327                                                                            \
328     for (j=0;j<w/16;j++) {                                                 \
329                                                                            \
330       y1ivP = (vector unsigned char *)y1i;                                 \
331       y2ivP = (vector unsigned char *)y2i;                                 \
332       uivP = (vector unsigned char *)ui;                                   \
333       vivP = (vector unsigned char *)vi;                                   \
334                                                                            \
335       align_perm = vec_lvsl (0, y1i);                                      \
336       y0 = (vector unsigned char)vec_perm (y1ivP[0], y1ivP[1], align_perm);\
337                                                                            \
338       align_perm = vec_lvsl (0, y2i);                                      \
339       y1 = (vector unsigned char)vec_perm (y2ivP[0], y2ivP[1], align_perm);\
340                                                                            \
341       align_perm = vec_lvsl (0, ui);                                       \
342       u = (vector signed char)vec_perm (uivP[0], uivP[1], align_perm);     \
343                                                                            \
344       align_perm = vec_lvsl (0, vi);                                       \
345       v = (vector signed char)vec_perm (vivP[0], vivP[1], align_perm);     \
346                                                                            \
347       u  = (vector signed char)                                            \
348                 vec_sub (u,(vector signed char)                            \
349                                 vec_splat((vector signed char)AVV(128),0));\
350       v  = (vector signed char)                                            \
351                 vec_sub (v,(vector signed char)                            \
352                                 vec_splat((vector signed char)AVV(128),0));\
353                                                                            \
354       U  = vec_unpackh (u);                                                \
355       V  = vec_unpackh (v);                                                \
356                                                                            \
357                                                                            \
358         Y0 = vec_unh (y0);                                                 \
359         Y1 = vec_unl (y0);                                                 \
360         Y2 = vec_unh (y1);                                                 \
361         Y3 = vec_unl (y1);                                                 \
362                                                                            \
363         Y0 = vec_mradds (Y0, lCY, lOY);                                    \
364         Y1 = vec_mradds (Y1, lCY, lOY);                                    \
365         Y2 = vec_mradds (Y2, lCY, lOY);                                    \
366         Y3 = vec_mradds (Y3, lCY, lOY);                                    \
367                                                                            \
368         /*   ux  = (CBU*(u<<CSHIFT)+0x4000)>>15 */                         \
369         ux = vec_sl (U, lCSHIFT);                                          \
370         ux = vec_mradds (ux, lCBU, (vector signed short)AVV(0));                   \
371         ux0  = vec_mergeh (ux,ux);                                         \
372         ux1  = vec_mergel (ux,ux);                                         \
373                                                                            \
374         /* vx  = (CRV*(v<<CSHIFT)+0x4000)>>15;  */                         \
375         vx = vec_sl (V, lCSHIFT);                                          \
376         vx = vec_mradds (vx, lCRV, (vector signed short)AVV(0));                   \
377         vx0  = vec_mergeh (vx,vx);                                         \
378         vx1  = vec_mergel (vx,vx);                                         \
379                                                                            \
380         /* uvx = ((CGU*u) + (CGV*v))>>15 */                                \
381         uvx = vec_mradds (U, lCGU, (vector signed short)AVV(0));                   \
382         uvx = vec_mradds (V, lCGV, uvx);                                   \
383         uvx0 = vec_mergeh (uvx,uvx);                                       \
384         uvx1 = vec_mergel (uvx,uvx);                                       \
385                                                                            \
386         R0 = vec_add (Y0,vx0);                                             \
387         G0 = vec_add (Y0,uvx0);                                            \
388         B0 = vec_add (Y0,ux0);                                             \
389         R1 = vec_add (Y1,vx1);                                             \
390         G1 = vec_add (Y1,uvx1);                                            \
391         B1 = vec_add (Y1,ux1);                                             \
392                                                                            \
393         R  = vec_packclp (R0,R1);                                          \
394         G  = vec_packclp (G0,G1);                                          \
395         B  = vec_packclp (B0,B1);                                          \
396                                                                            \
397         out_pixels(R,G,B,oute);                                            \
398                                                                            \
399         R0 = vec_add (Y2,vx0);                                             \
400         G0 = vec_add (Y2,uvx0);                                            \
401         B0 = vec_add (Y2,ux0);                                             \
402         R1 = vec_add (Y3,vx1);                                             \
403         G1 = vec_add (Y3,uvx1);                                            \
404         B1 = vec_add (Y3,ux1);                                             \
405         R  = vec_packclp (R0,R1);                                          \
406         G  = vec_packclp (G0,G1);                                          \
407         B  = vec_packclp (B0,B1);                                          \
408                                                                            \
409                                                                            \
410         out_pixels(R,G,B,outo);                                            \
411                                                                            \
412       y1i  += 16;                                                          \
413       y2i  += 16;                                                          \
414       ui   += 8;                                                           \
415       vi   += 8;                                                           \
416                                                                            \
417     }                                                                      \
418                                                                            \
419     outo += (outstrides[0])>>4;                                            \
420     oute += (outstrides[0])>>4;                                            \
421                                                                            \
422     ui    += instrides_scl[1];                                             \
423     vi    += instrides_scl[2];                                             \
424     y1i   += instrides_scl[0];                                             \
425     y2i   += instrides_scl[0];                                             \
426   }                                                                        \
427   return srcSliceH;                                                        \
428 }
429
430
431 #define out_abgr(a,b,c,ptr)  vec_mstrgb32(typeof(a),((typeof (a))AVV(0)),c,b,a,ptr)
432 #define out_bgra(a,b,c,ptr)  vec_mstrgb32(typeof(a),c,b,a,((typeof (a))AVV(0)),ptr)
433 #define out_rgba(a,b,c,ptr)  vec_mstrgb32(typeof(a),a,b,c,((typeof (a))AVV(0)),ptr)
434 #define out_argb(a,b,c,ptr)  vec_mstrgb32(typeof(a),((typeof (a))AVV(0)),a,b,c,ptr)
435 #define out_rgb24(a,b,c,ptr) vec_mstrgb24(a,b,c,ptr)
436 #define out_bgr24(a,b,c,ptr) vec_mstbgr24(a,b,c,ptr)
437
438 DEFCSP420_CVT (yuv2_abgr, out_abgr)
439 #if 1
440 DEFCSP420_CVT (yuv2_bgra, out_bgra)
441 #else
442 static int altivec_yuv2_bgra32 (SwsContext *c,                                  
443                                 unsigned char **in, int *instrides,        
444                                 int srcSliceY,  int srcSliceH,             
445                                 unsigned char **oplanes, int *outstrides)  
446 {                                                                          
447   int w = c->srcW;                                                         
448   int h = srcSliceH;                                                       
449   int i,j;                                                                 
450   int instrides_scl[3];                                                    
451   vector unsigned char y0,y1;                                              
452                                                                            
453   vector signed char  u,v;                                                 
454                                                                            
455   vector signed short Y0,Y1,Y2,Y3;                                         
456   vector signed short U,V;                                                 
457   vector signed short vx,ux,uvx;                                           
458   vector signed short vx0,ux0,uvx0;                                        
459   vector signed short vx1,ux1,uvx1;                                        
460   vector signed short R0,G0,B0;                                            
461   vector signed short R1,G1,B1;                                            
462   vector unsigned char R,G,B;                                              
463                                                                            
464   vector unsigned char *uivP, *vivP;                                       
465   vector unsigned char align_perm;                                         
466                                                                            
467   vector signed short                                                      
468     lCY  = c->CY,                                                          
469     lOY  = c->OY,                                                          
470     lCRV = c->CRV,                                                         
471     lCBU = c->CBU,                                                         
472     lCGU = c->CGU,                                                         
473     lCGV = c->CGV;                                                         
474                                                                            
475   vector unsigned short lCSHIFT = c->CSHIFT;                               
476                                                                            
477   ubyte *y1i   = in[0];                                                    
478   ubyte *y2i   = in[0]+w;                                                  
479   ubyte *ui    = in[1];                                                    
480   ubyte *vi    = in[2];                                                    
481                                                                            
482   vector unsigned char *oute                                               
483     = (vector unsigned char *)                                             
484         (oplanes[0]+srcSliceY*outstrides[0]);                              
485   vector unsigned char *outo                                               
486     = (vector unsigned char *)                                             
487         (oplanes[0]+srcSliceY*outstrides[0]+outstrides[0]);                
488                                                                            
489                                                                            
490   instrides_scl[0] = instrides[0];                                         
491   instrides_scl[1] = instrides[1]-w/2;  /* the loop moves ui by w/2 */     
492   instrides_scl[2] = instrides[2]-w/2;  /* the loop moves vi by w/2 */     
493                                                                            
494                                                                            
495   for (i=0;i<h/2;i++) {                                                    
496     vec_dstst (outo, (0x02000002|(((w*3+32)/32)<<16)), 0);                 
497     vec_dstst (oute, (0x02000002|(((w*3+32)/32)<<16)), 1);                 
498                                                                            
499     for (j=0;j<w/16;j++) {                                                 
500                                                                            
501       y0 = vec_ldl (0,y1i);                                                
502       y1 = vec_ldl (0,y2i);                                                
503       uivP = (vector unsigned char *)ui;                                   
504       vivP = (vector unsigned char *)vi;                                   
505                                                                            
506       align_perm = vec_lvsl (0, ui);                                       
507       u = (vector signed char)vec_perm (uivP[0], uivP[1], align_perm);     
508                                                                            
509       align_perm = vec_lvsl (0, vi);                                       
510       v = (vector signed char)vec_perm (vivP[0], vivP[1], align_perm);
511       u  = (vector signed char)
512                 vec_sub (u,(vector signed char)
513                                 vec_splat((vector signed char)AVV(128),0));
514       
515       v  = (vector signed char)
516                 vec_sub (v, (vector signed char)
517                                 vec_splat((vector signed char)AVV(128),0));
518       
519       U  = vec_unpackh (u);                                                
520       V  = vec_unpackh (v);                                                
521                                                                            
522                                                                            
523         Y0 = vec_unh (y0);                                                 
524         Y1 = vec_unl (y0);                                                 
525         Y2 = vec_unh (y1);                                                 
526         Y3 = vec_unl (y1);                                                 
527                                                                            
528         Y0 = vec_mradds (Y0, lCY, lOY);                                    
529         Y1 = vec_mradds (Y1, lCY, lOY);                                    
530         Y2 = vec_mradds (Y2, lCY, lOY);                                    
531         Y3 = vec_mradds (Y3, lCY, lOY);                                    
532                                                                            
533         /*   ux  = (CBU*(u<<CSHIFT)+0x4000)>>15 */                         
534         ux = vec_sl (U, lCSHIFT);                                          
535         ux = vec_mradds (ux, lCBU, (vector signed short)AVV(0));
536         ux0  = vec_mergeh (ux,ux);                                         
537         ux1  = vec_mergel (ux,ux);                                         
538                                                                            
539         /* vx  = (CRV*(v<<CSHIFT)+0x4000)>>15;  */                         
540         vx = vec_sl (V, lCSHIFT);                                          
541         vx = vec_mradds (vx, lCRV, (vector signed short)AVV(0));
542         vx0  = vec_mergeh (vx,vx);
543         vx1  = vec_mergel (vx,vx);
544         /* uvx = ((CGU*u) + (CGV*v))>>15 */
545         uvx = vec_mradds (U, lCGU, (vector signed short)AVV(0));
546         uvx = vec_mradds (V, lCGV, uvx);
547         uvx0 = vec_mergeh (uvx,uvx);
548         uvx1 = vec_mergel (uvx,uvx);
549         R0 = vec_add (Y0,vx0);
550         G0 = vec_add (Y0,uvx0);
551         B0 = vec_add (Y0,ux0);
552         R1 = vec_add (Y1,vx1);
553         G1 = vec_add (Y1,uvx1);
554         B1 = vec_add (Y1,ux1);
555         R  = vec_packclp (R0,R1);
556         G  = vec_packclp (G0,G1);
557         B  = vec_packclp (B0,B1);
558         
559         out_argb(R,G,B,oute);
560         R0 = vec_add (Y2,vx0);
561         G0 = vec_add (Y2,uvx0);
562         B0 = vec_add (Y2,ux0);
563         R1 = vec_add (Y3,vx1);
564         G1 = vec_add (Y3,uvx1);
565         B1 = vec_add (Y3,ux1);
566         R  = vec_packclp (R0,R1);
567         G  = vec_packclp (G0,G1);
568         B  = vec_packclp (B0,B1);
569         
570         out_argb(R,G,B,outo);
571         y1i  += 16;                                                        
572         y2i  += 16;                                                        
573         ui   += 8;
574         vi   += 8;                                                         
575                                                                            
576     }                                                                      
577                                                                            
578     outo += (outstrides[0])>>4;                                            
579     oute += (outstrides[0])>>4;                                            
580                                                                            
581     ui    += instrides_scl[1];                                             
582     vi    += instrides_scl[2];                                             
583     y1i   += instrides_scl[0];                                             
584     y2i   += instrides_scl[0];                                             
585   }                                                                        
586   return srcSliceH;                                                        
587 }
588
589 #endif
590
591
592 DEFCSP420_CVT (yuv2_rgba, out_rgba)
593 DEFCSP420_CVT (yuv2_argb, out_argb)
594 DEFCSP420_CVT (yuv2_rgb24,  out_rgb24)
595 DEFCSP420_CVT (yuv2_bgr24,  out_bgr24)
596
597
598 // uyvy|uyvy|uyvy|uyvy
599 // 0123 4567 89ab cdef
600 static
601 const vector unsigned char
602   demux_u = (const vector unsigned char)AVV(0x10,0x00,0x10,0x00,
603                                    0x10,0x04,0x10,0x04,
604                                    0x10,0x08,0x10,0x08,
605                                    0x10,0x0c,0x10,0x0c),
606   demux_v = (const vector unsigned char)AVV(0x10,0x02,0x10,0x02,
607                                    0x10,0x06,0x10,0x06,
608                                    0x10,0x0A,0x10,0x0A,
609                                    0x10,0x0E,0x10,0x0E),
610   demux_y = (const vector unsigned char)AVV(0x10,0x01,0x10,0x03,
611                                    0x10,0x05,0x10,0x07,
612                                    0x10,0x09,0x10,0x0B,
613                                    0x10,0x0D,0x10,0x0F);
614
615 /*
616   this is so I can play live CCIR raw video
617 */
618 static int altivec_uyvy_rgb32 (SwsContext *c,
619                                unsigned char **in, int *instrides,
620                                int srcSliceY,   int srcSliceH,
621                                unsigned char **oplanes, int *outstrides)
622 {
623   int w = c->srcW;
624   int h = srcSliceH;
625   int i,j;
626   vector unsigned char uyvy;
627   vector signed   short Y,U,V;
628   vector signed   short R0,G0,B0,R1,G1,B1;
629   vector unsigned char  R,G,B;
630   vector unsigned char *out;
631   ubyte *img;
632
633   img = in[0];
634   out = (vector unsigned char *)(oplanes[0]+srcSliceY*outstrides[0]);
635
636   for (i=0;i<h;i++) {
637     for (j=0;j<w/16;j++) {
638       uyvy = vec_ld (0, img);
639       U = (vector signed short)
640         vec_perm (uyvy, (vector unsigned char)AVV(0), demux_u);
641
642       V = (vector signed short)
643         vec_perm (uyvy, (vector unsigned char)AVV(0), demux_v);
644
645       Y = (vector signed short)
646         vec_perm (uyvy, (vector unsigned char)AVV(0), demux_y);
647
648       cvtyuvtoRGB (c, Y,U,V,&R0,&G0,&B0);
649
650       uyvy = vec_ld (16, img);
651       U = (vector signed short)
652         vec_perm (uyvy, (vector unsigned char)AVV(0), demux_u);
653
654       V = (vector signed short)
655         vec_perm (uyvy, (vector unsigned char)AVV(0), demux_v);
656
657       Y = (vector signed short)
658         vec_perm (uyvy, (vector unsigned char)AVV(0), demux_y);
659
660       cvtyuvtoRGB (c, Y,U,V,&R1,&G1,&B1);
661
662       R  = vec_packclp (R0,R1);
663       G  = vec_packclp (G0,G1);
664       B  = vec_packclp (B0,B1);
665
666       //      vec_mstbgr24 (R,G,B, out);
667       out_rgba (R,G,B,out);
668
669       img += 32;
670     }
671   }
672   return srcSliceH;
673 }
674
675
676
677 /* Ok currently the acceleration routine only supports
678    inputs of widths a multiple of 16
679    and heights a multiple 2
680
681    So we just fall back to the C codes for this.
682 */
683 SwsFunc yuv2rgb_init_altivec (SwsContext *c)
684 {
685   if (!(c->flags & SWS_CPU_CAPS_ALTIVEC))    
686     return NULL;
687
688   /*
689     and this seems not to matter too much I tried a bunch of 
690     videos with abnormal widths and mplayer crashes else where.
691     mplayer -vo x11 -rawvideo on:w=350:h=240 raw-350x240.eyuv 
692     boom with X11 bad match.
693     
694   */
695   if ((c->srcW & 0xf) != 0)    return NULL;
696
697   switch (c->srcFormat) {
698   case PIX_FMT_YUV410P:
699   case PIX_FMT_YUV420P:
700   /*case IMGFMT_CLPL:   ??? */
701   case PIX_FMT_GRAY8:
702   case PIX_FMT_NV12:
703   case PIX_FMT_NV21:
704     if ((c->srcH & 0x1) != 0)
705       return NULL;
706
707     switch(c->dstFormat){
708     case PIX_FMT_RGB24:
709       MSG_WARN("ALTIVEC: Color Space RGB24\n");
710       return altivec_yuv2_rgb24;
711     case PIX_FMT_BGR24:
712       MSG_WARN("ALTIVEC: Color Space BGR24\n");
713       return altivec_yuv2_bgr24;
714     case PIX_FMT_ARGB:
715       MSG_WARN("ALTIVEC: Color Space ARGB\n");
716       return altivec_yuv2_argb;
717     case PIX_FMT_ABGR:
718       MSG_WARN("ALTIVEC: Color Space ABGR\n");
719       return altivec_yuv2_abgr;
720     case PIX_FMT_RGBA:
721       MSG_WARN("ALTIVEC: Color Space RGBA\n");
722       return altivec_yuv2_rgba;
723     case PIX_FMT_BGRA:
724       MSG_WARN("ALTIVEC: Color Space BGRA\n");
725       return altivec_yuv2_bgra;
726     default: return NULL;
727     }
728     break;
729
730   case PIX_FMT_UYVY422:
731     switch(c->dstFormat){
732     case PIX_FMT_BGR32:
733       MSG_WARN("ALTIVEC: Color Space UYVY -> RGB32\n");
734       return altivec_uyvy_rgb32;
735     default: return NULL;
736     }
737     break;
738
739   }
740   return NULL;
741 }
742
743 static uint16_t roundToInt16(int64_t f){
744         int r= (f + (1<<15))>>16;
745              if(r<-0x7FFF) return 0x8000;
746         else if(r> 0x7FFF) return 0x7FFF;
747         else               return r;
748 }
749
750 void yuv2rgb_altivec_init_tables (SwsContext *c, const int inv_table[4],int brightness,int contrast, int saturation)
751 {
752   union {
753         signed short tmp[8] __attribute__ ((aligned(16)));
754         vector signed short vec;
755         } buf;
756
757   buf.tmp[0] =  ( (0xffffLL) * contrast>>8 )>>9;                        //cy
758   buf.tmp[1] =  -256*brightness;                                        //oy
759   buf.tmp[2] =  (inv_table[0]>>3) *(contrast>>16)*(saturation>>16);     //crv
760   buf.tmp[3] =  (inv_table[1]>>3) *(contrast>>16)*(saturation>>16);     //cbu
761   buf.tmp[4] = -((inv_table[2]>>1)*(contrast>>16)*(saturation>>16));    //cgu
762   buf.tmp[5] = -((inv_table[3]>>1)*(contrast>>16)*(saturation>>16));    //cgv
763
764
765   c->CSHIFT = (vector unsigned short)vec_splat_u16(2);
766   c->CY  = vec_splat ((vector signed short)buf.vec, 0);
767   c->OY  = vec_splat ((vector signed short)buf.vec, 1);
768   c->CRV  = vec_splat ((vector signed short)buf.vec, 2);
769   c->CBU  = vec_splat ((vector signed short)buf.vec, 3);
770   c->CGU  = vec_splat ((vector signed short)buf.vec, 4);
771   c->CGV  = vec_splat ((vector signed short)buf.vec, 5);
772 #if 0
773 {
774 int i;
775 char *v[6]={"cy","oy","crv","cbu","cgu","cgv"};
776 for (i=0; i<6;i++)
777   printf("%s %d ", v[i],buf.tmp[i] );
778   printf("\n");
779 }
780 #endif
781  return;
782 }
783
784
785 void
786 altivec_yuv2packedX (SwsContext *c,
787                        int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
788                        int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,
789                        uint8_t *dest, int dstW, int dstY)
790 {
791   int i,j;
792   vector signed short X,X0,X1,Y0,U0,V0,Y1,U1,V1,U,V;
793   vector signed short R0,G0,B0,R1,G1,B1;
794
795   vector unsigned char R,G,B;
796   vector unsigned char *out,*nout;
797
798   vector signed short   RND = vec_splat_s16(1<<3);
799   vector unsigned short SCL = vec_splat_u16(4);
800   unsigned long scratch[16] __attribute__ ((aligned (16)));
801
802   vector signed short *YCoeffs, *CCoeffs;
803
804   YCoeffs = c->vYCoeffsBank+dstY*lumFilterSize;
805   CCoeffs = c->vCCoeffsBank+dstY*chrFilterSize;
806
807   out = (vector unsigned char *)dest;
808
809   for(i=0; i<dstW; i+=16){
810     Y0 = RND;
811     Y1 = RND;
812     /* extract 16 coeffs from lumSrc */
813     for(j=0; j<lumFilterSize; j++) {
814       X0 = vec_ld (0,  &lumSrc[j][i]);
815       X1 = vec_ld (16, &lumSrc[j][i]);
816       Y0 = vec_mradds (X0, YCoeffs[j], Y0);
817       Y1 = vec_mradds (X1, YCoeffs[j], Y1);
818     }
819
820     U = RND;
821     V = RND;
822     /* extract 8 coeffs from U,V */
823     for(j=0; j<chrFilterSize; j++) {
824       X  = vec_ld (0, &chrSrc[j][i/2]);
825       U  = vec_mradds (X, CCoeffs[j], U);
826       X  = vec_ld (0, &chrSrc[j][i/2+2048]);
827       V  = vec_mradds (X, CCoeffs[j], V);
828     }
829
830     /* scale and clip signals */
831     Y0 = vec_sra (Y0, SCL);
832     Y1 = vec_sra (Y1, SCL);
833     U  = vec_sra (U,  SCL);
834     V  = vec_sra (V,  SCL);
835
836     Y0 = vec_clip_s16 (Y0);
837     Y1 = vec_clip_s16 (Y1);
838     U  = vec_clip_s16 (U);
839     V  = vec_clip_s16 (V);
840
841     /* now we have
842       Y0= y0 y1 y2 y3 y4 y5 y6 y7     Y1= y8 y9 y10 y11 y12 y13 y14 y15
843       U= u0 u1 u2 u3 u4 u5 u6 u7      V= v0 v1 v2 v3 v4 v5 v6 v7
844
845       Y0= y0 y1 y2 y3 y4 y5 y6 y7    Y1= y8 y9 y10 y11 y12 y13 y14 y15
846       U0= u0 u0 u1 u1 u2 u2 u3 u3    U1= u4 u4 u5 u5 u6 u6 u7 u7
847       V0= v0 v0 v1 v1 v2 v2 v3 v3    V1= v4 v4 v5 v5 v6 v6 v7 v7
848     */
849
850     U0 = vec_mergeh (U,U);
851     V0 = vec_mergeh (V,V);
852
853     U1 = vec_mergel (U,U);
854     V1 = vec_mergel (V,V);
855
856     cvtyuvtoRGB (c, Y0,U0,V0,&R0,&G0,&B0);
857     cvtyuvtoRGB (c, Y1,U1,V1,&R1,&G1,&B1);
858
859     R  = vec_packclp (R0,R1);
860     G  = vec_packclp (G0,G1);
861     B  = vec_packclp (B0,B1);
862
863     switch(c->dstFormat) {
864       case PIX_FMT_ABGR: out_abgr (R,G,B,out); break;
865       case PIX_FMT_BGRA: out_bgra (R,G,B,out); break;
866       case PIX_FMT_RGBA: out_rgba (R,G,B,out); break;
867       case PIX_FMT_ARGB: out_argb (R,G,B,out); break;
868       case PIX_FMT_RGB24: out_rgb24 (R,G,B,out); break;
869       case PIX_FMT_BGR24: out_bgr24 (R,G,B,out); break;
870       default:
871         {
872           /* If this is reached, the caller should have called yuv2packedXinC
873              instead. */
874           static int printed_error_message;
875           if(!printed_error_message) {
876             MSG_ERR("altivec_yuv2packedX doesn't support %s output\n",
877                     sws_format_name(c->dstFormat));
878             printed_error_message=1;
879           }
880           return;
881         }
882     }
883   }
884
885   if (i < dstW) {
886     i -= 16;
887
888     Y0 = RND;
889     Y1 = RND;
890     /* extract 16 coeffs from lumSrc */
891     for(j=0; j<lumFilterSize; j++) {
892       X0 = vec_ld (0,  &lumSrc[j][i]);
893       X1 = vec_ld (16, &lumSrc[j][i]);
894       Y0 = vec_mradds (X0, YCoeffs[j], Y0);
895       Y1 = vec_mradds (X1, YCoeffs[j], Y1);
896     }
897
898     U = RND;
899     V = RND;
900     /* extract 8 coeffs from U,V */
901     for(j=0; j<chrFilterSize; j++) {
902       X  = vec_ld (0, &chrSrc[j][i/2]);
903       U  = vec_mradds (X, CCoeffs[j], U);
904       X  = vec_ld (0, &chrSrc[j][i/2+2048]);
905       V  = vec_mradds (X, CCoeffs[j], V);
906     }
907
908     /* scale and clip signals */
909     Y0 = vec_sra (Y0, SCL);
910     Y1 = vec_sra (Y1, SCL);
911     U  = vec_sra (U,  SCL);
912     V  = vec_sra (V,  SCL);
913
914     Y0 = vec_clip_s16 (Y0);
915     Y1 = vec_clip_s16 (Y1);
916     U  = vec_clip_s16 (U);
917     V  = vec_clip_s16 (V);
918
919     /* now we have
920        Y0= y0 y1 y2 y3 y4 y5 y6 y7     Y1= y8 y9 y10 y11 y12 y13 y14 y15
921        U= u0 u1 u2 u3 u4 u5 u6 u7      V= v0 v1 v2 v3 v4 v5 v6 v7
922
923        Y0= y0 y1 y2 y3 y4 y5 y6 y7    Y1= y8 y9 y10 y11 y12 y13 y14 y15
924        U0= u0 u0 u1 u1 u2 u2 u3 u3    U1= u4 u4 u5 u5 u6 u6 u7 u7
925        V0= v0 v0 v1 v1 v2 v2 v3 v3    V1= v4 v4 v5 v5 v6 v6 v7 v7
926     */
927
928     U0 = vec_mergeh (U,U);
929     V0 = vec_mergeh (V,V);
930
931     U1 = vec_mergel (U,U);
932     V1 = vec_mergel (V,V);
933
934     cvtyuvtoRGB (c, Y0,U0,V0,&R0,&G0,&B0);
935     cvtyuvtoRGB (c, Y1,U1,V1,&R1,&G1,&B1);
936
937     R  = vec_packclp (R0,R1);
938     G  = vec_packclp (G0,G1);
939     B  = vec_packclp (B0,B1);
940
941     nout = (vector unsigned char *)scratch;
942     switch(c->dstFormat) {
943       case PIX_FMT_ABGR: out_abgr (R,G,B,nout); break;
944       case PIX_FMT_BGRA: out_bgra (R,G,B,nout); break;
945       case PIX_FMT_RGBA: out_rgba (R,G,B,nout); break;
946       case PIX_FMT_ARGB: out_argb (R,G,B,nout); break;
947       case PIX_FMT_RGB24: out_rgb24 (R,G,B,nout); break;
948       case PIX_FMT_BGR24: out_bgr24 (R,G,B,nout); break;
949       default:
950         /* Unreachable, I think. */
951         MSG_ERR("altivec_yuv2packedX doesn't support %s output\n",
952                 sws_format_name(c->dstFormat));
953         return;
954     }
955
956     memcpy (&((uint32_t*)dest)[i], scratch, (dstW-i)/4);
957   }
958
959 }