Add OmapCard and OmapFramebuffer
[android/external-libkmsxx.git] / kms++ / src / omap / omapframebuffer.cpp
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, PixelFormat format)
26         : MappedFramebuffer(card, width, height), m_omap_card(card), m_format(format)
27 {
28         Create();
29 }
31 OmapFramebuffer::~OmapFramebuffer()
32 {
33         Destroy();
34 }
36 void OmapFramebuffer::Create()
37 {
38         const PixelFormatInfo& format_info = get_pixel_format_info(m_format);
40         m_num_planes = format_info.num_planes;
42         for (int i = 0; i < format_info.num_planes; ++i) {
43                 const PixelFormatPlaneInfo& pi = format_info.planes[i];
44                 FramebufferPlane& plane = m_planes[i];
46                 uint32_t flags = OMAP_BO_SCANOUT | OMAP_BO_WC;
48                 uint32_t size = width() * height() * pi.bitspp / 8;
50                 struct omap_bo* bo =  omap_bo_new(m_omap_card.dev(), size, flags);
51                 if (!bo)
52                         throw invalid_argument(string("omap_bo_new failed: ") + strerror(errno));
54                 uint32_t stride = width() * pi.bitspp / 8;
56                 plane.omap_bo = bo;
57                 plane.handle = omap_bo_handle(bo);
58                 plane.stride = stride;
59                 plane.size = omap_bo_size(bo);
60                 plane.offset = 0;
61                 plane.map = 0;
62                 plane.prime_fd = -1;
63         }
65         /* create framebuffer object for the dumb-buffer */
66         uint32_t bo_handles[4] = { m_planes[0].handle, m_planes[1].handle };
67         uint32_t pitches[4] = { m_planes[0].stride, m_planes[1].stride };
68         uint32_t offsets[4] = { m_planes[0].offset, m_planes[1].offset };
69         uint32_t id;
70         int r = drmModeAddFB2(card().fd(), width(), height(), (uint32_t)format(),
71                           bo_handles, pitches, offsets, &id, 0);
72         if (r)
73                 throw invalid_argument(string("drmModeAddFB2 failed: ") + strerror(errno));
75         set_id(id);
76 }
78 void OmapFramebuffer::Destroy()
79 {
80         drmModeRmFB(card().fd(), id());
82         for (uint i = 0; i < m_num_planes; ++i) {
83                 FramebufferPlane& plane = m_planes[i];
85                 /* unmap buffer */
86                 if (plane.map)
87                         munmap(plane.map, plane.size);
89                 omap_bo_del(plane.omap_bo);
91                 if (plane.prime_fd >= 0)
92                         ::close(plane.prime_fd);
93         }
94 }
96 uint8_t* OmapFramebuffer::map(unsigned plane)
97 {
98         FramebufferPlane& p = m_planes[plane];
100         if (p.map)
101                 return p.map;
103         p.map = (uint8_t*)omap_bo_map(p.omap_bo);
104         if (p.map == MAP_FAILED)
105                 throw invalid_argument(string("mmap failed: ") + strerror(errno));
107         return p.map;
110 int OmapFramebuffer::prime_fd(unsigned int plane)
112         FramebufferPlane& p = m_planes[plane];
114         if (p.prime_fd >= 0)
115                 return p.prime_fd;
117         int fd = omap_bo_dmabuf(p.omap_bo);
118         if (fd < 0)
119                 throw std::runtime_error("omap_bo_dmabuf failed\n");
121         p.prime_fd = fd;
123         return fd;