21 #include "event_queue.h" 25 #include "wayland_pointer_p.h" 29 #include <QTemporaryFile> 34 #include <wayland-client-protocol.h> 41 class Q_DECL_HIDDEN ShmPool::Private
46 bool resizePool(int32_t newSize);
48 WaylandPointer<wl_shm, wl_shm_destroy> shm;
49 WaylandPointer<wl_shm_pool, wl_shm_pool_destroy> pool;
50 void *poolData =
nullptr;
56 EventQueue *queue =
nullptr;
61 ShmPool::Private::Private(ShmPool *q)
70 , d(new Private(this))
79 void ShmPool::release()
83 munmap(d->poolData, d->size);
84 d->poolData =
nullptr;
93 void ShmPool::destroy()
95 for (
auto b : d->buffers) {
100 munmap(d->poolData, d->size);
101 d->poolData =
nullptr;
110 void ShmPool::setup(wl_shm *shm)
115 d->valid = d->createPool();
128 bool ShmPool::Private::createPool()
130 if (!tmpFile->open()) {
131 qCDebug(KWAYLAND_CLIENT) <<
"Could not open temporary file for Shm pool";
134 if (unlink(tmpFile->fileName().toUtf8().constData()) != 0) {
135 qCDebug(KWAYLAND_CLIENT) <<
"Unlinking temporary file for Shm pool from file system failed";
137 if (ftruncate(tmpFile->handle(), size) < 0) {
138 qCDebug(KWAYLAND_CLIENT) <<
"Could not set size for Shm pool file";
141 poolData = mmap(
nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, tmpFile->handle(), 0);
142 pool.setup(wl_shm_create_pool(shm, tmpFile->handle(), size));
144 if (!poolData || !pool) {
145 qCDebug(KWAYLAND_CLIENT) <<
"Creating Shm pool failed";
151 bool ShmPool::Private::resizePool(int32_t newSize)
153 if (ftruncate(tmpFile->handle(), newSize) < 0) {
154 qCDebug(KWAYLAND_CLIENT) <<
"Could not set new size for Shm pool file";
157 wl_shm_pool_resize(pool, newSize);
158 munmap(poolData, size);
159 poolData = mmap(
nullptr, newSize, PROT_READ | PROT_WRITE, MAP_SHARED, tmpFile->handle(), 0);
162 qCDebug(KWAYLAND_CLIENT) <<
"Resizing Shm pool failed";
165 emit q->poolResized();
173 case QImage::Format_ARGB32_Premultiplied:
174 return Buffer::Format::ARGB32;
175 case QImage::Format_RGB32:
176 return Buffer::Format::RGB32;
177 case QImage::Format_ARGB32:
178 qCWarning(KWAYLAND_CLIENT) <<
"Unsupported image format: " << image.
format() <<
". expect slow performance. Use QImage::Format_ARGB32_Premultiplied";
179 return Buffer::Format::ARGB32;
181 qCWarning(KWAYLAND_CLIENT) <<
"Unsupported image format: " << image.
format() <<
". expect slow performance.";
182 return Buffer::Format::ARGB32;
189 if (image.
isNull() || !d->valid) {
192 auto format = toBufferFormat(image);
194 if (it == d->buffers.end()) {
197 if (format == Buffer::Format::ARGB32 && image.
format() != QImage::Format_ARGB32_Premultiplied) {
198 auto imageCopy = image.
convertToFormat(QImage::Format_ARGB32_Premultiplied);
199 (*it)->
copy(imageCopy.bits());
208 if (size.
isEmpty() || !d->valid) {
211 auto it = d->getBuffer(size, stride, format);
212 if (it == d->buffers.end()) {
223 case Buffer::Format::ARGB32:
224 return WL_SHM_FORMAT_ARGB8888;
225 case Buffer::Format::RGB32:
226 return WL_SHM_FORMAT_XRGB8888;
234 auto it = d->getBuffer(size, stride, format);
235 if (it == d->buffers.end()) {
243 for (
auto it = buffers.begin(); it != buffers.end(); ++it) {
245 if (!buffer->isReleased() || buffer->isUsed()) {
248 if (buffer->size() != s || buffer->stride() != stride || buffer->format() != format) {
251 buffer->setReleased(
false);
254 const int32_t byteCount = s.
height() * stride;
255 if (offset + byteCount > size) {
256 if (!resizePool(size + byteCount)) {
257 return buffers.end();
261 wl_buffer *native = wl_shm_pool_create_buffer(pool, offset, s.
width(), s.
height(),
262 stride, toWaylandFormat(format));
264 return buffers.end();
267 queue->addProxy(native);
269 Buffer *buffer =
new Buffer(q, native, s, stride, offset, format);
275 bool ShmPool::isValid()
const 280 void* ShmPool::poolAddress()
const 285 wl_shm *ShmPool::shm()
Wrapper class for wl_event_queue interface.
Wrapper class for wl_buffer interface.
QImage copy(const QRect &rectangle) const
Format
All image formats supported by the implementation.