3 * rgb2rgb.c, Software RGB to RGB convertor
4 * Written by Nick Kurshev.
5 * palette stuff & yuv stuff by Michael
10 #include "../mmx_defs.h"
13 static const uint64_t mask32 __attribute__((aligned(8))) = 0x00FFFFFF00FFFFFFULL;
14 static const uint64_t mask24l __attribute__((aligned(8))) = 0x0000000000FFFFFFULL;
15 static const uint64_t mask24h __attribute__((aligned(8))) = 0x0000FFFFFF000000ULL;
16 static const uint64_t mask15b __attribute__((aligned(8))) = 0x001F001F001F001FULL; /* 00000000 00011111 xxB */
17 static const uint64_t mask15rg __attribute__((aligned(8))) = 0x7FE07FE07FE07FE0ULL; /* 01111111 11100000 RGx */
18 static const uint64_t mask15s __attribute__((aligned(8))) = 0xFFE0FFE0FFE0FFE0ULL;
21 void rgb24to32(const uint8_t *src,uint8_t *dst,unsigned src_size)
24 const uint8_t *s = src;
31 __asm __volatile(PREFETCH" %0"::"m"(*s):"memory");
32 mm_end = (uint8_t*)((((unsigned long)end)/(MMREG_SIZE*2))*(MMREG_SIZE*2));
33 __asm __volatile("movq %0, %%mm7"::"m"(mask32):"memory");
34 if(mm_end == end) mm_end -= MMREG_SIZE*2;
43 "punpckldq %%mm1, %%mm0\n\t"
44 "punpckldq %%mm3, %%mm2\n\t"
45 "pand %%mm7, %%mm0\n\t"
46 "pand %%mm7, %%mm2\n\t"
47 MOVNTQ" %%mm0, %0\n\t"
55 __asm __volatile(SFENCE:::"memory");
56 __asm __volatile(EMMS:::"memory");
67 void rgb32to24(const uint8_t *src,uint8_t *dst,unsigned src_size)
70 const uint8_t *s = src;
77 __asm __volatile(PREFETCH" %0"::"m"(*s):"memory");
78 mm_end = (uint8_t*)((((unsigned long)end)/(MMREG_SIZE*2))*(MMREG_SIZE*2));
82 ::"m"(mask24l),"m"(mask24h):"memory");
83 if(mm_end == end) mm_end -= MMREG_SIZE*2;
90 "movq %%mm0, %%mm2\n\t"
91 "movq %%mm1, %%mm3\n\t"
94 "pand %%mm7, %%mm0\n\t"
95 "pand %%mm7, %%mm1\n\t"
96 "pand %%mm6, %%mm2\n\t"
97 "pand %%mm6, %%mm3\n\t"
98 "por %%mm2, %%mm0\n\t"
99 "por %%mm3, %%mm1\n\t"
100 MOVNTQ" %%mm0, %0\n\t"
108 __asm __volatile(SFENCE:::"memory");
109 __asm __volatile(EMMS:::"memory");
121 Original by Strepto/Astral
122 ported to gcc & bugfixed : A'rpi
123 MMX2, 3DNOW optimization by Nick Kurshev
124 32bit c version, and and&add trick by Michael Niedermayer
126 void rgb15to16(const uint8_t *src,uint8_t *dst,unsigned src_size)
129 register const char* s=src+src_size;
130 register char* d=dst+src_size;
131 register int offs=-src_size;
132 __asm __volatile(PREFETCH" %0"::"m"(*(s+offs)));
141 "movq 8%1, %%mm2\n\t"
142 "movq %%mm0, %%mm1\n\t"
143 "movq %%mm2, %%mm3\n\t"
144 "pand %%mm4, %%mm0\n\t"
145 "pand %%mm4, %%mm2\n\t"
146 "paddw %%mm1, %%mm0\n\t"
147 "paddw %%mm3, %%mm2\n\t"
148 MOVNTQ" %%mm0, %0\n\t"
155 __asm __volatile(SFENCE:::"memory");
156 __asm __volatile(EMMS:::"memory");
159 const uint16_t *s1=( uint16_t * )src;
160 uint16_t *d1=( uint16_t * )dst;
161 uint16_t *e=((uint8_t *)s1)+src_size;
163 register int x=*( s1++ );
166 0111 1111 1110 0000=0x7FE0
167 00000000000001 1111=0x001F */
168 *( d1++ )=( x&0x001F )|( ( x&0x7FE0 )<<1 );
171 const unsigned *s1=( unsigned * )src;
172 unsigned *d1=( unsigned * )dst;
174 int size= src_size>>2;
175 for(i=0; i<size; i++)
177 register int x= s1[i];
178 // d1[i] = x + (x&0x7FE07FE0); //faster but need msbit =0 which might not allways be true
179 d1[i] = (x&0x7FFF7FFF) + (x&0x7FE07FE0);
187 * Pallete is assumed to contain bgr32
189 void palette8torgb32(const uint8_t *src, uint8_t *dst, unsigned num_pixels, const uint8_t *palette)
192 for(i=0; i<num_pixels; i++)
193 ((unsigned *)dst)[i] = ((unsigned *)palette)[ src[i] ];
197 * Pallete is assumed to contain bgr32
199 void palette8torgb24(const uint8_t *src, uint8_t *dst, unsigned num_pixels, const uint8_t *palette)
203 writes 1 byte o much and might cause alignment issues on some architectures?
204 for(i=0; i<num_pixels; i++)
205 ((unsigned *)(&dst[i*3])) = ((unsigned *)palette)[ src[i] ];
207 for(i=0; i<num_pixels; i++)
210 dst[0]= palette[ src[i]*4+0 ];
211 dst[1]= palette[ src[i]*4+1 ];
212 dst[2]= palette[ src[i]*4+2 ];
217 void rgb32to16(const uint8_t *src, uint8_t *dst, unsigned src_size)
219 unsigned j,i,num_pixels=src_size/4;
220 uint16_t *d = (uint16_t *)dst;
221 for(i=0,j=0; j<num_pixels; i+=4,j++)
223 const int b= src[i+0];
224 const int g= src[i+1];
225 const int r= src[i+2];
227 d[j]= (b>>3) | ((g&0xFC)<<3) | ((r&0xF8)<<8);
231 void rgb32to15(const uint8_t *src, uint8_t *dst, unsigned src_size)
233 unsigned j,i,num_pixels=src_size/4;
234 uint16_t *d = (uint16_t *)dst;
235 for(i=0,j=0; j<num_pixels; i+=4,j++)
237 const int b= src[i+0];
238 const int g= src[i+1];
239 const int r= src[i+2];
241 d[j]= (b>>3) | ((g&0xF8)<<2) | ((r&0xF8)<<7);
245 void rgb24to16(const uint8_t *src, uint8_t *dst, unsigned src_size)
247 unsigned j,i,num_pixels=src_size/3;
248 uint16_t *d = (uint16_t *)dst;
249 for(i=0,j=0; j<num_pixels; i+=3,j++)
251 const int b= src[i+0];
252 const int g= src[i+1];
253 const int r= src[i+2];
255 d[j]= (b>>3) | ((g&0xFC)<<3) | ((r&0xF8)<<8);
259 void rgb24to15(const uint8_t *src, uint8_t *dst, unsigned src_size)
261 unsigned j,i,num_pixels=src_size/3;
262 uint16_t *d = (uint16_t *)dst;
263 for(i=0,j=0; j<num_pixels; i+=3,j++)
265 const int b= src[i+0];
266 const int g= src[i+1];
267 const int r= src[i+2];
269 d[j]= (b>>3) | ((g&0xF8)<<2) | ((r&0xF8)<<7);
274 * Palette is assumed to contain bgr16, see rgb32to16 to convert the palette
276 void palette8torgb16(const uint8_t *src, uint8_t *dst, unsigned num_pixels, const uint8_t *palette)
279 for(i=0; i<num_pixels; i++)
280 ((uint16_t *)dst)[i] = ((uint16_t *)palette)[ src[i] ];
284 * Pallete is assumed to contain bgr15, see rgb32to15 to convert the palette
286 void palette8torgb15(const uint8_t *src, uint8_t *dst, unsigned num_pixels, const uint8_t *palette)
289 for(i=0; i<num_pixels; i++)
290 ((uint16_t *)dst)[i] = ((uint16_t *)palette)[ src[i] ];
294 * width must be a multiple of 16 for the MMX version
296 void yv12toyuy2(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
297 int width, int height, int lumStride, int chromStride, int dstStride)
300 const int chromWidth= width>>1;
301 for(y=0; y<height; y++)
304 //FIXME handle 2 lines a once (fewer prefetch, reuse some chrom, but very likely limited by mem anyway)
306 "xorl %%eax, %%eax \n\t"
308 PREFETCH" 32(%1, %%eax, 2) \n\t"
309 PREFETCH" 32(%2, %%eax) \n\t"
310 PREFETCH" 32(%3, %%eax) \n\t"
311 "movq (%2, %%eax), %%mm0 \n\t" // U(0)
312 "movq %%mm0, %%mm2 \n\t" // U(0)
313 "movq (%3, %%eax), %%mm1 \n\t" // V(0)
314 "punpcklbw %%mm1, %%mm0 \n\t" // UVUV UVUV(0)
315 "punpckhbw %%mm1, %%mm2 \n\t" // UVUV UVUV(8)
317 "movq (%1, %%eax,2), %%mm3 \n\t" // Y(0)
318 "movq 8(%1, %%eax,2), %%mm5 \n\t" // Y(8)
319 "movq %%mm3, %%mm4 \n\t" // Y(0)
320 "movq %%mm5, %%mm6 \n\t" // Y(8)
321 "punpcklbw %%mm0, %%mm3 \n\t" // YUYV YUYV(0)
322 "punpckhbw %%mm0, %%mm4 \n\t" // YUYV YUYV(4)
323 "punpcklbw %%mm2, %%mm5 \n\t" // YUYV YUYV(8)
324 "punpckhbw %%mm2, %%mm6 \n\t" // YUYV YUYV(12)
326 MOVNTQ" %%mm3, (%0, %%eax, 4) \n\t"
327 MOVNTQ" %%mm4, 8(%0, %%eax, 4) \n\t"
328 MOVNTQ" %%mm5, 16(%0, %%eax, 4) \n\t"
329 MOVNTQ" %%mm6, 24(%0, %%eax, 4) \n\t"
331 "addl $8, %%eax \n\t"
332 "cmpl %4, %%eax \n\t"
334 ::"r"(dst), "r"(ysrc), "r"(usrc), "r"(vsrc), "r" (chromWidth)
339 for(i=0; i<chromWidth; i++)
341 dst[4*i+0] = ysrc[2*i+0];
342 dst[4*i+1] = usrc[i];
343 dst[4*i+2] = ysrc[2*i+1];
344 dst[4*i+3] = vsrc[i];
362 void yuy2toyv12(const uint8_t *src, uint8_t *ydst, uint8_t *udst, uint8_t *vdst, unsigned num_pixels)
366 "xorl %%eax, %%eax \n\t"
367 "pcmpeqw %%mm7, %%mm7 \n\t"
368 "psrlw $8, %%mm7 \n\t" // FF,00,FF,00...
370 PREFETCH" 64(%0, %%eax, 4) \n\t"
371 "movq (%0, %%eax, 4), %%mm0 \n\t" // YUYV YUYV(0)
372 "movq 8(%0, %%eax, 4), %%mm1 \n\t" // YUYV YUYV(4)
373 "movq %%mm0, %%mm2 \n\t" // YUYV YUYV(0)
374 "movq %%mm1, %%mm3 \n\t" // YUYV YUYV(4)
375 "psrlw $8, %%mm0 \n\t" // U0V0 U0V0(0)
376 "psrlw $8, %%mm1 \n\t" // U0V0 U0V0(4)
377 "pand %%mm7, %%mm2 \n\t" // Y0Y0 Y0Y0(0)
378 "pand %%mm7, %%mm3 \n\t" // Y0Y0 Y0Y0(4)
379 "packuswb %%mm1, %%mm0 \n\t" // UVUV UVUV(0)
380 "packuswb %%mm3, %%mm2 \n\t" // YYYY YYYY(0)
382 MOVNTQ" %%mm2, (%1, %%eax, 2) \n\t"
384 "movq 16(%0, %%eax, 4), %%mm1 \n\t" // YUYV YUYV(8)
385 "movq 24(%0, %%eax, 4), %%mm2 \n\t" // YUYV YUYV(12)
386 "movq %%mm1, %%mm3 \n\t" // YUYV YUYV(8)
387 "movq %%mm2, %%mm4 \n\t" // YUYV YUYV(12)
388 "psrlw $8, %%mm1 \n\t" // U0V0 U0V0(8)
389 "psrlw $8, %%mm2 \n\t" // U0V0 U0V0(12)
390 "pand %%mm7, %%mm3 \n\t" // Y0Y0 Y0Y0(8)
391 "pand %%mm7, %%mm4 \n\t" // Y0Y0 Y0Y0(12)
392 "packuswb %%mm2, %%mm1 \n\t" // UVUV UVUV(8)
393 "packuswb %%mm4, %%mm3 \n\t" // YYYY YYYY(8)
395 MOVNTQ" %%mm3, 8(%1, %%eax, 2) \n\t"
397 "movq %%mm0, %%mm2 \n\t" // UVUV UVUV(0)
398 "movq %%mm1, %%mm3 \n\t" // UVUV UVUV(8)
399 "psrlw $8, %%mm0 \n\t" // V0V0 V0V0(0)
400 "psrlw $8, %%mm1 \n\t" // V0V0 V0V0(8)
401 "pand %%mm7, %%mm2 \n\t" // U0U0 U0U0(0)
402 "pand %%mm7, %%mm3 \n\t" // U0U0 U0U0(8)
403 "packuswb %%mm1, %%mm0 \n\t" // VVVV VVVV(0)
404 "packuswb %%mm3, %%mm2 \n\t" // UUUU UUUU(0)
406 MOVNTQ" %%mm0, (%3, %%eax) \n\t"
407 MOVNTQ" %%mm2, (%2, %%eax) \n\t"
409 "addl $8, %%eax \n\t"
410 "cmpl %4, %%eax \n\t"
414 ::"r"(src), "r"(ydst), "r"(udst), "r"(vdst), "r" (num_pixels>>1)
420 for(i=0; i<num_pixels; i++)
422 ydst[2*i+0] = src[4*i+0];
423 udst[i] = src[4*i+1];
424 ydst[2*i+1] = src[4*i+2];
425 vdst[i] = src[4*i+3];