diff --git a/autotests/mock_effectshandler.h b/autotests/mock_effectshandler.h
index 9eeeafc117..b2aacfea26 100644
--- a/autotests/mock_effectshandler.h
+++ b/autotests/mock_effectshandler.h
@@ -278,6 +278,9 @@ public:
KSharedConfigPtr config() const override;
KSharedConfigPtr inputConfig() const override;
+ void renderEffectQuickView(KWin::EffectQuickView *quickView) const override {
+ Q_UNUSED(quickView);
+ }
private:
bool m_animationsSuported = true;
diff --git a/effects.cpp b/effects.cpp
index 07ede0ceea..429c31526b 100644
--- a/effects.cpp
+++ b/effects.cpp
@@ -46,9 +46,9 @@ along with this program. If not, see .
#include "window_property_notify_x11_filter.h"
#include "workspace.h"
#include "kwinglutils.h"
+#include "kwineffectquickview.h"
#include
-#include
#include
@@ -1702,6 +1702,14 @@ Effect *EffectsHandlerImpl::findEffect(const QString &name) const
return (*it).second;
}
+void EffectsHandlerImpl::renderEffectQuickView(EffectQuickView *w) const
+{
+ if (!w->isVisible()) {
+ return;
+ }
+ scene()->paintEffectQuickView(w);
+}
+
//****************************************
// EffectWindowImpl
//****************************************
diff --git a/effects.h b/effects.h
index 2419fc5724..23c5927497 100644
--- a/effects.h
+++ b/effects.h
@@ -273,6 +273,8 @@ public:
*/
Effect *findEffect(const QString &name) const;
+ void renderEffectQuickView(EffectQuickView *effectQuickView) const override;
+
public Q_SLOTS:
void slotCurrentTabAboutToChange(EffectWindow* from, EffectWindow* to);
void slotTabAdded(EffectWindow* from, EffectWindow* to);
diff --git a/libkwineffects/CMakeLists.txt b/libkwineffects/CMakeLists.txt
index cf1a025a83..4f8b81701a 100644
--- a/libkwineffects/CMakeLists.txt
+++ b/libkwineffects/CMakeLists.txt
@@ -40,6 +40,7 @@ install(TARGETS kwinxrenderutils EXPORT kdeworkspaceLibraryTargets ${INSTALL_TAR
set(kwin_EFFECTSLIB_SRCS
anidata.cpp
kwinanimationeffect.cpp
+ kwineffectquickview.cpp
kwineffects.cpp
logging.cpp
)
@@ -47,12 +48,14 @@ set(kwin_EFFECTSLIB_SRCS
set(kwineffects_QT_LIBS
Qt5::DBus
Qt5::Widgets
+ Qt5::Quick
)
set(kwineffects_KDE_LIBS
KF5::ConfigCore
KF5::CoreAddons
KF5::WindowSystem
+ KF5::Declarative
)
set(kwineffects_XCB_LIBS
@@ -66,6 +69,7 @@ target_link_libraries(kwineffects
${kwineffects_QT_LIBS}
${kwineffects_KDE_LIBS}
${kwineffects_XCB_LIBS}
+ kwinglutils
)
if (KWIN_HAVE_XRENDER_COMPOSITING)
target_link_libraries(kwineffects PRIVATE kwinxrenderutils XCB::XFIXES)
@@ -112,6 +116,7 @@ install(FILES
${CMAKE_CURRENT_BINARY_DIR}/kwinglutils_export.h
${CMAKE_CURRENT_BINARY_DIR}/kwinxrenderutils_export.h
kwinanimationeffect.h
+ kwineffectquickview.h
kwineffects.h
kwinglobals.h
kwinglplatform.h
diff --git a/libkwineffects/kwineffectquickview.cpp b/libkwineffects/kwineffectquickview.cpp
new file mode 100644
index 0000000000..f3d4f876bf
--- /dev/null
+++ b/libkwineffects/kwineffectquickview.cpp
@@ -0,0 +1,357 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2019 David Edmundson
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*********************************************************************/
+
+#include "kwineffectquickview.h"
+
+#include "kwinglutils.h"
+#include "kwineffects.h"
+#include "logging_p.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+
+using namespace KWin;
+
+static std::unique_ptr s_shareContext;
+
+class Q_DECL_HIDDEN EffectQuickView::Private
+{
+public:
+ QQuickWindow *m_view;
+ QQuickRenderControl *m_renderControl;
+ QScopedPointer m_glcontext;
+ QScopedPointer m_offscreenSurface;
+ QScopedPointer m_fbo;
+
+ QImage m_image;
+ QScopedPointer m_textureExport;
+ // if we should capture a QImage after rendering into our BO.
+ // Used for either software QtQuick rendering and nonGL kwin rendering
+ bool m_useBlit = false;
+ bool m_visible = true;
+
+ void releaseResources();
+};
+
+class Q_DECL_HIDDEN EffectQuickScene::Private
+{
+public:
+ KDeclarative::QmlObjectSharedEngine *qmlObject = nullptr;
+};
+
+EffectQuickView::EffectQuickView(QObject *parent)
+ : EffectQuickView(parent, effects->isOpenGLCompositing() ? ExportMode::Texture : ExportMode::Image)
+{
+}
+
+EffectQuickView::EffectQuickView(QObject *parent, ExportMode exportMode)
+ : QObject(parent)
+ , d(new EffectQuickView::Private)
+{
+ d->m_renderControl = new QQuickRenderControl(this);
+
+ d->m_view = new QQuickWindow(d->m_renderControl);
+ d->m_view->setFlags(Qt::FramelessWindowHint);
+ d->m_view->setColor(Qt::transparent);
+
+ if (exportMode == ExportMode::Image) {
+ d->m_useBlit = true;
+ }
+
+ const bool usingGl = d->m_view->rendererInterface()->graphicsApi() == QSGRendererInterface::OpenGL;
+
+ if (!usingGl) {
+ qCDebug(LIBKWINEFFECTS) << "QtQuick Software rendering mode detected";
+ d->m_useBlit = true;
+ d->m_renderControl->initialize(nullptr);
+ } else {
+ QSurfaceFormat format;
+ format.setOption(QSurfaceFormat::ResetNotification);
+ format.setDepthBufferSize(16);
+ format.setStencilBufferSize(8);
+
+ d->m_glcontext.reset(new QOpenGLContext);
+ d->m_glcontext->setShareContext(s_shareContext.get());
+ d->m_glcontext->setFormat(format);
+ d->m_glcontext->create();
+
+ // and the offscreen surface
+ d->m_offscreenSurface.reset(new QOffscreenSurface);
+ d->m_offscreenSurface->setFormat(d->m_glcontext->format());
+ d->m_offscreenSurface->create();
+
+ d->m_glcontext->makeCurrent(d->m_offscreenSurface.data());
+ d->m_renderControl->initialize(d->m_glcontext.data());
+ d->m_glcontext->doneCurrent();
+
+ if (!d->m_glcontext->shareContext()) {
+ qCDebug(LIBKWINEFFECTS) << "Failed to create a shared context, falling back to raster rendering";
+
+ qCDebug(LIBKWINEFFECTS) << "Extra debug:";
+ qCDebug(LIBKWINEFFECTS) << "our context:" << d->m_glcontext.data();
+ qCDebug(LIBKWINEFFECTS) << "share context:" << s_shareContext.get();
+
+ // still render via GL, but blit for presentation
+ d->m_useBlit = true;
+ }
+ }
+
+ auto updateSize = [this]() { contentItem()->setSize(d->m_view->size()); };
+ updateSize();
+ connect(d->m_view, &QWindow::widthChanged, this, updateSize);
+ connect(d->m_view, &QWindow::heightChanged, this, updateSize);
+
+ QTimer *t = new QTimer(this);
+ t->setSingleShot(true);
+ t->setInterval(10);
+
+ connect(t, &QTimer::timeout, this, &EffectQuickView::update);
+ connect(d->m_renderControl, &QQuickRenderControl::renderRequested, t, [t]() { t->start(); });
+ connect(d->m_renderControl, &QQuickRenderControl::sceneChanged, t, [t]() { t->start(); });
+}
+
+EffectQuickView::~EffectQuickView()
+{
+ if (d->m_glcontext) {
+ d->m_glcontext->makeCurrent(d->m_offscreenSurface.data());
+ d->m_renderControl->invalidate();
+ d->m_glcontext->doneCurrent();
+ }
+}
+
+void EffectQuickView::update()
+{
+ if (!d->m_visible) {
+ return;
+ }
+ if (d->m_view->size().isEmpty()) {
+ return;
+ }
+
+ bool usingGl = d->m_glcontext;
+
+ if (usingGl) {
+ if (!d->m_glcontext->makeCurrent(d->m_offscreenSurface.data())) {
+ // probably a context loss event, kwin is about to reset all the effects anyway
+ return;
+ }
+
+ if (d->m_fbo.isNull() || d->m_fbo->size() != d->m_view->size()) {
+ d->m_textureExport.reset(nullptr);
+ d->m_fbo.reset(new QOpenGLFramebufferObject(d->m_view->size(), QOpenGLFramebufferObject::CombinedDepthStencil));
+ if (!d->m_fbo->isValid()) {
+ d->m_fbo.reset();
+ d->m_glcontext->doneCurrent();
+ return;
+ }
+ }
+ d->m_view->setRenderTarget(d->m_fbo.data());
+ }
+
+ d->m_renderControl->polishItems();
+ d->m_renderControl->sync();
+
+ d->m_renderControl->render();
+ if (usingGl) {
+ d->m_view->resetOpenGLState();
+ }
+
+ if (d->m_useBlit) {
+ d->m_image = d->m_renderControl->grab();
+ }
+
+ if (usingGl) {
+ QOpenGLFramebufferObject::bindDefault();
+ d->m_glcontext->doneCurrent();
+ }
+ emit repaintNeeded();
+}
+
+void EffectQuickView::forwardMouseEvent(QEvent *e)
+{
+ if (!d->m_visible) {
+ return;
+ }
+ QMouseEvent *me = static_cast(e);
+ const QPoint widgetPos = d->m_view->mapFromGlobal(me->pos());
+
+ QMouseEvent cloneEvent(me->type(), widgetPos, me->pos(), me->button(), me->buttons(), me->modifiers());
+ QCoreApplication::sendEvent(d->m_view, &cloneEvent);
+ e->setAccepted(cloneEvent.isAccepted());
+}
+
+void EffectQuickView::forwardKeyEvent(QKeyEvent *keyEvent)
+{
+ if (!d->m_visible) {
+ return;
+ }
+ QCoreApplication::sendEvent(d->m_view, keyEvent);
+}
+
+void EffectQuickView::setShareContext(std::unique_ptr context)
+{
+ s_shareContext = std::move(context);
+}
+
+QRect EffectQuickView::geometry() const
+{
+ return d->m_view->geometry();
+}
+
+QQuickItem *EffectQuickView::contentItem() const
+{
+ return d->m_view->contentItem();
+}
+
+void EffectQuickView::setVisible(bool visible)
+{
+ if (d->m_visible == visible) {
+ return;
+ }
+ d->m_visible = visible;
+
+ if (visible){
+ d->m_renderControl->renderRequested();
+ } else {
+ // deferred to not change GL context
+ QTimer::singleShot(0, this, [this]() {
+ d->releaseResources();
+ });
+ }
+}
+
+bool EffectQuickView::isVisible() const
+{
+ return d->m_visible;
+}
+
+void EffectQuickView::show()
+{
+ setVisible(true);
+}
+
+void EffectQuickView::hide()
+{
+ setVisible(false);
+}
+
+GLTexture *EffectQuickView::bufferAsTexture()
+{
+ if (d->m_useBlit) {
+ if (d->m_image.isNull()) {
+ return nullptr;
+ }
+ d->m_textureExport.reset(new GLTexture(d->m_image));
+ } else {
+ if (!d->m_fbo) {
+ return nullptr;
+ }
+ if (!d->m_textureExport) {
+ d->m_textureExport.reset(new GLTexture(d->m_fbo->texture(), d->m_fbo->format().internalTextureFormat(), d->m_fbo->size()));
+ }
+ }
+ return d->m_textureExport.data();
+}
+
+QImage EffectQuickView::bufferAsImage() const
+{
+ return d->m_image;
+}
+
+QSize EffectQuickView::size() const
+{
+ return d->m_view->geometry().size();
+}
+
+void EffectQuickView::setGeometry(const QRect &rect)
+{
+ const QRect oldGeometry = d->m_view->geometry();
+ d->m_view->setGeometry(rect);
+ emit geometryChanged(oldGeometry, rect);
+}
+
+void EffectQuickView::Private::releaseResources()
+{
+ if (m_glcontext) {
+ m_glcontext->makeCurrent(m_offscreenSurface.data());
+ m_view->releaseResources();
+ m_glcontext->doneCurrent();
+ } else {
+ m_view->releaseResources();
+ }
+}
+
+EffectQuickScene::EffectQuickScene(QObject *parent)
+ : EffectQuickView(parent)
+ , d(new EffectQuickScene::Private)
+{
+}
+
+EffectQuickScene::EffectQuickScene(QObject *parent, EffectQuickView::ExportMode exportMode)
+ : EffectQuickView(parent, exportMode)
+ , d(new EffectQuickScene::Private)
+{
+}
+
+EffectQuickScene::~EffectQuickScene()
+{
+}
+
+void EffectQuickScene::setSource(const QUrl &source)
+{
+ if (!d->qmlObject) {
+ d->qmlObject = new KDeclarative::QmlObjectSharedEngine(this);
+ }
+ d->qmlObject->setSource(source);
+
+ QQuickItem *item = rootItem();
+ if (!item) {
+ qCDebug(LIBKWINEFFECTS) << "Could not load effect quick view" << source;
+ return;
+ }
+ item->setParentItem(contentItem());
+
+ auto updateSize = [item, this]() { item->setSize(contentItem()->size()); };
+ updateSize();
+ connect(contentItem(), &QQuickItem::widthChanged, item, updateSize);
+ connect(contentItem(), &QQuickItem::heightChanged, item, updateSize);
+}
+
+QQmlContext *EffectQuickScene::rootContext() const
+{
+ return d->qmlObject->rootContext();
+}
+
+QQuickItem *EffectQuickScene::rootItem() const
+{
+ return qobject_cast(d->qmlObject->rootObject());
+}
diff --git a/libkwineffects/kwineffectquickview.h b/libkwineffects/kwineffectquickview.h
new file mode 100644
index 0000000000..9c2252b5ba
--- /dev/null
+++ b/libkwineffects/kwineffectquickview.h
@@ -0,0 +1,179 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2019 David Edmundson
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*********************************************************************/
+
+#pragma once
+
+#include
+#include
+#include
+
+#include
+
+#include "kwineffects.h"
+
+#include
+
+class QKeyEvent;
+class QMouseEvent;
+class QOpenGLContext;
+
+class QMouseEvent;
+class QKeyEvent;
+
+class QQmlContext;
+class QQuickItem;
+
+namespace KWin
+{
+class GLTexture;
+
+class EffectQuickView;
+
+/**
+ * @brief The KwinQuickView class provides a convenient API for exporting
+ * QtQuick scenes as buffers that can be composited in any other fashion.
+ *
+ * Contents can be fetched as a GL Texture or as a QImage
+ * If data is to be fetched as an image, it should be specified upfront as
+ * blitting is performed when we update our FBO to keep kwin's render loop
+ * as fast as possible.
+ */
+class KWINEFFECTS_EXPORT EffectQuickView : public QObject
+{
+ Q_OBJECT
+
+public:
+ static void setShareContext(std::unique_ptr context);
+
+ enum class ExportMode {
+ /** The contents will be available as a texture in the shared contexts. Image will be blank*/
+ Texture,
+ /** The contents will be blit during the update into a QImage buffer. */
+ Image
+ };
+
+ /**
+ * Construct a new KWinQuickView
+ * Export mode will be determined by the current effectsHandler
+ */
+ EffectQuickView(QObject *parent);
+
+ /**
+ * Construct a new KWinQuickView explicitly stating an export mode
+ */
+ EffectQuickView(QObject *parent, ExportMode exportMode);
+
+ /**
+ * Note that this may change the current GL Context
+ */
+ ~EffectQuickView();
+
+ QSize size() const;
+
+ /**
+ * The geometry of the current view
+ * This may be out of sync with the current buffer size if an update is pending
+ */
+ void setGeometry(const QRect &rect);
+ QRect geometry() const;
+
+ /**
+ * Render the current scene graph into the FBO.
+ * This is typically done automatically when the scene changes
+ * albeit deffered by a timer
+ *
+ * It can be manually invoked to update the contents immediately.
+ * Note this will change the GL context
+ */
+ void update();
+
+ /** The invisble root item of the window*/
+ QQuickItem *contentItem() const;
+
+ /**
+ * @brief Marks the window as visible/invisible
+ * This can be used to release resources used by the window
+ * The default is true.
+ */
+ void setVisible(bool visible);
+ bool isVisible() const;
+
+ void show();
+ void hide();
+
+ /**
+ * Returns the current output of the scene graph
+ * @note The render context must valid at the time of calling
+ */
+ GLTexture *bufferAsTexture();
+
+ /**
+ * Returns the current output of the scene graph
+ */
+ QImage bufferAsImage() const;
+
+ /**
+ * Inject any mouse event into the QQuickWindow.
+ * Local co-ordinates are transformed
+ * If it is handled the event will be accepted
+ */
+ void forwardMouseEvent(QEvent *mouseEvent);
+ /**
+ * Inject a key event into the window.
+ * If it is handled the event will be accepted
+ */
+ void forwardKeyEvent(QKeyEvent *keyEvent);
+
+Q_SIGNALS:
+ /**
+ * The frame buffer has changed, contents need re-rendering on screen
+ */
+ void repaintNeeded();
+ void geometryChanged(const QRect &oldGeometry, const QRect &newGeometry);
+
+private:
+ class Private;
+ QScopedPointer d;
+};
+
+/**
+ * The KWinQuickScene class extends KWinQuickView
+ * adding QML support. This will represent a context
+ * powered by an engine
+ */
+class KWINEFFECTS_EXPORT EffectQuickScene : public EffectQuickView
+{
+public:
+ EffectQuickScene(QObject *parent);
+ EffectQuickScene(QObject *parent, ExportMode exportMode);
+ ~EffectQuickScene();
+
+ QQmlContext *rootContext() const;
+ /** top level item in the given source*/
+ QQuickItem *rootItem() const;
+
+ void setSource(const QUrl &source);
+
+private:
+ class Private;
+ QScopedPointer d;
+};
+
+}
diff --git a/libkwineffects/kwineffects.h b/libkwineffects/kwineffects.h
index bda19ae3b5..bf5a24a9c1 100644
--- a/libkwineffects/kwineffects.h
+++ b/libkwineffects/kwineffects.h
@@ -82,6 +82,7 @@ class EffectWindow;
class EffectWindowGroup;
class EffectFrame;
class EffectFramePrivate;
+class EffectQuickView;
class Effect;
class WindowQuad;
class GLShader;
@@ -187,7 +188,7 @@ X-KDE-Library=kwin4_effect_cooleffect
#define KWIN_EFFECT_API_MAKE_VERSION( major, minor ) (( major ) << 8 | ( minor ))
#define KWIN_EFFECT_API_VERSION_MAJOR 0
-#define KWIN_EFFECT_API_VERSION_MINOR 228
+#define KWIN_EFFECT_API_VERSION_MINOR 229
#define KWIN_EFFECT_API_VERSION KWIN_EFFECT_API_MAKE_VERSION( \
KWIN_EFFECT_API_VERSION_MAJOR, KWIN_EFFECT_API_VERSION_MINOR )
@@ -1359,6 +1360,13 @@ public:
*/
virtual bool hasActiveFullScreenEffect() const = 0;
+ /**
+ * Render the supplied EffectQuickView onto the scene
+ * It can be called at any point during the scene rendering
+ * @since 5.18
+ */
+ virtual void renderEffectQuickView(EffectQuickView *effectQuickView) const = 0;
+
Q_SIGNALS:
/**
* Signal emitted when the current desktop changed.
diff --git a/plugins/platforms/x11/standalone/CMakeLists.txt b/plugins/platforms/x11/standalone/CMakeLists.txt
index 6bfbc4a032..3d339c09e9 100644
--- a/plugins/platforms/x11/standalone/CMakeLists.txt
+++ b/plugins/platforms/x11/standalone/CMakeLists.txt
@@ -28,7 +28,7 @@ include_directories(${CMAKE_SOURCE_DIR}/platformsupport/scenes/opengl)
add_library(KWinX11Platform MODULE ${X11PLATFORM_SOURCES})
set_target_properties(KWinX11Platform PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/org.kde.kwin.platforms/")
-target_link_libraries(KWinX11Platform eglx11common kwin kwinxrenderutils SceneOpenGLBackend Qt5::X11Extras XCB::CURSOR KF5::Crash)
+target_link_libraries(KWinX11Platform eglx11common kwin kwinxrenderutils SceneOpenGLBackend Qt5::X11Extras XCB::CURSOR KF5::Crash )
if (X11_Xinput_FOUND)
target_link_libraries(KWinX11Platform ${X11_Xinput_LIB})
endif()
diff --git a/plugins/platforms/x11/standalone/glxbackend.cpp b/plugins/platforms/x11/standalone/glxbackend.cpp
index 1ae6ccd9ae..901f2c971c 100644
--- a/plugins/platforms/x11/standalone/glxbackend.cpp
+++ b/plugins/platforms/x11/standalone/glxbackend.cpp
@@ -38,11 +38,13 @@ along with this program. If not, see .
// kwin libs
#include
#include
+#include
#include
// Qt
#include
#include
#include
+#include
// system
#include
@@ -137,6 +139,7 @@ GlxBackend::~GlxBackend()
// do cleanup after initBuffer()
cleanupGL();
doneCurrent();
+ EffectQuickView::setShareContext(nullptr);
gs_tripleBufferUndetected = true;
gs_tripleBufferNeedsDetection = false;
@@ -359,6 +362,12 @@ bool GlxBackend::initRenderingContext()
return false;
}
+ auto qtContext = new QOpenGLContext;
+ QGLXNativeContext native(ctx, display());
+ qtContext->setNativeHandle(QVariant::fromValue(native));
+ qtContext->create();
+ EffectQuickView::setShareContext(std::unique_ptr(qtContext));
+
return true;
}
diff --git a/plugins/scenes/opengl/scene_opengl.cpp b/plugins/scenes/opengl/scene_opengl.cpp
index dfca31f3ad..0f8723d844 100644
--- a/plugins/scenes/opengl/scene_opengl.cpp
+++ b/plugins/scenes/opengl/scene_opengl.cpp
@@ -33,6 +33,7 @@ along with this program. If not, see .
#include "platformsupport/scenes/opengl/texture.h"
#include
+#include
#include "utils.h"
#include "x11client.h"
@@ -858,6 +859,30 @@ void SceneOpenGL::paintDesktop(int desktop, int mask, const QRegion ®ion, Scr
glDisable(GL_SCISSOR_TEST);
}
+void SceneOpenGL::paintEffectQuickView(EffectQuickView *w)
+{
+ GLShader *shader = ShaderManager::instance()->pushShader(ShaderTrait::MapTexture);
+ const QRect rect = w->geometry();
+
+ GLTexture *t = w->bufferAsTexture();
+ if (!t) {
+ return;
+ }
+
+ QMatrix4x4 mvp(projectionMatrix());
+ mvp.translate(rect.x(), rect.y());
+ shader->setUniform(GLShader::ModelViewProjectionMatrix, mvp);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ t->bind();
+ t->render(QRegion(infiniteRegion()), w->geometry());
+ t->unbind();
+ glDisable(GL_BLEND);
+ return;
+}
+
bool SceneOpenGL::makeOpenGLContextCurrent()
{
return m_backend->makeCurrent();
diff --git a/plugins/scenes/opengl/scene_opengl.h b/plugins/scenes/opengl/scene_opengl.h
index b2eea05f68..af4309bc59 100644
--- a/plugins/scenes/opengl/scene_opengl.h
+++ b/plugins/scenes/opengl/scene_opengl.h
@@ -90,6 +90,7 @@ protected:
void extendPaintRegion(QRegion ®ion, bool opaqueFullscreen) override;
QMatrix4x4 transformation(int mask, const ScreenPaintData &data) const;
void paintDesktop(int desktop, int mask, const QRegion ®ion, ScreenPaintData &data) override;
+ void paintEffectQuickView(EffectQuickView *w) override;
void handleGraphicsReset(GLenum status);
diff --git a/plugins/scenes/qpainter/scene_qpainter.cpp b/plugins/scenes/qpainter/scene_qpainter.cpp
index 0fe2a86571..8588ed96d8 100644
--- a/plugins/scenes/qpainter/scene_qpainter.cpp
+++ b/plugins/scenes/qpainter/scene_qpainter.cpp
@@ -29,6 +29,9 @@ along with this program. If not, see .
#include "toplevel.h"
#include "platform.h"
#include "wayland_server.h"
+
+#include
+
#include
#include
#include
@@ -173,6 +176,16 @@ void SceneQPainter::paintCursor()
kwinApp()->platform()->markCursorAsRendered();
}
+void SceneQPainter::paintEffectQuickView(EffectQuickView *w)
+{
+ QPainter *painter = effects->scenePainter();
+ const QImage buffer = w->bufferAsImage();
+ if (buffer.isNull()) {
+ return;
+ }
+ painter->drawImage(w->geometry(), buffer);
+}
+
Scene::Window *SceneQPainter::createWindow(Toplevel *toplevel)
{
return new SceneQPainter::Window(this, toplevel);
diff --git a/plugins/scenes/qpainter/scene_qpainter.h b/plugins/scenes/qpainter/scene_qpainter.h
index dad6e2f4c8..7aef28e3ba 100644
--- a/plugins/scenes/qpainter/scene_qpainter.h
+++ b/plugins/scenes/qpainter/scene_qpainter.h
@@ -62,6 +62,7 @@ protected:
void paintBackground(QRegion region) override;
Scene::Window *createWindow(Toplevel *toplevel) override;
void paintCursor() override;
+ void paintEffectQuickView(EffectQuickView *w) override;
private:
explicit SceneQPainter(QPainterBackend *backend, QObject *parent = nullptr);
diff --git a/plugins/scenes/xrender/scene_xrender.cpp b/plugins/scenes/xrender/scene_xrender.cpp
index 0050be1af8..439fac9da1 100644
--- a/plugins/scenes/xrender/scene_xrender.cpp
+++ b/plugins/scenes/xrender/scene_xrender.cpp
@@ -36,9 +36,11 @@ along with this program. If not, see .
#include "platform.h"
#include "screens.h"
#include "xcbutils.h"
-#include "kwinxrenderutils.h"
#include "decorations/decoratedclient.h"
+#include
+#include
+
#include
#include
@@ -1329,3 +1331,16 @@ void KWin::SceneXrender::paintCursor()
{
}
+
+void KWin::SceneXrender::paintEffectQuickView(KWin::EffectQuickView *w)
+{
+ const QImage buffer = w->bufferAsImage();
+ if (buffer.isNull()) {
+ return;
+ }
+ XRenderPicture picture(buffer);
+ xcb_render_composite(connection(), XCB_RENDER_PICT_OP_OVER, picture, XCB_RENDER_PICTURE_NONE,
+ effects->xrenderBufferPicture(),
+ 0, 0, 0, 0, w->geometry().x(), w->geometry().y(),
+ w->geometry().width(), w->geometry().height());
+}
diff --git a/plugins/scenes/xrender/scene_xrender.h b/plugins/scenes/xrender/scene_xrender.h
index 808cee2d53..7520ee34dd 100644
--- a/plugins/scenes/xrender/scene_xrender.h
+++ b/plugins/scenes/xrender/scene_xrender.h
@@ -178,6 +178,7 @@ protected:
void paintGenericScreen(int mask, ScreenPaintData data) override;
void paintDesktop(int desktop, int mask, const QRegion ®ion, ScreenPaintData &data) override;
void paintCursor() override;
+ void paintEffectQuickView(EffectQuickView *w) override;
private:
explicit SceneXrender(XRenderBackend *backend, QObject *parent = nullptr);
static ScreenPaintData screen_paint;
diff --git a/scene.h b/scene.h
index 7aa987cd2e..7199a9e74d 100644
--- a/scene.h
+++ b/scene.h
@@ -236,6 +236,9 @@ protected:
// the default is NOOP
virtual void extendPaintRegion(QRegion ®ion, bool opaqueFullscreen);
virtual void paintDesktop(int desktop, int mask, const QRegion ®ion, ScreenPaintData &data);
+
+ virtual void paintEffectQuickView(EffectQuickView *w) = 0;
+
// compute time since the last repaint
void updateTimeDiff();
// saved data for 2nd pass of optimized screen painting