From 5c020532fa63a6686047537fa368b15b195208ee Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 26 Apr 2016 11:54:40 +0300 Subject: kmacapture: atomic modesetting support --- tests/kmscapture.cpp | 64 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 15 deletions(-) diff --git a/tests/kmscapture.cpp b/tests/kmscapture.cpp index 4e81003..965d32e 100644 --- a/tests/kmscapture.cpp +++ b/tests/kmscapture.cpp @@ -27,7 +27,7 @@ enum class BufferProvider { class CameraPipeline { public: - CameraPipeline(int cam_fd, Card& card, Plane* plane, uint32_t x, uint32_t y, + CameraPipeline(int cam_fd, Card& card, Crtc* crtc, Plane* plane, uint32_t x, uint32_t y, uint32_t iw, uint32_t ih, PixelFormat pixfmt, BufferProvider buffer_provider); ~CameraPipeline(); @@ -35,11 +35,12 @@ public: CameraPipeline(const CameraPipeline& other) = delete; CameraPipeline& operator=(const CameraPipeline& other) = delete; - void show_next_frame(Crtc* crtc); + void show_next_frame(AtomicReq &req); int fd() const { return m_fd; } private: ExtFramebuffer* GetExtFrameBuffer(Card& card, uint32_t i, PixelFormat pixfmt); int m_fd; /* camera file descriptor */ + Crtc* m_crtc; Plane* m_plane; BufferProvider m_buffer_provider; vector m_fb; /* framebuffers for DRM buffers */ @@ -101,11 +102,12 @@ bool inline better_size(struct v4l2_frmsize_discrete* v4ldisc, return false; } -CameraPipeline::CameraPipeline(int cam_fd, Card& card, Plane* plane, uint32_t x, uint32_t y, +CameraPipeline::CameraPipeline(int cam_fd, Card& card, Crtc *crtc, Plane* plane, uint32_t x, uint32_t y, uint32_t iw, uint32_t ih, PixelFormat pixfmt, BufferProvider buffer_provider) - : m_fd(cam_fd), m_buffer_provider(buffer_provider) + : m_fd(cam_fd), m_crtc(crtc), m_buffer_provider(buffer_provider), m_prev_fb_index(-1) { + int r; uint32_t best_w = 320; uint32_t best_h = 240; @@ -183,13 +185,39 @@ CameraPipeline::CameraPipeline(int cam_fd, Card& card, Plane* plane, uint32_t x, else m_fb.push_back(fb); } - m_prev_fb_index = -1; + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; r = ioctl(m_fd, VIDIOC_STREAMON, &type); ASSERT(r == 0); m_plane = plane; + + // Do initial plane setup with first fb, so that we only need to + // set the FB when page flipping + AtomicReq req(card); + + Framebuffer *fb; + if (m_buffer_provider == BufferProvider::V4L2) + fb = m_extfb[0]; + else + fb = m_fb[0]; + + req.add(m_plane, "CRTC_ID", m_crtc->id()); + req.add(m_plane, "FB_ID", fb->id()); + + req.add(m_plane, "CRTC_X", m_out_x); + req.add(m_plane, "CRTC_Y", m_out_y); + req.add(m_plane, "CRTC_W", m_out_width); + req.add(m_plane, "CRTC_H", m_out_height); + + req.add(m_plane, "SRC_X", 0); + req.add(m_plane, "SRC_Y", 0); + req.add(m_plane, "SRC_W", m_in_width << 16); + req.add(m_plane, "SRC_H", m_in_height << 16); + + r = req.commit_sync(); + FAIL_IF(r, "initial plane setup failed"); } @@ -204,7 +232,7 @@ CameraPipeline::~CameraPipeline() ::close(m_fd); } -void CameraPipeline::show_next_frame(Crtc* crtc) +void CameraPipeline::show_next_frame(AtomicReq& req) { int r; uint32_t v4l_mem; @@ -224,16 +252,14 @@ void CameraPipeline::show_next_frame(Crtc* crtc) } unsigned fb_index = v4l2buf.index; + + Framebuffer *fb; if (m_buffer_provider == BufferProvider::V4L2) - r = crtc->set_plane(m_plane, *m_extfb[fb_index], - m_out_x, m_out_y, m_out_width, m_out_height, - 0, 0, m_in_width, m_in_height); + fb = m_extfb[fb_index]; else - r = crtc->set_plane(m_plane, *m_fb[fb_index], - m_out_x, m_out_y, m_out_width, m_out_height, - 0, 0, m_in_width, m_in_height); + fb = m_fb[fb_index]; - ASSERT(r == 0); + req.add(m_plane, "FB_ID", fb->id()); if (m_prev_fb_index >= 0) { memset(&v4l2buf, 0, sizeof(v4l2buf)); @@ -246,6 +272,7 @@ void CameraPipeline::show_next_frame(Crtc* crtc) ASSERT(r == 0); } + m_prev_fb_index = fb_index; } @@ -359,7 +386,7 @@ int main(int argc, char** argv) int cam_fd = camera_fds[i]; Plane* plane = available_planes[i]; - auto cam = new CameraPipeline(cam_fd, card, plane, i * plane_w, 0, + auto cam = new CameraPipeline(cam_fd, card, crtc, plane, i * plane_w, 0, plane_w, crtc->height(), pixfmt, buffer_provider); cameras.push_back(cam); } @@ -382,12 +409,19 @@ int main(int argc, char** argv) if (fds[nr_cameras].revents != 0) break; + AtomicReq req(card); + for (unsigned i = 0; i < nr_cameras; i++) { if (!fds[i].revents) continue; - cameras[i]->show_next_frame(crtc); + cameras[i]->show_next_frame(req); fds[i].revents = 0; } + + r = req.test(); + FAIL_IF(r, "Atomic commit failed: %d", r); + + req.commit(); } for (auto cam : cameras) -- cgit v1.2.3