summaryrefslogtreecommitdiff
path: root/firmware/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers')
-rw-r--r--firmware/drivers/lcd-16bit.c205
1 files changed, 204 insertions, 1 deletions
diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c
index 28c3285a9c..300dbba9ac 100644
--- a/firmware/drivers/lcd-16bit.c
+++ b/firmware/drivers/lcd-16bit.c
@@ -913,10 +913,213 @@ void lcd_bitmap_transparent(const fb_data *src, int x, int y,
913 lcd_bitmap_transparent_part(src, 0, 0, width, x, y, width, height); 913 lcd_bitmap_transparent_part(src, 0, 0, width, x, y, width, height);
914} 914}
915 915
916/**
917 * |R| |1.000000 -0.000001 1.402000| |Y'|
918 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
919 * |B| |1.000000 1.772000 0.000000| |Pr|
920 * Scaled, normalized, rounded and tweaked to yield RGB 565:
921 * |R| |74 0 101| |Y' - 16| >> 9
922 * |G| = |74 -24 -51| |Cb - 128| >> 8
923 * |B| |74 128 0| |Cr - 128| >> 9
924 */
925#define YFAC (74)
926#define RVFAC (101)
927#define GUFAC (-24)
928#define GVFAC (-51)
929#define BUFAC (128)
930
931static inline int clamp(int val, int min, int max)
932{
933 if (val < min)
934 val = min;
935 else if (val > max)
936 val = max;
937 return val;
938}
939
940__attribute__((weak)) void lcd_yuv_set_options(unsigned options)
941{
942 (void)options;
943}
944
945/* Draw a partial YUV colour bitmap - similiar behavior to lcd_blit_yuv
946 in the core */
947
948__attribute__((weak)) void lcd_blit_yuv(unsigned char * const src[3],
949 int src_x, int src_y, int stride,
950 int x, int y, int width, int height)
951{
952 const unsigned char *ysrc, *usrc, *vsrc;
953 int linecounter;
954 fb_data *dst, *row_end;
955 long z;
956
957 /* width and height must be >= 2 and an even number */
958 width &= ~1;
959 linecounter = height >> 1;
960
961#if LCD_WIDTH >= LCD_HEIGHT
962 dst = &lcd_framebuffer[y][x];
963 row_end = dst + width;
964#else
965 dst = &lcd_framebuffer[x][LCD_WIDTH - y - 1];
966 row_end = dst + LCD_WIDTH * width;
967#endif
968
969 z = stride * src_y;
970 ysrc = src[0] + z + src_x;
971 usrc = src[1] + (z >> 2) + (src_x >> 1);
972 vsrc = src[2] + (usrc - src[1]);
973
974 /* stride => amount to jump from end of last row to start of next */
975 stride -= width;
976
977 /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
978
979 do
980 {
981 do
982 {
983 int y, cb, cr, rv, guv, bu, r, g, b;
984
985 y = YFAC*(*ysrc++ - 16);
986 cb = *usrc++ - 128;
987 cr = *vsrc++ - 128;
988
989 rv = RVFAC*cr;
990 guv = GUFAC*cb + GVFAC*cr;
991 bu = BUFAC*cb;
992
993 r = y + rv;
994 g = y + guv;
995 b = y + bu;
996
997 if ((unsigned)(r | g | b) > 64*256-1)
998 {
999 r = clamp(r, 0, 64*256-1);
1000 g = clamp(g, 0, 64*256-1);
1001 b = clamp(b, 0, 64*256-1);
1002 }
1003
1004 *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
1005
1006#if LCD_WIDTH >= LCD_HEIGHT
1007 dst++;
1008#else
1009 dst += LCD_WIDTH;
1010#endif
1011
1012 y = YFAC*(*ysrc++ - 16);
1013 r = y + rv;
1014 g = y + guv;
1015 b = y + bu;
1016
1017 if ((unsigned)(r | g | b) > 64*256-1)
1018 {
1019 r = clamp(r, 0, 64*256-1);
1020 g = clamp(g, 0, 64*256-1);
1021 b = clamp(b, 0, 64*256-1);
1022 }
1023
1024 *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
1025
1026#if LCD_WIDTH >= LCD_HEIGHT
1027 dst++;
1028#else
1029 dst += LCD_WIDTH;
1030#endif
1031 }
1032 while (dst < row_end);
1033
1034 ysrc += stride;
1035 usrc -= width >> 1;
1036 vsrc -= width >> 1;
1037
1038#if LCD_WIDTH >= LCD_HEIGHT
1039 row_end += LCD_WIDTH;
1040 dst += LCD_WIDTH - width;
1041#else
1042 row_end -= 1;
1043 dst -= LCD_WIDTH*width + 1;
1044#endif
1045
1046 do
1047 {
1048 int y, cb, cr, rv, guv, bu, r, g, b;
1049
1050 y = YFAC*(*ysrc++ - 16);
1051 cb = *usrc++ - 128;
1052 cr = *vsrc++ - 128;
1053
1054 rv = RVFAC*cr;
1055 guv = GUFAC*cb + GVFAC*cr;
1056 bu = BUFAC*cb;
1057
1058 r = y + rv;
1059 g = y + guv;
1060 b = y + bu;
1061
1062 if ((unsigned)(r | g | b) > 64*256-1)
1063 {
1064 r = clamp(r, 0, 64*256-1);
1065 g = clamp(g, 0, 64*256-1);
1066 b = clamp(b, 0, 64*256-1);
1067 }
1068
1069 *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
1070
1071#if LCD_WIDTH >= LCD_HEIGHT
1072 dst++;
1073#else
1074 dst += LCD_WIDTH;
1075#endif
1076
1077 y = YFAC*(*ysrc++ - 16);
1078 r = y + rv;
1079 g = y + guv;
1080 b = y + bu;
1081
1082 if ((unsigned)(r | g | b) > 64*256-1)
1083 {
1084 r = clamp(r, 0, 64*256-1);
1085 g = clamp(g, 0, 64*256-1);
1086 b = clamp(b, 0, 64*256-1);
1087 }
1088
1089 *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
1090
1091#if LCD_WIDTH >= LCD_HEIGHT
1092 dst++;
1093#else
1094 dst += LCD_WIDTH;
1095#endif
1096 }
1097 while (dst < row_end);
1098
1099 ysrc += stride;
1100 usrc += stride >> 1;
1101 vsrc += stride >> 1;
1102
1103#if LCD_WIDTH >= LCD_HEIGHT
1104 row_end += LCD_WIDTH;
1105 dst += LCD_WIDTH - width;
1106#else
1107 row_end -= 1;
1108 dst -= LCD_WIDTH*width + 1;
1109#endif
1110 }
1111 while (--linecounter > 0);
1112
1113#if LCD_WIDTH >= LCD_HEIGHT
1114 lcd_update_rect(x, y, width, height);
1115#else
1116 lcd_update_rect(LCD_WIDTH - y - height, x, height, width);
1117#endif
1118}
1119
916#define ROW_INC LCD_WIDTH 1120#define ROW_INC LCD_WIDTH
917#define COL_INC 1 1121#define COL_INC 1
918 1122
919#include "lcd-16bit-common.c" 1123#include "lcd-16bit-common.c"
920 1124
921#include "lcd-bitmap-common.c" 1125#include "lcd-bitmap-common.c"
922