Changeset View
Changeset View
Standalone View
Standalone View
plugins/platforms/drm/drm_buffer.cpp
Show All 21 Lines | |||||
22 | 22 | | |||
23 | #include "logging.h" | 23 | #include "logging.h" | ||
24 | 24 | | |||
25 | // system | 25 | // system | ||
26 | #include <sys/mman.h> | 26 | #include <sys/mman.h> | ||
27 | #include <errno.h> | 27 | #include <errno.h> | ||
28 | // drm | 28 | // drm | ||
29 | #include <xf86drm.h> | 29 | #include <xf86drm.h> | ||
30 | #if HAVE_GBM | | |||
31 | #include <gbm.h> | | |||
32 | #endif | | |||
33 | 30 | | |||
34 | namespace KWin | 31 | namespace KWin | ||
35 | { | 32 | { | ||
36 | 33 | | |||
37 | 34 | DrmBuffer:: DrmBuffer(DrmBackend *backend) | |||
38 | DrmBuffer::DrmBuffer(DrmBackend *backend, const QSize &size) | | |||
39 | : m_backend(backend) | 35 | : m_backend(backend) | ||
40 | , m_size(size) | | |||
41 | { | 36 | { | ||
37 | } | ||||
38 | | ||||
39 | // DrmDumbBuffer | ||||
40 | DrmDumbBuffer::DrmDumbBuffer(DrmBackend *backend, const QSize &size) | ||||
41 | : DrmBuffer(backend) | ||||
42 | { | ||||
43 | m_size = size; | ||||
42 | drm_mode_create_dumb createArgs; | 44 | drm_mode_create_dumb createArgs; | ||
43 | memset(&createArgs, 0, sizeof createArgs); | 45 | memset(&createArgs, 0, sizeof createArgs); | ||
44 | createArgs.bpp = 32; | 46 | createArgs.bpp = 32; | ||
45 | createArgs.width = size.width(); | 47 | createArgs.width = size.width(); | ||
46 | createArgs.height = size.height(); | 48 | createArgs.height = size.height(); | ||
47 | if (drmIoctl(m_backend->fd(), DRM_IOCTL_MODE_CREATE_DUMB, &createArgs) != 0) { | 49 | if (drmIoctl(m_backend->fd(), DRM_IOCTL_MODE_CREATE_DUMB, &createArgs) != 0) { | ||
48 | qCWarning(KWIN_DRM) << "DRM_IOCTL_MODE_CREATE_DUMB failed"; | 50 | qCWarning(KWIN_DRM) << "DRM_IOCTL_MODE_CREATE_DUMB failed"; | ||
49 | return; | 51 | return; | ||
50 | } | 52 | } | ||
51 | m_handle = createArgs.handle; | 53 | m_handle = createArgs.handle; | ||
52 | m_bufferSize = createArgs.size; | 54 | m_bufferSize = createArgs.size; | ||
53 | m_stride = createArgs.pitch; | 55 | m_stride = createArgs.pitch; | ||
54 | if (drmModeAddFB(m_backend->fd(), size.width(), size.height(), 24, 32, | 56 | if (drmModeAddFB(m_backend->fd(), size.width(), size.height(), 24, 32, | ||
55 | m_stride, createArgs.handle, &m_bufferId) != 0) { | 57 | m_stride, createArgs.handle, &m_bufferId) != 0) { | ||
56 | qCWarning(KWIN_DRM) << "drmModeAddFB failed with errno" << errno; | 58 | qCWarning(KWIN_DRM) << "drmModeAddFB failed with errno" << errno; | ||
57 | } | 59 | } | ||
58 | } | 60 | } | ||
59 | 61 | | |||
60 | 62 | DrmDumbBuffer::~DrmDumbBuffer() | |||
61 | #if HAVE_GBM | | |||
62 | static void gbmCallback(gbm_bo *bo, void *data) | | |||
63 | { | | |||
64 | DrmBackend *backend = reinterpret_cast<DrmBackend*>(data); | | |||
65 | const auto &buffers = backend->buffers(); | | |||
66 | for (auto buffer: buffers) { | | |||
67 | if (buffer->gbm() == bo) { | | |||
68 | delete buffer; | | |||
69 | return; | | |||
70 | } | | |||
71 | } | | |||
72 | } | | |||
73 | #endif | | |||
74 | | ||||
75 | DrmBuffer::DrmBuffer(DrmBackend *backend, gbm_surface *surface) | | |||
76 | : m_backend(backend) | | |||
77 | , m_surface(surface) | | |||
78 | { | | |||
79 | #if HAVE_GBM | | |||
80 | m_bo = gbm_surface_lock_front_buffer(surface); | | |||
81 | if (!m_bo) { | | |||
82 | qCWarning(KWIN_DRM) << "Locking front buffer failed"; | | |||
83 | return; | | |||
84 | } | | |||
85 | m_size = QSize(gbm_bo_get_width(m_bo), gbm_bo_get_height(m_bo)); | | |||
86 | m_stride = gbm_bo_get_stride(m_bo); | | |||
87 | if (drmModeAddFB(m_backend->fd(), m_size.width(), m_size.height(), 24, 32, m_stride, gbm_bo_get_handle(m_bo).u32, &m_bufferId) != 0) { | | |||
88 | qCWarning(KWIN_DRM) << "drmModeAddFB failed"; | | |||
89 | } | | |||
90 | gbm_bo_set_user_data(m_bo, m_backend, gbmCallback); | | |||
91 | #endif | | |||
92 | } | | |||
93 | | ||||
94 | DrmBuffer::~DrmBuffer() | | |||
95 | { | 63 | { | ||
96 | if (m_bufferId) { | 64 | if (m_bufferId) { | ||
97 | drmModeRmFB(m_backend->fd(), m_bufferId); | 65 | drmModeRmFB(m_backend->fd(), m_bufferId); | ||
98 | } | 66 | } | ||
99 | m_backend->bufferDestroyed(this); | 67 | | ||
100 | delete m_image; | 68 | delete m_image; | ||
101 | if (m_memory) { | 69 | if (m_memory) { | ||
102 | munmap(m_memory, m_bufferSize); | 70 | munmap(m_memory, m_bufferSize); | ||
103 | } | 71 | } | ||
104 | if (m_handle) { | 72 | if (m_handle) { | ||
105 | drm_mode_destroy_dumb destroyArgs; | 73 | drm_mode_destroy_dumb destroyArgs; | ||
106 | destroyArgs.handle = m_handle; | 74 | destroyArgs.handle = m_handle; | ||
107 | drmIoctl(m_backend->fd(), DRM_IOCTL_MODE_DESTROY_DUMB, &destroyArgs); | 75 | drmIoctl(m_backend->fd(), DRM_IOCTL_MODE_DESTROY_DUMB, &destroyArgs); | ||
108 | } | 76 | } | ||
109 | releaseGbm(); | | |||
110 | } | 77 | } | ||
111 | 78 | | |||
112 | bool DrmBuffer::map(QImage::Format format) | 79 | bool DrmDumbBuffer::needsModeChange(DrmBuffer *b) const { | ||
80 | if (DrmDumbBuffer *db = dynamic_cast<DrmDumbBuffer*>(b)) { | ||||
81 | return m_stride != db->stride(); | ||||
82 | } else { | ||||
83 | return true; | ||||
84 | } | ||||
85 | } | ||||
86 | | ||||
87 | bool DrmDumbBuffer::map(QImage::Format format) | ||||
113 | { | 88 | { | ||
114 | if (!m_handle || !m_bufferId) { | 89 | if (!m_handle || !m_bufferId) { | ||
115 | return false; | 90 | return false; | ||
116 | } | 91 | } | ||
117 | drm_mode_map_dumb mapArgs; | 92 | drm_mode_map_dumb mapArgs; | ||
118 | memset(&mapArgs, 0, sizeof mapArgs); | 93 | memset(&mapArgs, 0, sizeof mapArgs); | ||
119 | mapArgs.handle = m_handle; | 94 | mapArgs.handle = m_handle; | ||
120 | if (drmIoctl(m_backend->fd(), DRM_IOCTL_MODE_MAP_DUMB, &mapArgs) != 0) { | 95 | if (drmIoctl(m_backend->fd(), DRM_IOCTL_MODE_MAP_DUMB, &mapArgs) != 0) { | ||
121 | return false; | 96 | return false; | ||
122 | } | 97 | } | ||
123 | void *address = mmap(nullptr, m_bufferSize, PROT_WRITE, MAP_SHARED, m_backend->fd(), mapArgs.offset); | 98 | void *address = mmap(nullptr, m_bufferSize, PROT_WRITE, MAP_SHARED, m_backend->fd(), mapArgs.offset); | ||
124 | if (address == MAP_FAILED) { | 99 | if (address == MAP_FAILED) { | ||
125 | return false; | 100 | return false; | ||
126 | } | 101 | } | ||
127 | m_memory = address; | 102 | m_memory = address; | ||
128 | m_image = new QImage((uchar*)m_memory, m_size.width(), m_size.height(), m_stride, format); | 103 | m_image = new QImage((uchar*)m_memory, m_size.width(), m_size.height(), m_stride, format); | ||
129 | return !m_image->isNull(); | 104 | return !m_image->isNull(); | ||
130 | } | 105 | } | ||
131 | 106 | | |||
132 | void DrmBuffer::releaseGbm() | | |||
133 | { | | |||
134 | #if HAVE_GBM | | |||
135 | if (m_bo) { | | |||
136 | gbm_surface_release_buffer(m_surface, m_bo); | | |||
137 | m_bo = nullptr; | | |||
138 | } | | |||
139 | #endif | | |||
140 | } | | |||
141 | | ||||
142 | } | 107 | } |