diff options
Diffstat (limited to 'firmware/asm/lcd-as-memframe.c')
-rw-r--r-- | firmware/asm/lcd-as-memframe.c | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/firmware/asm/lcd-as-memframe.c b/firmware/asm/lcd-as-memframe.c index f7f3473fad..fb31fa1953 100644 --- a/firmware/asm/lcd-as-memframe.c +++ b/firmware/asm/lcd-as-memframe.c | |||
@@ -9,3 +9,171 @@ void lcd_copy_buffer_rect(fb_data *dst, fb_data *src, int width, int height) | |||
9 | dst += LCD_WIDTH; | 9 | dst += LCD_WIDTH; |
10 | } while (--height); | 10 | } while (--height); |
11 | } | 11 | } |
12 | |||
13 | #define YFAC (74) | ||
14 | #define RVFAC (101) | ||
15 | #define GUFAC (-24) | ||
16 | #define GVFAC (-51) | ||
17 | #define BUFAC (128) | ||
18 | |||
19 | static inline int clamp(int val, int min, int max) | ||
20 | { | ||
21 | if (val < min) | ||
22 | val = min; | ||
23 | else if (val > max) | ||
24 | val = max; | ||
25 | return val; | ||
26 | } | ||
27 | |||
28 | extern void lcd_write_yuv420_lines(fb_data *dst, | ||
29 | unsigned char const * const src[3], | ||
30 | int width, | ||
31 | int stride) | ||
32 | { | ||
33 | /* Draw a partial YUV colour bitmap - similiar behavior to lcd_blit_yuv | ||
34 | in the core */ | ||
35 | const unsigned char *ysrc, *usrc, *vsrc; | ||
36 | fb_data *row_end; | ||
37 | |||
38 | /* width and height must be >= 2 and an even number */ | ||
39 | width &= ~1; | ||
40 | |||
41 | #if LCD_WIDTH >= LCD_HEIGHT | ||
42 | row_end = dst + width; | ||
43 | #else | ||
44 | row_end = dst + LCD_WIDTH * width; | ||
45 | #endif | ||
46 | |||
47 | ysrc = src[0]; | ||
48 | usrc = src[1]; | ||
49 | vsrc = src[2]; | ||
50 | |||
51 | /* stride => amount to jump from end of last row to start of next */ | ||
52 | stride -= width; | ||
53 | |||
54 | /* upsampling, YUV->RGB conversion and reduction to RGB in one go */ | ||
55 | |||
56 | do | ||
57 | { | ||
58 | int y, cb, cr, rv, guv, bu, r, g, b; | ||
59 | |||
60 | y = YFAC*(*ysrc++ - 16); | ||
61 | cb = *usrc++ - 128; | ||
62 | cr = *vsrc++ - 128; | ||
63 | |||
64 | rv = RVFAC*cr; | ||
65 | guv = GUFAC*cb + GVFAC*cr; | ||
66 | bu = BUFAC*cb; | ||
67 | |||
68 | r = y + rv; | ||
69 | g = y + guv; | ||
70 | b = y + bu; | ||
71 | |||
72 | if ((unsigned)(r | g | b) > 64*256-1) | ||
73 | { | ||
74 | r = clamp(r, 0, 64*256-1); | ||
75 | g = clamp(g, 0, 64*256-1); | ||
76 | b = clamp(b, 0, 64*256-1); | ||
77 | } | ||
78 | |||
79 | *dst = FB_RGBPACK(r >> 6, g >> 6, b >> 6); | ||
80 | |||
81 | #if LCD_WIDTH >= LCD_HEIGHT | ||
82 | dst++; | ||
83 | #else | ||
84 | dst += LCD_WIDTH; | ||
85 | #endif | ||
86 | |||
87 | y = YFAC*(*ysrc++ - 16); | ||
88 | r = y + rv; | ||
89 | g = y + guv; | ||
90 | b = y + bu; | ||
91 | |||
92 | if ((unsigned)(r | g | b) > 64*256-1) | ||
93 | { | ||
94 | r = clamp(r, 0, 64*256-1); | ||
95 | g = clamp(g, 0, 64*256-1); | ||
96 | b = clamp(b, 0, 64*256-1); | ||
97 | } | ||
98 | |||
99 | *dst = FB_RGBPACK(r >> 6, g >> 6, b >> 6); | ||
100 | |||
101 | #if LCD_WIDTH >= LCD_HEIGHT | ||
102 | dst++; | ||
103 | #else | ||
104 | dst += LCD_WIDTH; | ||
105 | #endif | ||
106 | } | ||
107 | while (dst < row_end); | ||
108 | |||
109 | ysrc += stride; | ||
110 | usrc -= width >> 1; | ||
111 | vsrc -= width >> 1; | ||
112 | |||
113 | #if LCD_WIDTH >= LCD_HEIGHT | ||
114 | row_end += LCD_WIDTH; | ||
115 | dst += LCD_WIDTH - width; | ||
116 | #else | ||
117 | row_end -= 1; | ||
118 | dst -= LCD_WIDTH*width + 1; | ||
119 | #endif | ||
120 | |||
121 | do | ||
122 | { | ||
123 | int y, cb, cr, rv, guv, bu, r, g, b; | ||
124 | |||
125 | y = YFAC*(*ysrc++ - 16); | ||
126 | cb = *usrc++ - 128; | ||
127 | cr = *vsrc++ - 128; | ||
128 | |||
129 | rv = RVFAC*cr; | ||
130 | guv = GUFAC*cb + GVFAC*cr; | ||
131 | bu = BUFAC*cb; | ||
132 | |||
133 | r = y + rv; | ||
134 | g = y + guv; | ||
135 | b = y + bu; | ||
136 | |||
137 | if ((unsigned)(r | g | b) > 64*256-1) | ||
138 | { | ||
139 | r = clamp(r, 0, 64*256-1); | ||
140 | g = clamp(g, 0, 64*256-1); | ||
141 | b = clamp(b, 0, 64*256-1); | ||
142 | } | ||
143 | |||
144 | *dst = FB_RGBPACK(r >> 6, g >> 6, b >> 6); | ||
145 | |||
146 | #if LCD_WIDTH >= LCD_HEIGHT | ||
147 | dst++; | ||
148 | #else | ||
149 | dst += LCD_WIDTH; | ||
150 | #endif | ||
151 | |||
152 | y = YFAC*(*ysrc++ - 16); | ||
153 | r = y + rv; | ||
154 | g = y + guv; | ||
155 | b = y + bu; | ||
156 | |||
157 | if ((unsigned)(r | g | b) > 64*256-1) | ||
158 | { | ||
159 | r = clamp(r, 0, 64*256-1); | ||
160 | g = clamp(g, 0, 64*256-1); | ||
161 | b = clamp(b, 0, 64*256-1); | ||
162 | } | ||
163 | |||
164 | *dst = FB_RGBPACK(r >> 6, g >> 6, b >> 6); | ||
165 | |||
166 | #if LCD_WIDTH >= LCD_HEIGHT | ||
167 | dst++; | ||
168 | #else | ||
169 | dst += LCD_WIDTH; | ||
170 | #endif | ||
171 | } | ||
172 | while (dst < row_end); | ||
173 | } | ||
174 | |||
175 | void lcd_write_yuv420_lines_odither(fb_data *dst, | ||
176 | unsigned char const * const src[3], | ||
177 | int width, int stride, | ||
178 | int x_screen, int y_screen) | ||
179 | __attribute__((alias("lcd_write_yuv420_lines"))); | ||