Changeset View
Changeset View
Standalone View
Standalone View
effects/screenshot/screenshot.cpp
Show First 20 Lines • Show All 153 Lines • ▼ Show 20 Line(s) | 122 | { | |||
---|---|---|---|---|---|
154 | xcb_free_gc(c, gc); | 154 | xcb_free_gc(c, gc); | ||
155 | 155 | | |||
156 | return pixmap; | 156 | return pixmap; | ||
157 | } | 157 | } | ||
158 | 158 | | |||
159 | void ScreenShotEffect::paintScreen(int mask, const QRegion ®ion, ScreenPaintData &data) | 159 | void ScreenShotEffect::paintScreen(int mask, const QRegion ®ion, ScreenPaintData &data) | ||
160 | { | 160 | { | ||
161 | m_cachedOutputGeometry = data.outputGeometry(); | 161 | m_cachedOutputGeometry = data.outputGeometry(); | ||
162 | m_cachedScale = data.screenScale(); | ||||
162 | effects->paintScreen(mask, region, data); | 163 | effects->paintScreen(mask, region, data); | ||
163 | } | 164 | } | ||
164 | 165 | | |||
165 | void ScreenShotEffect::postPaintScreen() | 166 | void ScreenShotEffect::postPaintScreen() | ||
166 | { | 167 | { | ||
167 | effects->postPaintScreen(); | 168 | effects->postPaintScreen(); | ||
168 | if (m_scheduledScreenshot) { | 169 | if (m_scheduledScreenshot) { | ||
169 | WindowPaintData d(m_scheduledScreenshot); | 170 | WindowPaintData d(m_scheduledScreenshot); | ||
▲ Show 20 Lines • Show All 112 Lines • ▼ Show 20 Line(s) | 278 | #endif | |||
282 | if (!m_scheduledGeometry.isNull()) { | 283 | if (!m_scheduledGeometry.isNull()) { | ||
283 | if (!m_cachedOutputGeometry.isNull()) { | 284 | if (!m_cachedOutputGeometry.isNull()) { | ||
284 | // special handling for per-output geometry rendering | 285 | // special handling for per-output geometry rendering | ||
285 | const QRect intersection = m_scheduledGeometry.intersected(m_cachedOutputGeometry); | 286 | const QRect intersection = m_scheduledGeometry.intersected(m_cachedOutputGeometry); | ||
286 | if (intersection.isEmpty()) { | 287 | if (intersection.isEmpty()) { | ||
287 | // doesn't intersect, not going onto this screenshot | 288 | // doesn't intersect, not going onto this screenshot | ||
288 | return; | 289 | return; | ||
289 | } | 290 | } | ||
290 | const QImage img = blitScreenshot(intersection); | 291 | QImage img = blitScreenshot(intersection, m_cachedScale); | ||
291 | if (img.size() == m_scheduledGeometry.size()) { | 292 | if (img.size() == (m_scheduledGeometry.size() * m_cachedScale)) { | ||
292 | // we are done | 293 | // we are done | ||
293 | sendReplyImage(img); | 294 | sendReplyImage(img); | ||
294 | return; | 295 | return; | ||
295 | } | 296 | } | ||
297 | img.setDevicePixelRatio(m_cachedScale); | ||||
296 | if (m_multipleOutputsImage.isNull()) { | 298 | if (m_multipleOutputsImage.isNull()) { | ||
297 | m_multipleOutputsImage = QImage(m_scheduledGeometry.size(), QImage::Format_ARGB32); | 299 | m_multipleOutputsImage = QImage(m_scheduledGeometry.size(), QImage::Format_ARGB32); | ||
298 | m_multipleOutputsImage.fill(Qt::transparent); | 300 | m_multipleOutputsImage.fill(Qt::transparent); | ||
299 | } | 301 | } | ||
300 | QPainter p; | 302 | QPainter p; | ||
301 | p.begin(&m_multipleOutputsImage); | 303 | p.begin(&m_multipleOutputsImage); | ||
302 | p.drawImage(intersection.topLeft() - m_scheduledGeometry.topLeft(), img); | 304 | p.drawImage(intersection.topLeft() - m_scheduledGeometry.topLeft(), img); | ||
303 | p.end(); | 305 | p.end(); | ||
▲ Show 20 Lines • Show All 295 Lines • ▼ Show 20 Line(s) | 588 | { | |||
599 | } | 601 | } | ||
600 | m_captureCursor = captureCursor; | 602 | m_captureCursor = captureCursor; | ||
601 | m_replyMessage = message(); | 603 | m_replyMessage = message(); | ||
602 | setDelayedReply(true); | 604 | setDelayedReply(true); | ||
603 | effects->addRepaint(m_scheduledGeometry); | 605 | effects->addRepaint(m_scheduledGeometry); | ||
604 | return QString(); | 606 | return QString(); | ||
605 | } | 607 | } | ||
606 | 608 | | |||
607 | QImage ScreenShotEffect::blitScreenshot(const QRect &geometry) | 609 | QImage ScreenShotEffect::blitScreenshot(const QRect &geometry, const qreal scale) | ||
608 | { | 610 | { | ||
609 | QImage img; | 611 | QImage img; | ||
610 | if (effects->isOpenGLCompositing()) | 612 | if (effects->isOpenGLCompositing()) | ||
611 | { | 613 | { | ||
612 | img = QImage(geometry.size(), QImage::Format_ARGB32); | 614 | int width = geometry.width(); | ||
615 | int height = geometry.height(); | ||||
613 | if (GLRenderTarget::blitSupported() && !GLPlatform::instance()->isGLES()) { | 616 | if (GLRenderTarget::blitSupported() && !GLPlatform::instance()->isGLES()) { | ||
614 | GLTexture tex(GL_RGBA8, geometry.width(), geometry.height()); | 617 | | ||
618 | width = static_cast<int>(width * scale); | ||||
619 | height = static_cast<int>(height * scale); | ||||
620 | | ||||
621 | img = QImage(width, height, QImage::Format_ARGB32); | ||||
622 | GLTexture tex(GL_RGBA8, width, height); | ||||
615 | GLRenderTarget target(tex); | 623 | GLRenderTarget target(tex); | ||
616 | target.blitFromFramebuffer(geometry); | 624 | target.blitFromFramebuffer(geometry); | ||
617 | // copy content from framebuffer into image | 625 | // copy content from framebuffer into image | ||
618 | tex.bind(); | 626 | tex.bind(); | ||
619 | glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)img.bits()); | 627 | glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, static_cast<GLvoid*>(img.bits())); | ||
620 | tex.unbind(); | 628 | tex.unbind(); | ||
621 | } else { | 629 | } else { | ||
622 | glReadPixels(0, 0, img.width(), img.height(), GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)img.bits()); | 630 | img = QImage(width, height, QImage::Format_ARGB32); | ||
631 | glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)img.bits()); | ||||
623 | } | 632 | } | ||
624 | ScreenShotEffect::convertFromGLImage(img, geometry.width(), geometry.height()); | 633 | ScreenShotEffect::convertFromGLImage(img, width, height); | ||
625 | } | 634 | } | ||
626 | 635 | | |||
627 | #ifdef KWIN_HAVE_XRENDER_COMPOSITING | 636 | #ifdef KWIN_HAVE_XRENDER_COMPOSITING | ||
628 | if (effects->compositingType() == XRenderCompositing) { | 637 | if (effects->compositingType() == XRenderCompositing) { | ||
629 | xcb_image_t *xImage = nullptr; | 638 | xcb_image_t *xImage = nullptr; | ||
630 | img = xPictureToImage(effects->xrenderBufferPicture(), geometry, &xImage); | 639 | img = xPictureToImage(effects->xrenderBufferPicture(), geometry, &xImage); | ||
631 | if (xImage) { | 640 | if (xImage) { | ||
632 | xcb_image_destroy(xImage); | 641 | xcb_image_destroy(xImage); | ||
633 | } | 642 | } | ||
634 | } | 643 | } | ||
635 | #endif | 644 | #endif | ||
636 | 645 | | |||
637 | if (m_captureCursor) { | 646 | if (m_captureCursor) { | ||
638 | grabPointerImage(img, geometry.x(), geometry.y()); | 647 | grabPointerImage(img, geometry.x() * scale, geometry.y() * scale); | ||
639 | } | 648 | } | ||
640 | 649 | | |||
641 | return img; | 650 | return img; | ||
642 | } | 651 | } | ||
643 | 652 | | |||
644 | void ScreenShotEffect::grabPointerImage(QImage& snapshot, int offsetx, int offsety) | 653 | void ScreenShotEffect::grabPointerImage(QImage& snapshot, int offsetx, int offsety) | ||
645 | { | 654 | { | ||
646 | const auto cursor = effects->cursorImage(); | 655 | const auto cursor = effects->cursorImage(); | ||
▲ Show 20 Lines • Show All 66 Lines • Show Last 20 Lines |