#include #include #include #include #include #include #include #include #include "kms++.h" #include "color.h" #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) namespace kms { static void draw_pixel(DumbFramebuffer& buf, unsigned x, unsigned y, RGB color) { switch (buf.format()) { case PixelFormat::XRGB8888: { uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4); *p = color.rgb888(); break; } case PixelFormat::XBGR8888: { uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4); *p = color.bgr888(); break; } case PixelFormat::RGB565: { uint16_t *p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2); *p = color.rgb565(); break; } case PixelFormat::UYVY: case PixelFormat::YUYV: case PixelFormat::YVYU: case PixelFormat::VYUY: { // HACK. we store the even pixels to c1, and only draw when at the odd pixel. static RGB c1; if ((x & 1) == 0) { c1 = color; return; } // adjust X back to the even pixel x--; uint8_t *p = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x * 2); YUV yuv1 = c1.yuv(); YUV yuv2 = color.yuv(); uint8_t y0 = yuv1.y; uint8_t y1 = yuv2.y; uint8_t u = (yuv1.u + yuv2.u) / 2; uint8_t v = (yuv1.v + yuv2.v) / 2; switch (buf.format()) { case PixelFormat::UYVY: p[0] = u; p[1] = y0; p[2] = v; p[3] = y1; break; case PixelFormat::YUYV: p[0] = y0; p[1] = u; p[2] = y1; p[3] = v; break; case PixelFormat::YVYU: p[0] = y0; p[1] = v; p[2] = y1; p[3] = u; break; case PixelFormat::VYUY: p[0] = v; p[1] = y0; p[2] = u; p[3] = y1; break; default: break; } break; } default: throw std::invalid_argument("unknown pixelformat"); } } static void draw_rgb_test_pattern(DumbFramebuffer& fb) { unsigned x, y; unsigned w = fb.width(); unsigned h = fb.height(); const unsigned mw = 20; const unsigned xm1 = mw; const unsigned xm2 = w - mw - 1; const unsigned ym1 = mw; const unsigned ym2 = h - mw - 1; for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { // white margin lines if (x == xm1 || x == xm2 || y == ym1 || y == ym2) draw_pixel(fb, x, y, RGB(255, 255, 255)); // white box outlines to corners else if ((x == 0 || x == w - 1) && (y < ym1 || y > ym2)) draw_pixel(fb, x, y, RGB(255, 255, 255)); // white box outlines to corners else if ((y == 0 || y == h - 1) && (x < xm1 || x > xm2)) draw_pixel(fb, x, y, RGB(255, 255, 255)); // blue bar on the left else if (x < xm1 && (y > ym1 && y < ym2)) draw_pixel(fb, x, y, RGB(0, 0, 255)); // blue bar on the top else if (y < ym1 && (x > xm1 && x < xm2)) draw_pixel(fb, x, y, RGB(0, 0, 255)); // red bar on the right else if (x > xm2 && (y > ym1 && y < ym2)) draw_pixel(fb, x, y, RGB(255, 0, 0)); // red bar on the bottom else if (y > ym2 && (x > xm1 && x < xm2)) draw_pixel(fb, x, y, RGB(255, 0, 0)); // inside the margins else if (x > xm1 && x < xm2 && y > ym1 && y < ym2) { // diagonal line if (x == y || w - x == h - y) draw_pixel(fb, x, y, RGB(255, 255, 255)); // diagonal line else if (w - x == y || x == h - y) draw_pixel(fb, x, y, RGB(255, 255, 255)); else { int t = (x - xm1 - 1) * 3 / (xm2 - xm1 - 1); unsigned r = 0, g = 0, b = 0; unsigned c = (y - ym1 - 1) % 256; switch (t) { case 0: r = c; break; case 1: g = c; break; case 2: b = c; break; } draw_pixel(fb, x, y, RGB(r, g, b)); } // black corners } else { draw_pixel(fb, x, y, RGB(0, 0, 0)); } } } } void draw_test_pattern(DumbFramebuffer& fb) { using namespace std::chrono; auto t1 = high_resolution_clock::now(); draw_rgb_test_pattern(fb); auto t2 = high_resolution_clock::now(); auto time_span = duration_cast(t2 - t1); printf("draw took %u us\n", (unsigned)time_span.count()); } }