2 marc.hoffman@analog.com March 8, 2004
4 Altivec Acceleration for Color Space Conversion revision 0.2
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.
12 lots of optimizations to be done here
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
17 2. the inefficient use of chroma loading needs a bit of brushing up
19 3. analysis of pipeline stalls needs to be done, use shark to identify pipeline stalls
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.
28 ADDED altivec_yuv2packedX vertical scl + RGB converter
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
38 so we have roughly 10clocks per pixel this is too high something has to be wrong.
40 OPTIMIZED clip codes to utilize vec_max and vec_packs removing the need for vec_min.
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.
50 Now MEMCPY is the largest mips consumer in the system, probably due
51 to the inefficient X11 stuff.
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))
58 GL2 libraries work now with patch for RGB32
60 NOTE quartz vo driver ARGB32_to_RGB24 consumes 30% of the processor
62 Integrated luma prescaling adjustment for saturation/contrast/brightness adjustment.
76 #include "swscale_internal.h"
78 #include "libvo/img_format.h" //FIXME try to reduce dependency of such stuff
80 #undef PROFILE_THE_BEAST
83 typedef unsigned char ubyte;
84 typedef signed char sbyte;
87 /* RGB interleaver, 16 planar pels 8-bit samples per channel in
88 homogeneous vector registers x0,x1,x2 are interleaved with the
91 o0 = vec_mergeh (x0,x1);
92 o1 = vec_perm (o0, x2, perm_rgb_0);
93 o2 = vec_perm (o0, x2, perm_rgb_1);
94 o3 = vec_mergel (x0,x1);
95 o4 = vec_perm (o3,o2,perm_rgb_2);
96 o5 = vec_perm (o3,o2,perm_rgb_3);
98 perm_rgb_0: o0(RG).h v1(B) --> o1*
104 perm_rgb_1: o0(RG).h v1(B) --> o2
110 perm_rgb_2: o3(RG).l o2(rgbB.l) --> o4*
116 perm_rgb_2: o3(RG).l o2(rgbB.l) ---> o5*
124 const vector unsigned char
125 perm_rgb_0 = (const vector unsigned char)AVV(0x00,0x01,0x10,0x02,0x03,0x11,0x04,0x05,
126 0x12,0x06,0x07,0x13,0x08,0x09,0x14,0x0a),
127 perm_rgb_1 = (const vector unsigned char)AVV(0x0b,0x15,0x0c,0x0d,0x16,0x0e,0x0f,0x17,
128 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f),
129 perm_rgb_2 = (const vector unsigned char)AVV(0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
130 0x00,0x01,0x18,0x02,0x03,0x19,0x04,0x05),
131 perm_rgb_3 = (const vector unsigned char)AVV(0x1a,0x06,0x07,0x1b,0x08,0x09,0x1c,0x0a,
132 0x0b,0x1d,0x0c,0x0d,0x1e,0x0e,0x0f,0x1f);
134 #define vec_merge3(x2,x1,x0,y0,y1,y2) \
136 typeof(x0) o0,o2,o3; \
137 o0 = vec_mergeh (x0,x1); \
138 y0 = vec_perm (o0, x2, perm_rgb_0);\
139 o2 = vec_perm (o0, x2, perm_rgb_1);\
140 o3 = vec_mergel (x0,x1); \
141 y1 = vec_perm (o3,o2,perm_rgb_2); \
142 y2 = vec_perm (o3,o2,perm_rgb_3); \
145 #define vec_mstbgr24(x0,x1,x2,ptr) \
147 typeof(x0) _0,_1,_2; \
148 vec_merge3 (x0,x1,x2,_0,_1,_2); \
149 vec_st (_0, 0, ptr++); \
150 vec_st (_1, 0, ptr++); \
151 vec_st (_2, 0, ptr++); \
154 #define vec_mstrgb24(x0,x1,x2,ptr) \
156 typeof(x0) _0,_1,_2; \
157 vec_merge3 (x2,x1,x0,_0,_1,_2); \
158 vec_st (_0, 0, ptr++); \
159 vec_st (_1, 0, ptr++); \
160 vec_st (_2, 0, ptr++); \
163 /* pack the pixels in rgb0 format
167 #define vec_mstrgb32(T,x0,x1,x2,x3,ptr) \
170 _0 = vec_mergeh (x0,x1); \
171 _1 = vec_mergeh (x2,x3); \
172 _2 = (T)vec_mergeh ((vector unsigned short)_0,(vector unsigned short)_1); \
173 _3 = (T)vec_mergel ((vector unsigned short)_0,(vector unsigned short)_1); \
174 vec_st (_2, 0*16, (T *)ptr); \
175 vec_st (_3, 1*16, (T *)ptr); \
176 _0 = vec_mergel (x0,x1); \
177 _1 = vec_mergel (x2,x3); \
178 _2 = (T)vec_mergeh ((vector unsigned short)_0,(vector unsigned short)_1); \
179 _3 = (T)vec_mergel ((vector unsigned short)_0,(vector unsigned short)_1); \
180 vec_st (_2, 2*16, (T *)ptr); \
181 vec_st (_3, 3*16, (T *)ptr); \
188 | 1 -0.3441 -0.7142 |x| Cb|
195 typical yuv conversion work on Y: 0-255 this version has been optimized for jpeg decode.
203 (vector signed short) \
204 vec_perm(x,(typeof(x))AVV(0),\
205 (vector unsigned char)AVV(0x10,0x00,0x10,0x01,0x10,0x02,0x10,0x03,\
206 0x10,0x04,0x10,0x05,0x10,0x06,0x10,0x07))
208 (vector signed short) \
209 vec_perm(x,(typeof(x))AVV(0),\
210 (vector unsigned char)AVV(0x10,0x08,0x10,0x09,0x10,0x0A,0x10,0x0B,\
211 0x10,0x0C,0x10,0x0D,0x10,0x0E,0x10,0x0F))
213 #define vec_clip_s16(x) \
214 vec_max (vec_min (x, (vector signed short)AVV(235,235,235,235,235,235,235,235)),\
215 (vector signed short)AVV(16, 16, 16, 16, 16, 16, 16, 16 ))
217 #define vec_packclp(x,y) \
218 (vector unsigned char)vec_packs \
219 ((vector unsigned short)vec_max (x,(vector signed short) AVV(0)), \
220 (vector unsigned short)vec_max (y,(vector signed short) AVV(0)))
222 //#define out_pixels(a,b,c,ptr) vec_mstrgb32(typeof(a),((typeof (a))AVV(0)),a,a,a,ptr)
225 static inline void cvtyuvtoRGB (SwsContext *c,
226 vector signed short Y, vector signed short U, vector signed short V,
227 vector signed short *R, vector signed short *G, vector signed short *B)
229 vector signed short vx,ux,uvx;
231 Y = vec_mradds (Y, c->CY, c->OY);
232 U = vec_sub (U,(vector signed short)
233 vec_splat((vector signed short)AVV(128),0));
234 V = vec_sub (V,(vector signed short)
235 vec_splat((vector signed short)AVV(128),0));
237 // ux = (CBU*(u<<c->CSHIFT)+0x4000)>>15;
238 ux = vec_sl (U, c->CSHIFT);
239 *B = vec_mradds (ux, c->CBU, Y);
241 // vx = (CRV*(v<<c->CSHIFT)+0x4000)>>15;
242 vx = vec_sl (V, c->CSHIFT);
243 *R = vec_mradds (vx, c->CRV, Y);
245 // uvx = ((CGU*u) + (CGV*v))>>15;
246 uvx = vec_mradds (U, c->CGU, Y);
247 *G = vec_mradds (V, c->CGV, uvx);
252 ------------------------------------------------------------------------------
254 ------------------------------------------------------------------------------
258 #define DEFCSP420_CVT(name,out_pixels) \
259 static int altivec_##name (SwsContext *c, \
260 unsigned char **in, int *instrides, \
261 int srcSliceY, int srcSliceH, \
262 unsigned char **oplanes, int *outstrides) \
267 int instrides_scl[3]; \
268 vector unsigned char y0,y1; \
270 vector signed char u,v; \
272 vector signed short Y0,Y1,Y2,Y3; \
273 vector signed short U,V; \
274 vector signed short vx,ux,uvx; \
275 vector signed short vx0,ux0,uvx0; \
276 vector signed short vx1,ux1,uvx1; \
277 vector signed short R0,G0,B0; \
278 vector signed short R1,G1,B1; \
279 vector unsigned char R,G,B; \
281 vector unsigned char *uivP, *vivP; \
282 vector unsigned char align_perm; \
284 vector signed short \
292 vector unsigned short lCSHIFT = c->CSHIFT; \
294 ubyte *y1i = in[0]; \
295 ubyte *y2i = in[0]+w; \
299 vector unsigned char *oute \
300 = (vector unsigned char *) \
301 (oplanes[0]+srcSliceY*outstrides[0]); \
302 vector unsigned char *outo \
303 = (vector unsigned char *) \
304 (oplanes[0]+srcSliceY*outstrides[0]+outstrides[0]); \
307 instrides_scl[0] = instrides[0]; \
308 instrides_scl[1] = instrides[1]-w/2; /* the loop moves ui by w/2 */ \
309 instrides_scl[2] = instrides[2]-w/2; /* the loop moves vi by w/2 */ \
312 for (i=0;i<h/2;i++) { \
313 vec_dstst (outo, (0x02000002|(((w*3+32)/32)<<16)), 0); \
314 vec_dstst (oute, (0x02000002|(((w*3+32)/32)<<16)), 1); \
316 for (j=0;j<w/16;j++) { \
318 y0 = vec_ldl (0,y1i); \
319 y1 = vec_ldl (0,y2i); \
320 uivP = (vector unsigned char *)ui; \
321 vivP = (vector unsigned char *)vi; \
323 align_perm = vec_lvsl (0, ui); \
324 u = (vector signed char)vec_perm (uivP[0], uivP[1], align_perm); \
326 align_perm = vec_lvsl (0, vi); \
327 v = (vector signed char)vec_perm (vivP[0], vivP[1], align_perm); \
329 u = (vector signed char) \
330 vec_sub (u,(vector signed char) \
331 vec_splat((vector signed char)AVV(128),0));\
332 v = (vector signed char) \
333 vec_sub (v,(vector signed char) \
334 vec_splat((vector signed char)AVV(128),0));\
336 U = vec_unpackh (u); \
337 V = vec_unpackh (v); \
345 Y0 = vec_mradds (Y0, lCY, lOY); \
346 Y1 = vec_mradds (Y1, lCY, lOY); \
347 Y2 = vec_mradds (Y2, lCY, lOY); \
348 Y3 = vec_mradds (Y3, lCY, lOY); \
350 /* ux = (CBU*(u<<CSHIFT)+0x4000)>>15 */ \
351 ux = vec_sl (U, lCSHIFT); \
352 ux = vec_mradds (ux, lCBU, (vector signed short)AVV(0)); \
353 ux0 = vec_mergeh (ux,ux); \
354 ux1 = vec_mergel (ux,ux); \
356 /* vx = (CRV*(v<<CSHIFT)+0x4000)>>15; */ \
357 vx = vec_sl (V, lCSHIFT); \
358 vx = vec_mradds (vx, lCRV, (vector signed short)AVV(0)); \
359 vx0 = vec_mergeh (vx,vx); \
360 vx1 = vec_mergel (vx,vx); \
362 /* uvx = ((CGU*u) + (CGV*v))>>15 */ \
363 uvx = vec_mradds (U, lCGU, (vector signed short)AVV(0)); \
364 uvx = vec_mradds (V, lCGV, uvx); \
365 uvx0 = vec_mergeh (uvx,uvx); \
366 uvx1 = vec_mergel (uvx,uvx); \
368 R0 = vec_add (Y0,vx0); \
369 G0 = vec_add (Y0,uvx0); \
370 B0 = vec_add (Y0,ux0); \
371 R1 = vec_add (Y1,vx1); \
372 G1 = vec_add (Y1,uvx1); \
373 B1 = vec_add (Y1,ux1); \
375 R = vec_packclp (R0,R1); \
376 G = vec_packclp (G0,G1); \
377 B = vec_packclp (B0,B1); \
379 out_pixels(R,G,B,oute); \
381 R0 = vec_add (Y2,vx0); \
382 G0 = vec_add (Y2,uvx0); \
383 B0 = vec_add (Y2,ux0); \
384 R1 = vec_add (Y3,vx1); \
385 G1 = vec_add (Y3,uvx1); \
386 B1 = vec_add (Y3,ux1); \
387 R = vec_packclp (R0,R1); \
388 G = vec_packclp (G0,G1); \
389 B = vec_packclp (B0,B1); \
392 out_pixels(R,G,B,outo); \
401 outo += (outstrides[0])>>4; \
402 oute += (outstrides[0])>>4; \
404 ui += instrides_scl[1]; \
405 vi += instrides_scl[2]; \
406 y1i += instrides_scl[0]; \
407 y2i += instrides_scl[0]; \
413 #define out_abgr(a,b,c,ptr) vec_mstrgb32(typeof(a),((typeof (a))AVV(0)),c,b,a,ptr)
414 #define out_bgra(a,b,c,ptr) vec_mstrgb32(typeof(a),c,b,a,((typeof (a))AVV(0)),ptr)
415 #define out_rgba(a,b,c,ptr) vec_mstrgb32(typeof(a),a,b,c,((typeof (a))AVV(0)),ptr)
416 #define out_argb(a,b,c,ptr) vec_mstrgb32(typeof(a),((typeof (a))AVV(0)),a,b,c,ptr)
417 #define out_rgb24(a,b,c,ptr) vec_mstrgb24(a,b,c,ptr)
418 #define out_bgr24(a,b,c,ptr) vec_mstbgr24(a,b,c,ptr)
420 DEFCSP420_CVT (yuv2_abgr, out_abgr)
422 DEFCSP420_CVT (yuv2_bgra, out_bgra)
424 static int altivec_yuv2_bgra32 (SwsContext *c,
425 unsigned char **in, int *instrides,
426 int srcSliceY, int srcSliceH,
427 unsigned char **oplanes, int *outstrides)
432 int instrides_scl[3];
433 vector unsigned char y0,y1;
435 vector signed char u,v;
437 vector signed short Y0,Y1,Y2,Y3;
438 vector signed short U,V;
439 vector signed short vx,ux,uvx;
440 vector signed short vx0,ux0,uvx0;
441 vector signed short vx1,ux1,uvx1;
442 vector signed short R0,G0,B0;
443 vector signed short R1,G1,B1;
444 vector unsigned char R,G,B;
446 vector unsigned char *uivP, *vivP;
447 vector unsigned char align_perm;
457 vector unsigned short lCSHIFT = c->CSHIFT;
460 ubyte *y2i = in[0]+w;
464 vector unsigned char *oute
465 = (vector unsigned char *)
466 (oplanes[0]+srcSliceY*outstrides[0]);
467 vector unsigned char *outo
468 = (vector unsigned char *)
469 (oplanes[0]+srcSliceY*outstrides[0]+outstrides[0]);
472 instrides_scl[0] = instrides[0];
473 instrides_scl[1] = instrides[1]-w/2; /* the loop moves ui by w/2 */
474 instrides_scl[2] = instrides[2]-w/2; /* the loop moves vi by w/2 */
477 for (i=0;i<h/2;i++) {
478 vec_dstst (outo, (0x02000002|(((w*3+32)/32)<<16)), 0);
479 vec_dstst (oute, (0x02000002|(((w*3+32)/32)<<16)), 1);
481 for (j=0;j<w/16;j++) {
483 y0 = vec_ldl (0,y1i);
484 y1 = vec_ldl (0,y2i);
485 uivP = (vector unsigned char *)ui;
486 vivP = (vector unsigned char *)vi;
488 align_perm = vec_lvsl (0, ui);
489 u = (vector signed char)vec_perm (uivP[0], uivP[1], align_perm);
491 align_perm = vec_lvsl (0, vi);
492 v = (vector signed char)vec_perm (vivP[0], vivP[1], align_perm);
493 u = (vector signed char)
494 vec_sub (u,(vector signed char)
495 vec_splat((vector signed char)AVV(128),0));
497 v = (vector signed char)
498 vec_sub (v, (vector signed char)
499 vec_splat((vector signed char)AVV(128),0));
510 Y0 = vec_mradds (Y0, lCY, lOY);
511 Y1 = vec_mradds (Y1, lCY, lOY);
512 Y2 = vec_mradds (Y2, lCY, lOY);
513 Y3 = vec_mradds (Y3, lCY, lOY);
515 /* ux = (CBU*(u<<CSHIFT)+0x4000)>>15 */
516 ux = vec_sl (U, lCSHIFT);
517 ux = vec_mradds (ux, lCBU, (vector signed short)AVV(0));
518 ux0 = vec_mergeh (ux,ux);
519 ux1 = vec_mergel (ux,ux);
521 /* vx = (CRV*(v<<CSHIFT)+0x4000)>>15; */
522 vx = vec_sl (V, lCSHIFT);
523 vx = vec_mradds (vx, lCRV, (vector signed short)AVV(0));
524 vx0 = vec_mergeh (vx,vx);
525 vx1 = vec_mergel (vx,vx);
526 /* uvx = ((CGU*u) + (CGV*v))>>15 */
527 uvx = vec_mradds (U, lCGU, (vector signed short)AVV(0));
528 uvx = vec_mradds (V, lCGV, uvx);
529 uvx0 = vec_mergeh (uvx,uvx);
530 uvx1 = vec_mergel (uvx,uvx);
531 R0 = vec_add (Y0,vx0);
532 G0 = vec_add (Y0,uvx0);
533 B0 = vec_add (Y0,ux0);
534 R1 = vec_add (Y1,vx1);
535 G1 = vec_add (Y1,uvx1);
536 B1 = vec_add (Y1,ux1);
537 R = vec_packclp (R0,R1);
538 G = vec_packclp (G0,G1);
539 B = vec_packclp (B0,B1);
541 out_argb(R,G,B,oute);
542 R0 = vec_add (Y2,vx0);
543 G0 = vec_add (Y2,uvx0);
544 B0 = vec_add (Y2,ux0);
545 R1 = vec_add (Y3,vx1);
546 G1 = vec_add (Y3,uvx1);
547 B1 = vec_add (Y3,ux1);
548 R = vec_packclp (R0,R1);
549 G = vec_packclp (G0,G1);
550 B = vec_packclp (B0,B1);
552 out_argb(R,G,B,outo);
560 outo += (outstrides[0])>>4;
561 oute += (outstrides[0])>>4;
563 ui += instrides_scl[1];
564 vi += instrides_scl[2];
565 y1i += instrides_scl[0];
566 y2i += instrides_scl[0];
574 DEFCSP420_CVT (yuv2_rgba, out_rgba)
575 DEFCSP420_CVT (yuv2_argb, out_argb)
576 DEFCSP420_CVT (yuv2_rgb24, out_rgb24)
577 DEFCSP420_CVT (yuv2_bgr24, out_bgr24)
580 // uyvy|uyvy|uyvy|uyvy
581 // 0123 4567 89ab cdef
583 const vector unsigned char
584 demux_u = (const vector unsigned char)AVV(0x10,0x00,0x10,0x00,
587 0x10,0x0c,0x10,0x0c),
588 demux_v = (const vector unsigned char)AVV(0x10,0x02,0x10,0x02,
591 0x10,0x0E,0x10,0x0E),
592 demux_y = (const vector unsigned char)AVV(0x10,0x01,0x10,0x03,
595 0x10,0x0D,0x10,0x0F);
598 this is so I can play live CCIR raw video
600 static int altivec_uyvy_rgb32 (SwsContext *c,
601 unsigned char **in, int *instrides,
602 int srcSliceY, int srcSliceH,
603 unsigned char **oplanes, int *outstrides)
608 vector unsigned char uyvy;
609 vector signed short Y,U,V;
610 vector signed short vx,ux,uvx;
611 vector signed short R0,G0,B0,R1,G1,B1;
612 vector unsigned char R,G,B;
613 vector unsigned char *out;
617 out = (vector unsigned char *)(oplanes[0]+srcSliceY*outstrides[0]);
620 for (j=0;j<w/16;j++) {
621 uyvy = vec_ld (0, img);
622 U = (vector signed short)
623 vec_perm (uyvy, (vector unsigned char)AVV(0), demux_u);
625 V = (vector signed short)
626 vec_perm (uyvy, (vector unsigned char)AVV(0), demux_v);
628 Y = (vector signed short)
629 vec_perm (uyvy, (vector unsigned char)AVV(0), demux_y);
631 cvtyuvtoRGB (c, Y,U,V,&R0,&G0,&B0);
633 uyvy = vec_ld (16, img);
634 U = (vector signed short)
635 vec_perm (uyvy, (vector unsigned char)AVV(0), demux_u);
637 V = (vector signed short)
638 vec_perm (uyvy, (vector unsigned char)AVV(0), demux_v);
640 Y = (vector signed short)
641 vec_perm (uyvy, (vector unsigned char)AVV(0), demux_y);
643 cvtyuvtoRGB (c, Y,U,V,&R1,&G1,&B1);
645 R = vec_packclp (R0,R1);
646 G = vec_packclp (G0,G1);
647 B = vec_packclp (B0,B1);
649 // vec_mstbgr24 (R,G,B, out);
650 out_rgba (R,G,B,out);
660 /* Ok currently the acceleration routine only supports
661 inputs of widths a multiple of 16
662 and heights a multiple 2
664 So we just fall back to the C codes for this.
666 SwsFunc yuv2rgb_init_altivec (SwsContext *c)
668 if (!(c->flags & SWS_CPU_CAPS_ALTIVEC))
672 and this seems not to matter too much I tried a bunch of
673 videos with abnormal widths and mplayer crashes else where.
674 mplayer -vo x11 -rawvideo on:w=350:h=240 raw-350x240.eyuv
675 boom with X11 bad match.
678 if ((c->srcW & 0xf) != 0) return NULL;
680 switch (c->srcFormat) {
691 if ((c->srcH & 0x1) != 0)
694 switch(c->dstFormat){
696 MSG_WARN("ALTIVEC: Color Space RGB24\n");
697 return altivec_yuv2_rgb24;
699 MSG_WARN("ALTIVEC: Color Space BGR24\n");
700 return altivec_yuv2_bgr24;
702 MSG_WARN("ALTIVEC: Color Space ARGB\n");
703 return altivec_yuv2_argb;
705 MSG_WARN("ALTIVEC: Color Space ABGR\n");
706 return altivec_yuv2_abgr;
708 MSG_WARN("ALTIVEC: Color Space RGBA\n");
709 return altivec_yuv2_rgba;
711 MSG_WARN("ALTIVEC: Color Space BGRA\n");
712 return altivec_yuv2_bgra;
713 default: return NULL;
718 switch(c->dstFormat){
720 MSG_WARN("ALTIVEC: Color Space UYVY -> RGB32\n");
721 return altivec_uyvy_rgb32;
722 default: return NULL;
730 static uint16_t roundToInt16(int64_t f){
731 int r= (f + (1<<15))>>16;
732 if(r<-0x7FFF) return 0x8000;
733 else if(r> 0x7FFF) return 0x7FFF;
737 void yuv2rgb_altivec_init_tables (SwsContext *c, const int inv_table[4],int brightness,int contrast, int saturation)
740 signed short tmp[8] __attribute__ ((aligned(16)));
741 vector signed short vec;
744 buf.tmp[0] = ( (0xffffLL) * contrast>>8 )>>9; //cy
745 buf.tmp[1] = -256*brightness; //oy
746 buf.tmp[2] = (inv_table[0]>>3) *(contrast>>16)*(saturation>>16); //crv
747 buf.tmp[3] = (inv_table[1]>>3) *(contrast>>16)*(saturation>>16); //cbu
748 buf.tmp[4] = -((inv_table[2]>>1)*(contrast>>16)*(saturation>>16)); //cgu
749 buf.tmp[5] = -((inv_table[3]>>1)*(contrast>>16)*(saturation>>16)); //cgv
752 c->CSHIFT = (vector unsigned short)vec_splat_u16(2);
753 c->CY = vec_splat ((vector signed short)buf.vec, 0);
754 c->OY = vec_splat ((vector signed short)buf.vec, 1);
755 c->CRV = vec_splat ((vector signed short)buf.vec, 2);
756 c->CBU = vec_splat ((vector signed short)buf.vec, 3);
757 c->CGU = vec_splat ((vector signed short)buf.vec, 4);
758 c->CGV = vec_splat ((vector signed short)buf.vec, 5);
762 char *v[6]={"cy","oy","crv","cbu","cgu","cgv"};
764 printf("%s %d ", v[i],buf.tmp[i] );
773 altivec_yuv2packedX (SwsContext *c,
774 int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
775 int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,
776 uint8_t *dest, int dstW, int dstY)
780 vector signed short X,X0,X1,Y0,U0,V0,Y1,U1,V1,U,V;
781 vector signed short R0,G0,B0,R1,G1,B1;
783 vector unsigned char R,G,B,pels[3];
784 vector unsigned char *out,*nout;
786 vector signed short RND = vec_splat_s16(1<<3);
787 vector unsigned short SCL = vec_splat_u16(4);
788 unsigned long scratch[16] __attribute__ ((aligned (16)));
790 vector signed short *YCoeffs, *CCoeffs;
792 YCoeffs = c->vYCoeffsBank+dstY*lumFilterSize;
793 CCoeffs = c->vCCoeffsBank+dstY*chrFilterSize;
795 out = (vector unsigned char *)dest;
797 for(i=0; i<dstW; i+=16){
800 /* extract 16 coeffs from lumSrc */
801 for(j=0; j<lumFilterSize; j++) {
802 X0 = vec_ld (0, &lumSrc[j][i]);
803 X1 = vec_ld (16, &lumSrc[j][i]);
804 Y0 = vec_mradds (X0, YCoeffs[j], Y0);
805 Y1 = vec_mradds (X1, YCoeffs[j], Y1);
810 /* extract 8 coeffs from U,V */
811 for(j=0; j<chrFilterSize; j++) {
812 X = vec_ld (0, &chrSrc[j][i/2]);
813 U = vec_mradds (X, CCoeffs[j], U);
814 X = vec_ld (0, &chrSrc[j][i/2+2048]);
815 V = vec_mradds (X, CCoeffs[j], V);
818 /* scale and clip signals */
819 Y0 = vec_sra (Y0, SCL);
820 Y1 = vec_sra (Y1, SCL);
821 U = vec_sra (U, SCL);
822 V = vec_sra (V, SCL);
824 Y0 = vec_clip_s16 (Y0);
825 Y1 = vec_clip_s16 (Y1);
826 U = vec_clip_s16 (U);
827 V = vec_clip_s16 (V);
830 Y0= y0 y1 y2 y3 y4 y5 y6 y7 Y1= y8 y9 y10 y11 y12 y13 y14 y15
831 U= u0 u1 u2 u3 u4 u5 u6 u7 V= v0 v1 v2 v3 v4 v5 v6 v7
833 Y0= y0 y1 y2 y3 y4 y5 y6 y7 Y1= y8 y9 y10 y11 y12 y13 y14 y15
834 U0= u0 u0 u1 u1 u2 u2 u3 u3 U1= u4 u4 u5 u5 u6 u6 u7 u7
835 V0= v0 v0 v1 v1 v2 v2 v3 v3 V1= v4 v4 v5 v5 v6 v6 v7 v7
838 U0 = vec_mergeh (U,U);
839 V0 = vec_mergeh (V,V);
841 U1 = vec_mergel (U,U);
842 V1 = vec_mergel (V,V);
844 cvtyuvtoRGB (c, Y0,U0,V0,&R0,&G0,&B0);
845 cvtyuvtoRGB (c, Y1,U1,V1,&R1,&G1,&B1);
847 R = vec_packclp (R0,R1);
848 G = vec_packclp (G0,G1);
849 B = vec_packclp (B0,B1);
851 switch(c->dstFormat) {
852 case IMGFMT_ABGR: out_abgr (R,G,B,out); break;
853 case IMGFMT_BGRA: out_bgra (R,G,B,out); break;
854 case IMGFMT_RGBA: out_rgba (R,G,B,out); break;
855 case IMGFMT_ARGB: out_argb (R,G,B,out); break;
856 case IMGFMT_RGB24: out_rgb24 (R,G,B,out); break;
857 case IMGFMT_BGR24: out_bgr24 (R,G,B,out); break;
860 /* If this is reached, the caller should have called yuv2packedXinC
862 static int printed_error_message;
863 if(!printed_error_message) {
864 MSG_ERR("altivec_yuv2packedX doesn't support %s output\n",
865 vo_format_name(c->dstFormat));
866 printed_error_message=1;
878 /* extract 16 coeffs from lumSrc */
879 for(j=0; j<lumFilterSize; j++) {
880 X0 = vec_ld (0, &lumSrc[j][i]);
881 X1 = vec_ld (16, &lumSrc[j][i]);
882 Y0 = vec_mradds (X0, YCoeffs[j], Y0);
883 Y1 = vec_mradds (X1, YCoeffs[j], Y1);
888 /* extract 8 coeffs from U,V */
889 for(j=0; j<chrFilterSize; j++) {
890 X = vec_ld (0, &chrSrc[j][i/2]);
891 U = vec_mradds (X, CCoeffs[j], U);
892 X = vec_ld (0, &chrSrc[j][i/2+2048]);
893 V = vec_mradds (X, CCoeffs[j], V);
896 /* scale and clip signals */
897 Y0 = vec_sra (Y0, SCL);
898 Y1 = vec_sra (Y1, SCL);
899 U = vec_sra (U, SCL);
900 V = vec_sra (V, SCL);
902 Y0 = vec_clip_s16 (Y0);
903 Y1 = vec_clip_s16 (Y1);
904 U = vec_clip_s16 (U);
905 V = vec_clip_s16 (V);
908 Y0= y0 y1 y2 y3 y4 y5 y6 y7 Y1= y8 y9 y10 y11 y12 y13 y14 y15
909 U= u0 u1 u2 u3 u4 u5 u6 u7 V= v0 v1 v2 v3 v4 v5 v6 v7
911 Y0= y0 y1 y2 y3 y4 y5 y6 y7 Y1= y8 y9 y10 y11 y12 y13 y14 y15
912 U0= u0 u0 u1 u1 u2 u2 u3 u3 U1= u4 u4 u5 u5 u6 u6 u7 u7
913 V0= v0 v0 v1 v1 v2 v2 v3 v3 V1= v4 v4 v5 v5 v6 v6 v7 v7
916 U0 = vec_mergeh (U,U);
917 V0 = vec_mergeh (V,V);
919 U1 = vec_mergel (U,U);
920 V1 = vec_mergel (V,V);
922 cvtyuvtoRGB (c, Y0,U0,V0,&R0,&G0,&B0);
923 cvtyuvtoRGB (c, Y1,U1,V1,&R1,&G1,&B1);
925 R = vec_packclp (R0,R1);
926 G = vec_packclp (G0,G1);
927 B = vec_packclp (B0,B1);
929 nout = (vector unsigned char *)scratch;
930 switch(c->dstFormat) {
931 case IMGFMT_ABGR: out_abgr (R,G,B,nout); break;
932 case IMGFMT_BGRA: out_bgra (R,G,B,nout); break;
933 case IMGFMT_RGBA: out_rgba (R,G,B,nout); break;
934 case IMGFMT_ARGB: out_argb (R,G,B,nout); break;
935 case IMGFMT_RGB24: out_rgb24 (R,G,B,nout); break;
936 case IMGFMT_BGR24: out_bgr24 (R,G,B,nout); break;
938 /* Unreachable, I think. */
939 MSG_ERR("altivec_yuv2packedX doesn't support %s output\n",
940 vo_format_name(c->dstFormat));
944 memcpy (&((uint32_t*)dest)[i], scratch, (dstW-i)/4);