diff --git a/tests/db.cpp b/tests/db.cpp
index 468a4cca385477af383c8e6e65695a64e5ad7671..6131263e63b148b5602e5f13c81c39454f11f92c 100644 (file)
--- a/tests/db.cpp
+++ b/tests/db.cpp
#include <cstdio>
#include <algorithm>
+#include <chrono>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <drm_fourcc.h>
#include "kms++.h"
-#include "utils/color.h"
#include "test.h"
using namespace std;
using namespace kms;
-static void draw_color_bar(Framebuffer& buf, int old_xpos, int xpos, int width);
-
static void main_loop(Card& card);
-#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
-
-struct Output
+class Flipper
{
- Connector* connector;
- Crtc* crtc;
- Framebuffer* fbs[2];
+public:
+ Flipper(Card& card, unsigned width, unsigned height)
+ : m_current(0), m_bar_xpos(0)
+ {
+ auto format = PixelFormat::XRGB8888;
+ m_fbs[0] = new DumbFramebuffer(card, width, height, format);
+ m_fbs[1] = new DumbFramebuffer(card, width, height, format);
+ }
- int front_buf;
- int bar_xpos;
-};
+ ~Flipper()
+ {
+ delete m_fbs[0];
+ delete m_fbs[1];
+ }
-static void do_flip(Output* out);
+ Framebuffer* get_next()
+ {
+ m_current ^= 1;
-int main()
-{
- Card card;
+ const int bar_width = 20;
+ const int bar_speed = 8;
- if (card.master() == false)
- printf("Not DRM master, modeset may fail\n");
+ auto fb = m_fbs[m_current];
- //card.print_short();
+ int current_xpos = m_bar_xpos;
+ int old_xpos = (current_xpos + (fb->width() - bar_width - bar_speed)) % (fb->width() - bar_width);
+ int new_xpos = (current_xpos + bar_speed) % (fb->width() - bar_width);
- vector<Output> outputs;
+ draw_color_bar(*fb, old_xpos, new_xpos, bar_width);
- for (auto conn : card.get_connectors())
- {
- if (conn->connected() == false)
- continue;
+ m_bar_xpos = new_xpos;
- auto mode = conn->get_default_mode();
+ return fb;
+ }
- Crtc* crtc = conn->get_current_crtc();
- if (!crtc) {
- for (auto c : conn->get_possible_crtcs()) {
- if (find_if(outputs.begin(), outputs.end(), [c](Output o) { return o.crtc == c; }) == outputs.end()) {
- crtc = c;
- break;
- }
- }
- }
+private:
+ DumbFramebuffer* m_fbs[2];
- if (!crtc) {
- printf("failed to find crtc\n");
- return -1;
- }
+ int m_current;
+ int m_bar_xpos;
+};
- auto fb1 = new Framebuffer(card, mode.hdisplay, mode.vdisplay, "XR24");
- auto fb2 = new Framebuffer(card, mode.hdisplay, mode.vdisplay, "XR24");
+class OutputFlipHandler : private PageFlipHandlerBase
+{
+public:
+ OutputFlipHandler(Connector* conn, Crtc* crtc, const Videomode& mode)
+ : m_connector(conn), m_crtc(crtc), m_mode(mode),
+ m_flipper(conn->card(), mode.hdisplay, mode.vdisplay),
+ m_plane(0), m_plane_flipper(0)
+ {
+ }
- printf("conn %u, crtc %u, fb1 %u, fb2 %u\n", conn->id(), crtc->id(), fb1->id(), fb2->id());
+ OutputFlipHandler(Connector* conn, Crtc* crtc, const Videomode& mode,
+ Plane* plane, unsigned pwidth, unsigned pheight)
+ : m_connector(conn), m_crtc(crtc), m_mode(mode),
+ m_flipper(conn->card(), mode.hdisplay, mode.vdisplay),
+ m_plane(plane)
+ {
+ m_plane_flipper = new Flipper(conn->card(), pwidth, pheight);
+ }
- Output output = { };
- output.connector = conn;
- output.crtc = crtc;
- output.fbs[0] = fb1;
- output.fbs[1] = fb2;
- outputs.push_back(output);
+ ~OutputFlipHandler()
+ {
+ if (m_plane_flipper)
+ delete m_plane_flipper;
}
- for(auto& out : outputs) {
- auto conn = out.connector;
- auto crtc = out.crtc;
+ OutputFlipHandler(const OutputFlipHandler& other) = delete;
+ OutputFlipHandler& operator=(const OutputFlipHandler& other) = delete;
- auto mode = conn->get_default_mode();
- int r = crtc->set_mode(conn, *out.fbs[0], mode);
+ void set_mode()
+ {
+ auto mode = m_connector->get_default_mode();
+ auto fb = m_flipper.get_next();
+ int r = m_crtc->set_mode(m_connector, *fb, mode);
ASSERT(r == 0);
+
+ if (m_plane) {
+ auto planefb = m_plane_flipper->get_next();
+ r = m_crtc->set_plane(m_plane, *planefb,
+ 0, 0, planefb->width(), planefb->height(),
+ 0, 0, planefb->width(), planefb->height());
+ ASSERT(r == 0);
+ }
}
- for(auto& out : outputs)
- do_flip(&out);
+ void start_flipping()
+ {
+ m_t1 = std::chrono::steady_clock::now();
+ m_frame_num = 0;
+ queue_next();
+ }
- main_loop(card);
+private:
+ void handle_page_flip(uint32_t frame, double time)
+ {
+ ++m_frame_num;
- for(auto& out : outputs) {
- delete out.fbs[0];
- delete out.fbs[1];
+ if (m_frame_num % 100 == 0) {
+ auto t2 = std::chrono::steady_clock::now();
+ std::chrono::duration<float> fsec = t2 - m_t1;
+ printf("Output %d: fps %f\n", m_connector->idx(), 100.0 / fsec.count());
+ m_t1 = t2;
+ }
+
+ queue_next();
}
-}
-static void do_flip(Output* out)
-{
- const int bar_width = 20;
- const int bar_speed = 8;
+ void queue_next()
+ {
+ auto crtc = m_crtc;
+ auto& card = crtc->card();
- auto crtc = out->crtc;
- auto fb = out->fbs[(out->front_buf + 1) % 2];
+ auto fb = m_flipper.get_next();
+ Framebuffer* planefb = m_plane ? m_plane_flipper->get_next() : 0;
- ASSERT(crtc);
- ASSERT(fb);
+ if (card.has_atomic()) {
+ int r;
- int current_xpos = out->bar_xpos;
- int old_xpos = (current_xpos + (fb->width() - bar_width - bar_speed)) % (fb->width() - bar_width);
- int new_xpos = (current_xpos + bar_speed) % (fb->width() - bar_width);
+ AtomicReq req(card);
- draw_color_bar(*fb, old_xpos, new_xpos, bar_width);
+ req.add(m_crtc, "FB_ID", fb->id());
+ if (m_plane)
+ req.add(m_plane, "FB_ID", planefb->id());
- out->bar_xpos = new_xpos;
+ r = req.test();
+ ASSERT(r == 0);
- auto& card = crtc->card();
+ r = req.commit(this);
+ ASSERT(r == 0);
+ } else {
+ int r = crtc->page_flip(*fb, this);
+ ASSERT(r == 0);
- if (card.has_atomic()) {
- int r;
+ if (m_plane) {
+ r = m_crtc->set_plane(m_plane, *planefb,
+ 0, 0, planefb->width(), planefb->height(),
+ 0, 0, planefb->width(), planefb->height());
+ ASSERT(r == 0);
+ }
+ }
+ }
- AtomicReq ctx(card);
+private:
+ Connector* m_connector;
+ Crtc* m_crtc;
+ Videomode m_mode;
- ctx.add(crtc, card.get_prop("FB_ID"), fb->id());
+ int m_frame_num;
+ chrono::steady_clock::time_point m_t1;
- r = ctx.test();
- ASSERT(r == 0);
+ Flipper m_flipper;
- r = ctx.commit(out);
- ASSERT(r == 0);
- } else {
- int r = drmModePageFlip(card.fd(), crtc->id(), fb->id(), DRM_MODE_PAGE_FLIP_EVENT, out);
- ASSERT(r == 0);
- }
-}
+ Plane* m_plane;
+ Flipper* m_plane_flipper;
+};
-static void page_flip_handler(int fd, unsigned int frame,
- unsigned int sec, unsigned int usec,
- void *data)
+int main()
{
- //printf("flip event %d, %d, %u, %u, %p\n", fd, frame, sec, usec, data);
+ Card card;
- auto out = (Output*)data;
+ if (card.master() == false)
+ printf("Not DRM master, modeset may fail\n");
- out->front_buf = (out->front_buf + 1) % 2;
+ //card.print_short();
- do_flip(out);
-}
+ vector<OutputFlipHandler*> outputs;
+
+ for (auto pipe : card.get_connected_pipelines())
+ {
+ auto conn = pipe.connector;
+ auto crtc = pipe.crtc;
+ auto mode = conn->get_default_mode();
+
+
+ Plane* plane = 0;
+#if 0 // disable the plane for now
+ for (Plane* p : crtc->get_possible_planes()) {
+ if (p->plane_type() == PlaneType::Overlay) {
+ plane = p;
+ break;
+ }
+ }
+#endif
+ OutputFlipHandler* output;
+ if (plane)
+ output = new OutputFlipHandler(conn, crtc, mode, plane, 500, 400);
+ else
+ output = new OutputFlipHandler(conn, crtc, mode);
+ outputs.push_back(output);
+ }
+
+ for(auto out : outputs)
+ out->set_mode();
+
+ for(auto out : outputs)
+ out->start_flipping();
+ main_loop(card);
+
+ for(auto out : outputs)
+ delete out;
+}
static void main_loop(Card& card)
{
- drmEventContext ev = {
- .version = DRM_EVENT_CONTEXT_VERSION,
- .vblank_handler = 0,
- .page_flip_handler = page_flip_handler,
- };
-
fd_set fds;
FD_ZERO(&fds);
fprintf(stderr, "exit due to user-input\n");
break;
} else if (FD_ISSET(fd, &fds)) {
- drmHandleEvent(fd, &ev);
+ card.call_page_flip_handlers();
}
}
}
-
-
-static const RGB colors32[] = {
- RGB(255, 255, 255),
- RGB(255, 0, 0),
- RGB(255, 255, 255),
- RGB(0, 255, 0),
- RGB(255, 255, 255),
- RGB(0, 0, 255),
- RGB(255, 255, 255),
- RGB(200, 200, 200),
- RGB(255, 255, 255),
- RGB(100, 100, 100),
- RGB(255, 255, 255),
- RGB(50, 50, 50),
-};
-
-static const uint16_t colors16[] = {
- colors32[0].rgb565(),
- colors32[1].rgb565(),
- colors32[2].rgb565(),
- colors32[3].rgb565(),
- colors32[4].rgb565(),
- colors32[5].rgb565(),
- colors32[6].rgb565(),
- colors32[7].rgb565(),
- colors32[8].rgb565(),
- colors32[9].rgb565(),
- colors32[10].rgb565(),
- colors32[11].rgb565(),
-};
-
-static void drm_draw_color_bar_rgb888(Framebuffer& buf, int old_xpos, int xpos, int width)
-{
- for (unsigned y = 0; y < buf.height(); ++y) {
- RGB bcol = colors32[y * ARRAY_SIZE(colors32) / buf.height()];
- uint32_t *line = (uint32_t*)(buf.map(0) + buf.stride(0) * y);
-
- if (old_xpos >= 0) {
- for (int x = old_xpos; x < old_xpos + width; ++x)
- line[x] = 0;
- }
-
- for (int x = xpos; x < xpos + width; ++x)
- line[x] = bcol.raw;
- }
-}
-
-static void drm_draw_color_bar_rgb565(Framebuffer& buf, int old_xpos, int xpos, int width)
-{
- static_assert(ARRAY_SIZE(colors32) == ARRAY_SIZE(colors16), "bad colors arrays");
-
- for (unsigned y = 0; y < buf.height(); ++y) {
- uint16_t bcol = colors16[y * ARRAY_SIZE(colors16) / buf.height()];
- uint16_t *line = (uint16_t*)(buf.map(0) + buf.stride(0) * y);
-
- if (old_xpos >= 0) {
- for (int x = old_xpos; x < old_xpos + width; ++x)
- line[x] = 0;
- }
-
- for (int x = xpos; x < xpos + width; ++x)
- line[x] = bcol;
- }
-}
-
-static void drm_draw_color_bar_semiplanar_yuv(Framebuffer& buf, int old_xpos, int xpos, int width)
-{
- const uint8_t colors[] = {
- 0xff,
- 0x00,
- 0xff,
- 0x20,
- 0xff,
- 0x40,
- 0xff,
- 0x80,
- 0xff,
- };
-
- for (unsigned y = 0; y < buf.height(); ++y) {
- unsigned int bcol = colors[y * ARRAY_SIZE(colors) / buf.height()];
- uint8_t *line = (uint8_t*)(buf.map(0) + buf.stride(0) * y);
-
- if (old_xpos >= 0) {
- for (int x = old_xpos; x < old_xpos + width; ++x)
- line[x] = 0;
- }
-
- for (int x = xpos; x < xpos + width; ++x)
- line[x] = bcol;
- }
-}
-
-static void draw_color_bar(Framebuffer& buf, int old_xpos, int xpos, int width)
-{
- switch (buf.format()) {
- case DRM_FORMAT_NV12:
- case DRM_FORMAT_NV21:
- // XXX not right but gets something on the screen
- drm_draw_color_bar_semiplanar_yuv(buf, old_xpos, xpos, width);
- break;
-
- case DRM_FORMAT_YUYV:
- case DRM_FORMAT_UYVY:
- // XXX not right but gets something on the screen
- drm_draw_color_bar_rgb565(buf, old_xpos, xpos, width);
- break;
-
- case DRM_FORMAT_RGB565:
- drm_draw_color_bar_rgb565(buf, old_xpos, xpos, width);
- break;
-
- case DRM_FORMAT_XRGB8888:
- drm_draw_color_bar_rgb888(buf, old_xpos, xpos, width);
- break;
-
- default:
- ASSERT(false);
- }
-}