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 "card.h"
13 #include "framebuffer.h"
14 #include "testpat.h"
15 #include "color.h"
17 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
19 namespace kms
20 {
21 static void draw_pixel(Framebuffer& buf, unsigned x, unsigned y, RGB color)
22 {
23 static RGB c1;
25 switch (buf.format()) {
26 case DRM_FORMAT_XRGB8888:
27 {
28 uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
29 *p = color.raw;
30 break;
31 }
32 case DRM_FORMAT_RGB565:
33 {
34 uint16_t *p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
35 *p = color.rgb565();
36 break;
37 }
38 case DRM_FORMAT_UYVY:
39 {
40 if ((x & 1) == 0) {
41 c1 = color;
42 return;
43 }
45 uint8_t *p = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
47 YUV yuv1 = c1.yuv();
48 YUV yuv2 = color.yuv();
50 p[0] = (yuv1.u + yuv2.u) / 2;
51 p[1] = yuv1.y;
52 p[2] = (yuv1.v + yuv2.v) / 2;
53 p[3] = yuv2.y;
54 break;
55 }
56 case DRM_FORMAT_YUYV:
57 {
58 if ((x & 1) == 0) {
59 c1 = color;
60 return;
61 }
63 uint8_t *p = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
65 YUV yuv1 = c1.yuv();
66 YUV yuv2 = color.yuv();
68 p[0] = yuv1.y;
69 p[1] = (yuv1.u + yuv2.u) / 2;
70 p[2] = yuv2.y;
71 p[3] = (yuv1.v + yuv2.v) / 2;
72 break;
73 }
74 }
75 }
77 static void draw_rgb_test_pattern(Framebuffer& fb)
78 {
79 unsigned x, y;
80 unsigned w = fb.width();
81 unsigned h = fb.height();
83 const unsigned mw = 20;
85 const unsigned xm1 = mw;
86 const unsigned xm2 = w - mw - 1;
87 const unsigned ym1 = mw;
88 const unsigned ym2 = h - mw - 1;
90 for (y = 0; y < h; y++) {
91 for (x = 0; x < w; x++) {
92 // white margin lines
93 if (x == xm1 || x == xm2 || y == ym1 || y == ym2)
94 draw_pixel(fb, x, y, RGB(255, 255, 255));
95 // white box outlines to corners
96 else if ((x == 0 || x == w - 1) && (y < ym1 || y > ym2))
97 draw_pixel(fb, x, y, RGB(255, 255, 255));
98 // white box outlines to corners
99 else if ((y == 0 || y == h - 1) && (x < xm1 || x > xm2))
100 draw_pixel(fb, x, y, RGB(255, 255, 255));
101 // blue bar on the left
102 else if (x < xm1 && (y > ym1 && y < ym2))
103 draw_pixel(fb, x, y, RGB(0, 0, 255));
104 // blue bar on the top
105 else if (y < ym1 && (x > xm1 && x < xm2))
106 draw_pixel(fb, x, y, RGB(0, 0, 255));
107 // red bar on the right
108 else if (x > xm2 && (y > ym1 && y < ym2))
109 draw_pixel(fb, x, y, RGB(255, 0, 0));
110 // red bar on the bottom
111 else if (y > ym2 && (x > xm1 && x < xm2))
112 draw_pixel(fb, x, y, RGB(255, 0, 0));
113 // inside the margins
114 else if (x > xm1 && x < xm2 && y > ym1 && y < ym2) {
115 // diagonal line
116 if (x == y || w - x == h - y)
117 draw_pixel(fb, x, y, RGB(255, 255, 255));
118 // diagonal line
119 else if (w - x == y || x == h - y)
120 draw_pixel(fb, x, y, RGB(255, 255, 255));
121 else {
122 int t = (x - xm1 - 1) * 3 / (xm2 - xm1 - 1);
123 unsigned r = 0, g = 0, b = 0;
125 unsigned c = (y - ym1 - 1) % 256;
127 switch (t) {
128 case 0:
129 r = c;
130 break;
131 case 1:
132 g = c;
133 break;
134 case 2:
135 b = c;
136 break;
137 }
139 draw_pixel(fb, x, y, RGB(r, g, b));
140 }
141 // black corners
142 } else {
143 draw_pixel(fb, x, y, RGB(0, 0, 0));
144 }
145 }
146 }
147 }
149 void draw_test_pattern(Framebuffer& fb)
150 {
151 using namespace std::chrono;
153 auto t1 = high_resolution_clock::now();
155 draw_rgb_test_pattern(fb);
157 auto t2 = high_resolution_clock::now();
158 auto time_span = duration_cast<microseconds>(t2 - t1);
160 printf("draw took %u us\n", (unsigned)time_span.count());
161 }
162 }