e1e2234a49985e3baec60da0863b3245519c1d66
2 #include <cstring>
3 #include <stdexcept>
4 #include <sys/mman.h>
5 #include <xf86drm.h>
6 #include <xf86drmMode.h>
7 #include <fcntl.h>
8 #include <unistd.h>
9 #include <drm_fourcc.h>
10 #include <drm.h>
11 #include <drm_mode.h>
13 #include <kms++/kms++.h>
14 #include <kms++/omap/omapkms++.h>
16 extern "C" {
17 #include <omap_drmif.h>
18 }
20 using namespace std;
22 namespace kms
23 {
25 OmapFramebuffer::OmapFramebuffer(OmapCard& card, uint32_t width, uint32_t height, const string& fourcc)
26 : OmapFramebuffer(card, width, height, FourCCToPixelFormat(fourcc))
27 {
28 }
30 OmapFramebuffer::OmapFramebuffer(OmapCard& card, uint32_t width, uint32_t height, PixelFormat format)
31 : MappedFramebuffer(card, width, height), m_omap_card(card), m_format(format)
32 {
33 Create();
34 }
36 OmapFramebuffer::~OmapFramebuffer()
37 {
38 Destroy();
39 }
41 void OmapFramebuffer::Create()
42 {
43 const PixelFormatInfo& format_info = get_pixel_format_info(m_format);
45 m_num_planes = format_info.num_planes;
47 for (int i = 0; i < format_info.num_planes; ++i) {
48 const PixelFormatPlaneInfo& pi = format_info.planes[i];
49 FramebufferPlane& plane = m_planes[i];
51 uint32_t flags = OMAP_BO_SCANOUT | OMAP_BO_WC;
53 uint32_t size = width() * height() * pi.bitspp / 8;
55 struct omap_bo* bo = omap_bo_new(m_omap_card.dev(), size, flags);
56 if (!bo)
57 throw invalid_argument(string("omap_bo_new failed: ") + strerror(errno));
59 uint32_t stride = width() * pi.bitspp / 8;
61 plane.omap_bo = bo;
62 plane.handle = omap_bo_handle(bo);
63 plane.stride = stride;
64 plane.size = omap_bo_size(bo);
65 plane.offset = 0;
66 plane.map = 0;
67 plane.prime_fd = -1;
68 }
70 /* create framebuffer object for the dumb-buffer */
71 uint32_t bo_handles[4] = { m_planes[0].handle, m_planes[1].handle };
72 uint32_t pitches[4] = { m_planes[0].stride, m_planes[1].stride };
73 uint32_t offsets[4] = { m_planes[0].offset, m_planes[1].offset };
74 uint32_t id;
75 int r = drmModeAddFB2(card().fd(), width(), height(), (uint32_t)format(),
76 bo_handles, pitches, offsets, &id, 0);
77 if (r)
78 throw invalid_argument(string("drmModeAddFB2 failed: ") + strerror(errno));
80 set_id(id);
81 }
83 void OmapFramebuffer::Destroy()
84 {
85 drmModeRmFB(card().fd(), id());
87 for (uint i = 0; i < m_num_planes; ++i) {
88 FramebufferPlane& plane = m_planes[i];
90 /* unmap buffer */
91 if (plane.map)
92 munmap(plane.map, plane.size);
94 omap_bo_del(plane.omap_bo);
96 if (plane.prime_fd >= 0)
97 ::close(plane.prime_fd);
98 }
99 }
101 uint8_t* OmapFramebuffer::map(unsigned plane)
102 {
103 FramebufferPlane& p = m_planes[plane];
105 if (p.map)
106 return p.map;
108 p.map = (uint8_t*)omap_bo_map(p.omap_bo);
109 if (p.map == MAP_FAILED)
110 throw invalid_argument(string("mmap failed: ") + strerror(errno));
112 return p.map;
113 }
115 int OmapFramebuffer::prime_fd(unsigned int plane)
116 {
117 FramebufferPlane& p = m_planes[plane];
119 if (p.prime_fd >= 0)
120 return p.prime_fd;
122 int fd = omap_bo_dmabuf(p.omap_bo);
123 if (fd < 0)
124 throw std::runtime_error("omap_bo_dmabuf failed\n");
126 p.prime_fd = fd;
128 return fd;
129 }
131 }