8cbfe9c276749e3a9be0b5713489d3e99bde0a71
[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 #include "libmpcodecs/img_format.h" //FIXME try to reduce dependency of such stuff
92
93 #undef PROFILE_THE_BEAST
94 #undef INC_SCALING
95
96 typedef unsigned char ubyte;
97 typedef signed char   sbyte;
98
99
100 /* RGB interleaver, 16 planar pels 8-bit samples per channel in
101    homogeneous vector registers x0,x1,x2 are interleaved with the
102    following technique:
103
104       o0 = vec_mergeh (x0,x1);
105       o1 = vec_perm (o0, x2, perm_rgb_0);
106       o2 = vec_perm (o0, x2, perm_rgb_1);
107       o3 = vec_mergel (x0,x1);
108       o4 = vec_perm (o3,o2,perm_rgb_2);
109       o5 = vec_perm (o3,o2,perm_rgb_3);
110
111   perm_rgb_0:   o0(RG).h v1(B) --> o1*
112               0   1  2   3   4
113              rgbr|gbrg|brgb|rgbr
114              0010 0100 1001 0010
115              0102 3145 2673 894A
116
117   perm_rgb_1:   o0(RG).h v1(B) --> o2
118               0   1  2   3   4
119              gbrg|brgb|bbbb|bbbb
120              0100 1001 1111 1111
121              B5CD 6EF7 89AB CDEF
122
123   perm_rgb_2:   o3(RG).l o2(rgbB.l) --> o4*
124               0   1  2   3   4
125              gbrg|brgb|rgbr|gbrg
126              1111 1111 0010 0100
127              89AB CDEF 0182 3945
128
129   perm_rgb_2:   o3(RG).l o2(rgbB.l) ---> o5*
130               0   1  2   3   4
131              brgb|rgbr|gbrg|brgb
132              1001 0010 0100 1001
133              a67b 89cA BdCD eEFf
134
135 */
136 static
137 const vector unsigned char
138   perm_rgb_0 = (const vector unsigned char)AVV(0x00,0x01,0x10,0x02,0x03,0x11,0x04,0x05,
139                                       0x12,0x06,0x07,0x13,0x08,0x09,0x14,0x0a),
140   perm_rgb_1 = (const vector unsigned char)AVV(0x0b,0x15,0x0c,0x0d,0x16,0x0e,0x0f,0x17,
141                                       0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f),
142   perm_rgb_2 = (const vector unsigned char)AVV(0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
143                                       0x00,0x01,0x18,0x02,0x03,0x19,0x04,0x05),
144   perm_rgb_3 = (const vector unsigned char)AVV(0x1a,0x06,0x07,0x1b,0x08,0x09,0x1c,0x0a,
145                                       0x0b,0x1d,0x0c,0x0d,0x1e,0x0e,0x0f,0x1f);
146
147 #define vec_merge3(x2,x1,x0,y0,y1,y2)    \
148 do {                                     \
149   typeof(x0) o0,o2,o3;                   \
150       o0 = vec_mergeh (x0,x1);           \
151       y0 = vec_perm (o0, x2, perm_rgb_0);\
152       o2 = vec_perm (o0, x2, perm_rgb_1);\
153       o3 = vec_mergel (x0,x1);           \
154       y1 = vec_perm (o3,o2,perm_rgb_2);  \
155       y2 = vec_perm (o3,o2,perm_rgb_3);  \
156 } while(0)
157
158 #define vec_mstbgr24(x0,x1,x2,ptr)        \
159 do {                                     \
160   typeof(x0) _0,_1,_2;                   \
161   vec_merge3 (x0,x1,x2,_0,_1,_2);        \
162   vec_st (_0, 0, ptr++);                 \
163   vec_st (_1, 0, ptr++);                 \
164   vec_st (_2, 0, ptr++);                 \
165 }  while (0);
166
167 #define vec_mstrgb24(x0,x1,x2,ptr)       \
168 do {                                     \
169   typeof(x0) _0,_1,_2;                   \
170   vec_merge3 (x2,x1,x0,_0,_1,_2);        \
171   vec_st (_0, 0, ptr++);                 \
172   vec_st (_1, 0, ptr++);                 \
173   vec_st (_2, 0, ptr++);                 \
174 }  while (0);
175
176 /* pack the pixels in rgb0 format
177    msb R
178    lsb 0
179 */
180 #define vec_mstrgb32(T,x0,x1,x2,x3,ptr)                                                \
181 do {                                                                                   \
182   T _0,_1,_2,_3;                                                                       \
183   _0 = vec_mergeh (x0,x1);                                                             \
184   _1 = vec_mergeh (x2,x3);                                                             \
185   _2 = (T)vec_mergeh ((vector unsigned short)_0,(vector unsigned short)_1);            \
186   _3 = (T)vec_mergel ((vector unsigned short)_0,(vector unsigned short)_1);            \
187   vec_st (_2, 0*16, (T *)ptr);                                                         \
188   vec_st (_3, 1*16, (T *)ptr);                                                         \
189   _0 = vec_mergel (x0,x1);                                                             \
190   _1 = vec_mergel (x2,x3);                                                             \
191   _2 = (T)vec_mergeh ((vector unsigned short)_0,(vector unsigned short)_1);            \
192   _3 = (T)vec_mergel ((vector unsigned short)_0,(vector unsigned short)_1);            \
193   vec_st (_2, 2*16, (T *)ptr);                                                         \
194   vec_st (_3, 3*16, (T *)ptr);                                                         \
195   ptr += 4;                                                                            \
196 }  while (0);
197
198 /*
199
200   | 1     0       1.4021   | | Y |
201   | 1    -0.3441 -0.7142   |x| Cb|
202   | 1     1.7718  0        | | Cr|
203
204
205   Y:      [-128 127]
206   Cb/Cr : [-128 127]
207
208   typical yuv conversion work on Y: 0-255 this version has been optimized for jpeg decode.
209
210 */
211
212
213
214
215 #define vec_unh(x) \
216   (vector signed short) \
217     vec_perm(x,(typeof(x))AVV(0),\
218              (vector unsigned char)AVV(0x10,0x00,0x10,0x01,0x10,0x02,0x10,0x03,\
219                                     0x10,0x04,0x10,0x05,0x10,0x06,0x10,0x07))
220 #define vec_unl(x) \
221   (vector signed short) \
222     vec_perm(x,(typeof(x))AVV(0),\
223              (vector unsigned char)AVV(0x10,0x08,0x10,0x09,0x10,0x0A,0x10,0x0B,\
224                                     0x10,0x0C,0x10,0x0D,0x10,0x0E,0x10,0x0F))
225
226 #define vec_clip_s16(x) \
227   vec_max (vec_min (x, (vector signed short)AVV(235,235,235,235,235,235,235,235)),\
228                        (vector signed short)AVV(16, 16, 16, 16, 16, 16, 16, 16 ))
229
230 #define vec_packclp(x,y) \
231   (vector unsigned char)vec_packs \
232       ((vector unsigned short)vec_max (x,(vector signed short) AVV(0)), \
233        (vector unsigned short)vec_max (y,(vector signed short) AVV(0)))
234
235 //#define out_pixels(a,b,c,ptr) vec_mstrgb32(typeof(a),((typeof (a))AVV(0)),a,a,a,ptr)
236
237
238 static inline void cvtyuvtoRGB (SwsContext *c,
239                            vector signed short Y, vector signed short U, vector signed short V,
240                            vector signed short *R, vector signed short *G, vector signed short *B)
241 {
242   vector signed   short vx,ux,uvx;
243
244   Y = vec_mradds (Y, c->CY, c->OY);
245   U  = vec_sub (U,(vector signed short)
246                         vec_splat((vector signed short)AVV(128),0));
247   V  = vec_sub (V,(vector signed short)
248                         vec_splat((vector signed short)AVV(128),0));
249
250   //   ux  = (CBU*(u<<c->CSHIFT)+0x4000)>>15;
251   ux = vec_sl (U, c->CSHIFT);
252   *B = vec_mradds (ux, c->CBU, Y);
253
254   // vx  = (CRV*(v<<c->CSHIFT)+0x4000)>>15;
255   vx = vec_sl (V, c->CSHIFT);
256   *R = vec_mradds (vx, c->CRV, Y);
257
258   // uvx = ((CGU*u) + (CGV*v))>>15;
259   uvx = vec_mradds (U, c->CGU, Y);
260   *G = vec_mradds (V, c->CGV, uvx);
261 }
262
263
264 /*
265   ------------------------------------------------------------------------------
266   CS converters
267   ------------------------------------------------------------------------------
268 */
269
270
271 #define DEFCSP420_CVT(name,out_pixels)                                     \
272 static int altivec_##name (SwsContext *c,                                  \
273                                 unsigned char **in, int *instrides,        \
274                                 int srcSliceY,  int srcSliceH,             \
275                                 unsigned char **oplanes, int *outstrides)  \
276 {                                                                          \
277   int w = c->srcW;                                                         \
278   int h = srcSliceH;                                                       \
279   int i,j;                                                                 \
280   int instrides_scl[3];                                                    \
281   vector unsigned char y0,y1;                                              \
282                                                                            \
283   vector signed char  u,v;                                                 \
284                                                                            \
285   vector signed short Y0,Y1,Y2,Y3;                                         \
286   vector signed short U,V;                                                 \
287   vector signed short vx,ux,uvx;                                           \
288   vector signed short vx0,ux0,uvx0;                                        \
289   vector signed short vx1,ux1,uvx1;                                        \
290   vector signed short R0,G0,B0;                                            \
291   vector signed short R1,G1,B1;                                            \
292   vector unsigned char R,G,B;                                              \
293                                                                            \
294   vector unsigned char *y1ivP, *y2ivP, *uivP, *vivP;                       \
295   vector unsigned char align_perm;                                         \
296                                                                            \
297   vector signed short                                                      \
298     lCY  = c->CY,                                                          \
299     lOY  = c->OY,                                                          \
300     lCRV = c->CRV,                                                         \
301     lCBU = c->CBU,                                                         \
302     lCGU = c->CGU,                                                         \
303     lCGV = c->CGV;                                                         \
304                                                                            \
305   vector unsigned short lCSHIFT = c->CSHIFT;                               \
306                                                                            \
307   ubyte *y1i   = in[0];                                                    \
308   ubyte *y2i   = in[0]+instrides[0];                                       \
309   ubyte *ui    = in[1];                                                    \
310   ubyte *vi    = in[2];                                                    \
311                                                                            \
312   vector unsigned char *oute                                               \
313     = (vector unsigned char *)                                             \
314         (oplanes[0]+srcSliceY*outstrides[0]);                              \
315   vector unsigned char *outo                                               \
316     = (vector unsigned char *)                                             \
317         (oplanes[0]+srcSliceY*outstrides[0]+outstrides[0]);                \
318                                                                            \
319                                                                            \
320   instrides_scl[0] = instrides[0]*2-w;  /* the loop moves y{1,2}i by w */  \
321   instrides_scl[1] = instrides[1]-w/2;  /* the loop moves ui by w/2 */     \
322   instrides_scl[2] = instrides[2]-w/2;  /* the loop moves vi by w/2 */     \
323                                                                            \
324                                                                            \
325   for (i=0;i<h/2;i++) {                                                    \
326     vec_dstst (outo, (0x02000002|(((w*3+32)/32)<<16)), 0);                 \
327     vec_dstst (oute, (0x02000002|(((w*3+32)/32)<<16)), 1);                 \
328                                                                            \
329     for (j=0;j<w/16;j++) {                                                 \
330                                                                            \
331       y1ivP = (vector unsigned char *)y1i;                                 \
332       y2ivP = (vector unsigned char *)y2i;                                 \
333       uivP = (vector unsigned char *)ui;                                   \
334       vivP = (vector unsigned char *)vi;                                   \
335                                                                            \
336       align_perm = vec_lvsl (0, y1i);                                      \
337       y0 = (vector unsigned char)vec_perm (y1ivP[0], y1ivP[1], align_perm);\
338                                                                            \
339       align_perm = vec_lvsl (0, y2i);                                      \
340       y1 = (vector unsigned char)vec_perm (y2ivP[0], y2ivP[1], align_perm);\
341                                                                            \
342       align_perm = vec_lvsl (0, ui);                                       \
343       u = (vector signed char)vec_perm (uivP[0], uivP[1], align_perm);     \
344                                                                            \
345       align_perm = vec_lvsl (0, vi);                                       \
346       v = (vector signed char)vec_perm (vivP[0], vivP[1], align_perm);     \
347                                                                            \
348       u  = (vector signed char)                                            \
349                 vec_sub (u,(vector signed char)                            \
350                                 vec_splat((vector signed char)AVV(128),0));\
351       v  = (vector signed char)                                            \
352                 vec_sub (v,(vector signed char)                            \
353                                 vec_splat((vector signed char)AVV(128),0));\
354                                                                            \
355       U  = vec_unpackh (u);                                                \
356       V  = vec_unpackh (v);                                                \
357                                                                            \
358                                                                            \
359         Y0 = vec_unh (y0);                                                 \
360         Y1 = vec_unl (y0);                                                 \
361         Y2 = vec_unh (y1);                                                 \
362         Y3 = vec_unl (y1);                                                 \
363                                                                            \
364         Y0 = vec_mradds (Y0, lCY, lOY);                                    \
365         Y1 = vec_mradds (Y1, lCY, lOY);                                    \
366         Y2 = vec_mradds (Y2, lCY, lOY);                                    \
367         Y3 = vec_mradds (Y3, lCY, lOY);                                    \
368                                                                            \
369         /*   ux  = (CBU*(u<<CSHIFT)+0x4000)>>15 */                         \
370         ux = vec_sl (U, lCSHIFT);                                          \
371         ux = vec_mradds (ux, lCBU, (vector signed short)AVV(0));                   \
372         ux0  = vec_mergeh (ux,ux);                                         \
373         ux1  = vec_mergel (ux,ux);                                         \
374                                                                            \
375         /* vx  = (CRV*(v<<CSHIFT)+0x4000)>>15;  */                         \
376         vx = vec_sl (V, lCSHIFT);                                          \
377         vx = vec_mradds (vx, lCRV, (vector signed short)AVV(0));                   \
378         vx0  = vec_mergeh (vx,vx);                                         \
379         vx1  = vec_mergel (vx,vx);                                         \
380                                                                            \
381         /* uvx = ((CGU*u) + (CGV*v))>>15 */                                \
382         uvx = vec_mradds (U, lCGU, (vector signed short)AVV(0));                   \
383         uvx = vec_mradds (V, lCGV, uvx);                                   \
384         uvx0 = vec_mergeh (uvx,uvx);                                       \
385         uvx1 = vec_mergel (uvx,uvx);                                       \
386                                                                            \
387         R0 = vec_add (Y0,vx0);                                             \
388         G0 = vec_add (Y0,uvx0);                                            \
389         B0 = vec_add (Y0,ux0);                                             \
390         R1 = vec_add (Y1,vx1);                                             \
391         G1 = vec_add (Y1,uvx1);                                            \
392         B1 = vec_add (Y1,ux1);                                             \
393                                                                            \
394         R  = vec_packclp (R0,R1);                                          \
395         G  = vec_packclp (G0,G1);                                          \
396         B  = vec_packclp (B0,B1);                                          \
397                                                                            \
398         out_pixels(R,G,B,oute);                                            \
399                                                                            \
400         R0 = vec_add (Y2,vx0);                                             \
401         G0 = vec_add (Y2,uvx0);                                            \
402         B0 = vec_add (Y2,ux0);                                             \
403         R1 = vec_add (Y3,vx1);                                             \
404         G1 = vec_add (Y3,uvx1);                                            \
405         B1 = vec_add (Y3,ux1);                                             \
406         R  = vec_packclp (R0,R1);                                          \
407         G  = vec_packclp (G0,G1);                                          \
408         B  = vec_packclp (B0,B1);                                          \
409                                                                            \
410                                                                            \
411         out_pixels(R,G,B,outo);                                            \
412                                                                            \
413       y1i  += 16;                                                          \
414       y2i  += 16;                                                          \
415       ui   += 8;                                                           \
416       vi   += 8;                                                           \
417                                                                            \
418     }                                                                      \
419                                                                            \
420     outo += (outstrides[0])>>4;                                            \
421     oute += (outstrides[0])>>4;                                            \
422                                                                            \
423     ui    += instrides_scl[1];                                             \
424     vi    += instrides_scl[2];                                             \
425     y1i   += instrides_scl[0];                                             \
426     y2i   += instrides_scl[0];                                             \
427   }                                                                        \
428   return srcSliceH;                                                        \
429 }
430
431
432 #define out_abgr(a,b,c,ptr)  vec_mstrgb32(typeof(a),((typeof (a))AVV(0)),c,b,a,ptr)
433 #define out_bgra(a,b,c,ptr)  vec_mstrgb32(typeof(a),c,b,a,((typeof (a))AVV(0)),ptr)
434 #define out_rgba(a,b,c,ptr)  vec_mstrgb32(typeof(a),a,b,c,((typeof (a))AVV(0)),ptr)
435 #define out_argb(a,b,c,ptr)  vec_mstrgb32(typeof(a),((typeof (a))AVV(0)),a,b,c,ptr)
436 #define out_rgb24(a,b,c,ptr) vec_mstrgb24(a,b,c,ptr)
437 #define out_bgr24(a,b,c,ptr) vec_mstbgr24(a,b,c,ptr)
438
439 DEFCSP420_CVT (yuv2_abgr, out_abgr)
440 #if 1
441 DEFCSP420_CVT (yuv2_bgra, out_bgra)
442 #else
443 static int altivec_yuv2_bgra32 (SwsContext *c,                                  
444                                 unsigned char **in, int *instrides,        
445                                 int srcSliceY,  int srcSliceH,             
446                                 unsigned char **oplanes, int *outstrides)  
447 {                                                                          
448   int w = c->srcW;                                                         
449   int h = srcSliceH;                                                       
450   int i,j;                                                                 
451   int instrides_scl[3];                                                    
452   vector unsigned char y0,y1;                                              
453                                                                            
454   vector signed char  u,v;                                                 
455                                                                            
456   vector signed short Y0,Y1,Y2,Y3;                                         
457   vector signed short U,V;                                                 
458   vector signed short vx,ux,uvx;                                           
459   vector signed short vx0,ux0,uvx0;                                        
460   vector signed short vx1,ux1,uvx1;                                        
461   vector signed short R0,G0,B0;                                            
462   vector signed short R1,G1,B1;                                            
463   vector unsigned char R,G,B;                                              
464                                                                            
465   vector unsigned char *uivP, *vivP;                                       
466   vector unsigned char align_perm;                                         
467                                                                            
468   vector signed short                                                      
469     lCY  = c->CY,                                                          
470     lOY  = c->OY,                                                          
471     lCRV = c->CRV,                                                         
472     lCBU = c->CBU,                                                         
473     lCGU = c->CGU,                                                         
474     lCGV = c->CGV;                                                         
475                                                                            
476   vector unsigned short lCSHIFT = c->CSHIFT;                               
477                                                                            
478   ubyte *y1i   = in[0];                                                    
479   ubyte *y2i   = in[0]+w;                                                  
480   ubyte *ui    = in[1];                                                    
481   ubyte *vi    = in[2];                                                    
482                                                                            
483   vector unsigned char *oute                                               
484     = (vector unsigned char *)                                             
485         (oplanes[0]+srcSliceY*outstrides[0]);                              
486   vector unsigned char *outo                                               
487     = (vector unsigned char *)                                             
488         (oplanes[0]+srcSliceY*outstrides[0]+outstrides[0]);                
489                                                                            
490                                                                            
491   instrides_scl[0] = instrides[0];                                         
492   instrides_scl[1] = instrides[1]-w/2;  /* the loop moves ui by w/2 */     
493   instrides_scl[2] = instrides[2]-w/2;  /* the loop moves vi by w/2 */     
494                                                                            
495                                                                            
496   for (i=0;i<h/2;i++) {                                                    
497     vec_dstst (outo, (0x02000002|(((w*3+32)/32)<<16)), 0);                 
498     vec_dstst (oute, (0x02000002|(((w*3+32)/32)<<16)), 1);                 
499                                                                            
500     for (j=0;j<w/16;j++) {                                                 
501                                                                            
502       y0 = vec_ldl (0,y1i);                                                
503       y1 = vec_ldl (0,y2i);                                                
504       uivP = (vector unsigned char *)ui;                                   
505       vivP = (vector unsigned char *)vi;                                   
506                                                                            
507       align_perm = vec_lvsl (0, ui);                                       
508       u = (vector signed char)vec_perm (uivP[0], uivP[1], align_perm);     
509                                                                            
510       align_perm = vec_lvsl (0, vi);                                       
511       v = (vector signed char)vec_perm (vivP[0], vivP[1], align_perm);
512       u  = (vector signed char)
513                 vec_sub (u,(vector signed char)
514                                 vec_splat((vector signed char)AVV(128),0));
515       
516       v  = (vector signed char)
517                 vec_sub (v, (vector signed char)
518                                 vec_splat((vector signed char)AVV(128),0));
519       
520       U  = vec_unpackh (u);                                                
521       V  = vec_unpackh (v);                                                
522                                                                            
523                                                                            
524         Y0 = vec_unh (y0);                                                 
525         Y1 = vec_unl (y0);                                                 
526         Y2 = vec_unh (y1);                                                 
527         Y3 = vec_unl (y1);                                                 
528                                                                            
529         Y0 = vec_mradds (Y0, lCY, lOY);                                    
530         Y1 = vec_mradds (Y1, lCY, lOY);                                    
531         Y2 = vec_mradds (Y2, lCY, lOY);                                    
532         Y3 = vec_mradds (Y3, lCY, lOY);                                    
533                                                                            
534         /*   ux  = (CBU*(u<<CSHIFT)+0x4000)>>15 */                         
535         ux = vec_sl (U, lCSHIFT);                                          
536         ux = vec_mradds (ux, lCBU, (vector signed short)AVV(0));
537         ux0  = vec_mergeh (ux,ux);                                         
538         ux1  = vec_mergel (ux,ux);                                         
539                                                                            
540         /* vx  = (CRV*(v<<CSHIFT)+0x4000)>>15;  */                         
541         vx = vec_sl (V, lCSHIFT);                                          
542         vx = vec_mradds (vx, lCRV, (vector signed short)AVV(0));
543         vx0  = vec_mergeh (vx,vx);
544         vx1  = vec_mergel (vx,vx);
545         /* uvx = ((CGU*u) + (CGV*v))>>15 */
546         uvx = vec_mradds (U, lCGU, (vector signed short)AVV(0));
547         uvx = vec_mradds (V, lCGV, uvx);
548         uvx0 = vec_mergeh (uvx,uvx);
549         uvx1 = vec_mergel (uvx,uvx);
550         R0 = vec_add (Y0,vx0);
551         G0 = vec_add (Y0,uvx0);
552         B0 = vec_add (Y0,ux0);
553         R1 = vec_add (Y1,vx1);
554         G1 = vec_add (Y1,uvx1);
555         B1 = vec_add (Y1,ux1);
556         R  = vec_packclp (R0,R1);
557         G  = vec_packclp (G0,G1);
558         B  = vec_packclp (B0,B1);
559         
560         out_argb(R,G,B,oute);
561         R0 = vec_add (Y2,vx0);
562         G0 = vec_add (Y2,uvx0);
563         B0 = vec_add (Y2,ux0);
564         R1 = vec_add (Y3,vx1);
565         G1 = vec_add (Y3,uvx1);
566         B1 = vec_add (Y3,ux1);
567         R  = vec_packclp (R0,R1);
568         G  = vec_packclp (G0,G1);
569         B  = vec_packclp (B0,B1);
570         
571         out_argb(R,G,B,outo);
572         y1i  += 16;                                                        
573         y2i  += 16;                                                        
574         ui   += 8;
575         vi   += 8;                                                         
576                                                                            
577     }                                                                      
578                                                                            
579     outo += (outstrides[0])>>4;                                            
580     oute += (outstrides[0])>>4;                                            
581                                                                            
582     ui    += instrides_scl[1];                                             
583     vi    += instrides_scl[2];                                             
584     y1i   += instrides_scl[0];                                             
585     y2i   += instrides_scl[0];                                             
586   }                                                                        
587   return srcSliceH;                                                        
588 }
589
590 #endif
591
592
593 DEFCSP420_CVT (yuv2_rgba, out_rgba)
594 DEFCSP420_CVT (yuv2_argb, out_argb)
595 DEFCSP420_CVT (yuv2_rgb24,  out_rgb24)
596 DEFCSP420_CVT (yuv2_bgr24,  out_bgr24)
597
598
599 // uyvy|uyvy|uyvy|uyvy
600 // 0123 4567 89ab cdef
601 static
602 const vector unsigned char
603   demux_u = (const vector unsigned char)AVV(0x10,0x00,0x10,0x00,
604                                    0x10,0x04,0x10,0x04,
605                                    0x10,0x08,0x10,0x08,
606                                    0x10,0x0c,0x10,0x0c),
607   demux_v = (const vector unsigned char)AVV(0x10,0x02,0x10,0x02,
608                                    0x10,0x06,0x10,0x06,
609                                    0x10,0x0A,0x10,0x0A,
610                                    0x10,0x0E,0x10,0x0E),
611   demux_y = (const vector unsigned char)AVV(0x10,0x01,0x10,0x03,
612                                    0x10,0x05,0x10,0x07,
613                                    0x10,0x09,0x10,0x0B,
614                                    0x10,0x0D,0x10,0x0F);
615
616 /*
617   this is so I can play live CCIR raw video
618 */
619 static int altivec_uyvy_rgb32 (SwsContext *c,
620                                unsigned char **in, int *instrides,
621                                int srcSliceY,   int srcSliceH,
622                                unsigned char **oplanes, int *outstrides)
623 {
624   int w = c->srcW;
625   int h = srcSliceH;
626   int i,j;
627   vector unsigned char uyvy;
628   vector signed   short Y,U,V;
629   vector signed   short vx,ux,uvx;
630   vector signed   short R0,G0,B0,R1,G1,B1;
631   vector unsigned char  R,G,B;
632   vector unsigned char *out;
633   ubyte *img;
634
635   img = in[0];
636   out = (vector unsigned char *)(oplanes[0]+srcSliceY*outstrides[0]);
637
638   for (i=0;i<h;i++) {
639     for (j=0;j<w/16;j++) {
640       uyvy = vec_ld (0, img);
641       U = (vector signed short)
642         vec_perm (uyvy, (vector unsigned char)AVV(0), demux_u);
643
644       V = (vector signed short)
645         vec_perm (uyvy, (vector unsigned char)AVV(0), demux_v);
646
647       Y = (vector signed short)
648         vec_perm (uyvy, (vector unsigned char)AVV(0), demux_y);
649
650       cvtyuvtoRGB (c, Y,U,V,&R0,&G0,&B0);
651
652       uyvy = vec_ld (16, img);
653       U = (vector signed short)
654         vec_perm (uyvy, (vector unsigned char)AVV(0), demux_u);
655
656       V = (vector signed short)
657         vec_perm (uyvy, (vector unsigned char)AVV(0), demux_v);
658
659       Y = (vector signed short)
660         vec_perm (uyvy, (vector unsigned char)AVV(0), demux_y);
661
662       cvtyuvtoRGB (c, Y,U,V,&R1,&G1,&B1);
663
664       R  = vec_packclp (R0,R1);
665       G  = vec_packclp (G0,G1);
666       B  = vec_packclp (B0,B1);
667
668       //      vec_mstbgr24 (R,G,B, out);
669       out_rgba (R,G,B,out);
670
671       img += 32;
672     }
673   }
674   return srcSliceH;
675 }
676
677
678
679 /* Ok currently the acceleration routine only supports
680    inputs of widths a multiple of 16
681    and heights a multiple 2
682
683    So we just fall back to the C codes for this.
684 */
685 SwsFunc yuv2rgb_init_altivec (SwsContext *c)
686 {
687   if (!(c->flags & SWS_CPU_CAPS_ALTIVEC))    
688     return NULL;
689
690   /*
691     and this seems not to matter too much I tried a bunch of 
692     videos with abnormal widths and mplayer crashes else where.
693     mplayer -vo x11 -rawvideo on:w=350:h=240 raw-350x240.eyuv 
694     boom with X11 bad match.
695     
696   */
697   if ((c->srcW & 0xf) != 0)    return NULL;
698
699   switch (c->srcFormat) {
700   case IMGFMT_YVU9:
701   case IMGFMT_IF09:
702   case IMGFMT_YV12:
703   case IMGFMT_I420:
704   case IMGFMT_IYUV:
705   case IMGFMT_CLPL:
706   case IMGFMT_Y800:
707   case IMGFMT_Y8:
708   case IMGFMT_NV12:
709   case IMGFMT_NV21:
710     if ((c->srcH & 0x1) != 0)
711       return NULL;
712
713     switch(c->dstFormat){
714     case IMGFMT_RGB24:
715       MSG_WARN("ALTIVEC: Color Space RGB24\n");
716       return altivec_yuv2_rgb24;
717     case IMGFMT_BGR24:
718       MSG_WARN("ALTIVEC: Color Space BGR24\n");
719       return altivec_yuv2_bgr24;
720     case IMGFMT_ARGB:
721       MSG_WARN("ALTIVEC: Color Space ARGB\n");
722       return altivec_yuv2_argb;
723     case IMGFMT_ABGR:
724       MSG_WARN("ALTIVEC: Color Space ABGR\n");
725       return altivec_yuv2_abgr;
726     case IMGFMT_RGBA:
727       MSG_WARN("ALTIVEC: Color Space RGBA\n");
728       return altivec_yuv2_rgba;
729     case IMGFMT_BGRA:
730       MSG_WARN("ALTIVEC: Color Space BGRA\n");
731       return altivec_yuv2_bgra;
732     default: return NULL;
733     }
734     break;
735
736   case IMGFMT_UYVY:
737     switch(c->dstFormat){
738     case IMGFMT_RGB32:
739       MSG_WARN("ALTIVEC: Color Space UYVY -> RGB32\n");
740       return altivec_uyvy_rgb32;
741     default: return NULL;
742     }
743     break;
744
745   }
746   return NULL;
747 }
748
749 static uint16_t roundToInt16(int64_t f){
750         int r= (f + (1<<15))>>16;
751              if(r<-0x7FFF) return 0x8000;
752         else if(r> 0x7FFF) return 0x7FFF;
753         else               return r;
754 }
755
756 void yuv2rgb_altivec_init_tables (SwsContext *c, const int inv_table[4],int brightness,int contrast, int saturation)
757 {
758   union {
759         signed short tmp[8] __attribute__ ((aligned(16)));
760         vector signed short vec;
761         } buf;
762
763   buf.tmp[0] =  ( (0xffffLL) * contrast>>8 )>>9;                        //cy
764   buf.tmp[1] =  -256*brightness;                                        //oy
765   buf.tmp[2] =  (inv_table[0]>>3) *(contrast>>16)*(saturation>>16);     //crv
766   buf.tmp[3] =  (inv_table[1]>>3) *(contrast>>16)*(saturation>>16);     //cbu
767   buf.tmp[4] = -((inv_table[2]>>1)*(contrast>>16)*(saturation>>16));    //cgu
768   buf.tmp[5] = -((inv_table[3]>>1)*(contrast>>16)*(saturation>>16));    //cgv
769
770
771   c->CSHIFT = (vector unsigned short)vec_splat_u16(2);
772   c->CY  = vec_splat ((vector signed short)buf.vec, 0);
773   c->OY  = vec_splat ((vector signed short)buf.vec, 1);
774   c->CRV  = vec_splat ((vector signed short)buf.vec, 2);
775   c->CBU  = vec_splat ((vector signed short)buf.vec, 3);
776   c->CGU  = vec_splat ((vector signed short)buf.vec, 4);
777   c->CGV  = vec_splat ((vector signed short)buf.vec, 5);
778 #if 0
779 {
780 int i;
781 char *v[6]={"cy","oy","crv","cbu","cgu","cgv"};
782 for (i=0; i<6;i++)
783   printf("%s %d ", v[i],buf.tmp[i] );
784   printf("\n");
785 }
786 #endif
787  return;
788 }
789
790
791 void
792 altivec_yuv2packedX (SwsContext *c,
793                        int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
794                        int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,
795                        uint8_t *dest, int dstW, int dstY)
796 {
797   int i,j;
798   short *f;
799   vector signed short X,X0,X1,Y0,U0,V0,Y1,U1,V1,U,V;
800   vector signed short R0,G0,B0,R1,G1,B1;
801
802   vector unsigned char R,G,B,pels[3];
803   vector unsigned char *out,*nout;
804
805   vector signed short   RND = vec_splat_s16(1<<3);
806   vector unsigned short SCL = vec_splat_u16(4);
807   unsigned long scratch[16] __attribute__ ((aligned (16)));
808
809   vector signed short *YCoeffs, *CCoeffs;
810
811   YCoeffs = c->vYCoeffsBank+dstY*lumFilterSize;
812   CCoeffs = c->vCCoeffsBank+dstY*chrFilterSize;
813
814   out = (vector unsigned char *)dest;
815
816   for(i=0; i<dstW; i+=16){
817     Y0 = RND;
818     Y1 = RND;
819     /* extract 16 coeffs from lumSrc */
820     for(j=0; j<lumFilterSize; j++) {
821       X0 = vec_ld (0,  &lumSrc[j][i]);
822       X1 = vec_ld (16, &lumSrc[j][i]);
823       Y0 = vec_mradds (X0, YCoeffs[j], Y0);
824       Y1 = vec_mradds (X1, YCoeffs[j], Y1);
825     }
826
827     U = RND;
828     V = RND;
829     /* extract 8 coeffs from U,V */
830     for(j=0; j<chrFilterSize; j++) {
831       X  = vec_ld (0, &chrSrc[j][i/2]);
832       U  = vec_mradds (X, CCoeffs[j], U);
833       X  = vec_ld (0, &chrSrc[j][i/2+2048]);
834       V  = vec_mradds (X, CCoeffs[j], V);
835     }
836
837     /* scale and clip signals */
838     Y0 = vec_sra (Y0, SCL);
839     Y1 = vec_sra (Y1, SCL);
840     U  = vec_sra (U,  SCL);
841     V  = vec_sra (V,  SCL);
842
843     Y0 = vec_clip_s16 (Y0);
844     Y1 = vec_clip_s16 (Y1);
845     U  = vec_clip_s16 (U);
846     V  = vec_clip_s16 (V);
847
848     /* now we have
849       Y0= y0 y1 y2 y3 y4 y5 y6 y7     Y1= y8 y9 y10 y11 y12 y13 y14 y15
850       U= u0 u1 u2 u3 u4 u5 u6 u7      V= v0 v1 v2 v3 v4 v5 v6 v7
851
852       Y0= y0 y1 y2 y3 y4 y5 y6 y7    Y1= y8 y9 y10 y11 y12 y13 y14 y15
853       U0= u0 u0 u1 u1 u2 u2 u3 u3    U1= u4 u4 u5 u5 u6 u6 u7 u7
854       V0= v0 v0 v1 v1 v2 v2 v3 v3    V1= v4 v4 v5 v5 v6 v6 v7 v7
855     */
856
857     U0 = vec_mergeh (U,U);
858     V0 = vec_mergeh (V,V);
859
860     U1 = vec_mergel (U,U);
861     V1 = vec_mergel (V,V);
862
863     cvtyuvtoRGB (c, Y0,U0,V0,&R0,&G0,&B0);
864     cvtyuvtoRGB (c, Y1,U1,V1,&R1,&G1,&B1);
865
866     R  = vec_packclp (R0,R1);
867     G  = vec_packclp (G0,G1);
868     B  = vec_packclp (B0,B1);
869
870     switch(c->dstFormat) {
871       case IMGFMT_ABGR: out_abgr (R,G,B,out); break;
872       case IMGFMT_BGRA: out_bgra (R,G,B,out); break;
873       case IMGFMT_RGBA: out_rgba (R,G,B,out); break;
874       case IMGFMT_ARGB: out_argb (R,G,B,out); break;
875       case IMGFMT_RGB24: out_rgb24 (R,G,B,out); break;
876       case IMGFMT_BGR24: out_bgr24 (R,G,B,out); break;
877       default:
878         {
879           /* If this is reached, the caller should have called yuv2packedXinC
880              instead. */
881           static int printed_error_message;
882           if(!printed_error_message) {
883             MSG_ERR("altivec_yuv2packedX doesn't support %s output\n",
884                     sws_format_name(c->dstFormat));
885             printed_error_message=1;
886           }
887           return;
888         }
889     }
890   }
891
892   if (i < dstW) {
893     i -= 16;
894
895     Y0 = RND;
896     Y1 = RND;
897     /* extract 16 coeffs from lumSrc */
898     for(j=0; j<lumFilterSize; j++) {
899       X0 = vec_ld (0,  &lumSrc[j][i]);
900       X1 = vec_ld (16, &lumSrc[j][i]);
901       Y0 = vec_mradds (X0, YCoeffs[j], Y0);
902       Y1 = vec_mradds (X1, YCoeffs[j], Y1);
903     }
904
905     U = RND;
906     V = RND;
907     /* extract 8 coeffs from U,V */
908     for(j=0; j<chrFilterSize; j++) {
909       X  = vec_ld (0, &chrSrc[j][i/2]);
910       U  = vec_mradds (X, CCoeffs[j], U);
911       X  = vec_ld (0, &chrSrc[j][i/2+2048]);
912       V  = vec_mradds (X, CCoeffs[j], V);
913     }
914
915     /* scale and clip signals */
916     Y0 = vec_sra (Y0, SCL);
917     Y1 = vec_sra (Y1, SCL);
918     U  = vec_sra (U,  SCL);
919     V  = vec_sra (V,  SCL);
920
921     Y0 = vec_clip_s16 (Y0);
922     Y1 = vec_clip_s16 (Y1);
923     U  = vec_clip_s16 (U);
924     V  = vec_clip_s16 (V);
925
926     /* now we have
927        Y0= y0 y1 y2 y3 y4 y5 y6 y7     Y1= y8 y9 y10 y11 y12 y13 y14 y15
928        U= u0 u1 u2 u3 u4 u5 u6 u7      V= v0 v1 v2 v3 v4 v5 v6 v7
929
930        Y0= y0 y1 y2 y3 y4 y5 y6 y7    Y1= y8 y9 y10 y11 y12 y13 y14 y15
931        U0= u0 u0 u1 u1 u2 u2 u3 u3    U1= u4 u4 u5 u5 u6 u6 u7 u7
932        V0= v0 v0 v1 v1 v2 v2 v3 v3    V1= v4 v4 v5 v5 v6 v6 v7 v7
933     */
934
935     U0 = vec_mergeh (U,U);
936     V0 = vec_mergeh (V,V);
937
938     U1 = vec_mergel (U,U);
939     V1 = vec_mergel (V,V);
940
941     cvtyuvtoRGB (c, Y0,U0,V0,&R0,&G0,&B0);
942     cvtyuvtoRGB (c, Y1,U1,V1,&R1,&G1,&B1);
943
944     R  = vec_packclp (R0,R1);
945     G  = vec_packclp (G0,G1);
946     B  = vec_packclp (B0,B1);
947
948     nout = (vector unsigned char *)scratch;
949     switch(c->dstFormat) {
950       case IMGFMT_ABGR: out_abgr (R,G,B,nout); break;
951       case IMGFMT_BGRA: out_bgra (R,G,B,nout); break;
952       case IMGFMT_RGBA: out_rgba (R,G,B,nout); break;
953       case IMGFMT_ARGB: out_argb (R,G,B,nout); break;
954       case IMGFMT_RGB24: out_rgb24 (R,G,B,nout); break;
955       case IMGFMT_BGR24: out_bgr24 (R,G,B,nout); break;
956       default:
957         /* Unreachable, I think. */
958         MSG_ERR("altivec_yuv2packedX doesn't support %s output\n",
959                 sws_format_name(c->dstFormat));
960         return;
961     }
962
963     memcpy (&((uint32_t*)dest)[i], scratch, (dstW-i)/4);
964   }
965
966 }