diff options
-rw-r--r-- | firmware/drivers/lcd-ipod.c | 180 |
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 */ |
417 | void lcd_yuv_blit(unsigned char * const src[3], | 418 | void 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 | ||