Add support for YVYU and VYUY
[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         static RGB c1;
23         switch (buf.format()) {
24         case PixelFormat::XRGB8888:
25         {
26                 uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
27                 *p = color.rgb888();
28                 break;
29         }
30         case PixelFormat::XBGR8888:
31         {
32                 uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
33                 *p = color.bgr888();
34                 break;
35         }
36         case PixelFormat::RGB565:
37         {
38                 uint16_t *p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
39                 *p = color.rgb565();
40                 break;
41         }
42         case PixelFormat::UYVY:
43         case PixelFormat::YUYV:
44         case PixelFormat::YVYU:
45         case PixelFormat::VYUY:
46         {
47                 if ((x & 1) == 0) {
48                         c1 = color;
49                         return;
50                 }
52                 uint8_t *p = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
54                 YUV yuv1 = c1.yuv();
55                 YUV yuv2 = color.yuv();
57                 switch (buf.format()) {
58                 case PixelFormat::UYVY:
59                         p[0] = (yuv1.u + yuv2.u) / 2;
60                         p[1] = yuv1.y;
61                         p[2] = (yuv1.v + yuv2.v) / 2;
62                         p[3] = yuv2.y;
63                         break;
65                 case PixelFormat::YUYV:
66                         p[0] = yuv1.y;
67                         p[1] = (yuv1.u + yuv2.u) / 2;
68                         p[2] = yuv2.y;
69                         p[3] = (yuv1.v + yuv2.v) / 2;
70                         break;
72                 case PixelFormat::YVYU:
73                         p[0] = yuv1.y;
74                         p[1] = (yuv1.v + yuv2.v) / 2;
75                         p[2] = yuv2.y;
76                         p[3] = (yuv1.u + yuv2.u) / 2;
77                         break;
79                 case PixelFormat::VYUY:
80                         p[0] = (yuv1.v + yuv2.v) / 2;
81                         p[1] = yuv1.y;
82                         p[2] = (yuv1.u + yuv2.u) / 2;
83                         p[3] = yuv2.y;
84                         break;
85                 default:
86                         break;
87                 }
89                 break;
90         }
91         default:
92                 throw std::invalid_argument("unknown pixelformat");
93         }
94 }
96 static void draw_rgb_test_pattern(DumbFramebuffer& fb)
97 {
98         unsigned x, y;
99         unsigned w = fb.width();
100         unsigned h = fb.height();
102         const unsigned mw = 20;
104         const unsigned xm1 = mw;
105         const unsigned xm2 = w - mw - 1;
106         const unsigned ym1 = mw;
107         const unsigned ym2 = h - mw - 1;
109         for (y = 0; y < h; y++) {
110                 for (x = 0; x < w; x++) {
111                         // white margin lines
112                         if (x == xm1 || x == xm2 || y == ym1 || y == ym2)
113                                 draw_pixel(fb, x, y, RGB(255, 255, 255));
114                         // white box outlines to corners
115                         else if ((x == 0 || x == w - 1) && (y < ym1 || y > ym2))
116                                 draw_pixel(fb, x, y, RGB(255, 255, 255));
117                         // white box outlines to corners
118                         else if ((y == 0 || y == h - 1) && (x < xm1 || x > xm2))
119                                 draw_pixel(fb, x, y, RGB(255, 255, 255));
120                         // blue bar on the left
121                         else if (x < xm1 && (y > ym1 && y < ym2))
122                                 draw_pixel(fb, x, y, RGB(0, 0, 255));
123                         // blue bar on the top
124                         else if (y < ym1 && (x > xm1 && x < xm2))
125                                 draw_pixel(fb, x, y, RGB(0, 0, 255));
126                         // red bar on the right
127                         else if (x > xm2 && (y > ym1 && y < ym2))
128                                 draw_pixel(fb, x, y, RGB(255, 0, 0));
129                         // red bar on the bottom
130                         else if (y > ym2 && (x > xm1 && x < xm2))
131                                 draw_pixel(fb, x, y, RGB(255, 0, 0));
132                         // inside the margins
133                         else if (x > xm1 && x < xm2 && y > ym1 && y < ym2) {
134                                 // diagonal line
135                                 if (x == y || w - x == h - y)
136                                         draw_pixel(fb, x, y, RGB(255, 255, 255));
137                                 // diagonal line
138                                 else if (w - x == y || x == h - y)
139                                         draw_pixel(fb, x, y, RGB(255, 255, 255));
140                                 else {
141                                         int t = (x - xm1 - 1) * 3 / (xm2 - xm1 - 1);
142                                         unsigned r = 0, g = 0, b = 0;
144                                         unsigned c = (y - ym1 - 1) % 256;
146                                         switch (t) {
147                                         case 0:
148                                                 r = c;
149                                                 break;
150                                         case 1:
151                                                 g = c;
152                                                 break;
153                                         case 2:
154                                                 b = c;
155                                                 break;
156                                         }
158                                         draw_pixel(fb, x, y, RGB(r, g, b));
159                                 }
160                                 // black corners
161                         } else {
162                                 draw_pixel(fb, x, y, RGB(0, 0, 0));
163                         }
164                 }
165         }
168 void draw_test_pattern(DumbFramebuffer& fb)
170         using namespace std::chrono;
172         auto t1 = high_resolution_clock::now();
174         draw_rgb_test_pattern(fb);
176         auto t2 = high_resolution_clock::now();
177         auto time_span = duration_cast<microseconds>(t2 - t1);
179         printf("draw took %u us\n", (unsigned)time_span.count());