1
0
Fork 0
forked from len0rd/rockbox

Parts of FS #7951 by Andree Buschmann. Faster YUV BLIT (means faster mpegplayer) for Ipods Nano and Video while we're waiting for the assembler ones.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15147 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Thom Johansen 2007-10-16 19:47:15 +00:00
parent 3688e94083
commit b5f779b2ef
2 changed files with 92 additions and 118 deletions

View file

@ -134,16 +134,33 @@ void lcd_blit(const fb_data* data, int x, int by, int width,
#define CSUB_X 2 #define CSUB_X 2
#define CSUB_Y 2 #define CSUB_Y 2
#define RYFAC (31*257) /* YUV- > RGB565 conversion
#define GYFAC (31*257) * |R| |1.000000 -0.000001 1.402000| |Y'|
#define BYFAC (31*257) * |G| = |1.000000 -0.334136 -0.714136| |Pb|
#define RVFAC 11170 /* 31 * 257 * 1.402 */ * |B| |1.000000 1.772000 0.000000| |Pr|
#define GVFAC (-5690) /* 31 * 257 * -0.714136 */ * Scaled, normalized, rounded and tweaked to yield RGB 565:
#define GUFAC (-2742) /* 31 * 257 * -0.344136 */ * |R| |74 0 101| |Y' - 16| >> 9
#define BUFAC 14118 /* 31 * 257 * 1.772 */ * |G| = |74 -24 -51| |Cb - 128| >> 8
* |B| |74 128 0| |Cr - 128| >> 9
*/
#define ROUNDOFFS (127*257) #define RGBYFAC 74 /* 1.0 */
#define ROUNDOFFSG (63*257) #define RVFAC 101 /* 1.402 */
#define GVFAC (-51) /* -0.714136 */
#define GUFAC (-24) /* -0.334136 */
#define BUFAC 128 /* 1.772 */
/* ROUNDOFFS contain constant for correct round-offs as well as
constant parts of the conversion matrix (e.g. (Y'-16)*RGBYFAC
-> constant part = -16*RGBYFAC). Through extraction of these
constant parts we save at leat 4 substractions in the conversion
loop */
#define ROUNDOFFSR (256 - 16*RGBYFAC - 128*RVFAC)
#define ROUNDOFFSG (128 - 16*RGBYFAC - 128*GVFAC - 128*GUFAC)
#define ROUNDOFFSB (256 - 16*RGBYFAC - 128*BUFAC)
#define MAX_5BIT 0x1f
#define MAX_6BIT 0x3f
/* Performance function to blit a YUV bitmap directly to the LCD */ /* Performance function to blit a YUV bitmap directly to the LCD */
void lcd_yuv_blit(unsigned char * const src[3], void lcd_yuv_blit(unsigned char * const src[3],
@ -225,10 +242,9 @@ void lcd_yuv_blit(unsigned char * const src[3],
const unsigned char *vsrc = src[2] + uvoffset; const unsigned char *vsrc = src[2] + uvoffset;
const unsigned char *row_end = ysrc + width; const unsigned char *row_end = ysrc + width;
int y, u, v; int yp, up, vp;
int red1, green1, blue1; int red1, green1, blue1;
int red2, green2, blue2; int red2, green2, blue2;
unsigned rbits, gbits, bbits;
int rc, gc, bc; int rc, gc, bc;
int pixels_to_write; int pixels_to_write;
@ -257,94 +273,52 @@ void lcd_yuv_blit(unsigned char * const src[3],
do do
{ {
u = *usrc++ - 128; up = *usrc++;
v = *vsrc++ - 128; vp = *vsrc++;
rc = RVFAC * v + ROUNDOFFS; rc = RVFAC * vp + ROUNDOFFSR;
gc = GVFAC * v + GUFAC * u + ROUNDOFFSG; gc = GVFAC * vp + GUFAC * up + ROUNDOFFSG;
bc = BUFAC * u + ROUNDOFFS; bc = BUFAC * up + ROUNDOFFSB;
/* Pixel 1 */ /* Pixel 1 -> RGB565 */
y = *ysrc++; yp = *ysrc++ * RGBYFAC;
red1 = (yp + rc) >> 9;
green1 = (yp + gc) >> 8;
blue1 = (yp + bc) >> 9;
red1 = RYFAC * y + rc; /* Pixel 2 -> RGB565 */
green1 = GYFAC * y + gc; yp = *ysrc++ * RGBYFAC;
blue1 = BYFAC * y + bc; red2 = (yp + rc) >> 9;
green2 = (yp + gc) >> 8;
/* Pixel 2 */ blue2 = (yp + bc) >> 9;
y = *ysrc++;
red2 = RYFAC * y + rc;
green2 = GYFAC * y + gc;
blue2 = BYFAC * y + bc;
/* Since out of bounds errors are relatively rare, we check two /* Since out of bounds errors are relatively rare, we check two
pixels at once to see if any components are out of bounds, and pixels at once to see if any components are out of bounds, and
then fix whichever is broken. This works due to high values and then fix whichever is broken. This works due to high values and
negative values both becoming larger than the cutoff when negative values both being !=0 when bitmasking them.
casted to unsigned. And ORing them together checks all of them We first check for red and blue components (5bit range). */
simultaneously. */ if ((red1 | blue1 | red2 | blue2) & ~MAX_5BIT)
if (((unsigned)(red1 | green1 | blue1 | {
red2 | green2 | blue2)) > (RYFAC*255+ROUNDOFFS)) { if (red1 & ~MAX_5BIT)
if (((unsigned)(red1 | green1 | blue1)) > red1 = (red1 >> 31) ? 0 : MAX_5BIT;
(RYFAC*255+ROUNDOFFS)) { if (blue1 & ~MAX_5BIT)
if ((unsigned)red1 > (RYFAC*255+ROUNDOFFS)) blue1 = (blue1 >> 31) ? 0 : MAX_5BIT;
{ if (red2 & ~MAX_5BIT)
if (red1 < 0) red2 = (red2 >> 31) ? 0 : MAX_5BIT;
red1 = 0; if (blue2 & ~MAX_5BIT)
else blue2 = (blue2 >> 31) ? 0 : MAX_5BIT;
red1 = (RYFAC*255+ROUNDOFFS); }
} /* We second check for green component (6bit range) */
if ((unsigned)green1 > (GYFAC*255+ROUNDOFFSG)) if ((green1 | green2) & ~MAX_6BIT)
{ {
if (green1 < 0) if (green1 & ~MAX_6BIT)
green1 = 0; green1 = (green1 >> 31) ? 0 : MAX_6BIT;
else if (green2 & ~MAX_6BIT)
green1 = (GYFAC*255+ROUNDOFFSG); green2 = (green2 >> 31) ? 0 : MAX_6BIT;
}
if ((unsigned)blue1 > (BYFAC*255+ROUNDOFFS))
{
if (blue1 < 0)
blue1 = 0;
else
blue1 = (BYFAC*255+ROUNDOFFS);
}
}
if (((unsigned)(red2 | green2 | blue2)) >
(RYFAC*255+ROUNDOFFS)) {
if ((unsigned)red2 > (RYFAC*255+ROUNDOFFS))
{
if (red2 < 0)
red2 = 0;
else
red2 = (RYFAC*255+ROUNDOFFS);
}
if ((unsigned)green2 > (GYFAC*255+ROUNDOFFSG))
{
if (green2 < 0)
green2 = 0;
else
green2 = (GYFAC*255+ROUNDOFFSG);
}
if ((unsigned)blue2 > (BYFAC*255+ROUNDOFFS))
{
if (blue2 < 0)
blue2 = 0;
else
blue2 = (BYFAC*255+ROUNDOFFS);
}
}
} }
rbits = red1 >> 16 ; pixel1 = swap16((red1 << 11) | (green1 << 5) | blue1);
gbits = green1 >> 15 ;
bbits = blue1 >> 16 ;
pixel1 = swap16((rbits << 11) | (gbits << 5) | bbits); pixel2 = swap16((red2 << 11) | (green2 << 5) | blue2);
rbits = red2 >> 16 ;
gbits = green2 >> 15 ;
bbits = blue2 >> 16 ;
pixel2 = swap16((rbits << 11) | (gbits << 5) | bbits);
while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_TXOK)); while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_TXOK));

View file

@ -135,14 +135,16 @@ void lcd_update_rect(int x, int y, int width, int height)
} }
} }
if (finishup_needed) { if (finishup_needed)
unsigned int data; {
/* Bottom-half of original lcd_bcm_finishup() function */ /* Bottom-half of original lcd_bcm_finishup() function */
do { unsigned int data = lcd_bcm_read32(0x1F8);
/* This function takes about 14ms to execute - so we yield() */ while (data == 0xFFFA0005 || data == 0xFFFF)
{
/* This loop can wait for up to 14ms - so we yield() */
yield(); yield();
data = lcd_bcm_read32(0x1F8); data = lcd_bcm_read32(0x1F8);
} while (data == 0xFFFA0005 || data == 0xFFFF); }
} }
lcd_bcm_read32(0x1FC); lcd_bcm_read32(0x1FC);
@ -234,17 +236,21 @@ void lcd_update(void)
#define MAX_6BIT 0x3f #define MAX_6BIT 0x3f
/* Performance function to blit a YUV bitmap directly to the LCD */ /* Performance function to blit a YUV bitmap directly to the LCD */
void lcd_yuv_blit(unsigned char * const src[3],
int src_x, int src_y, int stride,
int x, int y, int width, int height) ICODE_ATTR;
void lcd_yuv_blit(unsigned char * const src[3], void lcd_yuv_blit(unsigned char * const src[3],
int src_x, int src_y, int stride, int src_x, int src_y, int stride,
int x, int y, int width, int height) int x, int y, int width, int height)
{ {
width = (width + 1) & ~1; width = (width + 1) & ~1;
if (finishup_needed) { if (finishup_needed)
unsigned int data; {
/* Bottom-half of original lcd_bcm_finishup() function */ /* Bottom-half of original lcd_bcm_finishup() function */
data = lcd_bcm_read32(0x1F8); unsigned int data = lcd_bcm_read32(0x1F8);
while (data == 0xFFFA0005 || data == 0xFFFF) { while (data == 0xFFFA0005 || data == 0xFFFF)
{
/* This loop can wait for up to 14ms - so we yield() */ /* This loop can wait for up to 14ms - so we yield() */
yield(); yield();
data = lcd_bcm_read32(0x1F8); data = lcd_bcm_read32(0x1F8);
@ -321,28 +327,22 @@ void lcd_yuv_blit(unsigned char * const src[3],
We first check for red and blue components (5bit range). */ We first check for red and blue components (5bit range). */
if ((red1 | blue1 | red2 | blue2) & ~MAX_5BIT) if ((red1 | blue1 | red2 | blue2) & ~MAX_5BIT)
{ {
if ((red1 | blue1) & ~MAX_5BIT) if (red1 & ~MAX_5BIT)
{ red1 = (red1 >> 31) ? 0 : MAX_5BIT;
if (red1 & ~MAX_5BIT) if (blue1 & ~MAX_5BIT)
red1 = (red1 >> 31) ? 0 : MAX_5BIT; blue1 = (blue1 >> 31) ? 0 : MAX_5BIT;
if (blue1 & ~MAX_5BIT) if (red2 & ~MAX_5BIT)
blue1 = (blue1 >> 31) ? 0 : MAX_5BIT; red2 = (red2 >> 31) ? 0 : MAX_5BIT;
} if (blue2 & ~MAX_5BIT)
if ((red2 | blue2) & ~MAX_5BIT) blue2 = (blue2 >> 31) ? 0 : MAX_5BIT;
{
if (red2 & ~MAX_5BIT)
red2 = (red2 >> 31) ? 0 : MAX_5BIT;
if (blue2 & ~MAX_5BIT)
blue2 = (blue2 >> 31) ? 0 : MAX_5BIT;
}
} }
/* We second check for green component (6bit range) */ /* We second check for green component (6bit range) */
if ((green1 | green2) & ~MAX_6BIT) if ((green1 | green2) & ~MAX_6BIT)
{ {
if (green1 & ~MAX_6BIT) if (green1 & ~MAX_6BIT)
green1 = (green1 >> 31) ? 0 : MAX_6BIT; green1 = (green1 >> 31) ? 0 : MAX_6BIT;
if (green2 & ~MAX_6BIT) if (green2 & ~MAX_6BIT)
green2 = (green2 >> 31) ? 0 : MAX_6BIT; green2 = (green2 >> 31) ? 0 : MAX_6BIT;
} }
/* pixel1 */ /* pixel1 */