2 #include <kms++/kms++.h>
3 #include <kms++util/kms++util.h>
5 using namespace std;
7 namespace kms
8 {
9 void draw_rgb_pixel(IFramebuffer& buf, unsigned x, unsigned y, RGB color)
10 {
11 switch (buf.format()) {
12 case PixelFormat::XRGB8888:
13 case PixelFormat::ARGB8888:
14 {
15 uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
16 *p = color.argb8888();
17 break;
18 }
19 case PixelFormat::XBGR8888:
20 case PixelFormat::ABGR8888:
21 {
22 uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
23 *p = color.abgr8888();
24 break;
25 }
26 case PixelFormat::RGB888:
27 {
28 uint8_t *p = buf.map(0) + buf.stride(0) * y + x * 3;
29 p[0] = color.b;
30 p[1] = color.g;
31 p[2] = color.r;
32 break;
33 }
34 case PixelFormat::BGR888:
35 {
36 uint8_t *p = buf.map(0) + buf.stride(0) * y + x * 3;
37 p[0] = color.r;
38 p[1] = color.g;
39 p[2] = color.b;
40 break;
41 }
42 case PixelFormat::RGB565:
43 {
44 uint16_t *p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
45 *p = color.rgb565();
46 break;
47 }
48 case PixelFormat::BGR565:
49 {
50 uint16_t *p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
51 *p = color.bgr565();
52 break;
53 }
54 default:
55 throw std::invalid_argument("invalid pixelformat");
56 }
57 }
59 void draw_yuv422_macropixel(IFramebuffer& buf, unsigned x, unsigned y, YUV yuv1, YUV yuv2)
60 {
61 ASSERT((x & 1) == 0);
63 uint8_t *p = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
65 uint8_t y0 = yuv1.y;
66 uint8_t y1 = yuv2.y;
67 uint8_t u = (yuv1.u + yuv2.u) / 2;
68 uint8_t v = (yuv1.v + yuv2.v) / 2;
70 switch (buf.format()) {
71 case PixelFormat::UYVY:
72 p[0] = u;
73 p[1] = y0;
74 p[2] = v;
75 p[3] = y1;
76 break;
78 case PixelFormat::YUYV:
79 p[0] = y0;
80 p[1] = u;
81 p[2] = y1;
82 p[3] = v;
83 break;
85 case PixelFormat::YVYU:
86 p[0] = y0;
87 p[1] = v;
88 p[2] = y1;
89 p[3] = u;
90 break;
92 case PixelFormat::VYUY:
93 p[0] = v;
94 p[1] = y0;
95 p[2] = u;
96 p[3] = y1;
97 break;
99 default:
100 throw std::invalid_argument("invalid pixelformat");
101 }
102 }
104 void draw_yuv420_macropixel(IFramebuffer& buf, unsigned x, unsigned y,
105 YUV yuv1, YUV yuv2, YUV yuv3, YUV yuv4)
106 {
107 ASSERT((x & 1) == 0);
108 ASSERT((y & 1) == 0);
110 uint8_t *py1 = (uint8_t*)(buf.map(0) + buf.stride(0) * (y + 0) + x);
111 uint8_t *py2 = (uint8_t*)(buf.map(0) + buf.stride(0) * (y + 1) + x);
113 uint8_t *puv = (uint8_t*)(buf.map(1) + buf.stride(1) * (y / 2) + x);
115 uint8_t y0 = yuv1.y;
116 uint8_t y1 = yuv2.y;
117 uint8_t y2 = yuv3.y;
118 uint8_t y3 = yuv4.y;
119 uint8_t u = (yuv1.u + yuv2.u + yuv3.u + yuv4.u) / 4;
120 uint8_t v = (yuv1.v + yuv2.v + yuv3.v + yuv4.v) / 4;
122 switch (buf.format()) {
123 case PixelFormat::NV12:
124 py1[0] = y0;
125 py1[1] = y1;
126 py2[0] = y2;
127 py2[1] = y3;
128 puv[0] = u;
129 puv[1] = v;
130 break;
132 case PixelFormat::NV21:
133 py1[0] = y0;
134 py1[1] = y1;
135 py2[0] = y2;
136 py2[1] = y3;
137 puv[0] = v;
138 puv[1] = u;
139 break;
141 default:
142 throw std::invalid_argument("invalid pixelformat");
143 }
144 }
146 void draw_rect(IFramebuffer &fb, uint32_t x, uint32_t y, uint32_t w, uint32_t h, RGB color)
147 {
148 unsigned i, j;
149 YUV yuvcolor = color.yuv();
151 switch (fb.format()) {
152 case PixelFormat::XRGB8888:
153 case PixelFormat::XBGR8888:
154 case PixelFormat::ARGB8888:
155 case PixelFormat::ABGR8888:
156 case PixelFormat::RGB888:
157 case PixelFormat::BGR888:
158 case PixelFormat::RGB565:
159 case PixelFormat::BGR565:
160 for (j = 0; j < h; j++) {
161 for (i = 0; i < w; i++) {
162 draw_rgb_pixel(fb, x + i, y + j, color);
163 }
164 }
165 break;
167 case PixelFormat::UYVY:
168 case PixelFormat::YUYV:
169 case PixelFormat::YVYU:
170 case PixelFormat::VYUY:
171 for (j = 0; j < h; j++) {
172 for (i = 0; i < w; i += 2) {
173 draw_yuv422_macropixel(fb, x + i, y + j, yuvcolor, yuvcolor);
174 }
175 }
176 break;
178 case PixelFormat::NV12:
179 case PixelFormat::NV21:
180 for (j = 0; j < h; j += 2) {
181 for (i = 0; i < w; i += 2) {
182 draw_yuv420_macropixel(fb, x + i, y + j,
183 yuvcolor, yuvcolor, yuvcolor, yuvcolor);
184 }
185 }
186 break;
187 default:
188 throw std::invalid_argument("unknown pixelformat");
189 }
190 }
192 static bool get_char_pixel(char c, uint32_t x, uint32_t y)
193 {
194 #include "font_8x8.h"
196 uint8_t bits = fontdata_8x8[8 * c + y];
197 bool bit = (bits >> (7 - x)) & 1;
199 return bit;
200 }
202 static void draw_char(IFramebuffer& buf, uint32_t xpos, uint32_t ypos, char c, RGB color)
203 {
204 unsigned x, y;
205 YUV yuvcolor = color.yuv();
207 switch (buf.format()) {
208 case PixelFormat::XRGB8888:
209 case PixelFormat::XBGR8888:
210 case PixelFormat::ARGB8888:
211 case PixelFormat::ABGR8888:
212 case PixelFormat::RGB888:
213 case PixelFormat::BGR888:
214 case PixelFormat::RGB565:
215 case PixelFormat::BGR565:
216 for (y = 0; y < 8; y++) {
217 for (x = 0; x < 8; x++) {
218 bool b = get_char_pixel(c, x, y);
220 draw_rgb_pixel(buf, xpos + x, ypos + y, b ? color : RGB());
221 }
222 }
223 break;
225 case PixelFormat::UYVY:
226 case PixelFormat::YUYV:
227 case PixelFormat::YVYU:
228 case PixelFormat::VYUY:
229 for (y = 0; y < 8; y++) {
230 for (x = 0; x < 8; x += 2) {
231 bool b0 = get_char_pixel(c, x, y);
232 bool b1 = get_char_pixel(c, x + 1, y);
234 draw_yuv422_macropixel(buf, xpos + x, ypos + y,
235 b0 ? yuvcolor : YUV(RGB()), b1 ? yuvcolor : YUV(RGB()));
236 }
237 }
238 break;
240 case PixelFormat::NV12:
241 case PixelFormat::NV21:
242 for (y = 0; y < 8; y += 2) {
243 for (x = 0; x < 8; x += 2) {
244 bool b00 = get_char_pixel(c, x, y);
245 bool b10 = get_char_pixel(c, x + 1, y);
246 bool b01 = get_char_pixel(c, x, y + 1);
247 bool b11 = get_char_pixel(c, x + 1, y + 1);
249 draw_yuv420_macropixel(buf, xpos + x, ypos + y,
250 b00 ? yuvcolor : YUV(RGB()), b10 ? yuvcolor : YUV(RGB()),
251 b01 ? yuvcolor : YUV(RGB()), b11 ? yuvcolor : YUV(RGB()));
252 }
253 }
254 break;
255 default:
256 throw std::invalid_argument("unknown pixelformat");
257 }
258 }
260 void draw_text(IFramebuffer& buf, uint32_t x, uint32_t y, const string& str, RGB color)
261 {
262 for(unsigned i = 0; i < str.size(); i++)
263 draw_char(buf, (x + 8 * i), y, str[i], color);
264 }
266 }