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