468a4cca385477af383c8e6e65695a64e5ad7671
[android/external-libkmsxx.git] / tests / db.cpp
1 #include <cstdio>
2 #include <algorithm>
4 #include <xf86drm.h>
5 #include <xf86drmMode.h>
6 #include <drm_fourcc.h>
8 #include "kms++.h"
9 #include "utils/color.h"
11 #include "test.h"
13 using namespace std;
14 using namespace kms;
16 static void draw_color_bar(Framebuffer& buf, int old_xpos, int xpos, int width);
18 static void main_loop(Card& card);
20 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
22 struct Output
23 {
24         Connector* connector;
25         Crtc* crtc;
26         Framebuffer* fbs[2];
28         int front_buf;
29         int bar_xpos;
30 };
32 static void do_flip(Output* out);
34 int main()
35 {
36         Card card;
38         if (card.master() == false)
39                 printf("Not DRM master, modeset may fail\n");
41         //card.print_short();
43         vector<Output> outputs;
45         for (auto conn : card.get_connectors())
46         {
47                 if (conn->connected() == false)
48                         continue;
50                 auto mode = conn->get_default_mode();
52                 Crtc* crtc = conn->get_current_crtc();
53                 if (!crtc) {
54                         for (auto c : conn->get_possible_crtcs()) {
55                                 if (find_if(outputs.begin(), outputs.end(), [c](Output o) { return o.crtc == c; }) == outputs.end()) {
56                                         crtc = c;
57                                         break;
58                                 }
59                         }
60                 }
62                 if (!crtc) {
63                         printf("failed to find crtc\n");
64                         return -1;
65                 }
67                 auto fb1 = new Framebuffer(card, mode.hdisplay, mode.vdisplay, "XR24");
68                 auto fb2 = new Framebuffer(card, mode.hdisplay, mode.vdisplay, "XR24");
70                 printf("conn %u, crtc %u, fb1 %u, fb2 %u\n", conn->id(), crtc->id(), fb1->id(), fb2->id());
72                 Output output = { };
73                 output.connector = conn;
74                 output.crtc = crtc;
75                 output.fbs[0] = fb1;
76                 output.fbs[1] = fb2;
77                 outputs.push_back(output);
78         }
80         for(auto& out : outputs) {
81                 auto conn = out.connector;
82                 auto crtc = out.crtc;
84                 auto mode = conn->get_default_mode();
85                 int r = crtc->set_mode(conn, *out.fbs[0], mode);
86                 ASSERT(r == 0);
87         }
89         for(auto& out : outputs)
90                 do_flip(&out);
92         main_loop(card);
94         for(auto& out : outputs) {
95                 delete out.fbs[0];
96                 delete out.fbs[1];
97         }
98 }
100 static void do_flip(Output* out)
102         const int bar_width = 20;
103         const int bar_speed = 8;
105         auto crtc = out->crtc;
106         auto fb = out->fbs[(out->front_buf + 1) % 2];
108         ASSERT(crtc);
109         ASSERT(fb);
111         int current_xpos = out->bar_xpos;
112         int old_xpos = (current_xpos + (fb->width() - bar_width - bar_speed)) % (fb->width() - bar_width);
113         int new_xpos = (current_xpos + bar_speed) % (fb->width() - bar_width);
115         draw_color_bar(*fb, old_xpos, new_xpos, bar_width);
117         out->bar_xpos = new_xpos;
119         auto& card = crtc->card();
121         if (card.has_atomic()) {
122                 int r;
124                 AtomicReq ctx(card);
126                 ctx.add(crtc, card.get_prop("FB_ID"), fb->id());
128                 r = ctx.test();
129                 ASSERT(r == 0);
131                 r = ctx.commit(out);
132                 ASSERT(r == 0);
133         } else {
134                 int r = drmModePageFlip(card.fd(), crtc->id(), fb->id(), DRM_MODE_PAGE_FLIP_EVENT, out);
135                 ASSERT(r == 0);
136         }
139 static void page_flip_handler(int fd, unsigned int frame,
140                               unsigned int sec, unsigned int usec,
141                               void *data)
143         //printf("flip event %d, %d, %u, %u, %p\n", fd, frame, sec, usec, data);
145         auto out = (Output*)data;
147         out->front_buf = (out->front_buf + 1) % 2;
149         do_flip(out);
153 static void main_loop(Card& card)
155         drmEventContext ev = {
156                 .version = DRM_EVENT_CONTEXT_VERSION,
157                 .vblank_handler = 0,
158                 .page_flip_handler = page_flip_handler,
159         };
161         fd_set fds;
163         FD_ZERO(&fds);
165         int fd = card.fd();
167         printf("press enter to exit\n");
169         while (true) {
170                 int r;
172                 FD_SET(0, &fds);
173                 FD_SET(fd, &fds);
175                 r = select(fd + 1, &fds, NULL, NULL, NULL);
176                 if (r < 0) {
177                         fprintf(stderr, "select() failed with %d: %m\n", errno);
178                         break;
179                 } else if (FD_ISSET(0, &fds)) {
180                         fprintf(stderr, "exit due to user-input\n");
181                         break;
182                 } else if (FD_ISSET(fd, &fds)) {
183                         drmHandleEvent(fd, &ev);
184                 }
185         }
189 static const RGB colors32[] = {
190         RGB(255, 255, 255),
191         RGB(255, 0, 0),
192         RGB(255, 255, 255),
193         RGB(0, 255, 0),
194         RGB(255, 255, 255),
195         RGB(0, 0, 255),
196         RGB(255, 255, 255),
197         RGB(200, 200, 200),
198         RGB(255, 255, 255),
199         RGB(100, 100, 100),
200         RGB(255, 255, 255),
201         RGB(50, 50, 50),
202 };
204 static const uint16_t colors16[] = {
205         colors32[0].rgb565(),
206         colors32[1].rgb565(),
207         colors32[2].rgb565(),
208         colors32[3].rgb565(),
209         colors32[4].rgb565(),
210         colors32[5].rgb565(),
211         colors32[6].rgb565(),
212         colors32[7].rgb565(),
213         colors32[8].rgb565(),
214         colors32[9].rgb565(),
215         colors32[10].rgb565(),
216         colors32[11].rgb565(),
217 };
219 static void drm_draw_color_bar_rgb888(Framebuffer& buf, int old_xpos, int xpos, int width)
221         for (unsigned y = 0; y < buf.height(); ++y) {
222                 RGB bcol = colors32[y * ARRAY_SIZE(colors32) / buf.height()];
223                 uint32_t *line = (uint32_t*)(buf.map(0) + buf.stride(0) * y);
225                 if (old_xpos >= 0) {
226                         for (int x = old_xpos; x < old_xpos + width; ++x)
227                                 line[x] = 0;
228                 }
230                 for (int x = xpos; x < xpos + width; ++x)
231                         line[x] = bcol.raw;
232         }
235 static void drm_draw_color_bar_rgb565(Framebuffer& buf, int old_xpos, int xpos, int width)
237         static_assert(ARRAY_SIZE(colors32) == ARRAY_SIZE(colors16), "bad colors arrays");
239         for (unsigned y = 0; y < buf.height(); ++y) {
240                 uint16_t bcol = colors16[y * ARRAY_SIZE(colors16) / buf.height()];
241                 uint16_t *line = (uint16_t*)(buf.map(0) + buf.stride(0) * y);
243                 if (old_xpos >= 0) {
244                         for (int x = old_xpos; x < old_xpos + width; ++x)
245                                 line[x] = 0;
246                 }
248                 for (int x = xpos; x < xpos + width; ++x)
249                         line[x] = bcol;
250         }
253 static void drm_draw_color_bar_semiplanar_yuv(Framebuffer& buf, int old_xpos, int xpos, int width)
255         const uint8_t colors[] = {
256                 0xff,
257                 0x00,
258                 0xff,
259                 0x20,
260                 0xff,
261                 0x40,
262                 0xff,
263                 0x80,
264                 0xff,
265         };
267         for (unsigned y = 0; y < buf.height(); ++y) {
268                 unsigned int bcol = colors[y * ARRAY_SIZE(colors) / buf.height()];
269                 uint8_t *line = (uint8_t*)(buf.map(0) + buf.stride(0) * y);
271                 if (old_xpos >= 0) {
272                         for (int x = old_xpos; x < old_xpos + width; ++x)
273                                 line[x] = 0;
274                 }
276                 for (int x = xpos; x < xpos + width; ++x)
277                         line[x] = bcol;
278         }
281 static void draw_color_bar(Framebuffer& buf, int old_xpos, int xpos, int width)
283         switch (buf.format()) {
284         case DRM_FORMAT_NV12:
285         case DRM_FORMAT_NV21:
286                 // XXX not right but gets something on the screen
287                 drm_draw_color_bar_semiplanar_yuv(buf, old_xpos, xpos, width);
288                 break;
290         case DRM_FORMAT_YUYV:
291         case DRM_FORMAT_UYVY:
292                 // XXX not right but gets something on the screen
293                 drm_draw_color_bar_rgb565(buf, old_xpos, xpos, width);
294                 break;
296         case DRM_FORMAT_RGB565:
297                 drm_draw_color_bar_rgb565(buf, old_xpos, xpos, width);
298                 break;
300         case DRM_FORMAT_XRGB8888:
301                 drm_draw_color_bar_rgb888(buf, old_xpos, xpos, width);
302                 break;
304         default:
305                 ASSERT(false);
306         }