12#include <xcb/xcb_image.h>
13#include <xcb/render.h>
14#include <xcb/xcb_renderutil.h>
27#include <QtGui/private/qhighdpiscaling_p.h>
28#include <qpa/qplatformgraphicsbuffer.h>
29#include <private/qimage_p.h>
34#if (XCB_SHM_MAJOR_VERSION
== 1
&& XCB_SHM_MINOR_VERSION
>= 2
) || XCB_SHM_MAJOR_VERSION
> 1
40class QXcbBackingStore;
53 bool scroll(
const QRegion &area,
int dx,
int dy);
61 bool hasShm()
const {
return m_shm_info.shmaddr !=
nullptr; }
63 void put(xcb_drawable_t dst,
const QRegion ®ion,
const QPoint &offset);
67 xcb_shm_segment_info_t *shm_info =
nullptr);
70 void init(
const QSize &size, uint depth, QImage::Format format);
72 void createShmSegment(size_t segmentSize);
73 void destroyShmSegment();
74 void destroy(
bool destroyShm);
76 void ensureGC(xcb_drawable_t dst);
77 void shmPutImage(xcb_drawable_t drawable,
const QRegion ®ion,
const QPoint &offset = QPoint());
78 void flushPixmap(
const QRegion ®ion,
bool fullRegion =
false);
79 void setClip(
const QRegion ®ion);
81 xcb_shm_segment_info_t m_shm_info;
82 size_t m_segmentSize = 0;
85 xcb_image_t *m_xcb_image =
nullptr;
88 QPlatformGraphicsBuffer *m_graphics_buffer =
nullptr;
90 xcb_gcontext_t m_gc = 0;
91 xcb_drawable_t m_gc_drawable = 0;
98 xcb_pixmap_t m_xcb_pixmap = 0;
99 QRegion m_pendingFlush;
102 QRegion m_scrolledRegion;
109 QByteArray m_flushBuffer;
111 bool m_hasAlpha =
false;
112 bool m_clientSideScroll =
false;
114 const xcb_format_t *m_xcb_format =
nullptr;
126 bool doLock(AccessTypes access,
const QRect &rect)
override
129 if (access & ~(QPlatformGraphicsBuffer::SWReadAccess | QPlatformGraphicsBuffer::SWWriteAccess))
132 m_access_lock |= access;
137 const uchar *
data()
const override {
return m_image->bits(); }
141 Origin origin()
const override {
return QPlatformGraphicsBuffer::OriginTopLeft; }
145 QImage *m_image =
nullptr;
150 return static_cast<size_t>(image->stride) * image->height;
155 , m_backingStore(backingStore)
157 auto window =
static_cast<QXcbWindow *>(m_backingStore->window()->handle());
158 init(size, window->depth(), window->imageFormat());
162 uint depth, QImage::Format format)
164 , m_backingStore(backingStore)
166 init(size, depth, format);
171 m_xcb_format =
connection()->formatForDepth(depth);
172 Q_ASSERT(m_xcb_format);
174 m_qimage_format = format;
175 m_hasAlpha = QImage::toPixelFormat(m_qimage_format).alphaUsage() == QPixelFormat::UsesAlpha;
177 m_qimage_format = qt_maybeDataCompatibleAlphaVersion(m_qimage_format);
179 memset(&m_shm_info, 0,
sizeof m_shm_info);
188 auto byteOrder = QSysInfo::ByteOrder == QSysInfo::BigEndian ? XCB_IMAGE_ORDER_MSB_FIRST
189 : XCB_IMAGE_ORDER_LSB_FIRST;
190 m_xcb_image = xcb_image_create(size.width(), size.height(),
191 XCB_IMAGE_FORMAT_Z_PIXMAP,
192 m_xcb_format->scanline_pad,
194 m_xcb_format->bits_per_pixel,
196 XCB_IMAGE_ORDER_MSB_FIRST,
197 nullptr, ~0,
nullptr);
199 const size_t segmentSize = imageDataSize(m_xcb_image);
202 if (segmentSize == 0) {
203 if (m_segmentSize > 0) {
205 qCDebug(lcQpaXcb) <<
"[" << m_backingStore->window()
206 <<
"] destroyed SHM segment due to resize to" << size;
212 if (m_shm_info.shmaddr && (m_segmentSize < segmentSize || m_segmentSize / 2 >= segmentSize))
214 if (!m_shm_info.shmaddr) {
215 qCDebug(lcQpaXcb) <<
"[" << m_backingStore->window()
216 <<
"] creating shared memory" << segmentSize <<
"bytes for"
217 << size <<
"depth" << m_xcb_format->depth <<
"bits"
218 << m_xcb_format->bits_per_pixel;
219 createShmSegment(segmentSize);
224 if (segmentSize == 0)
227 m_xcb_image->data = m_shm_info.shmaddr ? m_shm_info.shmaddr : (uint8_t *)malloc(segmentSize);
228 m_qimage = QImage(
static_cast<uchar *>(m_xcb_image->data), m_xcb_image->width,
229 m_xcb_image->height, m_xcb_image->stride, m_qimage_format);
230 m_graphics_buffer =
new QXcbGraphicsBuffer(&m_qimage);
233 auto xcbScreen =
static_cast<QXcbScreen *>(m_backingStore->window()->screen()->handle());
238 m_xcb_image->width, m_xcb_image->height);
244 if (m_xcb_image->data) {
245 if (m_shm_info.shmaddr) {
249 free(m_xcb_image->data);
252 xcb_image_destroy(m_xcb_image);
261 delete m_graphics_buffer;
262 m_graphics_buffer =
nullptr;
274 if (m_clientSideScroll == clientSideScroll)
277 m_clientSideScroll = clientSideScroll;
279 if (m_scrolledRegion.isNull())
282 if (hasShm() && m_dirtyShm.intersects(m_scrolledRegion)) {
284 m_dirtyShm = QRegion();
287 if (m_clientSideScroll) {
289 for (
const QRect &rect : m_scrolledRegion) {
290 const int w = rect.width();
291 const int h = rect.height();
301 if (reply && reply->depth == m_xcb_image->depth) {
302 const QImage img(xcb_get_image_data(reply.get()), w, h, m_qimage.format());
304 QPainter p(&m_qimage);
305 p.setCompositionMode(QPainter::CompositionMode_Source);
306 p.drawImage(rect.topLeft(), img);
309 m_scrolledRegion = QRegion();
312 ensureGC(m_xcb_pixmap);
314 shmPutImage(m_xcb_pixmap, m_scrolledRegion);
316 flushPixmap(m_scrolledRegion,
true);
323 Q_ASSERT(m_segmentSize == 0);
327 if (Q_UNLIKELY(segmentSize >
std::numeric_limits<uint32_t>::max())) {
328 qCWarning(lcQpaXcb,
"xcb_shm_create_segment() can't be called for size %zu, maximum"
329 "allowed size is %u", segmentSize, std::numeric_limits<uint32_t>::max());
337 qCWarning(lcQpaXcb,
"xcb_shm_create_segment() failed for size %zu", segmentSize);
341 int *fds = xcb_shm_create_segment_reply_fds(
xcb_connection(), reply.get());
342 if (reply->nfd != 1) {
343 for (
int i = 0; i < reply->nfd; i++)
346 qCWarning(lcQpaXcb,
"failed to get file descriptor for shm segment of size %zu", segmentSize);
350 void *addr = mmap(
nullptr, segmentSize, PROT_READ|PROT_WRITE, MAP_SHARED, fds[0], 0);
352 qCWarning(lcQpaXcb,
"failed to mmap segment from X server (%d: %s) for size %zu",
353 errno, strerror(errno), segmentSize);
360 m_shm_info.shmseg = seg;
361 m_shm_info.shmaddr =
static_cast<quint8 *>(addr);
362 m_segmentSize = segmentSize;
366 if (createSystemVShmSegment(xcb_connection(), segmentSize, &m_shm_info))
367 m_segmentSize = segmentSize;
372 xcb_shm_segment_info_t *shmInfo)
374 const int id = shmget(IPC_PRIVATE, segmentSize, IPC_CREAT | 0600);
376 qCWarning(lcQpaXcb,
"shmget() failed (%d: %s) for size %zu", errno, strerror(errno), segmentSize);
380 void *addr = shmat(id,
nullptr, 0);
381 if (addr == (
void *)-1) {
382 qCWarning(lcQpaXcb,
"shmat() failed (%d: %s) for id %d", errno, strerror(errno), id);
386 if (shmctl(id, IPC_RMID,
nullptr) == -1)
387 qCWarning(lcQpaXcb,
"Error while marking the shared memory segment to be destroyed");
389 const auto seg = xcb_generate_id(c);
390 auto cookie = xcb_shm_attach_checked(c, seg, id,
false);
391 auto *error = xcb_request_check(c, cookie);
393 qCWarning(lcQpaXcb(),
"xcb_shm_attach() failed");
395 if (shmdt(addr) == -1)
396 qCWarning(lcQpaXcb,
"shmdt() failed (%d: %s) for %p", errno, strerror(errno), addr);
398 }
else if (!shmInfo) {
399 xcb_shm_detach(c, seg);
400 auto shmaddr =
static_cast<quint8 *>(addr);
401 if (shmdt(shmaddr) == -1)
402 qCWarning(lcQpaXcb,
"shmdt() failed (%d: %s) for %p", errno, strerror(errno), shmaddr);
405 shmInfo->shmseg = seg;
407 shmInfo->shmaddr =
static_cast<quint8 *>(addr);
414 auto cookie = xcb_shm_detach_checked(
xcb_connection(), m_shm_info.shmseg);
415 xcb_generic_error_t *error = xcb_request_check(
xcb_connection(), cookie);
417 connection()->printXcbError(
"xcb_shm_detach() failed with error", error);
418 m_shm_info.shmseg = 0;
422 if (munmap(m_shm_info.shmaddr, m_segmentSize) == -1) {
423 qCWarning(lcQpaXcb,
"munmap() failed (%d: %s) for %p with size %zu",
424 errno, strerror(errno), m_shm_info.shmaddr, m_segmentSize);
429 if (shmdt(m_shm_info.shmaddr) == -1) {
430 qCWarning(lcQpaXcb,
"shmdt() failed (%d: %s) for %p",
431 errno, strerror(errno), m_shm_info.shmaddr);
433 m_shm_info.shmid = 0;
435 m_shm_info.shmaddr =
nullptr;
444 const QRect bounds(QPoint(), size());
445 const QRegion scrollArea(area & bounds);
446 const QPoint delta(dx, dy);
447 const QRegion destinationRegion = scrollArea.translated(delta).intersected(bounds);
449 if (m_clientSideScroll) {
450 if (m_qimage.isNull())
454 preparePaint(destinationRegion);
456 const QRect rect = scrollArea.boundingRect();
457 qt_scrollRectInImage(m_qimage, rect, delta);
459 ensureGC(m_xcb_pixmap);
462 QRegion partialFlushRegion = m_pendingFlush.intersected(scrollArea);
463 shmPutImage(m_xcb_pixmap, partialFlushRegion);
464 m_pendingFlush -= partialFlushRegion;
466 flushPixmap(scrollArea);
469 for (
const QRect &src : scrollArea) {
470 const QRect dst = src.translated(delta).intersected(bounds);
471 xcb_copy_area(xcb_connection(),
477 dst.width(), dst.height());
481 m_pendingFlush -= destinationRegion;
484 m_scrolledRegion |= destinationRegion;
491 if (m_gc_drawable != dst) {
495 static const uint32_t mask = XCB_GC_GRAPHICS_EXPOSURES;
496 static const uint32_t values[] = { 0 };
505static inline void copy_unswapped(
char *dst,
int dstBytesPerLine,
const QImage &img,
const QRect &rect)
507 const uchar *srcData = img.constBits();
508 const qsizetype srcBytesPerLine = img.bytesPerLine();
510 const int leftOffset = rect.left() * img.depth() >> 3;
511 const int bottom = rect.bottom() + 1;
513 for (
int yy = rect.top(); yy < bottom; ++yy) {
514 const uchar *src = srcData + yy * srcBytesPerLine + leftOffset;
515 ::memmove(dst, src, dstBytesPerLine);
516 dst += dstBytesPerLine;
520template <
class Pixel>
521static inline void copy_swapped(
char *dst,
const int dstStride,
const QImage &img,
const QRect &rect)
523 const uchar *srcData = img.constBits();
524 const qsizetype srcBytesPerLine = img.bytesPerLine();
526 const int left = rect.left();
527 const int width = rect.width();
528 const int bottom = rect.bottom() + 1;
530 for (
int yy = rect.top(); yy < bottom; ++yy) {
531 Pixel *dstPixels =
reinterpret_cast<Pixel *>(dst);
532 const Pixel *srcPixels =
reinterpret_cast<
const Pixel *>(srcData + yy * srcBytesPerLine) + left;
534 for (
int i = 0; i < width; ++i)
535 dstPixels[i] = qbswap<Pixel>(*srcPixels++);
543 if (!swap && src.rect() == rect && src.bytesPerLine() == dstStride)
546 buffer->resize(rect.height() * dstStride);
549 switch (src.depth()) {
551 copy_swapped<quint32>(buffer->data(), dstStride, src, rect);
554 copy_swapped<quint16>(buffer->data(), dstStride, src, rect);
558 copy_unswapped(buffer->data(), dstStride, src, rect);
561 return QImage(
reinterpret_cast<
const uchar *>(buffer->constData()), rect.width(), rect.height(), dstStride, src.format());
566 return (base + pad - 1) & -pad;
569void QXcbBackingStoreImage::shmPutImage(xcb_drawable_t drawable,
const QRegion ®ion,
const QPoint &offset)
571 for (
const QRect &rect : region) {
572 const QPoint source = rect.translated(offset).topLeft();
573 xcb_shm_put_image(xcb_connection(),
578 source.x(), source.y(),
579 rect.width(), rect.height(),
585 m_xcb_image->data - m_shm_info.shmaddr);
587 m_dirtyShm |= region.translated(offset);
593 auto actualRegion = m_pendingFlush.intersected(region);
594 m_pendingFlush -= region;
595 flushPixmap(actualRegion,
true);
599 xcb_image_t xcb_subimage;
600 memset(&xcb_subimage, 0,
sizeof(xcb_image_t));
602 xcb_subimage.format = m_xcb_image->format;
603 xcb_subimage.scanline_pad = m_xcb_image->scanline_pad;
604 xcb_subimage.depth = m_xcb_image->depth;
605 xcb_subimage.bpp = m_xcb_image->bpp;
606 xcb_subimage.unit = m_xcb_image->unit;
607 xcb_subimage.plane_mask = m_xcb_image->plane_mask;
608 xcb_subimage.byte_order = (xcb_image_order_t)
connection()->setup()->image_byte_order;
609 xcb_subimage.bit_order = m_xcb_image->bit_order;
611 const bool needsByteSwap = xcb_subimage.byte_order != m_xcb_image->byte_order;
613 const auto maxPutImageRequestDataBytes =
connection()->maxRequestDataBytes(
sizeof(xcb_put_image_request_t));
615 for (
const QRect &rect : region) {
616 const quint32 stride = round_up_scanline(rect.width() * m_qimage.depth(), xcb_subimage.scanline_pad) >> 3;
617 const int rows_per_put = maxPutImageRequestDataBytes / stride;
623 Q_ASSERT(rows_per_put > 0);
629 const int x = rect.x();
631 const int width = rect.width();
632 int height = rect.height();
635 const int rows = std::min(height, rows_per_put);
636 const QRect subRect(x, y, width, rows);
637 const QImage subImage = native_sub_image(&m_flushBuffer, stride, m_qimage, subRect, needsByteSwap);
639 Q_ASSERT(
static_cast<size_t>(subImage.sizeInBytes()) <= maxPutImageRequestDataBytes);
641 xcb_subimage.width = width;
642 xcb_subimage.height = rows;
643 xcb_subimage.data =
const_cast<uint8_t *>(subImage.constBits());
644 xcb_image_annotate(&xcb_subimage);
646 xcb_image_put(xcb_connection(),
662 if (region.isEmpty()) {
663 static const uint32_t mask = XCB_GC_CLIP_MASK;
664 static const uint32_t values[] = { XCB_NONE };
667 const auto xcb_rects = qRegionToXcbRectangleList(region);
669 XCB_CLIP_ORDERING_YX_BANDED,
672 xcb_rects.size(), xcb_rects.constData());
678 Q_ASSERT(!m_clientSideScroll);
686 const QRegion scrolledRegion = m_scrolledRegion.translated(-offset);
687 for (
const QRect &rect : scrolledRegion) {
688 const QPoint source = rect.translated(offset).topLeft();
689 xcb_copy_area(xcb_connection(),
693 source.x(), source.y(),
695 rect.width(), rect.height());
699 const QRegion notScrolledArea = region - scrolledRegion;
700 shmPutImage(dst, notScrolledArea, offset);
702 const QRect bounds = region.boundingRect();
703 const QPoint target = bounds.topLeft();
704 const QRect source = bounds.translated(offset);
718 source.x(), source.y(),
719 target.x(), target.y(),
720 source.width(), source.height());
730 if (m_dirtyShm.intersects(region)) {
732 m_dirtyShm = QRegion();
735 m_scrolledRegion -= region;
736 m_pendingFlush |= region;
739bool QXcbBackingStore::createSystemVShmSegment(xcb_connection_t *c, size_t segmentSize,
void *shmInfo)
741 auto info =
reinterpret_cast<xcb_shm_segment_info_t *>(shmInfo);
742 return QXcbBackingStoreImage::createSystemVShmSegment(c, segmentSize, info);
746 : QPlatformBackingStore(window)
748 QXcbScreen *screen =
static_cast<QXcbScreen *>(window->screen()->handle());
761 return m_rgbImage.isNull() ? m_image->image() : &m_rgbImage;
769 m_paintRegions.push(region);
774 p.setCompositionMode(QPainter::CompositionMode_Source);
775 const QColor blank = Qt::transparent;
776 for (
const QRect &rect : region)
777 p.fillRect(rect, blank);
783 if (Q_UNLIKELY(m_paintRegions.isEmpty())) {
784 qCWarning(lcQpaXcb,
"%s: paint regions empty!", Q_FUNC_INFO);
788 const QRegion region = m_paintRegions.pop();
791 QXcbWindow *platformWindow =
static_cast<QXcbWindow *>(window()->handle());
792 if (!platformWindow || !platformWindow->imageNeedsRgbSwap())
797 auto it = region.begin();
798 const auto end = region.end();
803 const QRect rect = *(it++);
804 p.drawImage(rect.topLeft(), m_rgbImage.copy(rect).rgbSwapped());
811 if (!m_rgbImage.isNull())
819 QImage image = *
m_image->image();
824 return QImage(image.constBits(), image.width(), image.height(), image.format());
839 QSize imageSize =
m_image->size();
841 QRegion clipped = region;
842 clipped &= QRect(QPoint(), QHighDpi::toNativePixels(window->size(), window));
843 clipped &= QRect(0, 0, imageSize.width(), imageSize.height()).translated(-offset);
845 QRect bounds = clipped.boundingRect();
850 QXcbWindow *platformWindow =
static_cast<QXcbWindow *>(window->handle());
851 if (!platformWindow) {
852 qCWarning(lcQpaXcb,
"%s QWindow has no platform window, see QTBUG-32681", Q_FUNC_INFO);
856 render(platformWindow->xcb_window(), clipped, offset);
858 if (platformWindow->needsSync())
859 platformWindow->updateSyncRequestCounter();
866 m_image->put(window, region, offset);
870 qreal sourceDevicePixelRatio,
871 const QRegion ®ion,
872 const QPoint &offset,
873 QPlatformTextureList *textures,
874 bool translucentBackground,
875 qreal sourceTransformFactor)
877 if (!m_image || m_image->size().isEmpty())
882 auto result = QPlatformBackingStore::rhiFlush(window, sourceDevicePixelRatio, region, offset,
883 textures, translucentBackground, sourceTransformFactor);
884 if (result != FlushSuccess)
886 QXcbWindow *platformWindow =
static_cast<QXcbWindow *>(window->handle());
887 if (platformWindow->needsSync()) {
888 platformWindow->updateSyncRequestCounter();
901 QPlatformWindow *pw = window()->handle();
904 pw = window()->handle();
906 QXcbWindow* win =
static_cast<QXcbWindow *>(pw);
908 recreateImage(win, size);
920 if (win->imageNeedsRgbSwap()) {
921 m_rgbImage = QImage(size, win->imageFormat());
928 return m_image->scroll(area, dx, dy);
947 auto *platformWindow =
static_cast<QXcbWindow *>(window->handle());
948 quint8 depth =
connection()->primaryScreen()->depthOfVisual(platformWindow->visualId());
951 platformWindow->setParentRelativeBackPixmap();
953 m_useGrabbedBackgound = !m_usingXRenderMode;
959 if (m_xrenderPicture) {
961 m_xrenderPicture = XCB_NONE;
963 if (m_xrenderPixmap) {
965 m_xrenderPixmap = XCB_NONE;
967 if (m_windowPicture) {
969 m_windowPicture = XCB_NONE;
975 QXcbBackingStore::beginPaint(region);
977 if (m_useGrabbedBackgound) {
979 p.setCompositionMode(QPainter::CompositionMode_Source);
980 for (
const QRect &rect: region)
981 p.drawPixmap(rect, m_grabbedBackground, rect);
987 if (!m_usingXRenderMode) {
988 QXcbBackingStore::render(window, region, offset);
992 m_image->put(m_xrenderPixmap, region, offset);
993 const QRect bounds = region.boundingRect();
994 const QPoint target = bounds.topLeft();
995 const QRect source = bounds.translated(offset);
997 target.x(), target.y(), source.width(), source.height());
999 m_xrenderPicture, 0, m_windowPicture,
1000 target.x(), target.y(), 0, 0, target.x(), target.y(),
1001 source.width(), source.height());
1006 if (!m_usingXRenderMode) {
1007 QXcbBackingStore::recreateImage(win, size);
1009 if (m_useGrabbedBackgound) {
1011 0, 0, size.width(), size.height());
1012 m_grabbedBackground = win->xcbScreen()->grabWindow(win->winId(), 0, 0,
1013 size.width(), size.height());
1018 if (m_xrenderPicture) {
1020 m_xrenderPicture = XCB_NONE;
1022 if (m_xrenderPixmap) {
1024 m_xrenderPixmap = XCB_NONE;
1027 QXcbScreen *screen = win->xcbScreen();
1030 xcb_create_pixmap(
xcb_connection(), 32, m_xrenderPixmap, screen->root(), size.width(), size.height());
1033 xcb_render_create_picture(
xcb_connection(), m_xrenderPicture, m_xrenderPixmap, m_xrenderPictFormat, 0,
nullptr);
1039 m_image =
new QXcbBackingStoreImage(
this, size, 32, QImage::Format_ARGB32_Premultiplied);
1048 auto formatsReply =
Q_XCB_REPLY(xcb_render_query_pict_formats, conn);
1050 if (!formatsReply) {
1051 qWarning(
"QXcbSystemTrayBackingStore: xcb_render_query_pict_formats() failed");
1055 xcb_render_pictforminfo_t *fmt = xcb_render_util_find_standard_format(formatsReply.get(),
1056 XCB_PICT_STANDARD_ARGB_32);
1058 qWarning(
"QXcbSystemTrayBackingStore: Failed to find format PICT_STANDARD_ARGB_32");
1062 m_xrenderPictFormat = fmt->id;
1064 auto *platformWindow =
static_cast<QXcbWindow *>(window()->handle());
1065 xcb_render_pictvisual_t *vfmt = xcb_render_util_find_visual_format(formatsReply.get(), platformWindow->visualId());
1068 qWarning(
"QXcbSystemTrayBackingStore: Failed to find format for visual %x", platformWindow->visualId());
1072 m_windowPicture = xcb_generate_id(conn);
1073 xcb_void_cookie_t cookie =
1074 xcb_render_create_picture_checked(conn, m_windowPicture, platformWindow->xcb_window(), vfmt->format, 0,
nullptr);
1075 xcb_generic_error_t *error = xcb_request_check(conn, cookie);
1077 qWarning(
"QXcbSystemTrayBackingStore: Failed to create Picture with format %x for window %x, error code %d",
1078 vfmt->format, platformWindow->xcb_window(), error->error_code);
1083 m_usingXRenderMode =
true;
QPainter(QPaintDevice *)
Constructs a painter that begins painting the paint device immediately.
QRect window() const
Returns the window rectangle.
void flushScrolledRegion(bool clientSideScroll)
QXcbBackingStoreImage(QXcbBackingStore *backingStore, const QSize &size)
void put(xcb_drawable_t dst, const QRegion ®ion, const QPoint &offset)
void resize(const QSize &size)
void preparePaint(const QRegion ®ion)
QXcbBackingStoreImage(QXcbBackingStore *backingStore, const QSize &size, uint depth, QImage::Format format)
QPlatformGraphicsBuffer * graphicsBuffer()
bool scroll(const QRegion &area, int dx, int dy)
static bool createSystemVShmSegment(xcb_connection_t *c, size_t segmentSize=1, xcb_shm_segment_info_t *shm_info=nullptr)
QXcbBackingStoreImage * m_image
QPlatformGraphicsBuffer * graphicsBuffer() const override
Accessor for a backingstores graphics buffer abstraction.
void resize(const QSize &size, const QRegion &staticContents) override
QPaintDevice * paintDevice() override
Implement this function to return the appropriate paint device.
void endPaint() override
This function is called after painting onto the surface has ended.
virtual void render(xcb_window_t window, const QRegion ®ion, const QPoint &offset)
void beginPaint(const QRegion &) override
This function is called before painting onto the surface begins, with the region in which the paintin...
virtual void recreateImage(QXcbWindow *win, const QSize &size)
QImage toImage() const override
Implemented in subclasses to return the content of the backingstore as a QImage.
bool scroll(const QRegion &area, int dx, int dy) override
Scrolls the given area dx pixels to the right and dy downward; both dx and dy may be negative.
uchar * data() override
Accessor for the bytes of the buffer.
QXcbGraphicsBuffer(QImage *image)
const uchar * data() const override
Accessor for the bytes of the buffer.
int bytesPerLine() const override
Accessor for bytes per line in the graphics buffer.
Origin origin() const override
In origin of the content of the graphics buffer.
bool doLock(AccessTypes access, const QRect &rect) override
This function should be reimplemented by subclasses.
void doUnlock() override
This function should remove all locks set on the buffer.
QXcbConnection * connection() const
xcb_connection_t * xcb_connection() const
void setConnection(QXcbConnection *connection)
~QXcbSystemTrayBackingStore()
void render(xcb_window_t window, const QRegion ®ion, const QPoint &offset) override
void beginPaint(const QRegion &) override
This function is called before painting onto the surface begins, with the region in which the paintin...
void recreateImage(QXcbWindow *win, const QSize &size) override
static void copy_swapped(char *dst, const int dstStride, const QImage &img, const QRect &rect)
void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset)
static QImage native_sub_image(QByteArray *buffer, const int dstStride, const QImage &src, const QRect &rect, bool swap)
static quint32 round_up_scanline(quint32 base, quint32 pad)
static void copy_unswapped(char *dst, int dstBytesPerLine, const QImage &img, const QRect &rect)
static size_t imageDataSize(const xcb_image_t *image)
#define Q_XCB_REPLY(call,...)
#define Q_XCB_REPLY_UNCHECKED(call,...)