• Skip to content
  • Skip to link menu
Brand

API Documentation

  1. KDE API Reference
  2. The KDE Frameworks
  3. KWayland
  • KDE Home
  • Contact Us

Quick Links

Skip menu "KWayland"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • File List
  • Modules
  • Dependencies
  • Related Pages

Class Picker

About

Qt-style API to interact with the wayland-client and wayland-server API

Maintainer
Martin Flöser
Supported platforms
FreeBSD, Linux
Community
IRC: #kde-devel on Freenode
Mailing list: kde-frameworks-devel
Use with CMake
find_package(KF5Wayland)
target_link_libraries(yourapp KF5::WaylandClient KF5::WaylandServer)
Use with QMake
QT += KWaylandClient KWaylandServer 
Clone
git clone git://anongit.kde.org/kwayland.git
Browse source
KWayland on cgit.kde.org

KWayland

  • frameworks
  • frameworks
  • kwayland
  • src
  • client
shm_pool.cpp
1 /********************************************************************
2 Copyright 2013 Martin Gräßlin <[email protected]>
3 
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) version 3, or any
8 later version accepted by the membership of KDE e.V. (or its
9 successor approved by the membership of KDE e.V.), which shall
10 act as a proxy defined in Section 6 of version 3 of the license.
11 
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16 
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library. If not, see <http://www.gnu.org/licenses/>.
19 *********************************************************************/
20 #include "shm_pool.h"
21 #include "event_queue.h"
22 #include "buffer.h"
23 #include "buffer_p.h"
24 #include "logging.h"
25 #include "wayland_pointer_p.h"
26 // Qt
27 #include <QDebug>
28 #include <QImage>
29 #include <QTemporaryFile>
30 // system
31 #include <unistd.h>
32 #include <sys/mman.h>
33 // wayland
34 #include <wayland-client-protocol.h>
35 
36 namespace KWayland
37 {
38 namespace Client
39 {
40 
41 class Q_DECL_HIDDEN ShmPool::Private
42 {
43 public:
44  Private(ShmPool *q);
45  bool createPool();
46  bool resizePool(int32_t newSize);
47  QList<QSharedPointer<Buffer>>::iterator getBuffer(const QSize &size, int32_t stride, Buffer::Format format);
48  WaylandPointer<wl_shm, wl_shm_destroy> shm;
49  WaylandPointer<wl_shm_pool, wl_shm_pool_destroy> pool;
50  void *poolData = nullptr;
51  int32_t size = 1024;
52  QScopedPointer<QTemporaryFile> tmpFile;
53  bool valid = false;
54  int offset = 0;
55  QList<QSharedPointer<Buffer>> buffers;
56  EventQueue *queue = nullptr;
57 private:
58  ShmPool *q;
59 };
60 
61 ShmPool::Private::Private(ShmPool *q)
62  : tmpFile(new QTemporaryFile())
63  , q(q)
64 {
65 }
66 
67 
68 ShmPool::ShmPool(QObject *parent)
69  : QObject(parent)
70  , d(new Private(this))
71 {
72 }
73 
74 ShmPool::~ShmPool()
75 {
76  release();
77 }
78 
79 void ShmPool::release()
80 {
81  d->buffers.clear();
82  if (d->poolData) {
83  munmap(d->poolData, d->size);
84  d->poolData = nullptr;
85  }
86  d->pool.release();
87  d->shm.release();
88  d->tmpFile->close();
89  d->valid = false;
90  d->offset = 0;
91 }
92 
93 void ShmPool::destroy()
94 {
95  for (auto b : d->buffers) {
96  b->d->destroy();
97  }
98  d->buffers.clear();
99  if (d->poolData) {
100  munmap(d->poolData, d->size);
101  d->poolData = nullptr;
102  }
103  d->pool.destroy();
104  d->shm.destroy();
105  d->tmpFile->close();
106  d->valid = false;
107  d->offset = 0;
108 }
109 
110 void ShmPool::setup(wl_shm *shm)
111 {
112  Q_ASSERT(shm);
113  Q_ASSERT(!d->shm);
114  d->shm.setup(shm);
115  d->valid = d->createPool();
116 }
117 
118 void ShmPool::setEventQueue(EventQueue *queue)
119 {
120  d->queue = queue;
121 }
122 
123 EventQueue *ShmPool::eventQueue()
124 {
125  return d->queue;
126 }
127 
128 bool ShmPool::Private::createPool()
129 {
130  if (!tmpFile->open()) {
131  qCDebug(KWAYLAND_CLIENT) << "Could not open temporary file for Shm pool";
132  return false;
133  }
134  if (unlink(tmpFile->fileName().toUtf8().constData()) != 0) {
135  qCDebug(KWAYLAND_CLIENT) << "Unlinking temporary file for Shm pool from file system failed";
136  }
137  if (ftruncate(tmpFile->handle(), size) < 0) {
138  qCDebug(KWAYLAND_CLIENT) << "Could not set size for Shm pool file";
139  return false;
140  }
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));
143 
144  if (!poolData || !pool) {
145  qCDebug(KWAYLAND_CLIENT) << "Creating Shm pool failed";
146  return false;
147  }
148  return true;
149 }
150 
151 bool ShmPool::Private::resizePool(int32_t newSize)
152 {
153  if (ftruncate(tmpFile->handle(), newSize) < 0) {
154  qCDebug(KWAYLAND_CLIENT) << "Could not set new size for Shm pool file";
155  return false;
156  }
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);
160  size = newSize;
161  if (!poolData) {
162  qCDebug(KWAYLAND_CLIENT) << "Resizing Shm pool failed";
163  return false;
164  }
165  emit q->poolResized();
166  return true;
167 }
168 
169 namespace {
170 static Buffer::Format toBufferFormat(const QImage &image)
171 {
172  switch (image.format()) {
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;
180  default:
181  qCWarning(KWAYLAND_CLIENT) << "Unsupported image format: " << image.format() << ". expect slow performance.";
182  return Buffer::Format::ARGB32;
183  }
184 }
185 }
186 
187 Buffer::Ptr ShmPool::createBuffer(const QImage& image)
188 {
189  if (image.isNull() || !d->valid) {
190  return QWeakPointer<Buffer>();
191  }
192  auto format = toBufferFormat(image);
193  auto it = d->getBuffer(image.size(), image.bytesPerLine(), format);
194  if (it == d->buffers.end()) {
195  return QWeakPointer<Buffer>();
196  }
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());
200  } else {
201  (*it)->copy(image.bits());
202  }
203  return QWeakPointer<Buffer>(*it);
204 }
205 
206 Buffer::Ptr ShmPool::createBuffer(const QSize &size, int32_t stride, const void *src, Buffer::Format format)
207 {
208  if (size.isEmpty() || !d->valid) {
209  return QWeakPointer<Buffer>();
210  }
211  auto it = d->getBuffer(size, stride, format);
212  if (it == d->buffers.end()) {
213  return QWeakPointer<Buffer>();
214  }
215  (*it)->copy(src);
216  return QWeakPointer<Buffer>(*it);
217 }
218 
219 namespace {
220 static wl_shm_format toWaylandFormat(Buffer::Format format)
221 {
222  switch (format) {
223  case Buffer::Format::ARGB32:
224  return WL_SHM_FORMAT_ARGB8888;
225  case Buffer::Format::RGB32:
226  return WL_SHM_FORMAT_XRGB8888;
227  }
228  abort();
229 }
230 }
231 
232 Buffer::Ptr ShmPool::getBuffer(const QSize &size, int32_t stride, Buffer::Format format)
233 {
234  auto it = d->getBuffer(size, stride, format);
235  if (it == d->buffers.end()) {
236  return QWeakPointer<Buffer>();
237  }
238  return QWeakPointer<Buffer>(*it);
239 }
240 
241 QList<QSharedPointer<Buffer>>::iterator ShmPool::Private::getBuffer(const QSize &s, int32_t stride, Buffer::Format format)
242 {
243  for (auto it = buffers.begin(); it != buffers.end(); ++it) {
244  auto buffer = *it;
245  if (!buffer->isReleased() || buffer->isUsed()) {
246  continue;
247  }
248  if (buffer->size() != s || buffer->stride() != stride || buffer->format() != format) {
249  continue;
250  }
251  buffer->setReleased(false);
252  return it;
253  }
254  const int32_t byteCount = s.height() * stride;
255  if (offset + byteCount > size) {
256  if (!resizePool(size + byteCount)) {
257  return buffers.end();
258  }
259  }
260  // we don't have a buffer which we could reuse - need to create a new one
261  wl_buffer *native = wl_shm_pool_create_buffer(pool, offset, s.width(), s.height(),
262  stride, toWaylandFormat(format));
263  if (!native) {
264  return buffers.end();
265  }
266  if (queue) {
267  queue->addProxy(native);
268  }
269  Buffer *buffer = new Buffer(q, native, s, stride, offset, format);
270  offset += byteCount;
271  auto it = buffers.insert(buffers.end(), QSharedPointer<Buffer>(buffer));
272  return it;
273 }
274 
275 bool ShmPool::isValid() const
276 {
277  return d->valid;
278 }
279 
280 void* ShmPool::poolAddress() const
281 {
282  return d->poolData;
283 }
284 
285 wl_shm *ShmPool::shm()
286 {
287  return d->shm;
288 }
289 
290 }
291 }
QImage::convertToFormat
QImage convertToFormat(Format format, Qt::ImageConversionFlags flags) const
QSize::width
int width() const
QSize::isEmpty
bool isEmpty() const
KWayland::Client::EventQueue
Wrapper class for wl_event_queue interface.
Definition: event_queue.h:69
KWayland::Client::Buffer
Wrapper class for wl_buffer interface.
Definition: buffer.h:45
QImage::isNull
bool isNull() const
QImage::copy
QImage copy(const QRect &rectangle) const
KWayland::Client::Buffer::Format
Format
All image formats supported by the implementation.
Definition: buffer.h:51
QSharedPointer
QObject
QScopedPointer< QTemporaryFile >
QList
QSize
QImage
QImage::bytesPerLine
int bytesPerLine() const
QSize::height
int height() const
QImage::size
QSize size() const
QWeakPointer
QImage::bits
uchar * bits()
KWayland
Definition: appmenu.cpp:27
QTemporaryFile
QObject::parent
QObject * parent() const
QImage::format
Format format() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2019 The KDE developers.
Generated on Thu Dec 12 2019 02:14:23 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal