diff --git a/plugins/scenes/opengl/scene_opengl.cpp b/plugins/scenes/opengl/scene_opengl.cpp --- a/plugins/scenes/opengl/scene_opengl.cpp +++ b/plugins/scenes/opengl/scene_opengl.cpp @@ -51,6 +51,7 @@ #include #include +#include #include #include #include @@ -2438,6 +2439,47 @@ return image; } +static inline void padScanLine(const uint *src, uint *dest, int size, int padding) +{ + std::fill(dest, dest + padding, *src); + dest += padding; + + std::copy(src, src + size, dest); + dest += size; + + std::fill(dest, dest + padding, *(src + size - 1)); +} + +static QImage pad(const QImage &src, int padding) +{ + const qreal dpr = src.devicePixelRatio(); + + QImage dest(src.size() + QSize(padding * 2, padding * 2), src.format()); + dest.setDevicePixelRatio(dpr); + + const uint *srcData = reinterpret_cast(src.scanLine(0)); + uint *destData = reinterpret_cast(dest.scanLine(0)); + + for (int i = 0; i < padding; i++) { + padScanLine(srcData, destData, src.width(), padding); + destData += dest.width(); + } + + for (int i = 0; i < src.height(); i++) { + padScanLine(srcData, destData, src.width(), padding); + srcData += src.width(); + destData += dest.width(); + } + + srcData -= src.width(); + for (int i = 0; i < padding; i++) { + padScanLine(srcData, destData, src.width(), padding); + destData += dest.width(); + } + + return dest; +} + void SceneOpenGLDecorationRenderer::render() { const QRegion scheduled = getScheduled(); @@ -2460,21 +2502,26 @@ const QRect geometry = dirty ? QRect(QPoint(0, 0), client()->client()->geometry().size()) : scheduled.boundingRect(); - auto renderPart = [this](const QRect &geo, const QRect &partRect, const QPoint &offset, bool rotated = false) { + const int padding = 1; + const int spacing = 1; + + auto renderPart = [this, padding](const QRect &geo, const QRect &partRect, const QPoint &offset, bool rotated = false) { if (geo.isNull()) { return; } QImage image = renderToImage(geo); if (rotated) { // TODO: get this done directly when rendering to the image image = rotate(image, QRect(geo.topLeft() - partRect.topLeft(), geo.size())); } + // Need to pad each part in order to avoid texture bleeding. + image = pad(image, padding); m_texture->update(image, (geo.topLeft() - partRect.topLeft() + offset) * image.devicePixelRatio()); }; - renderPart(left.intersected(geometry), left, QPoint(0, top.height() + bottom.height() + 2), true); - renderPart(top.intersected(geometry), top, QPoint(0, 0)); - renderPart(right.intersected(geometry), right, QPoint(0, top.height() + bottom.height() + left.width() + 3), true); - renderPart(bottom.intersected(geometry), bottom, QPoint(0, top.height() + 1)); + renderPart(top.intersected(geometry), top, QPoint(0, 0 * (2 * padding + spacing))); + renderPart(bottom.intersected(geometry), bottom, QPoint(0, top.height() + 1 * (2 * padding + spacing))); + renderPart(left.intersected(geometry), left, QPoint(0, top.height() + bottom.height() + 2 * (2 * padding + spacing)), true); + renderPart(right.intersected(geometry), right, QPoint(0, top.height() + bottom.height() + left.width() + 3 * (2 * padding + spacing)), true); } static int align(int value, int align) @@ -2488,10 +2535,14 @@ client()->client()->layoutDecorationRects(left, top, right, bottom); QSize size; + const int padding = 1; + const int spacing = 1; + size.rwidth() = qMax(qMax(top.width(), bottom.width()), qMax(left.height(), right.height())); size.rheight() = top.height() + bottom.height() + - left.width() + right.width() + 3; + left.width() + right.width() + + 3 * spacing + 4 * 2 * padding; size.rwidth() = align(size.width(), 128); diff --git a/scene.cpp b/scene.cpp --- a/scene.cpp +++ b/scene.cpp @@ -884,11 +884,22 @@ { WindowQuadList list; + const int padding = 1; + const int spacing = 1; + const QPoint offsets[4] = { - QPoint(-rects[0].x() + rects[1].height() + rects[3].height() + 2, -rects[0].y()), // Left - QPoint(-rects[1].x(), -rects[1].y()), // Top - QPoint(-rects[2].x() + rects[1].height() + rects[3].height() + rects[0].width() + 3, -rects[2].y()), // Right - QPoint(-rects[3].x(), -rects[3].y() + rects[1].height() + 1) // Bottom + // Left + QPoint(-rects[0].x() + rects[1].height() + rects[3].height() + 2 * (2 * padding + spacing) + padding, + -rects[0].y() + padding), + // Top + QPoint(-rects[1].x() + padding, + -rects[1].y() + 0 * (2 * padding + spacing) + padding), + // Right + QPoint(-rects[2].x() + rects[1].height() + rects[3].height() + rects[0].width() + 3 * (2 * padding + spacing) + padding, + -rects[2].y() + padding), + // Bottom + QPoint(-rects[3].x() + padding, + -rects[3].y() + rects[1].height() + 1 * (2 * padding + spacing) + padding) }; const Qt::Orientation orientations[4] = {