5 #include <kms++/kms++.h>
6 #include <kms++util/kms++util.h>
12 void draw_rgb_pixel(IFramebuffer& buf, unsigned x, unsigned y, RGB color)
14 if (x >= buf.width() || y >= buf.height())
15 throw runtime_error("attempt to draw outside the buffer");
17 switch (buf.format()) {
18 case PixelFormat::XRGB8888:
19 case PixelFormat::ARGB8888: {
20 uint32_t* p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
21 *p = color.argb8888();
24 case PixelFormat::XBGR8888:
25 case PixelFormat::ABGR8888: {
26 uint32_t* p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
27 *p = color.abgr8888();
30 case PixelFormat::RGBX8888:
31 case PixelFormat::RGBA8888: {
32 uint32_t* p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
33 *p = color.rgba8888();
36 case PixelFormat::BGRX8888:
37 case PixelFormat::BGRA8888: {
38 uint32_t* p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
39 *p = color.bgra8888();
42 case PixelFormat::XRGB2101010:
43 case PixelFormat::ARGB2101010: {
44 uint32_t* p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
45 *p = color.argb2101010();
48 case PixelFormat::XBGR2101010:
49 case PixelFormat::ABGR2101010: {
50 uint32_t* p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
51 *p = color.abgr2101010();
54 case PixelFormat::RGBX1010102:
55 case PixelFormat::RGBA1010102: {
56 uint32_t* p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
57 *p = color.rgba1010102();
60 case PixelFormat::BGRX1010102:
61 case PixelFormat::BGRA1010102: {
62 uint32_t* p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
63 *p = color.bgra1010102();
66 case PixelFormat::RGB888: {
67 uint8_t* p = buf.map(0) + buf.stride(0) * y + x * 3;
73 case PixelFormat::BGR888: {
74 uint8_t* p = buf.map(0) + buf.stride(0) * y + x * 3;
80 case PixelFormat::RGB332: {
81 uint8_t* p = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x);
85 case PixelFormat::RGB565: {
86 uint16_t* p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
90 case PixelFormat::BGR565: {
91 uint16_t* p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
95 case PixelFormat::XRGB4444:
96 case PixelFormat::ARGB4444: {
97 uint16_t* p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
98 *p = color.argb4444();
101 case PixelFormat::XRGB1555:
102 case PixelFormat::ARGB1555: {
103 uint16_t* p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
104 *p = color.argb1555();
108 throw std::invalid_argument("invalid pixelformat");
112 void draw_yuv444_pixel(IFramebuffer& buf, unsigned x, unsigned y, YUV yuv)
114 if (x >= buf.width() || y >= buf.height())
115 throw runtime_error("attempt to draw outside the buffer");
117 uint8_t* py = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x);
118 uint8_t* pu = (uint8_t*)(buf.map(1) + buf.stride(1) * y + x);
119 uint8_t* pv = (uint8_t*)(buf.map(2) + buf.stride(2) * y + x);
121 switch (buf.format()) {
122 case PixelFormat::YUV444:
128 case PixelFormat::YVU444:
135 throw std::invalid_argument("invalid pixelformat");
139 static void draw_yuv422_packed_macropixel(IFramebuffer& buf, unsigned x, unsigned y,
142 uint8_t* p = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
146 uint8_t u = (yuv1.u + yuv2.u) / 2;
147 uint8_t v = (yuv1.v + yuv2.v) / 2;
149 switch (buf.format()) {
150 case PixelFormat::UYVY:
157 case PixelFormat::YUYV:
164 case PixelFormat::YVYU:
171 case PixelFormat::VYUY:
179 throw std::invalid_argument("invalid pixelformat");
183 static void draw_yuv422_semiplanar_macropixel(IFramebuffer& buf, unsigned x, unsigned y,
186 uint8_t* py = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x);
187 uint8_t* puv = (uint8_t*)(buf.map(1) + buf.stride(1) * y + x);
191 uint8_t u = (yuv1.u + yuv2.u) / 2;
192 uint8_t v = (yuv1.v + yuv2.v) / 2;
194 switch (buf.format()) {
195 case PixelFormat::NV16:
202 case PixelFormat::NV61:
210 throw std::invalid_argument("invalid pixelformat");
214 static void draw_yuv422_planar_macropixel(IFramebuffer& buf, unsigned x, unsigned y,
217 uint8_t* py = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x);
218 uint8_t* pu = (uint8_t*)(buf.map(1) + buf.stride(1) * y + x / 2);
219 uint8_t* pv = (uint8_t*)(buf.map(2) + buf.stride(2) * y + x / 2);
223 uint8_t u = (yuv1.u + yuv2.u) / 2;
224 uint8_t v = (yuv1.v + yuv2.v) / 2;
226 switch (buf.format()) {
227 case PixelFormat::YUV422:
234 case PixelFormat::YVU422:
242 throw std::invalid_argument("invalid pixelformat");
246 void draw_yuv422_macropixel(IFramebuffer& buf, unsigned x, unsigned y, YUV yuv1, YUV yuv2)
248 if ((x + 1) >= buf.width() || y >= buf.height())
249 throw runtime_error("attempt to draw outside the buffer");
251 ASSERT((x & 1) == 0);
253 switch (buf.format()) {
254 case PixelFormat::UYVY:
255 case PixelFormat::YUYV:
256 case PixelFormat::YVYU:
257 case PixelFormat::VYUY:
258 draw_yuv422_packed_macropixel(buf, x, y, yuv1, yuv2);
261 case PixelFormat::NV16:
262 case PixelFormat::NV61:
263 draw_yuv422_semiplanar_macropixel(buf, x, y, yuv1, yuv2);
266 case PixelFormat::YUV422:
267 case PixelFormat::YVU422:
268 draw_yuv422_planar_macropixel(buf, x, y, yuv1, yuv2);
272 throw std::invalid_argument("invalid pixelformat");
276 static void draw_yuv420_semiplanar_macropixel(IFramebuffer& buf, unsigned x, unsigned y,
277 YUV yuv1, YUV yuv2, YUV yuv3, YUV yuv4)
279 uint8_t* py1 = (uint8_t*)(buf.map(0) + buf.stride(0) * (y + 0) + x);
280 uint8_t* py2 = (uint8_t*)(buf.map(0) + buf.stride(0) * (y + 1) + x);
282 uint8_t* puv = (uint8_t*)(buf.map(1) + buf.stride(1) * (y / 2) + x);
288 uint8_t u = (yuv1.u + yuv2.u + yuv3.u + yuv4.u) / 4;
289 uint8_t v = (yuv1.v + yuv2.v + yuv3.v + yuv4.v) / 4;
291 switch (buf.format()) {
292 case PixelFormat::NV12:
301 case PixelFormat::NV21:
311 throw std::invalid_argument("invalid pixelformat");
315 static void draw_yuv420_planar_macropixel(IFramebuffer& buf, unsigned x, unsigned y,
316 YUV yuv1, YUV yuv2, YUV yuv3, YUV yuv4)
318 uint8_t* py1 = (uint8_t*)(buf.map(0) + buf.stride(0) * (y + 0) + x);
319 uint8_t* py2 = (uint8_t*)(buf.map(0) + buf.stride(0) * (y + 1) + x);
321 uint8_t* pu = (uint8_t*)(buf.map(1) + buf.stride(1) * (y / 2) + x / 2);
322 uint8_t* pv = (uint8_t*)(buf.map(2) + buf.stride(2) * (y / 2) + x / 2);
328 uint8_t u = (yuv1.u + yuv2.u + yuv3.u + yuv4.u) / 4;
329 uint8_t v = (yuv1.v + yuv2.v + yuv3.v + yuv4.v) / 4;
331 switch (buf.format()) {
332 case PixelFormat::YUV420:
341 case PixelFormat::YVU420:
351 throw std::invalid_argument("invalid pixelformat");
355 void draw_yuv420_macropixel(IFramebuffer& buf, unsigned x, unsigned y,
356 YUV yuv1, YUV yuv2, YUV yuv3, YUV yuv4)
358 if ((x + 1) >= buf.width() || (y + 1) >= buf.height())
359 throw runtime_error("attempt to draw outside the buffer");
361 ASSERT((x & 1) == 0);
362 ASSERT((y & 1) == 0);
364 switch (buf.format()) {
365 case PixelFormat::NV12:
366 case PixelFormat::NV21:
367 draw_yuv420_semiplanar_macropixel(buf, x, y, yuv1, yuv2, yuv3, yuv4);
370 case PixelFormat::YUV420:
371 case PixelFormat::YVU420:
372 draw_yuv420_planar_macropixel(buf, x, y, yuv1, yuv2, yuv3, yuv4);
376 throw std::invalid_argument("invalid pixelformat");
380 void draw_rect(IFramebuffer& fb, uint32_t x, uint32_t y, uint32_t w, uint32_t h, RGB color)
383 YUV yuvcolor = color.yuv();
385 switch (fb.format()) {
386 case PixelFormat::XRGB8888:
387 case PixelFormat::XBGR8888:
388 case PixelFormat::ARGB8888:
389 case PixelFormat::ABGR8888:
390 case PixelFormat::RGB888:
391 case PixelFormat::BGR888:
392 case PixelFormat::RGB565:
393 case PixelFormat::BGR565:
394 case PixelFormat::XRGB4444:
395 case PixelFormat::XRGB1555:
396 case PixelFormat::ARGB4444:
397 case PixelFormat::ARGB1555:
398 case PixelFormat::RGB332:
399 for (j = 0; j < h; j++) {
400 for (i = 0; i < w; i++) {
401 draw_rgb_pixel(fb, x + i, y + j, color);
406 case PixelFormat::YUV444:
407 case PixelFormat::YVU444:
408 for (j = 0; j < h; j++) {
409 for (i = 0; i < w; i++) {
410 draw_yuv444_pixel(fb, x + i, y + j, yuvcolor);
415 case PixelFormat::UYVY:
416 case PixelFormat::YUYV:
417 case PixelFormat::YVYU:
418 case PixelFormat::VYUY:
419 case PixelFormat::NV16:
420 case PixelFormat::NV61:
421 case PixelFormat::YUV422:
422 case PixelFormat::YVU422:
423 for (j = 0; j < h; j++) {
424 for (i = 0; i < w; i += 2) {
425 draw_yuv422_macropixel(fb, x + i, y + j, yuvcolor, yuvcolor);
430 case PixelFormat::NV12:
431 case PixelFormat::NV21:
432 case PixelFormat::YUV420:
433 case PixelFormat::YVU420:
434 for (j = 0; j < h; j += 2) {
435 for (i = 0; i < w; i += 2) {
436 draw_yuv420_macropixel(fb, x + i, y + j,
437 yuvcolor, yuvcolor, yuvcolor, yuvcolor);
442 throw std::invalid_argument("draw_rect: unknown pixelformat");
446 void draw_horiz_line(IFramebuffer& fb, uint32_t x1, uint32_t x2, uint32_t y, RGB color)
448 for (uint32_t x = x1; x <= x2; ++x)
449 draw_rgb_pixel(fb, x, y, color);
452 void draw_circle(IFramebuffer& fb, int32_t xCenter, int32_t yCenter, int32_t radius, RGB color)
454 int32_t r2 = radius * radius;
456 for (int y = -radius; y <= radius; y++) {
457 int32_t x = (int)(sqrt(r2 - y * y) + 0.5);
458 draw_horiz_line(fb, xCenter - x, xCenter + x, yCenter - y, color);
462 static bool get_char_pixel(char c, uint32_t x, uint32_t y)
464 #include "font_8x8.h"
466 uint8_t bits = fontdata_8x8[8 * c + y];
467 bool bit = (bits >> (7 - x)) & 1;
472 static void draw_char(IFramebuffer& buf, uint32_t xpos, uint32_t ypos, char c, RGB color)
475 YUV yuvcolor = color.yuv();
477 switch (buf.format()) {
478 case PixelFormat::XRGB8888:
479 case PixelFormat::XBGR8888:
480 case PixelFormat::ARGB8888:
481 case PixelFormat::ABGR8888:
482 case PixelFormat::RGB888:
483 case PixelFormat::BGR888:
484 case PixelFormat::RGB565:
485 case PixelFormat::BGR565:
486 case PixelFormat::XRGB4444:
487 case PixelFormat::XRGB1555:
488 case PixelFormat::ARGB4444:
489 case PixelFormat::ARGB1555:
490 case PixelFormat::RGB332:
491 for (y = 0; y < 8; y++) {
492 for (x = 0; x < 8; x++) {
493 bool b = get_char_pixel(c, x, y);
495 draw_rgb_pixel(buf, xpos + x, ypos + y, b ? color : RGB());
500 case PixelFormat::YUV444:
501 case PixelFormat::YVU444:
502 for (y = 0; y < 8; y++) {
503 for (x = 0; x < 8; x++) {
504 bool b = get_char_pixel(c, x, y);
506 draw_yuv444_pixel(buf, xpos + x, ypos + y, b ? yuvcolor : YUV(RGB()));
511 case PixelFormat::UYVY:
512 case PixelFormat::YUYV:
513 case PixelFormat::YVYU:
514 case PixelFormat::VYUY:
515 case PixelFormat::NV16:
516 case PixelFormat::NV61:
517 case PixelFormat::YUV422:
518 case PixelFormat::YVU422:
519 for (y = 0; y < 8; y++) {
520 for (x = 0; x < 8; x += 2) {
521 bool b0 = get_char_pixel(c, x, y);
522 bool b1 = get_char_pixel(c, x + 1, y);
524 draw_yuv422_macropixel(buf, xpos + x, ypos + y,
525 b0 ? yuvcolor : YUV(RGB()), b1 ? yuvcolor : YUV(RGB()));
530 case PixelFormat::NV12:
531 case PixelFormat::NV21:
532 case PixelFormat::YUV420:
533 case PixelFormat::YVU420:
534 for (y = 0; y < 8; y += 2) {
535 for (x = 0; x < 8; x += 2) {
536 bool b00 = get_char_pixel(c, x, y);
537 bool b10 = get_char_pixel(c, x + 1, y);
538 bool b01 = get_char_pixel(c, x, y + 1);
539 bool b11 = get_char_pixel(c, x + 1, y + 1);
541 draw_yuv420_macropixel(buf, xpos + x, ypos + y,
542 b00 ? yuvcolor : YUV(RGB()), b10 ? yuvcolor : YUV(RGB()),
543 b01 ? yuvcolor : YUV(RGB()), b11 ? yuvcolor : YUV(RGB()));
548 throw std::invalid_argument("draw_char: unknown pixelformat");
552 void draw_text(IFramebuffer& buf, uint32_t x, uint32_t y, const string& str, RGB color)
554 for (unsigned i = 0; i < str.size(); i++)
555 draw_char(buf, (x + 8 * i), y, str[i], color);
558 void dump_framebuffer(IFramebuffer& fb, int fd)
560 for (unsigned int i = 0; i < fb.num_planes(); ++i)
561 ::write(fd, fb.map(i), fb.size(i));