2 #include <chrono>
3 #include <cstring>
4 #include <cassert>
6 #include <xf86drm.h>
7 #include <xf86drmMode.h>
8 #include <drm_fourcc.h>
9 #include <drm.h>
10 #include <drm_mode.h>
12 #include "kms++.h"
13 #include "color.h"
15 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
17 namespace kms
18 {
19 static void draw_pixel(DumbFramebuffer& buf, unsigned x, unsigned y, RGB color)
20 {
21 switch (buf.format()) {
22 case PixelFormat::XRGB8888:
23 {
24 uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
25 *p = color.rgb888();
26 break;
27 }
28 case PixelFormat::XBGR8888:
29 {
30 uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
31 *p = color.bgr888();
32 break;
33 }
34 case PixelFormat::RGB565:
35 {
36 uint16_t *p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
37 *p = color.rgb565();
38 break;
39 }
40 case PixelFormat::UYVY:
41 case PixelFormat::YUYV:
42 case PixelFormat::YVYU:
43 case PixelFormat::VYUY:
44 {
45 // HACK. we store the even pixels to c1, and only draw when at the odd pixel.
47 static RGB c1;
49 if ((x & 1) == 0) {
50 c1 = color;
51 return;
52 }
54 // adjust X back to the even pixel
55 x--;
57 uint8_t *p = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
59 YUV yuv1 = c1.yuv();
60 YUV yuv2 = color.yuv();
62 uint8_t y0 = yuv1.y;
63 uint8_t y1 = yuv2.y;
64 uint8_t u = (yuv1.u + yuv2.u) / 2;
65 uint8_t v = (yuv1.v + yuv2.v) / 2;
67 switch (buf.format()) {
68 case PixelFormat::UYVY:
69 p[0] = u;
70 p[1] = y0;
71 p[2] = v;
72 p[3] = y1;
73 break;
75 case PixelFormat::YUYV:
76 p[0] = y0;
77 p[1] = u;
78 p[2] = y1;
79 p[3] = v;
80 break;
82 case PixelFormat::YVYU:
83 p[0] = y0;
84 p[1] = v;
85 p[2] = y1;
86 p[3] = u;
87 break;
89 case PixelFormat::VYUY:
90 p[0] = v;
91 p[1] = y0;
92 p[2] = u;
93 p[3] = y1;
94 break;
95 default:
96 break;
97 }
99 break;
100 }
101 default:
102 throw std::invalid_argument("unknown pixelformat");
103 }
104 }
106 static void draw_rgb_test_pattern(DumbFramebuffer& fb)
107 {
108 unsigned x, y;
109 unsigned w = fb.width();
110 unsigned h = fb.height();
112 const unsigned mw = 20;
114 const unsigned xm1 = mw;
115 const unsigned xm2 = w - mw - 1;
116 const unsigned ym1 = mw;
117 const unsigned ym2 = h - mw - 1;
119 for (y = 0; y < h; y++) {
120 for (x = 0; x < w; x++) {
121 // white margin lines
122 if (x == xm1 || x == xm2 || y == ym1 || y == ym2)
123 draw_pixel(fb, x, y, RGB(255, 255, 255));
124 // white box outlines to corners
125 else if ((x == 0 || x == w - 1) && (y < ym1 || y > ym2))
126 draw_pixel(fb, x, y, RGB(255, 255, 255));
127 // white box outlines to corners
128 else if ((y == 0 || y == h - 1) && (x < xm1 || x > xm2))
129 draw_pixel(fb, x, y, RGB(255, 255, 255));
130 // blue bar on the left
131 else if (x < xm1 && (y > ym1 && y < ym2))
132 draw_pixel(fb, x, y, RGB(0, 0, 255));
133 // blue bar on the top
134 else if (y < ym1 && (x > xm1 && x < xm2))
135 draw_pixel(fb, x, y, RGB(0, 0, 255));
136 // red bar on the right
137 else if (x > xm2 && (y > ym1 && y < ym2))
138 draw_pixel(fb, x, y, RGB(255, 0, 0));
139 // red bar on the bottom
140 else if (y > ym2 && (x > xm1 && x < xm2))
141 draw_pixel(fb, x, y, RGB(255, 0, 0));
142 // inside the margins
143 else if (x > xm1 && x < xm2 && y > ym1 && y < ym2) {
144 // diagonal line
145 if (x == y || w - x == h - y)
146 draw_pixel(fb, x, y, RGB(255, 255, 255));
147 // diagonal line
148 else if (w - x == y || x == h - y)
149 draw_pixel(fb, x, y, RGB(255, 255, 255));
150 else {
151 int t = (x - xm1 - 1) * 3 / (xm2 - xm1 - 1);
152 unsigned r = 0, g = 0, b = 0;
154 unsigned c = (y - ym1 - 1) % 256;
156 switch (t) {
157 case 0:
158 r = c;
159 break;
160 case 1:
161 g = c;
162 break;
163 case 2:
164 b = c;
165 break;
166 }
168 draw_pixel(fb, x, y, RGB(r, g, b));
169 }
170 // black corners
171 } else {
172 draw_pixel(fb, x, y, RGB(0, 0, 0));
173 }
174 }
175 }
176 }
178 void draw_test_pattern(DumbFramebuffer& fb)
179 {
180 using namespace std::chrono;
182 auto t1 = high_resolution_clock::now();
184 draw_rgb_test_pattern(fb);
186 auto t2 = high_resolution_clock::now();
187 auto time_span = duration_cast<microseconds>(t2 - t1);
189 printf("draw took %u us\n", (unsigned)time_span.count());
190 }
191 }