diff --git a/effects/screenshot/screenshot.h b/effects/screenshot/screenshot.h --- a/effects/screenshot/screenshot.h +++ b/effects/screenshot/screenshot.h @@ -141,7 +141,7 @@ private: void grabPointerImage(QImage& snapshot, int offsetx, int offsety); - QImage blitScreenshot(const QRect &geometry); + QImage blitScreenshot(const QRect &geometry, const qreal scale = 1.0); QString saveTempImage(const QImage &img); void sendReplyImage(const QImage &img); enum class InfoMessageMode { @@ -167,6 +167,7 @@ }; WindowMode m_windowMode = WindowMode::NoCapture; int m_fd = -1; + qreal m_cachedScale; }; } // namespace diff --git a/effects/screenshot/screenshot.cpp b/effects/screenshot/screenshot.cpp --- a/effects/screenshot/screenshot.cpp +++ b/effects/screenshot/screenshot.cpp @@ -159,6 +159,7 @@ void ScreenShotEffect::paintScreen(int mask, const QRegion ®ion, ScreenPaintData &data) { m_cachedOutputGeometry = data.outputGeometry(); + m_cachedScale = data.screenScale(); effects->paintScreen(mask, region, data); } @@ -287,12 +288,13 @@ // doesn't intersect, not going onto this screenshot return; } - const QImage img = blitScreenshot(intersection); - if (img.size() == m_scheduledGeometry.size()) { + QImage img = blitScreenshot(intersection, m_cachedScale); + if (img.size() == (m_scheduledGeometry.size() * m_cachedScale)) { // we are done sendReplyImage(img); return; } + img.setDevicePixelRatio(m_cachedScale); if (m_multipleOutputsImage.isNull()) { m_multipleOutputsImage = QImage(m_scheduledGeometry.size(), QImage::Format_ARGB32); m_multipleOutputsImage.fill(Qt::transparent); @@ -604,24 +606,31 @@ return QString(); } -QImage ScreenShotEffect::blitScreenshot(const QRect &geometry) +QImage ScreenShotEffect::blitScreenshot(const QRect &geometry, const qreal scale) { QImage img; if (effects->isOpenGLCompositing()) { - img = QImage(geometry.size(), QImage::Format_ARGB32); + int width = geometry.width(); + int height = geometry.height(); if (GLRenderTarget::blitSupported() && !GLPlatform::instance()->isGLES()) { - GLTexture tex(GL_RGBA8, geometry.width(), geometry.height()); + + width = static_cast(width * scale); + height = static_cast(height * scale); + + img = QImage(width, height, QImage::Format_ARGB32); + GLTexture tex(GL_RGBA8, width, height); GLRenderTarget target(tex); target.blitFromFramebuffer(geometry); // copy content from framebuffer into image tex.bind(); - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)img.bits()); + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, static_cast(img.bits())); tex.unbind(); } else { - glReadPixels(0, 0, img.width(), img.height(), GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)img.bits()); + img = QImage(width, height, QImage::Format_ARGB32); + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)img.bits()); } - ScreenShotEffect::convertFromGLImage(img, geometry.width(), geometry.height()); + ScreenShotEffect::convertFromGLImage(img, width, height); } #ifdef KWIN_HAVE_XRENDER_COMPOSITING @@ -635,7 +644,7 @@ #endif if (m_captureCursor) { - grabPointerImage(img, geometry.x(), geometry.y()); + grabPointerImage(img, geometry.x() * scale, geometry.y() * scale); } return img; diff --git a/libkwineffects/kwineffects.h b/libkwineffects/kwineffects.h --- a/libkwineffects/kwineffects.h +++ b/libkwineffects/kwineffects.h @@ -2991,7 +2991,7 @@ { public: ScreenPaintData(); - ScreenPaintData(const QMatrix4x4 &projectionMatrix, const QRect &outputGeometry = QRect()); + ScreenPaintData(const QMatrix4x4 &projectionMatrix, const QRect &outputGeometry = QRect(), const qreal screenScale = 1.0); ScreenPaintData(const ScreenPaintData &other); ~ScreenPaintData() override; /** @@ -3053,6 +3053,13 @@ * @since 5.9 */ QRect outputGeometry() const; + + /** + * The scale factor for the output + * + * @since 5.19 + */ + qreal screenScale() const; private: class Private; QScopedPointer d; diff --git a/libkwineffects/kwineffects.cpp b/libkwineffects/kwineffects.cpp --- a/libkwineffects/kwineffects.cpp +++ b/libkwineffects/kwineffects.cpp @@ -423,20 +423,22 @@ public: QMatrix4x4 projectionMatrix; QRect outputGeometry; + qreal screenScale; }; ScreenPaintData::ScreenPaintData() : PaintData() , d(new Private()) { } -ScreenPaintData::ScreenPaintData(const QMatrix4x4 &projectionMatrix, const QRect &outputGeometry) +ScreenPaintData::ScreenPaintData(const QMatrix4x4 &projectionMatrix, const QRect &outputGeometry, const qreal screenScale) : PaintData() , d(new Private()) { d->projectionMatrix = projectionMatrix; d->outputGeometry = outputGeometry; + d->screenScale = screenScale; } ScreenPaintData::~ScreenPaintData() = default; @@ -526,6 +528,11 @@ return d->outputGeometry; } +qreal ScreenPaintData::screenScale() const +{ + return d->screenScale; +} + //**************************************** // Effect //**************************************** 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 @@ -649,7 +649,7 @@ int mask = 0; updateProjectionMatrix(); - paintScreen(&mask, damage.intersected(geo), repaint, &update, &valid, projectionMatrix(), geo); // call generic implementation + paintScreen(&mask, damage.intersected(geo), repaint, &update, &valid, projectionMatrix(), geo, screens()->scale(i)); // call generic implementation paintCursor(); GLVertexBuffer::streamingBuffer()->endOfFrame(); diff --git a/scene.h b/scene.h --- a/scene.h +++ b/scene.h @@ -213,7 +213,7 @@ void clearStackingOrder(); // shared implementation, starts painting the screen void paintScreen(int *mask, const QRegion &damage, const QRegion &repaint, - QRegion *updateRegion, QRegion *validRegion, const QMatrix4x4 &projection = QMatrix4x4(), const QRect &outputGeometry = QRect()); + QRegion *updateRegion, QRegion *validRegion, const QMatrix4x4 &projection = QMatrix4x4(), const QRect &outputGeometry = QRect(), const qreal screenScale = 1.0); // Render cursor texture in case hardware cursor is disabled/non-applicable virtual void paintCursor() = 0; friend class EffectsHandlerImpl; diff --git a/scene.cpp b/scene.cpp --- a/scene.cpp +++ b/scene.cpp @@ -105,7 +105,7 @@ // returns mask and possibly modified region void Scene::paintScreen(int* mask, const QRegion &damage, const QRegion &repaint, - QRegion *updateRegion, QRegion *validRegion, const QMatrix4x4 &projection, const QRect &outputGeometry) + QRegion *updateRegion, QRegion *validRegion, const QMatrix4x4 &projection, const QRect &outputGeometry, const qreal screenScale) { const QSize &screenSize = screens()->size(); const QRegion displayRegion(0, 0, screenSize.width(), screenSize.height()); @@ -145,7 +145,7 @@ paintBackground(region); } - ScreenPaintData data(projection, outputGeometry); + ScreenPaintData data(projection, outputGeometry, screenScale); effects->paintScreen(*mask, region, data); foreach (Window *w, stacking_order) {