Changeset View
Changeset View
Standalone View
Standalone View
effects/screenshot/screenshot.cpp
Show First 20 Lines • Show All 601 Lines • ▼ Show 20 Line(s) | 586 | { | |||
---|---|---|---|---|---|
602 | setDelayedReply(true); | 602 | setDelayedReply(true); | ||
603 | effects->addRepaint(m_scheduledGeometry); | 603 | effects->addRepaint(m_scheduledGeometry); | ||
604 | return QString(); | 604 | return QString(); | ||
605 | } | 605 | } | ||
606 | 606 | | |||
607 | QImage ScreenShotEffect::blitScreenshot(const QRect &geometry) | 607 | QImage ScreenShotEffect::blitScreenshot(const QRect &geometry) | ||
608 | { | 608 | { | ||
609 | QImage img; | 609 | QImage img; | ||
610 | qreal scale = 1; | ||||
611 | auto scaledGeometry = geometry; | ||||
612 | | ||||
610 | if (effects->isOpenGLCompositing()) | 613 | if (effects->isOpenGLCompositing()) | ||
611 | { | 614 | { | ||
612 | img = QImage(geometry.size(), QImage::Format_ARGB32); | 615 | int width = geometry.width(); | ||
616 | int height = geometry.height(); | ||||
613 | if (GLRenderTarget::blitSupported() && !GLPlatform::instance()->isGLES()) { | 617 | if (GLRenderTarget::blitSupported() && !GLPlatform::instance()->isGLES()) { | ||
614 | GLTexture tex(GL_RGBA8, geometry.width(), geometry.height()); | 618 | // HARDCODED, need to get this properly | ||
619 | // tried QGuiApplication::primaryScreen() | ||||
620 | // and GLRenderTarget::virtualScreenScale() | ||||
davidedmundson: Good question.
Use of Qt methods is slightly weird, as kwin implements it's own QPA which… | |||||
621 | scale = 2; | ||||
622 | width = static_cast<int>(width * scale); | ||||
623 | height = static_cast<int>(height * scale); | ||||
624 | img = QImage(width, height, QImage::Format_ARGB32); | ||||
625 | GLTexture tex(GL_RGBA8, width, height); | ||||
615 | GLRenderTarget target(tex); | 626 | GLRenderTarget target(tex); | ||
616 | target.blitFromFramebuffer(geometry); | 627 | const auto scaledGeometry = QRect(static_cast<int>(geometry.x() * scale), | ||
Avoid the term scaled in any variable name. It can mean scaled from logical to device, or scaled from device to logical. Which means it fails to convey the one piece of important information you're trying to say. use something like"deviceGeometry" davidedmundson: Avoid the term scaled in any variable name.
It can mean scaled from logical to device, or… | |||||
628 | static_cast<int>(geometry.y() * scale), | ||||
629 | width, height); | ||||
630 | target.blitFromFramebuffer(geometry, scaledGeometry); | ||||
617 | // copy content from framebuffer into image | 631 | // copy content from framebuffer into image | ||
618 | tex.bind(); | 632 | tex.bind(); | ||
619 | glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)img.bits()); | 633 | glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, static_cast<GLvoid*>(img.bits())); | ||
620 | tex.unbind(); | 634 | tex.unbind(); | ||
621 | } else { | 635 | } else { | ||
622 | glReadPixels(0, 0, img.width(), img.height(), GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)img.bits()); | 636 | img = QImage(width, height, QImage::Format_ARGB32); | ||
637 | glReadPixels(0, 0, img.width(), img.height(), GL_RGBA, GL_UNSIGNED_BYTE, static_cast<GLvoid*>(img.bits())); | ||||
623 | } | 638 | } | ||
624 | ScreenShotEffect::convertFromGLImage(img, geometry.width(), geometry.height()); | 639 | ScreenShotEffect::convertFromGLImage(img, width, height); | ||
625 | } | 640 | } | ||
626 | 641 | | |||
627 | #ifdef KWIN_HAVE_XRENDER_COMPOSITING | 642 | #ifdef KWIN_HAVE_XRENDER_COMPOSITING | ||
628 | if (effects->compositingType() == XRenderCompositing) { | 643 | if (effects->compositingType() == XRenderCompositing) { | ||
629 | xcb_image_t *xImage = nullptr; | 644 | xcb_image_t *xImage = nullptr; | ||
630 | img = xPictureToImage(effects->xrenderBufferPicture(), geometry, &xImage); | 645 | img = xPictureToImage(effects->xrenderBufferPicture(), scaledGeometry, &xImage); | ||
631 | if (xImage) { | 646 | if (xImage) { | ||
632 | xcb_image_destroy(xImage); | 647 | xcb_image_destroy(xImage); | ||
633 | } | 648 | } | ||
634 | } | 649 | } | ||
635 | #endif | 650 | #endif | ||
636 | 651 | | |||
637 | if (m_captureCursor) { | 652 | if (m_captureCursor) { | ||
638 | grabPointerImage(img, geometry.x(), geometry.y()); | 653 | grabPointerImage(img, static_cast<int>(geometry.x() * scale), static_cast<int>(geometry.y() * scale)); | ||
639 | } | 654 | } | ||
640 | 655 | | |||
641 | return img; | 656 | return img; | ||
642 | } | 657 | } | ||
643 | 658 | | |||
644 | void ScreenShotEffect::grabPointerImage(QImage& snapshot, int offsetx, int offsety) | 659 | void ScreenShotEffect::grabPointerImage(QImage& snapshot, int offsetx, int offsety) | ||
645 | { | 660 | { | ||
646 | const auto cursor = effects->cursorImage(); | 661 | const auto cursor = effects->cursorImage(); | ||
▲ Show 20 Lines • Show All 66 Lines • Show Last 20 Lines |
Good question.
Use of Qt methods is slightly weird, as kwin implements it's own QPA which means we're reading things via an abstraction layer rather than directly. In theory it should work, but you're going to struggle to tie a QScreen to what's being rendered.
Ideally we would want to use KWin::Screens() but that's not exposed to effects.
GLRenderTarget::virtualScreenScale() is currently only set to screen->scale during the paint method. This is postPaint. We could set it during pre/postPaint too.