rgb2rgb.c 2.4 KB
Newer Older
N
Nick Kurshev 已提交
1 2 3
#include <inttypes.h>
#include "../config.h"
#include "rgb2rgb.h"
N
Nick Kurshev 已提交
4
#include "mmx.h"
N
Nick Kurshev 已提交
5 6 7

void rgb24to32(uint8_t *src,uint8_t *dst,uint32_t src_size)
{
N
Nick Kurshev 已提交
8
  uint8_t *dest = dst;
N
Nick Kurshev 已提交
9 10
  uint8_t *s = src;
  uint8_t *end;
N
Nick Kurshev 已提交
11 12 13 14
#ifdef HAVE_MMX
  const uint64_t mask32 = 0x00FFFFFF00FFFFFFULL;
  uint8_t *mm_end;
#endif
N
Nick Kurshev 已提交
15
  end = s + src_size;
N
Nick Kurshev 已提交
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
#ifdef HAVE_MMX
  mm_end = (uint8_t*)((((unsigned long)end)/16)*16);
  __asm __volatile("movq %0, %%mm7"::"m"(mask32):"memory");
  while(s < mm_end)
  {
    __asm __volatile(
	"movd	%1, %%mm0\n\t"
	"movd	3%1, %%mm1\n\t"
	"movd	6%1, %%mm2\n\t"
	"movd	9%1, %%mm3\n\t"
	"punpckldq %%mm1, %%mm0\n\t"
	"punpckldq %%mm3, %%mm2\n\t"
	"pand	%%mm7, %%mm0\n\t"
	"pand	%%mm7, %%mm2\n\t"
	"movq	%%mm0, %0\n\t"
	"movq	%%mm2, 8%0"
	:"=m"(*dest)
	:"m"(*s)
	:"memory");
    dest += 16;
    s += 12;
  }
#endif
N
Nick Kurshev 已提交
39 40
  while(s < end)
  {
N
Nick Kurshev 已提交
41 42 43 44
    *dest++ = *s++;
    *dest++ = *s++;
    *dest++ = *s++;
    *dest++ = 0;
N
Nick Kurshev 已提交
45 46
  }
}
N
Nick Kurshev 已提交
47

N
Nick Kurshev 已提交
48
/* TODO: MMX optimization */
N
Nick Kurshev 已提交
49 50 51 52 53 54 55 56 57 58 59 60 61 62
void rgb32to24(uint8_t *src,uint8_t *dst,uint32_t src_size)
{
  uint8_t *dest = dst;
  uint8_t *s = src;
  uint8_t *end;
  end = s + src_size;
  while(s < end)
  {
    *dest++ = *s++;
    *dest++ = *s++;
    *dest++ = *s++;
    s++;
  }
}
N
Nick Kurshev 已提交
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114

/* Original by Strepto/Astral
 ported to gcc & bugfixed : A'rpi */
void rgb15to16(uint8_t *src,uint8_t *dst,uint32_t src_size)
{
#ifdef HAVE_MMX
  static uint64_t mask_b  = 0x001F001F001F001FLL; // 00000000 00011111  xxB
  static uint64_t mask_rg = 0x7FE07FE07FE07FE0LL; // 01111111 11100000  RGx
  register char* s=src+src_size;
  register char* d=dst+src_size;
  register int offs=-src_size;
  movq_m2r (mask_b,  mm4);
  movq_m2r (mask_rg, mm5);
  while(offs<0){
    movq_m2r (*(s+offs), mm0);
    movq_r2r (mm0, mm1);

    movq_m2r (*(s+8+offs), mm2);
    movq_r2r (mm2, mm3);
    
    pand_r2r (mm4, mm0);
    pand_r2r (mm5, mm1);
    
    psllq_i2r(1,mm1);
    pand_r2r (mm4, mm2);

    pand_r2r (mm5, mm3);
    por_r2r  (mm1, mm0);

    psllq_i2r(1,mm3);
    movq_r2m (mm0,*(d+offs));

    por_r2r  (mm3,mm2);
    movq_r2m (mm2,*(d+8+offs));

    offs+=16;
  }
  emms();
#else
   uint16_t *s1=( uint16_t * )src;
   uint16_t *d1=( uint16_t * )dst;
   uint16_t *e=((uint8_t *)s1)+src_size;
   while( s1<e ){
     register int x=*( s1++ );
     /* rrrrrggggggbbbbb
        0rrrrrgggggbbbbb
        0111 1111 1110 0000=0x7FE0
        00000000000001 1111=0x001F */
     *( d1++ )=( x&0x001F )|( ( x&0x7FE0 )<<1 );
   }
#endif
}