summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2006-08-17 09:03:16 +0000
committerDave Chapman <dave@dchapman.com>2006-08-17 09:03:16 +0000
commit5b71470185e7ef5fe9fcea25fbb1c59ca16e3f4e (patch)
tree6c4aaf6f4ae5ce2bef7fda547ec8c180ccb03242
parent30f237303b98a6a0ca72bfc66d12d1e6f07bf506 (diff)
downloadrockbox-5b71470185e7ef5fe9fcea25fbb1c59ca16e3f4e.tar.gz
rockbox-5b71470185e7ef5fe9fcea25fbb1c59ca16e3f4e.zip
Port Tom Meyer's lcd_yuv_blit() optimisations for the ipod 5g to the ipod Photo/Color and Nano - gives a similar 10-15% speedup in mpegplayer.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10629 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/drivers/lcd-ipod.c180
1 files changed, 100 insertions, 80 deletions
diff --git a/firmware/drivers/lcd-ipod.c b/firmware/drivers/lcd-ipod.c
index d39aad163f..ed2847d665 100644
--- a/firmware/drivers/lcd-ipod.c
+++ b/firmware/drivers/lcd-ipod.c
@@ -404,14 +404,15 @@ void lcd_blit(const fb_data* data, int x, int by, int width,
404#define CSUB_Y 2 404#define CSUB_Y 2
405 405
406#define RYFAC (31*257) 406#define RYFAC (31*257)
407#define GYFAC (63*257) 407#define GYFAC (31*257)
408#define BYFAC (31*257) 408#define BYFAC (31*257)
409#define RVFAC 11170 /* 31 * 257 * 1.402 */ 409#define RVFAC 11170 /* 31 * 257 * 1.402 */
410#define GVFAC (-11563) /* 63 * 257 * -0.714136 */ 410#define GVFAC (-5690) /* 31 * 257 * -0.714136 */
411#define GUFAC (-5572) /* 63 * 257 * -0.344136 */ 411#define GUFAC (-2742) /* 31 * 257 * -0.344136 */
412#define BUFAC 14118 /* 31 * 257 * 1.772 */ 412#define BUFAC 14118 /* 31 * 257 * 1.772 */
413 413
414#define ROUNDOFFS (127*257) 414#define ROUNDOFFS (127*257)
415#define ROUNDOFFSG (63*257)
415 416
416/* Performance function to blit a YUV bitmap directly to the LCD */ 417/* Performance function to blit a YUV bitmap directly to the LCD */
417void lcd_yuv_blit(unsigned char * const src[3], 418void lcd_yuv_blit(unsigned char * const src[3],
@@ -478,14 +479,27 @@ void lcd_yuv_blit(unsigned char * const src[3],
478 lcd_send_lo(LCD_CNTL_WRITE_TO_GRAM); 479 lcd_send_lo(LCD_CNTL_WRITE_TO_GRAM);
479 } 480 }
480 481
482 const int stride_div_csub_x = stride/CSUB_X;
483
481 h=0; 484 h=0;
482 while (1) { 485 while (1) {
483 int pixels_to_write; 486 /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
484 const unsigned char *ysrc = src[0] + stride * src_y + src_x; 487 const unsigned char *ysrc = src[0] + stride * src_y + src_x;
488
489 const int uvoffset = stride_div_csub_x * (src_y/CSUB_Y) +
490 (src_x/CSUB_X);
491
492 const unsigned char *usrc = src[1] + uvoffset;
493 const unsigned char *vsrc = src[2] + uvoffset;
485 const unsigned char *row_end = ysrc + width; 494 const unsigned char *row_end = ysrc + width;
495
486 int y, u, v; 496 int y, u, v;
487 int red, green, blue; 497 int red1, green1, blue1;
498 int red2, green2, blue2;
488 unsigned rbits, gbits, bbits; 499 unsigned rbits, gbits, bbits;
500
501 int rc, gc, bc;
502 int pixels_to_write;
489 fb_data pixel1,pixel2; 503 fb_data pixel1,pixel2;
490 504
491 if (h==0) { 505 if (h==0) {
@@ -509,90 +523,96 @@ void lcd_yuv_blit(unsigned char * const src[3],
509 outl(0x34000000, 0x70008a20); 523 outl(0x34000000, 0x70008a20);
510 } 524 }
511 525
512 /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
513 const unsigned char *usrc = src[1] + (stride/CSUB_X) * (src_y/CSUB_Y)
514 + (src_x/CSUB_X);
515 const unsigned char *vsrc = src[2] + (stride/CSUB_X) * (src_y/CSUB_Y)
516 + (src_x/CSUB_X);
517 int rc, gc, bc;
518
519 u = *usrc++ - 128;
520 v = *vsrc++ - 128;
521 rc = RVFAC * v + ROUNDOFFS;
522 gc = GVFAC * v + GUFAC * u + ROUNDOFFS;
523 bc = BUFAC * u + ROUNDOFFS;
524
525 do 526 do
526 { 527 {
528 u = *usrc++ - 128;
529 v = *vsrc++ - 128;
530 rc = RVFAC * v + ROUNDOFFS;
531 gc = GVFAC * v + GUFAC * u + ROUNDOFFSG;
532 bc = BUFAC * u + ROUNDOFFS;
533
534 /* Pixel 1 */
527 y = *ysrc++; 535 y = *ysrc++;
528 red = RYFAC * y + rc;
529 green = GYFAC * y + gc;
530 blue = BYFAC * y + bc;
531
532 if ((unsigned)red > (RYFAC*255+ROUNDOFFS))
533 {
534 if (red < 0)
535 red = 0;
536 else
537 red = (RYFAC*255+ROUNDOFFS);
538 }
539 if ((unsigned)green > (GYFAC*255+ROUNDOFFS))
540 {
541 if (green < 0)
542 green = 0;
543 else
544 green = (GYFAC*255+ROUNDOFFS);
545 }
546 if ((unsigned)blue > (BYFAC*255+ROUNDOFFS))
547 {
548 if (blue < 0)
549 blue = 0;
550 else
551 blue = (BYFAC*255+ROUNDOFFS);
552 }
553 rbits = ((unsigned)red) >> 16 ;
554 gbits = ((unsigned)green) >> 16 ;
555 bbits = ((unsigned)blue) >> 16 ;
556 536
557 pixel1 = swap16((rbits << 11) | (gbits << 5) | bbits); 537 red1 = RYFAC * y + rc;
538 green1 = GYFAC * y + gc;
539 blue1 = BYFAC * y + bc;
558 540
541 /* Pixel 2 */
559 y = *ysrc++; 542 y = *ysrc++;
560 red = RYFAC * y + rc; 543 red2 = RYFAC * y + rc;
561 green = GYFAC * y + gc; 544 green2 = GYFAC * y + gc;
562 blue = BYFAC * y + bc; 545 blue2 = BYFAC * y + bc;
563 546
564 if ((unsigned)red > (RYFAC*255+ROUNDOFFS)) 547 /* Since out of bounds errors are relatively rare, we check two
565 { 548 pixels at once to see if any components are out of bounds, and
566 if (red < 0) 549 then fix whichever is broken. This works due to high values and
567 red = 0; 550 negative values both becoming larger than the cutoff when
568 else 551 casted to unsigned. And ORing them together checks all of them
569 red = (RYFAC*255+ROUNDOFFS); 552 simultaneously. */
570 } 553 if (((unsigned)(red1 | green1 | blue1 |
571 if ((unsigned)green > (GYFAC*255+ROUNDOFFS)) 554 red2 | green2 | blue2)) > (RYFAC*255+ROUNDOFFS)) {
572 { 555 if (((unsigned)(red1 | green1 | blue1)) >
573 if (green < 0) 556 (RYFAC*255+ROUNDOFFS)) {
574 green = 0; 557 if ((unsigned)red1 > (RYFAC*255+ROUNDOFFS))
575 else 558 {
576 green = (GYFAC*255+ROUNDOFFS); 559 if (red1 < 0)
577 } 560 red1 = 0;
578 if ((unsigned)blue > (BYFAC*255+ROUNDOFFS)) 561 else
579 { 562 red1 = (RYFAC*255+ROUNDOFFS);
580 if (blue < 0) 563 }
581 blue = 0; 564 if ((unsigned)green1 > (GYFAC*255+ROUNDOFFSG))
582 else 565 {
583 blue = (BYFAC*255+ROUNDOFFS); 566 if (green1 < 0)
567 green1 = 0;
568 else
569 green1 = (GYFAC*255+ROUNDOFFSG);
570 }
571 if ((unsigned)blue1 > (BYFAC*255+ROUNDOFFS))
572 {
573 if (blue1 < 0)
574 blue1 = 0;
575 else
576 blue1 = (BYFAC*255+ROUNDOFFS);
577 }
578 }
579
580 if (((unsigned)(red2 | green2 | blue2)) >
581 (RYFAC*255+ROUNDOFFS)) {
582 if ((unsigned)red2 > (RYFAC*255+ROUNDOFFS))
583 {
584 if (red2 < 0)
585 red2 = 0;
586 else
587 red2 = (RYFAC*255+ROUNDOFFS);
588 }
589 if ((unsigned)green2 > (GYFAC*255+ROUNDOFFSG))
590 {
591 if (green2 < 0)
592 green2 = 0;
593 else
594 green2 = (GYFAC*255+ROUNDOFFSG);
595 }
596 if ((unsigned)blue2 > (BYFAC*255+ROUNDOFFS))
597 {
598 if (blue2 < 0)
599 blue2 = 0;
600 else
601 blue2 = (BYFAC*255+ROUNDOFFS);
602 }
603 }
584 } 604 }
585 rbits = ((unsigned)red) >> 16 ; 605
586 gbits = ((unsigned)green) >> 16 ; 606 rbits = red1 >> 16 ;
587 bbits = ((unsigned)blue) >> 16 ; 607 gbits = green1 >> 15 ;
608 bbits = blue1 >> 16 ;
588 609
589 pixel2 = swap16((rbits << 11) | (gbits << 5) | bbits); 610 pixel1 = swap16((rbits << 11) | (gbits << 5) | bbits);
590 611
591 u = *usrc++ - 128; 612 rbits = red2 >> 16 ;
592 v = *vsrc++ - 128; 613 gbits = green2 >> 15 ;
593 rc = RVFAC * v + ROUNDOFFS; 614 bbits = blue2 >> 16 ;
594 gc = GVFAC * v + GUFAC * u + ROUNDOFFS; 615 pixel2 = swap16((rbits << 11) | (gbits << 5) | bbits);
595 bc = BUFAC * u + ROUNDOFFS;
596 616
597 while ((inl(0x70008a20) & 0x1000000) == 0); 617 while ((inl(0x70008a20) & 0x1000000) == 0);
598 618