diff options
Diffstat (limited to 'firmware/drivers/lcd-16bit.c')
-rw-r--r-- | firmware/drivers/lcd-16bit.c | 315 |
1 files changed, 248 insertions, 67 deletions
diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c index 6d6a3b2104..d8405235f7 100644 --- a/firmware/drivers/lcd-16bit.c +++ b/firmware/drivers/lcd-16bit.c | |||
@@ -85,6 +85,28 @@ void lcd_set_viewport(struct viewport* vp) | |||
85 | current_vp = &default_vp; | 85 | current_vp = &default_vp; |
86 | else | 86 | else |
87 | current_vp = vp; | 87 | current_vp = vp; |
88 | |||
89 | #if defined(SIMULATOR) | ||
90 | /* Force the viewport to be within bounds. If this happens it should | ||
91 | * be considered an error - the viewport will not draw as it might be | ||
92 | * expected. | ||
93 | */ | ||
94 | if((unsigned) current_vp->x > (unsigned) LCD_WIDTH | ||
95 | || (unsigned) current_vp->y > (unsigned) LCD_HEIGHT | ||
96 | || current_vp->x + current_vp->width > LCD_WIDTH | ||
97 | || current_vp->y + current_vp->height > LCD_HEIGHT) | ||
98 | { | ||
99 | #if !defined(HAVE_VIEWPORT_CLIP) | ||
100 | DEBUGF("ERROR: " | ||
101 | #else | ||
102 | DEBUGF("NOTE: " | ||
103 | #endif | ||
104 | "set_viewport out of bounds: x: %d y: %d width: %d height:%d\n", | ||
105 | current_vp->x, current_vp->y, | ||
106 | current_vp->width, current_vp->height); | ||
107 | } | ||
108 | |||
109 | #endif | ||
88 | } | 110 | } |
89 | 111 | ||
90 | void lcd_update_viewport(void) | 112 | void lcd_update_viewport(void) |
@@ -305,8 +327,13 @@ void lcd_clear_display(void) | |||
305 | /* Set a single pixel */ | 327 | /* Set a single pixel */ |
306 | void lcd_drawpixel(int x, int y) | 328 | void lcd_drawpixel(int x, int y) |
307 | { | 329 | { |
308 | if (((unsigned)x < (unsigned)current_vp->width) && | 330 | if ( ((unsigned)x < (unsigned)current_vp->width) |
309 | ((unsigned)y < (unsigned)current_vp->height)) | 331 | && ((unsigned)y < (unsigned)current_vp->height) |
332 | #if defined(HAVE_VIEWPORT_CLIP) | ||
333 | && ((unsigned)x < (unsigned)LCD_WIDTH) | ||
334 | && ((unsigned)y < (unsigned)LCD_HEIGHT) | ||
335 | #endif | ||
336 | ) | ||
310 | lcd_fastpixelfuncs[current_vp->drawmode](LCDADDR(current_vp->x+x, current_vp->y+y)); | 337 | lcd_fastpixelfuncs[current_vp->drawmode](LCDADDR(current_vp->x+x, current_vp->y+y)); |
311 | } | 338 | } |
312 | 339 | ||
@@ -375,7 +402,13 @@ void lcd_drawline(int x1, int y1, int x2, int y2) | |||
375 | 402 | ||
376 | for (i = 0; i < numpixels; i++) | 403 | for (i = 0; i < numpixels; i++) |
377 | { | 404 | { |
378 | if (((unsigned)x < (unsigned)current_vp->width) && ((unsigned)y < (unsigned)current_vp->height)) | 405 | if ( ((unsigned)x < (unsigned)current_vp->width) |
406 | && ((unsigned)y < (unsigned)current_vp->height) | ||
407 | #if defined(HAVE_VIEWPORT_CLIP) | ||
408 | && ((unsigned)x < (unsigned)LCD_WIDTH) | ||
409 | && ((unsigned)y < (unsigned)LCD_HEIGHT) | ||
410 | #endif | ||
411 | ) | ||
379 | pfunc(LCDADDR(x + current_vp->x, y + current_vp->y)); | 412 | pfunc(LCDADDR(x + current_vp->x, y + current_vp->y)); |
380 | 413 | ||
381 | if (d < 0) | 414 | if (d < 0) |
@@ -409,11 +442,38 @@ void lcd_hline(int x1, int x2, int y) | |||
409 | x2 = x; | 442 | x2 = x; |
410 | } | 443 | } |
411 | 444 | ||
445 | /******************** In viewport clipping **********************/ | ||
412 | /* nothing to draw? */ | 446 | /* nothing to draw? */ |
413 | if (((unsigned)y >= (unsigned)current_vp->height) || | 447 | if (((unsigned)y >= (unsigned)current_vp->height) || |
414 | (x1 >= current_vp->width) || | 448 | (x1 >= current_vp->width) || |
415 | (x2 < 0)) | 449 | (x2 < 0)) |
416 | return; | 450 | return; |
451 | |||
452 | if (x1 < 0) | ||
453 | x1 = 0; | ||
454 | if (x2 >= current_vp->width) | ||
455 | x2 = current_vp->width-1; | ||
456 | |||
457 | /* Adjust x1 and y to viewport */ | ||
458 | x1 += current_vp->x; | ||
459 | x2 += current_vp->x; | ||
460 | y += current_vp->y; | ||
461 | |||
462 | #if defined(HAVE_VIEWPORT_CLIP) | ||
463 | /********************* Viewport on screen clipping ********************/ | ||
464 | /* nothing to draw? */ | ||
465 | if (((unsigned)y >= (unsigned) LCD_HEIGHT) || (x1 >= LCD_WIDTH) | ||
466 | || (x2 < 0)) | ||
467 | return; | ||
468 | |||
469 | /* clipping */ | ||
470 | if (x1 < 0) | ||
471 | x1 = 0; | ||
472 | if (x2 >= LCD_WIDTH) | ||
473 | x2 = LCD_WIDTH-1; | ||
474 | #endif | ||
475 | |||
476 | width = x2 - x1 + 1; | ||
417 | 477 | ||
418 | /* drawmode and optimisation */ | 478 | /* drawmode and optimisation */ |
419 | if (current_vp->drawmode & DRMODE_INVERSEVID) | 479 | if (current_vp->drawmode & DRMODE_INVERSEVID) |
@@ -440,18 +500,6 @@ void lcd_hline(int x1, int x2, int y) | |||
440 | if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) | 500 | if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) |
441 | return; | 501 | return; |
442 | 502 | ||
443 | /* clipping */ | ||
444 | if (x1 < 0) | ||
445 | x1 = 0; | ||
446 | if (x2 >= current_vp->width) | ||
447 | x2 = current_vp->width-1; | ||
448 | |||
449 | width = x2 - x1 + 1; | ||
450 | |||
451 | /* Adjust x1 and y to viewport */ | ||
452 | x1 += current_vp->x; | ||
453 | y += current_vp->y; | ||
454 | |||
455 | dst = LCDADDR(x1, y); | 503 | dst = LCDADDR(x1, y); |
456 | 504 | ||
457 | switch (fillopt) | 505 | switch (fillopt) |
@@ -489,19 +537,38 @@ void lcd_vline(int x, int y1, int y2) | |||
489 | y2 = y; | 537 | y2 = y; |
490 | } | 538 | } |
491 | 539 | ||
540 | /******************** In viewport clipping **********************/ | ||
492 | /* nothing to draw? */ | 541 | /* nothing to draw? */ |
493 | if (((unsigned)x >= (unsigned)current_vp->width) || | 542 | if (((unsigned)x >= (unsigned)current_vp->width) || |
494 | (y1 >= current_vp->height) || | 543 | (y1 >= current_vp->height) || |
495 | (y2 < 0)) | 544 | (y2 < 0)) |
496 | return; | 545 | return; |
497 | 546 | ||
498 | /* clipping */ | ||
499 | if (y1 < 0) | 547 | if (y1 < 0) |
500 | y1 = 0; | 548 | y1 = 0; |
501 | if (y2 >= current_vp->height) | 549 | if (y2 >= current_vp->height) |
502 | y2 = current_vp->height-1; | 550 | y2 = current_vp->height-1; |
551 | |||
552 | /* adjust for viewport */ | ||
553 | x += current_vp->x; | ||
554 | y1 += current_vp->y; | ||
555 | y2 += current_vp->y; | ||
556 | |||
557 | #if defined(HAVE_VIEWPORT_CLIP) | ||
558 | /********************* Viewport on screen clipping ********************/ | ||
559 | /* nothing to draw? */ | ||
560 | if (( (unsigned) x >= (unsigned)LCD_WIDTH) || (y1 >= LCD_HEIGHT) | ||
561 | || (y2 < 0)) | ||
562 | return; | ||
563 | |||
564 | /* clipping */ | ||
565 | if (y1 < 0) | ||
566 | y1 = 0; | ||
567 | if (y2 >= LCD_HEIGHT) | ||
568 | y2 = LCD_HEIGHT-1; | ||
569 | #endif | ||
503 | 570 | ||
504 | dst = LCDADDR(x + current_vp->x, y1 + current_vp->y); | 571 | dst = LCDADDR(x , y1); |
505 | dst_end = dst + (y2 - y1) * LCD_WIDTH; | 572 | dst_end = dst + (y2 - y1) * LCD_WIDTH; |
506 | 573 | ||
507 | do | 574 | do |
@@ -534,11 +601,55 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
534 | enum fill_opt fillopt = OPT_NONE; | 601 | enum fill_opt fillopt = OPT_NONE; |
535 | fb_data *dst, *dst_end; | 602 | fb_data *dst, *dst_end; |
536 | 603 | ||
604 | /******************** In viewport clipping **********************/ | ||
537 | /* nothing to draw? */ | 605 | /* nothing to draw? */ |
538 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | 606 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || |
539 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | 607 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
540 | return; | 608 | return; |
541 | 609 | ||
610 | if (x < 0) | ||
611 | { | ||
612 | width += x; | ||
613 | x = 0; | ||
614 | } | ||
615 | if (y < 0) | ||
616 | { | ||
617 | height += y; | ||
618 | y = 0; | ||
619 | } | ||
620 | if (x + width > current_vp->width) | ||
621 | width = current_vp->width - x; | ||
622 | if (y + height > current_vp->height) | ||
623 | height = current_vp->height - y; | ||
624 | |||
625 | /* adjust for viewport */ | ||
626 | x += current_vp->x; | ||
627 | y += current_vp->y; | ||
628 | |||
629 | #if defined(HAVE_VIEWPORT_CLIP) | ||
630 | /********************* Viewport on screen clipping ********************/ | ||
631 | /* nothing to draw? */ | ||
632 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
633 | || (x + width <= 0) || (y + height <= 0)) | ||
634 | return; | ||
635 | |||
636 | /* clip image in viewport in screen */ | ||
637 | if (x < 0) | ||
638 | { | ||
639 | width += x; | ||
640 | x = 0; | ||
641 | } | ||
642 | if (y < 0) | ||
643 | { | ||
644 | height += y; | ||
645 | y = 0; | ||
646 | } | ||
647 | if (x + width > LCD_WIDTH) | ||
648 | width = LCD_WIDTH - x; | ||
649 | if (y + height > LCD_HEIGHT) | ||
650 | height = LCD_HEIGHT - y; | ||
651 | #endif | ||
652 | |||
542 | /* drawmode and optimisation */ | 653 | /* drawmode and optimisation */ |
543 | if (current_vp->drawmode & DRMODE_INVERSEVID) | 654 | if (current_vp->drawmode & DRMODE_INVERSEVID) |
544 | { | 655 | { |
@@ -564,23 +675,7 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
564 | if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) | 675 | if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) |
565 | return; | 676 | return; |
566 | 677 | ||
567 | /* clipping */ | 678 | dst = LCDADDR(x, y); |
568 | if (x < 0) | ||
569 | { | ||
570 | width += x; | ||
571 | x = 0; | ||
572 | } | ||
573 | if (y < 0) | ||
574 | { | ||
575 | height += y; | ||
576 | y = 0; | ||
577 | } | ||
578 | if (x + width > current_vp->width) | ||
579 | width = current_vp->width - x; | ||
580 | if (y + height > current_vp->height) | ||
581 | height = current_vp->height - y; | ||
582 | |||
583 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); | ||
584 | dst_end = dst + height * LCD_WIDTH; | 679 | dst_end = dst + height * LCD_WIDTH; |
585 | 680 | ||
586 | do | 681 | do |
@@ -634,12 +729,12 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | |||
634 | unsigned dmask = 0x100; /* bit 8 == sentinel */ | 729 | unsigned dmask = 0x100; /* bit 8 == sentinel */ |
635 | int drmode = current_vp->drawmode; | 730 | int drmode = current_vp->drawmode; |
636 | 731 | ||
732 | /******************** Image in viewport clipping **********************/ | ||
637 | /* nothing to draw? */ | 733 | /* nothing to draw? */ |
638 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | 734 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || |
639 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | 735 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
640 | return; | 736 | return; |
641 | 737 | ||
642 | /* clipping */ | ||
643 | if (x < 0) | 738 | if (x < 0) |
644 | { | 739 | { |
645 | width += x; | 740 | width += x; |
@@ -656,11 +751,41 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | |||
656 | width = current_vp->width - x; | 751 | width = current_vp->width - x; |
657 | if (y + height > current_vp->height) | 752 | if (y + height > current_vp->height) |
658 | height = current_vp->height - y; | 753 | height = current_vp->height - y; |
754 | |||
755 | /* adjust for viewport */ | ||
756 | x += current_vp->x; | ||
757 | y += current_vp->y; | ||
758 | |||
759 | #if defined(HAVE_VIEWPORT_CLIP) | ||
760 | /********************* Viewport on screen clipping ********************/ | ||
761 | /* nothing to draw? */ | ||
762 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
763 | || (x + width <= 0) || (y + height <= 0)) | ||
764 | return; | ||
765 | |||
766 | /* clip image in viewport in screen */ | ||
767 | if (x < 0) | ||
768 | { | ||
769 | width += x; | ||
770 | src_x -= x; | ||
771 | x = 0; | ||
772 | } | ||
773 | if (y < 0) | ||
774 | { | ||
775 | height += y; | ||
776 | src_y -= y; | ||
777 | y = 0; | ||
778 | } | ||
779 | if (x + width > LCD_WIDTH) | ||
780 | width = LCD_WIDTH - x; | ||
781 | if (y + height > LCD_HEIGHT) | ||
782 | height = LCD_HEIGHT - y; | ||
783 | #endif | ||
659 | 784 | ||
660 | src += stride * (src_y >> 3) + src_x; /* move starting point */ | 785 | src += stride * (src_y >> 3) + src_x; /* move starting point */ |
661 | src_y &= 7; | 786 | src_y &= 7; |
662 | src_end = src + width; | 787 | src_end = src + width; |
663 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); | 788 | dst = LCDADDR(x, y); |
664 | dst_end = dst + height * LCD_WIDTH; | 789 | dst_end = dst + height * LCD_WIDTH; |
665 | 790 | ||
666 | if (drmode & DRMODE_INVERSEVID) | 791 | if (drmode & DRMODE_INVERSEVID) |
@@ -784,34 +909,62 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, | |||
784 | { | 909 | { |
785 | fb_data *dst; | 910 | fb_data *dst; |
786 | 911 | ||
787 | if (x + width > current_vp->width) | 912 | /******************** Image in viewport clipping **********************/ |
788 | width = current_vp->width - x; /* Clip right */ | 913 | /* nothing to draw? */ |
789 | 914 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | |
790 | if (x < 0) /* Clip left */ | 915 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
916 | return; | ||
917 | |||
918 | if (x < 0) | ||
791 | { | 919 | { |
792 | width += x; | 920 | width += x; |
793 | src_x -= x; | 921 | src_x -= x; |
794 | x = 0; | 922 | x = 0; |
795 | } | 923 | } |
796 | 924 | if (y < 0) | |
797 | if (width <= 0) | 925 | { |
798 | return; /* nothing left to do */ | 926 | height += y; |
799 | 927 | src_y -= y; | |
928 | y = 0; | ||
929 | } | ||
930 | |||
931 | if (x + width > current_vp->width) | ||
932 | width = current_vp->width - x; | ||
800 | if (y + height > current_vp->height) | 933 | if (y + height > current_vp->height) |
801 | height = current_vp->height - y; /* Clip bottom */ | 934 | height = current_vp->height - y; |
802 | 935 | ||
803 | if (y < 0) /* Clip top */ | 936 | /* adjust for viewport */ |
937 | x += current_vp->x; | ||
938 | y += current_vp->y; | ||
939 | |||
940 | #if defined(HAVE_VIEWPORT_CLIP) | ||
941 | /********************* Viewport on screen clipping ********************/ | ||
942 | /* nothing to draw? */ | ||
943 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
944 | || (x + width <= 0) || (y + height <= 0)) | ||
945 | return; | ||
946 | |||
947 | /* clip image in viewport in screen */ | ||
948 | if (x < 0) | ||
949 | { | ||
950 | width += x; | ||
951 | src_x -= x; | ||
952 | x = 0; | ||
953 | } | ||
954 | if (y < 0) | ||
804 | { | 955 | { |
805 | height += y; | 956 | height += y; |
806 | src_y -= y; | 957 | src_y -= y; |
807 | y = 0; | 958 | y = 0; |
808 | } | 959 | } |
809 | 960 | if (x + width > LCD_WIDTH) | |
810 | if (height <= 0) | 961 | width = LCD_WIDTH - x; |
811 | return; /* nothing left to do */ | 962 | if (y + height > LCD_HEIGHT) |
812 | 963 | height = LCD_HEIGHT - y; | |
964 | #endif | ||
965 | |||
813 | src += stride * src_y + src_x; /* move starting point */ | 966 | src += stride * src_y + src_x; /* move starting point */ |
814 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); | 967 | dst = LCDADDR(x, y); |
815 | 968 | ||
816 | do | 969 | do |
817 | { | 970 | { |
@@ -836,34 +989,62 @@ void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, | |||
836 | fb_data *dst; | 989 | fb_data *dst; |
837 | unsigned fg = current_vp->fg_pattern; | 990 | unsigned fg = current_vp->fg_pattern; |
838 | 991 | ||
839 | if (x + width > current_vp->width) | 992 | /******************** Image in viewport clipping **********************/ |
840 | width = current_vp->width - x; /* Clip right */ | 993 | /* nothing to draw? */ |
841 | 994 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | |
842 | if (x < 0) /* Clip left */ | 995 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
996 | return; | ||
997 | |||
998 | if (x < 0) | ||
843 | { | 999 | { |
844 | width += x; | 1000 | width += x; |
845 | src_x -= x; | 1001 | src_x -= x; |
846 | x = 0; | 1002 | x = 0; |
847 | } | 1003 | } |
848 | 1004 | if (y < 0) | |
849 | if (width <= 0) | 1005 | { |
850 | return; /* nothing left to do */ | 1006 | height += y; |
851 | 1007 | src_y -= y; | |
1008 | y = 0; | ||
1009 | } | ||
1010 | |||
1011 | if (x + width > current_vp->width) | ||
1012 | width = current_vp->width - x; | ||
852 | if (y + height > current_vp->height) | 1013 | if (y + height > current_vp->height) |
853 | height = current_vp->height - y; /* Clip bottom */ | 1014 | height = current_vp->height - y; |
854 | 1015 | ||
855 | if (y < 0) /* Clip top */ | 1016 | /* adjust for viewport */ |
1017 | x += current_vp->x; | ||
1018 | y += current_vp->y; | ||
1019 | |||
1020 | #if defined(HAVE_VIEWPORT_CLIP) | ||
1021 | /********************* Viewport on screen clipping ********************/ | ||
1022 | /* nothing to draw? */ | ||
1023 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
1024 | || (x + width <= 0) || (y + height <= 0)) | ||
1025 | return; | ||
1026 | |||
1027 | /* clip image in viewport in screen */ | ||
1028 | if (x < 0) | ||
1029 | { | ||
1030 | width += x; | ||
1031 | src_x -= x; | ||
1032 | x = 0; | ||
1033 | } | ||
1034 | if (y < 0) | ||
856 | { | 1035 | { |
857 | height += y; | 1036 | height += y; |
858 | src_y -= y; | 1037 | src_y -= y; |
859 | y = 0; | 1038 | y = 0; |
860 | } | 1039 | } |
861 | 1040 | if (x + width > LCD_WIDTH) | |
862 | if (height <= 0) | 1041 | width = LCD_WIDTH - x; |
863 | return; /* nothing left to do */ | 1042 | if (y + height > LCD_HEIGHT) |
1043 | height = LCD_HEIGHT - y; | ||
1044 | #endif | ||
864 | 1045 | ||
865 | src += stride * src_y + src_x; /* move starting point */ | 1046 | src += stride * src_y + src_x; /* move starting point */ |
866 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); | 1047 | dst = LCDADDR(x, y); |
867 | 1048 | ||
868 | #ifdef CPU_ARM | 1049 | #ifdef CPU_ARM |
869 | { | 1050 | { |