add CMY and WB to test pattern
[android/external-libkmsxx.git] / tests / db.cpp
1 #include <cstdio>
2 #include <algorithm>
3 #include <chrono>
5 #include <xf86drm.h>
6 #include <xf86drmMode.h>
7 #include <drm_fourcc.h>
9 #include "kms++.h"
11 #include "test.h"
13 using namespace std;
14 using namespace kms;
16 static void main_loop(Card& card);
18 class OutputFlipHandler : private PageFlipHandlerBase
19 {
20 public:
21         OutputFlipHandler(Connector* conn, Crtc* crtc, DumbFramebuffer* fb1, DumbFramebuffer* fb2)
22                 : m_connector(conn), m_crtc(crtc), m_fbs { fb1, fb2 }, m_front_buf(1), m_bar_xpos(0)
23         {
24         }
26         ~OutputFlipHandler()
27         {
28                 delete m_fbs[0];
29                 delete m_fbs[1];
30         }
32         OutputFlipHandler(const OutputFlipHandler& other) = delete;
33         OutputFlipHandler& operator=(const OutputFlipHandler& other) = delete;
35         void set_mode()
36         {
37                 auto mode = m_connector->get_default_mode();
38                 int r = m_crtc->set_mode(m_connector, *m_fbs[0], mode);
39                 ASSERT(r == 0);
40         }
42         void start_flipping()
43         {
44                 m_t1 = std::chrono::steady_clock::now();
45                 m_frame_num = 0;
46                 queue_next();
47         }
49 private:
50         void handle_page_flip(uint32_t frame, double time)
51         {
52                 ++m_frame_num;
54                 if (m_frame_num  % 100 == 0) {
55                         auto t2 = std::chrono::steady_clock::now();
56                         std::chrono::duration<float> fsec = t2 - m_t1;
57                         printf("Output %d: fps %f\n", m_connector->idx(), 100.0 / fsec.count());
58                         m_t1 = t2;
59                 }
61                 queue_next();
62         }
64         void queue_next()
65         {
66                 m_front_buf = (m_front_buf + 1) % 2;
68                 const int bar_width = 20;
69                 const int bar_speed = 8;
71                 auto crtc = m_crtc;
72                 auto fb = m_fbs[(m_front_buf + 1) % 2];
74                 ASSERT(crtc);
75                 ASSERT(fb);
77                 int current_xpos = m_bar_xpos;
78                 int old_xpos = (current_xpos + (fb->width() - bar_width - bar_speed)) % (fb->width() - bar_width);
79                 int new_xpos = (current_xpos + bar_speed) % (fb->width() - bar_width);
81                 draw_color_bar(*fb, old_xpos, new_xpos, bar_width);
83                 m_bar_xpos = new_xpos;
85                 auto& card = crtc->card();
87                 if (card.has_atomic()) {
88                         int r;
90                         AtomicReq req(card);
92                         req.add(m_crtc, "FB_ID", fb->id());
94                         r = req.test();
95                         ASSERT(r == 0);
97                         r = req.commit(this);
98                         ASSERT(r == 0);
99                 } else {
100                         int r = crtc->page_flip(*fb, this);
101                         ASSERT(r == 0);
102                 }
103         }
105 private:
106         Connector* m_connector;
107         Crtc* m_crtc;
108         DumbFramebuffer* m_fbs[2];
110         int m_front_buf;
111         int m_bar_xpos;
113         int m_frame_num;
114         chrono::steady_clock::time_point m_t1;
115 };
117 int main()
119         Card card;
121         if (card.master() == false)
122                 printf("Not DRM master, modeset may fail\n");
124         //card.print_short();
126         vector<OutputFlipHandler*> outputs;
128         for (auto pipe : card.get_connected_pipelines())
129         {
130                 auto conn = pipe.connector;
131                 auto crtc = pipe.crtc;
133                 auto mode = conn->get_default_mode();
135                 auto fb1 = new DumbFramebuffer(card, mode.hdisplay, mode.vdisplay, PixelFormat::XRGB8888);
136                 auto fb2 = new DumbFramebuffer(card, mode.hdisplay, mode.vdisplay, PixelFormat::XRGB8888);
138                 printf("conn %u, crtc %u, fb1 %u, fb2 %u\n", conn->id(), crtc->id(), fb1->id(), fb2->id());
140                 auto output = new OutputFlipHandler(conn, crtc, fb1, fb2);
141                 outputs.push_back(output);
142         }
144         for(auto out : outputs)
145                 out->set_mode();
147         for(auto out : outputs)
148                 out->start_flipping();
150         main_loop(card);
152         for(auto out : outputs)
153                 delete out;
156 static void main_loop(Card& card)
158         fd_set fds;
160         FD_ZERO(&fds);
162         int fd = card.fd();
164         printf("press enter to exit\n");
166         while (true) {
167                 int r;
169                 FD_SET(0, &fds);
170                 FD_SET(fd, &fds);
172                 r = select(fd + 1, &fds, NULL, NULL, NULL);
173                 if (r < 0) {
174                         fprintf(stderr, "select() failed with %d: %m\n", errno);
175                         break;
176                 } else if (FD_ISSET(0, &fds)) {
177                         fprintf(stderr, "exit due to user-input\n");
178                         break;
179                 } else if (FD_ISSET(fd, &fds)) {
180                         card.call_page_flip_handlers();
181                 }
182         }