From 760b2929a3b268e2edf14a561329bdb78fbdc26e Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Wed, 13 Apr 2016 16:20:40 -0700 Subject: xcb: Fix image scanline padding Commit b9d386f2ccd69c7f6a766a6d90a6024eeb48e90a neglects to account for the scanline padding requested by the X server. This can result in visual artifacts if padding is required. This commit fixes this by factoring in the X server's requested scanline padding when calculating image stride. Change-Id: I082cb7101ec3a9c554b9b58a76f53f780b87d31e Reviewed-by: Lars Knoll --- src/plugins/platforms/xcb/qxcbbackingstore.cpp | 37 +++++++++++++++----------- 1 file changed, 22 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index 844ed8f579..51c6b198e5 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -305,47 +305,52 @@ static inline void copy_unswapped(char *dst, int dstBytesPerLine, const QImage & } template -static inline void copy_swapped(Pixel *dst, const QImage &img, const QRect &rect) +static inline void copy_swapped(char *dst, const int dstStride, const QImage &img, const QRect &rect) { const uchar *srcData = img.constBits(); const int srcBytesPerLine = img.bytesPerLine(); const int left = rect.left(); - const int right = rect.right() + 1; + const int width = rect.width(); const int bottom = rect.bottom() + 1; for (int yy = rect.top(); yy < bottom; ++yy) { - const Pixel *src = reinterpret_cast(srcData + yy * srcBytesPerLine) + left; + Pixel *dstPixels = reinterpret_cast(dst); + const Pixel *srcPixels = reinterpret_cast(srcData + yy * srcBytesPerLine) + left; - for (int xx = left; xx < right; ++xx) - *dst++ = qbswap(*src++); + for (int i = 0; i < width; ++i) + dstPixels[i] = qbswap(*srcPixels++); + + dst += dstStride; } } -static QImage native_sub_image(QByteArray *buffer, const QImage &src, int x, int y, int w, int h, bool swap) +static QImage native_sub_image(QByteArray *buffer, const int dstStride, const QImage &src, const QRect &rect, bool swap) { - const QRect rect(x, y, w, h); - - if (!swap && src.rect() == rect) + if (!swap && src.rect() == rect && src.bytesPerLine() == dstStride) return src; - const int dstStride = w * src.depth() >> 3; - buffer->resize(h * dstStride); + buffer->resize(rect.height() * dstStride); if (swap) { switch (src.depth()) { case 32: - copy_swapped(reinterpret_cast(buffer->data()), src, rect); + copy_swapped(buffer->data(), dstStride, src, rect); break; case 16: - copy_swapped(reinterpret_cast(buffer->data()), src, rect); + copy_swapped(buffer->data(), dstStride, src, rect); break; } } else { copy_unswapped(buffer->data(), dstStride, src, rect); } - return QImage(reinterpret_cast(buffer->constData()), w, h, dstStride, src.format()); + return QImage(reinterpret_cast(buffer->constData()), rect.width(), rect.height(), dstStride, src.format()); +} + +static inline quint32 round_up_scanline(quint32 base, quint32 pad) +{ + return (base + pad - 1) & -pad; } void QXcbShmImage::flushPixmap(const QRegion ®ion) @@ -390,7 +395,9 @@ void QXcbShmImage::flushPixmap(const QRegion ®ion) while (height > 0) { const int rows = std::min(height, rows_per_put); - const QImage subImage = native_sub_image(&m_flushBuffer, m_qimage, x, y, width, rows, needsByteSwap); + const QRect subRect(x, y, width, rows); + const quint32 stride = round_up_scanline(width * m_qimage.depth(), xcb_subimage.scanline_pad) >> 3; + const QImage subImage = native_sub_image(&m_flushBuffer, stride, m_qimage, subRect, needsByteSwap); xcb_subimage.width = width; xcb_subimage.height = rows; -- cgit v1.2.3