f65a1f87bd35eed5bc99a1ac0d220b612d7d72da
[android/external-libkmsxx.git] / libkmstest / testpat.cpp
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         }
106 static void draw_rgb_test_pattern(DumbFramebuffer& fb)
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         }
178 void draw_test_pattern(DumbFramebuffer& fb)
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());