4356e97b8bdc45689ce6c3413f09093c43ed4557
[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 Flipper
19 {
20 public:
21         Flipper(Card& card, unsigned width, unsigned height)
22                 : m_current(0), m_bar_xpos(0)
23         {
24                 auto format = PixelFormat::XRGB8888;
25                 m_fbs[0] = new DumbFramebuffer(card, width, height, format);
26                 m_fbs[1] = new DumbFramebuffer(card, width, height, format);
27         }
29         ~Flipper()
30         {
31                 delete m_fbs[0];
32                 delete m_fbs[1];
33         }
35         Framebuffer* get_next()
36         {
37                 m_current ^= 1;
39                 const int bar_width = 20;
40                 const int bar_speed = 8;
42                 auto fb = m_fbs[m_current];
44                 int current_xpos = m_bar_xpos;
45                 int old_xpos = (current_xpos + (fb->width() - bar_width - bar_speed)) % (fb->width() - bar_width);
46                 int new_xpos = (current_xpos + bar_speed) % (fb->width() - bar_width);
48                 draw_color_bar(*fb, old_xpos, new_xpos, bar_width);
50                 m_bar_xpos = new_xpos;
52                 return fb;
53         }
55 private:
56         DumbFramebuffer* m_fbs[2];
58         int m_current;
59         int m_bar_xpos;
60 };
62 class OutputFlipHandler : private PageFlipHandlerBase
63 {
64 public:
65         OutputFlipHandler(Connector* conn, Crtc* crtc, const Videomode& mode)
66                 : m_connector(conn), m_crtc(crtc), m_mode(mode),
67                   m_flipper(conn->card(), mode.hdisplay, mode.vdisplay),
68                   m_plane(0), m_plane_flipper(0)
69         {
70         }
72         OutputFlipHandler(Connector* conn, Crtc* crtc, const Videomode& mode,
73                           Plane* plane, unsigned pwidth, unsigned pheight)
74                 : m_connector(conn), m_crtc(crtc), m_mode(mode),
75                   m_flipper(conn->card(), mode.hdisplay, mode.vdisplay),
76                   m_plane(plane)
77         {
78                 m_plane_flipper = new Flipper(conn->card(), pwidth, pheight);
79         }
81         ~OutputFlipHandler()
82         {
83                 if (m_plane_flipper)
84                         delete m_plane_flipper;
85         }
87         OutputFlipHandler(const OutputFlipHandler& other) = delete;
88         OutputFlipHandler& operator=(const OutputFlipHandler& other) = delete;
90         void set_mode()
91         {
92                 auto mode = m_connector->get_default_mode();
93                 auto fb = m_flipper.get_next();
94                 int r = m_crtc->set_mode(m_connector, *fb, mode);
95                 ASSERT(r == 0);
97                 if (m_plane) {
98                         auto planefb = m_plane_flipper->get_next();
99                         r = m_crtc->set_plane(m_plane, *planefb,
100                                               0, 0, planefb->width(), planefb->height(),
101                                               0, 0, planefb->width(), planefb->height());
102                         ASSERT(r == 0);
103                 }
104         }
106         void start_flipping()
107         {
108                 m_t1 = std::chrono::steady_clock::now();
109                 m_frame_num = 0;
110                 queue_next();
111         }
113 private:
114         void handle_page_flip(uint32_t frame, double time)
115         {
116                 ++m_frame_num;
118                 if (m_frame_num  % 100 == 0) {
119                         auto t2 = std::chrono::steady_clock::now();
120                         std::chrono::duration<float> fsec = t2 - m_t1;
121                         printf("Output %d: fps %f\n", m_connector->idx(), 100.0 / fsec.count());
122                         m_t1 = t2;
123                 }
125                 queue_next();
126         }
128         void queue_next()
129         {
130                 auto crtc = m_crtc;
131                 auto& card = crtc->card();
133                 auto fb = m_flipper.get_next();
134                 Framebuffer* planefb = m_plane ? m_plane_flipper->get_next() : 0;
136                 if (card.has_atomic()) {
137                         int r;
139                         AtomicReq req(card);
141                         req.add(m_crtc, "FB_ID", fb->id());
142                         if (m_plane)
143                                 req.add(m_plane, "FB_ID", planefb->id());
145                         r = req.test();
146                         ASSERT(r == 0);
148                         r = req.commit(this);
149                         ASSERT(r == 0);
150                 } else {
151                         int r = crtc->page_flip(*fb, this);
152                         ASSERT(r == 0);
154                         if (m_plane) {
155                                 r = m_crtc->set_plane(m_plane, *planefb,
156                                                       0, 0, planefb->width(), planefb->height(),
157                                                       0, 0, planefb->width(), planefb->height());
158                                 ASSERT(r == 0);
159                         }
160                 }
161         }
163 private:
164         Connector* m_connector;
165         Crtc* m_crtc;
166         Videomode m_mode;
168         int m_frame_num;
169         chrono::steady_clock::time_point m_t1;
171         Flipper m_flipper;
173         Plane* m_plane;
174         Flipper* m_plane_flipper;
175 };
177 int main()
179         Card card;
181         if (card.master() == false)
182                 printf("Not DRM master, modeset may fail\n");
184         vector<OutputFlipHandler*> outputs;
186         for (auto pipe : card.get_connected_pipelines())
187         {
188                 auto conn = pipe.connector;
189                 auto crtc = pipe.crtc;
190                 auto mode = conn->get_default_mode();
193                 Plane* plane = 0;
194 #if 0 // disable the plane for now
195                 for (Plane* p : crtc->get_possible_planes()) {
196                         if (p->plane_type() == PlaneType::Overlay) {
197                                 plane = p;
198                                 break;
199                         }
200                 }
201 #endif
202                 OutputFlipHandler* output;
203                 if (plane)
204                         output = new OutputFlipHandler(conn, crtc, mode, plane, 500, 400);
205                 else
206                         output = new OutputFlipHandler(conn, crtc, mode);
207                 outputs.push_back(output);
208         }
210         for(auto out : outputs)
211                 out->set_mode();
213         for(auto out : outputs)
214                 out->start_flipping();
216         main_loop(card);
218         for(auto out : outputs)
219                 delete out;
222 static void main_loop(Card& card)
224         fd_set fds;
226         FD_ZERO(&fds);
228         int fd = card.fd();
230         printf("press enter to exit\n");
232         while (true) {
233                 int r;
235                 FD_SET(0, &fds);
236                 FD_SET(fd, &fds);
238                 r = select(fd + 1, &fds, NULL, NULL, NULL);
239                 if (r < 0) {
240                         fprintf(stderr, "select() failed with %d: %m\n", errno);
241                         break;
242                 } else if (FD_ISSET(0, &fds)) {
243                         fprintf(stderr, "exit due to user-input\n");
244                         break;
245                 } else if (FD_ISSET(fd, &fds)) {
246                         card.call_page_flip_handlers();
247                 }
248         }